분석결과 레포트 수정

This commit is contained in:
Macbook
2026-06-19 07:19:32 +09:00
parent 8bceadc55b
commit 2514e0adae
7 changed files with 565 additions and 8 deletions
@@ -4,10 +4,11 @@
* BacktestDashboard — 카드 기반 대시보드 (재사용 가능)
* BacktestResultModal — 드래그 팝업으로 Dashboard를 감싸는 래퍼
*/
import React from 'react';
import React, { useMemo, useState } from 'react';
import type { BacktestAnalysis, BacktestSignal, BacktestStats } from '../utils/backendApi';
import { useDraggablePanel } from '../hooks/useDraggablePanel';
import { repairUtf8Mojibake } from '../utils/textEncoding';
import type { EvaluationAllocationReport } from './backtest/BacktestAnalysisReportModal';
import {
pct,
pctAbs,
@@ -58,6 +59,9 @@ export interface BacktestDashboardProps {
reportMode?: boolean;
/** false — 거래 시그널 섹션 숨김 (별도 패널에 표시) */
hideSignals?: boolean;
/** 전략평가 — 일괄/분할 매수 방식별 분석 */
evaluationAllocations?: EvaluationAllocationReport[];
reportSignalFilterNote?: string;
}
// ── 시그널 타입 ───────────────────────────────────────────────────────────
@@ -70,8 +74,17 @@ export function BacktestDashboard({
analysis, signals, strategyName, symbol, timeframe, barCount, createdAt,
reportMode = false,
hideSignals = false,
evaluationAllocations,
reportSignalFilterNote,
}: BacktestDashboardProps) {
const a = analysis;
const [allocMode, setAllocMode] = useState<'full' | 'split'>('split');
const displayAnalysis = useMemo(() => {
if (!evaluationAllocations?.length) return analysis;
return evaluationAllocations.find(e => e.mode === allocMode)?.analysis ?? analysis;
}, [analysis, evaluationAllocations, allocMode]);
const a = displayAnalysis;
if (!a) {
return (
<div className="brd-empty-state">
@@ -120,6 +133,49 @@ export function BacktestDashboard({
</div>
</div>
{evaluationAllocations && evaluationAllocations.length >= 2 && (
<div className="brd-row">
<div className="brd-card brd-card--full">
<SectionTitle icon="📋" title="매수 방식별 수익률 비교" />
{reportSignalFilterNote && (
<p className="brd-eval-filter-note">{reportSignalFilterNote}</p>
)}
<div className="brd-alloc-tabs">
{evaluationAllocations.map(item => (
<button
key={item.mode}
type="button"
className={`brd-alloc-tab${allocMode === item.mode ? ' brd-alloc-tab--active' : ''}`}
onClick={() => setAllocMode(item.mode)}
>
{item.label}
</button>
))}
</div>
<div className="brd-alloc-compare">
{evaluationAllocations.map(item => (
<div
key={item.mode}
className={`brd-alloc-card${allocMode === item.mode ? ' brd-alloc-card--active' : ''}`}
role="button"
tabIndex={0}
onClick={() => setAllocMode(item.mode)}
onKeyDown={e => { if (e.key === 'Enter' || e.key === ' ') setAllocMode(item.mode); }}
>
<div className="brd-alloc-card-label">{item.label}</div>
<div className={`brd-alloc-card-return ${colorCls(item.analysis.totalReturnPct)}`}>
{pct(item.analysis.totalReturnPct)}
</div>
<div className="brd-alloc-card-sub">
{wonFmt(item.analysis.finalEquity)} · {pctAbs(item.analysis.winRate)}
</div>
</div>
))}
</div>
</div>
</div>
)}
{/* ── Row 1: KPI 카드 6개 ── */}
<div className="brd-row">
<div className="brd-kpi-grid">