백테스팅 분석결과 레포트 출력
This commit is contained in:
@@ -11,6 +11,7 @@ import {
|
||||
type BacktestResultRecord,
|
||||
type BacktestAnalysis,
|
||||
type BacktestSignal,
|
||||
type StrategyDto,
|
||||
} from '../utils/backendApi';
|
||||
import type { Theme } from '../types';
|
||||
import { buildEquityFromSignals } from '../utils/backtestEquity';
|
||||
@@ -25,6 +26,11 @@ import BacktestExecutionList, { type ExecutionListTab } from './backtest/Backtes
|
||||
import BacktestAnalysisChart from './backtest/BacktestAnalysisChart';
|
||||
import BacktestKpiPanel from './backtest/BacktestKpiPanel';
|
||||
import BacktestTradeHistoryCard from './backtest/BacktestTradeHistoryCard';
|
||||
import BacktestAnalysisReportModal from './backtest/BacktestAnalysisReportModal';
|
||||
import {
|
||||
buildBacktestReportModel,
|
||||
buildLiveReportModel,
|
||||
} from '../utils/backtestReportModel';
|
||||
import { buildLiveExecutionItems, paperTradesToSignals, type LiveExecutionItem } from '../utils/liveExecutionGroups';
|
||||
import { PAPER_TRADES_CHANGED_EVENT } from '../utils/paperTradeEvents';
|
||||
import {
|
||||
@@ -34,6 +40,7 @@ import {
|
||||
} from './strategyEditor/usePanelResize';
|
||||
import '../styles/strategyEditorTheme.css';
|
||||
import { getKoreanName } from '../utils/marketNameCache';
|
||||
import { repairUtf8Mojibake } from '../utils/textEncoding';
|
||||
|
||||
const LEFT_KEY = 'btd-left-width';
|
||||
const RIGHT_KEY = 'btd-right-width';
|
||||
@@ -65,6 +72,8 @@ export function BacktestHistoryPage({ theme = 'dark' }: Props) {
|
||||
const [selectedBacktest, setSelectedBacktest] = useState<BacktestResultRecord | null>(null);
|
||||
const [selectedLive, setSelectedLive] = useState<LiveExecutionItem | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [reportOpen, setReportOpen] = useState(false);
|
||||
const [strategies, setStrategies] = useState<StrategyDto[]>([]);
|
||||
|
||||
const [leftWidth, setLeftWidth] = useState(() => readMinWidth(LEFT_KEY, LEFT_DEFAULT));
|
||||
const [rightWidth, setRightWidth] = useState(() => readMinWidth(RIGHT_KEY, RIGHT_DEFAULT));
|
||||
@@ -121,6 +130,7 @@ export function BacktestHistoryPage({ theme = 'dark' }: Props) {
|
||||
]);
|
||||
const strategyNames = Object.fromEntries(strategies.map(s => [s.id, s.name]));
|
||||
const live = buildLiveExecutionItems(trades, summary, strategyNames);
|
||||
setStrategies(strategies);
|
||||
setRecords(list);
|
||||
setLiveItems(live);
|
||||
setSelectedBacktest(prev => (prev && list.some(x => x.id === prev.id) ? prev : list[0] ?? null));
|
||||
@@ -224,6 +234,32 @@ export function BacktestHistoryPage({ theme = 'dark' }: Props) {
|
||||
|
||||
const footerTrades = equityData.trades;
|
||||
|
||||
const strategyNamesById = useMemo(
|
||||
() => Object.fromEntries(
|
||||
strategies.map(s => [s.id, repairUtf8Mojibake(s.name)]),
|
||||
),
|
||||
[strategies],
|
||||
);
|
||||
|
||||
const reportModel = useMemo(() => {
|
||||
if (tab === 'backtest' && selectedBacktest && backtestDetail?.analysis) {
|
||||
return buildBacktestReportModel(
|
||||
selectedBacktest,
|
||||
backtestDetail.analysis,
|
||||
backtestDetail.signals,
|
||||
strategyNamesById,
|
||||
);
|
||||
}
|
||||
if (tab === 'live' && selectedLive) {
|
||||
return buildLiveReportModel(
|
||||
selectedLive,
|
||||
activeSignals,
|
||||
chartProps?.timeframe ?? '1h',
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}, [tab, selectedBacktest, backtestDetail, selectedLive, activeSignals, chartProps?.timeframe, strategyNamesById]);
|
||||
|
||||
const showRightDetail = tab === 'backtest'
|
||||
? backtestDetail?.analysis != null
|
||||
: selectedLive != null;
|
||||
@@ -305,6 +341,8 @@ export function BacktestHistoryPage({ theme = 'dark' }: Props) {
|
||||
signals={activeSignals}
|
||||
strategyId={chartProps.strategyId}
|
||||
theme={theme}
|
||||
onOpenReport={() => setReportOpen(true)}
|
||||
reportDisabled={!reportModel}
|
||||
/>
|
||||
) : (
|
||||
<div className="btd-empty">
|
||||
@@ -347,6 +385,12 @@ export function BacktestHistoryPage({ theme = 'dark' }: Props) {
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
|
||||
<BacktestAnalysisReportModal
|
||||
open={reportOpen}
|
||||
onClose={() => setReportOpen(false)}
|
||||
model={reportModel}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user