Update scoring and progress
This commit is contained in:
@@ -5,7 +5,7 @@ import useApiUrlStore from '../../../app/store/apiStore'
|
||||
import useBacktestStore from '../../../app/store/backtestStore'
|
||||
import type {Backtest} from '../../../generated/ManagingApi'
|
||||
import {BacktestClient} from '../../../generated/ManagingApi'
|
||||
import {CardText, ConfigDisplayModal, IndicatorsDisplay, SelectColumnFilter, Table} from '../../mollecules'
|
||||
import {ConfigDisplayModal, IndicatorsDisplay, SelectColumnFilter, Table} from '../../mollecules'
|
||||
import {UnifiedTradingModal} from '../index'
|
||||
import Toast from '../../mollecules/Toast/Toast'
|
||||
|
||||
@@ -37,6 +37,9 @@ const BacktestTable: React.FC<BacktestTableProps> = ({list, isFetching, displayS
|
||||
medianCooldown: 0,
|
||||
})
|
||||
|
||||
// Summary collapse state
|
||||
const [isSummaryCollapsed, setIsSummaryCollapsed] = useState(true)
|
||||
|
||||
// Bot configuration modal state
|
||||
const [showBotConfigModal, setShowBotConfigModal] = useState(false)
|
||||
const [selectedBacktest, setSelectedBacktest] = useState<Backtest | null>(null)
|
||||
@@ -471,37 +474,56 @@ const BacktestTable: React.FC<BacktestTableProps> = ({list, isFetching, displayS
|
||||
) : (
|
||||
<>
|
||||
{list && list.length > 0 && displaySummary && (
|
||||
<>
|
||||
<div className="mb-4">
|
||||
<CardText
|
||||
title="Average Optimized Money Management"
|
||||
content={
|
||||
"SL: " + optimizedMoneyManagement.stopLoss.toFixed(2) + "% | TP: " +
|
||||
optimizedMoneyManagement.takeProfit.toFixed(2) + "% | R/R: " +
|
||||
(optimizedMoneyManagement.takeProfit / optimizedMoneyManagement.stopLoss || 0).toFixed(2)
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<CardText
|
||||
title="Position Timing Statistics"
|
||||
content={
|
||||
"Avg: " + positionTimingStats.averageOpenTime.toFixed(1) + "h | " +
|
||||
"Median: " + positionTimingStats.medianOpenTime.toFixed(1) + "h | " +
|
||||
"Losing Avg: " + positionTimingStats.losingPositionsAverageOpenTime.toFixed(1) + "h"
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
<div className="mb-4">
|
||||
<CardText
|
||||
title="Cooldown Recommendations"
|
||||
content={
|
||||
"Avg: " + cooldownRecommendations.averageCooldown + " candles | " +
|
||||
"Median: " + cooldownRecommendations.medianCooldown + " candles"
|
||||
}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
<div className="mb-4">
|
||||
<button
|
||||
onClick={() => setIsSummaryCollapsed(!isSummaryCollapsed)}
|
||||
className="btn btn-sm btn-outline mb-2"
|
||||
>
|
||||
{isSummaryCollapsed ? (
|
||||
<>
|
||||
<ChevronRightIcon className="w-4 h-4 mr-1" />
|
||||
Show Summary
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<ChevronDownIcon className="w-4 h-4 mr-1" />
|
||||
Hide Summary
|
||||
</>
|
||||
)}
|
||||
</button>
|
||||
|
||||
{!isSummaryCollapsed && (
|
||||
<div className="bg-base-200 p-4 rounded-lg space-y-3">
|
||||
<div className="flex flex-wrap gap-4 text-sm">
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="font-semibold text-xs text-gray-600 mb-1">Money Management</div>
|
||||
<div className="flex gap-2">
|
||||
<span className="badge badge-outline">SL: {optimizedMoneyManagement.stopLoss.toFixed(2)}%</span>
|
||||
<span className="badge badge-outline">TP: {optimizedMoneyManagement.takeProfit.toFixed(2)}%</span>
|
||||
<span className="badge badge-outline">R/R: {(optimizedMoneyManagement.takeProfit / optimizedMoneyManagement.stopLoss || 0).toFixed(2)}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="font-semibold text-xs text-gray-600 mb-1">Position Timing</div>
|
||||
<div className="flex gap-2">
|
||||
<span className="badge badge-outline">Avg: {positionTimingStats.averageOpenTime.toFixed(1)}h</span>
|
||||
<span className="badge badge-outline">Median: {positionTimingStats.medianOpenTime.toFixed(1)}h</span>
|
||||
<span className="badge badge-outline">Losing: {positionTimingStats.losingPositionsAverageOpenTime.toFixed(1)}h</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="font-semibold text-xs text-gray-600 mb-1">Cooldown</div>
|
||||
<div className="flex gap-2">
|
||||
<span className="badge badge-outline">Avg: {cooldownRecommendations.averageCooldown} candles</span>
|
||||
<span className="badge badge-outline">Median: {cooldownRecommendations.medianCooldown} candles</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
<Table
|
||||
columns={columns}
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import React from 'react';
|
||||
import Plot from 'react-plotly.js';
|
||||
import {Backtest} from '../../../generated/ManagingApi';
|
||||
import useTheme from '../../../hooks/useTheme';
|
||||
|
||||
interface Fitness3DPlotProps {
|
||||
backtests: Backtest[];
|
||||
theme: { secondary: string };
|
||||
}
|
||||
|
||||
const Fitness3DPlot: React.FC<Fitness3DPlotProps> = ({ backtests, theme }) => {
|
||||
const Fitness3DPlot: React.FC<Fitness3DPlotProps> = ({ backtests }) => {
|
||||
const theme = useTheme().themeProperty()
|
||||
|
||||
const LOOPBACK_CONFIG = {
|
||||
singleIndicator: 1,
|
||||
multipleIndicators: { min: 5, max: 15 },
|
||||
@@ -113,9 +116,9 @@ const Fitness3DPlot: React.FC<Fitness3DPlotProps> = ({ backtests, theme }) => {
|
||||
layout={{
|
||||
title: {text: 'Fitness Score vs Score vs Win Rate'},
|
||||
scene: {
|
||||
xaxis: {title: {text: 'Fitness Score'}},
|
||||
yaxis: {title: {text: 'Score'}},
|
||||
zaxis: {title: {text: 'Win Rate (%)'}},
|
||||
xaxis: {title: {text: 'Fitness Score'}, zerolinecolor: theme.secondary, color: theme.secondary},
|
||||
yaxis: {title: {text: 'Score'}, zerolinecolor: theme.secondary, color: theme.secondary},
|
||||
zaxis: {title: {text: 'Win Rate (%)'}, zerolinecolor: theme.secondary, color: theme.secondary},
|
||||
},
|
||||
width: 750,
|
||||
height: 600,
|
||||
@@ -126,8 +129,8 @@ const Fitness3DPlot: React.FC<Fitness3DPlotProps> = ({ backtests, theme }) => {
|
||||
r: 0,
|
||||
t: 0,
|
||||
},
|
||||
paper_bgcolor: '#121212',
|
||||
plot_bgcolor: theme.secondary,
|
||||
paper_bgcolor: "rgba(0,0,0,0)",
|
||||
plot_bgcolor: "rgba(0,0,0,0)",
|
||||
}}
|
||||
config={{displayModeBar: false}}
|
||||
/>
|
||||
|
||||
@@ -1,13 +1,16 @@
|
||||
import React from 'react'
|
||||
import Plot from 'react-plotly.js'
|
||||
import {Backtest} from '../../../generated/ManagingApi'
|
||||
import useTheme from '../../../hooks/useTheme'
|
||||
|
||||
interface ScoreVsGenerationProps {
|
||||
backtests: Backtest[]
|
||||
theme: { secondary: string }
|
||||
}
|
||||
|
||||
const ScoreVsGeneration: React.FC<ScoreVsGenerationProps> = ({ backtests, theme }) => {
|
||||
const ScoreVsGeneration: React.FC<ScoreVsGenerationProps> = ({ backtests }) => {
|
||||
const theme = useTheme().themeProperty()
|
||||
|
||||
// Helper function to get generation from metadata
|
||||
const getGeneration = (backtest: Backtest): number => {
|
||||
if (backtest.metadata && typeof backtest.metadata === 'object' && 'generation' in backtest.metadata) {
|
||||
@@ -115,7 +118,7 @@ const ScoreVsGeneration: React.FC<ScoreVsGenerationProps> = ({ backtests, theme
|
||||
color: theme.secondary
|
||||
}
|
||||
},
|
||||
gridcolor: theme.secondary,
|
||||
gridcolor: theme.neutral,
|
||||
zerolinecolor: theme.secondary,
|
||||
color: theme.secondary
|
||||
},
|
||||
@@ -126,7 +129,7 @@ const ScoreVsGeneration: React.FC<ScoreVsGenerationProps> = ({ backtests, theme
|
||||
color: theme.secondary
|
||||
}
|
||||
},
|
||||
gridcolor: theme.secondary,
|
||||
gridcolor: theme.neutral,
|
||||
zerolinecolor: theme.secondary,
|
||||
color: theme.secondary
|
||||
},
|
||||
|
||||
@@ -86,9 +86,9 @@ const TPvsSLvsPnL3DPlot: React.FC<TPvsSLvsPnL3DPlotProps> = ({ backtests, theme
|
||||
layout={{
|
||||
title: {text: 'Take Profit % vs Stop Loss % vs PnL'},
|
||||
scene: {
|
||||
xaxis: {title: {text: 'Take Profit (%)'}},
|
||||
yaxis: {title: {text: 'Stop Loss (%)'}},
|
||||
zaxis: {title: {text: 'PnL ($)'}},
|
||||
xaxis: {title: {text: 'Take Profit (%)'}, zerolinecolor: theme.secondary, color: theme.secondary},
|
||||
yaxis: {title: {text: 'Stop Loss (%)'}, zerolinecolor: theme.secondary, color: theme.secondary},
|
||||
zaxis: {title: {text: 'PnL ($)'}, zerolinecolor: theme.secondary, color: theme.secondary},
|
||||
},
|
||||
width: 750,
|
||||
height: 600,
|
||||
@@ -99,8 +99,8 @@ const TPvsSLvsPnL3DPlot: React.FC<TPvsSLvsPnL3DPlotProps> = ({ backtests, theme
|
||||
r: 0,
|
||||
t: 0,
|
||||
},
|
||||
paper_bgcolor: '#121212',
|
||||
plot_bgcolor: theme.secondary,
|
||||
paper_bgcolor: "rgba(0,0,0,0)",
|
||||
plot_bgcolor: "rgba(0,0,0,0)",
|
||||
}}
|
||||
config={{displayModeBar: false}}
|
||||
/>
|
||||
|
||||
@@ -248,20 +248,34 @@ const BacktestGeneticBundle: React.FC = () => {
|
||||
accessor: 'timeframe',
|
||||
},
|
||||
{
|
||||
Header: 'Progress',
|
||||
Header: 'Progress & Status',
|
||||
accessor: 'currentGeneration',
|
||||
Cell: ({value, row}: { value: number, row: any }) => {
|
||||
const generations = row.original.generations
|
||||
const currentGen = value || 0
|
||||
const percentage = generations > 0 ? Math.round((currentGen / generations) * 100) : 0
|
||||
const status = row.original.status
|
||||
|
||||
// Calculate color based on percentage (red to green)
|
||||
const getProgressColor = (percent: number) => {
|
||||
if (percent <= 25) return 'progress-error'
|
||||
if (percent <= 50) return 'progress-warning'
|
||||
if (percent <= 75) return 'progress-info'
|
||||
return 'progress-success'
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="text-xs">
|
||||
{currentGen} / {generations}
|
||||
<div className="flex flex-col gap-2">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className={`badge badge-sm ${getStatusBadgeColor(status)}`}>
|
||||
{status}
|
||||
</span>
|
||||
<div className="text-xs">
|
||||
{currentGen} / {generations}
|
||||
</div>
|
||||
</div>
|
||||
<progress
|
||||
className="progress progress-primary w-full h-2"
|
||||
className={`progress w-56 ${getProgressColor(percentage)}`}
|
||||
value={percentage}
|
||||
max="100"
|
||||
/>
|
||||
@@ -290,15 +304,7 @@ const BacktestGeneticBundle: React.FC = () => {
|
||||
<span className="text-xs">{value}</span>
|
||||
),
|
||||
},
|
||||
{
|
||||
Header: 'Status',
|
||||
accessor: 'status',
|
||||
Cell: ({value}: { value: string }) => (
|
||||
<span className={`badge ${getStatusBadgeColor(value)}`}>
|
||||
{value}
|
||||
</span>
|
||||
),
|
||||
},
|
||||
|
||||
{
|
||||
Header: 'Actions',
|
||||
accessor: 'actions',
|
||||
|
||||
Reference in New Issue
Block a user