백테스팅 분석결과 레포트 출력

This commit is contained in:
Macbook
2026-06-03 12:14:08 +09:00
parent c228f18c25
commit ee7b1a6123
11 changed files with 1207 additions and 15 deletions
@@ -7,6 +7,7 @@
import React, { useState } from 'react';
import type { BacktestAnalysis, BacktestSignal, BacktestStats } from '../utils/backendApi';
import { useDraggablePanel } from '../hooks/useDraggablePanel';
import { repairUtf8Mojibake } from '../utils/textEncoding';
// ── 포맷 유틸 ────────────────────────────────────────────────────────────────
@@ -60,6 +61,8 @@ export interface BacktestDashboardProps {
timeframe: string;
barCount: number;
createdAt?: string;
/** 레포트·PDF — 시그널 전체 표시·인쇄용 레이아웃 */
reportMode?: boolean;
}
// ── 섹션 제목 ─────────────────────────────────────────────────────────────
@@ -177,8 +180,9 @@ const SIG_COLOR: Record<string, string> = {
export function BacktestDashboard({
analysis, signals, strategyName, symbol, timeframe, barCount, createdAt,
reportMode = false,
}: BacktestDashboardProps) {
const [sigExpanded, setSigExpanded] = useState(false);
const [sigExpanded, setSigExpanded] = useState(reportMode);
const a = analysis;
if (!a) {
@@ -190,7 +194,7 @@ export function BacktestDashboard({
);
}
const sigLimit = sigExpanded ? signals.length : 8;
const sigLimit = reportMode || sigExpanded ? signals.length : 8;
const periodStr = signals.length >= 2
? `${fmtDate(signals[0].time)} ~ ${fmtDate(signals[signals.length-1].time)}`
: `${barCount}`;
@@ -198,12 +202,12 @@ export function BacktestDashboard({
const sharpeLevel = a.sharpeRatio >= 2 ? '탁월' : a.sharpeRatio >= 1 ? '우수' : a.sharpeRatio >= 0 ? '보통' : '미흡';
return (
<div className="brd-dashboard">
<div className={`brd-dashboard${reportMode ? ' brd-dashboard--report' : ''}`}>
{/* ── 대시보드 헤더 ── */}
<div className="brd-dash-header">
<div className="brd-dash-header-left">
<div className="brd-dash-strategy">{strategyName}</div>
<div className="brd-dash-strategy">{repairUtf8Mojibake(strategyName)}</div>
<div className="brd-dash-meta">
<span className="brd-dash-badge">{symbol}</span>
<span className="brd-dash-badge">{timeframe}</span>
@@ -211,12 +215,12 @@ export function BacktestDashboard({
{createdAt && <span className="brd-dash-badge brd-dash-badge--time"> {fmtDateStr(createdAt)}</span>}
</div>
</div>
<div className="brd-dash-header-kpi">
<div className="brd-dash-big-kpi">
<div className={`brd-dash-header-kpi${reportMode ? ' brd-dash-header-kpi--report' : ''}`}>
<div className={`brd-dash-big-kpi${reportMode ? ' brd-dash-big-kpi--report' : ''}`}>
<div className={`brd-dash-big-val ${colorCls(a.totalReturnPct)}`}>{pct(a.totalReturnPct)}</div>
<div className="brd-dash-big-label"> </div>
</div>
<div className="brd-dash-big-kpi">
<div className={`brd-dash-big-kpi${reportMode ? ' brd-dash-big-kpi--report' : ''}`}>
<div className={`brd-dash-big-val ${colorCls(a.finalEquity - a.initialCapital)}`}>
{wonFmt(a.finalEquity)}
</div>
@@ -390,7 +394,7 @@ export function BacktestDashboard({
<td style={{fontVariantNumeric:'tabular-nums'}}>{fmtDate(s.time)}</td>
<td>
<span className={`brd-sig-badge ${SIG_COLOR[s.type] ?? ''}`}>
{SIG_LABEL[s.type] ?? s.type}
{repairUtf8Mojibake(SIG_LABEL[s.type] ?? s.type)}
</span>
</td>
<td style={{textAlign:'right',fontVariantNumeric:'tabular-nums',fontWeight:600}}>
@@ -402,7 +406,7 @@ export function BacktestDashboard({
</tbody>
</table>
</div>
{signals.length > 8 && (
{!reportMode && signals.length > 8 && (
<button className="brd-expand-btn" onClick={() => setSigExpanded(v => !v)}>
{sigExpanded ? '▲ 접기' : `▼ 전체 보기 (${signals.length}건)`}
</button>