분석 레포트 화면 수정

This commit is contained in:
Macbook
2026-06-07 17:43:22 +09:00
parent 7ec754770d
commit 5928599fd0
11 changed files with 1802 additions and 187 deletions
@@ -0,0 +1,91 @@
/**
* 백테스팅 · 투자분석 — 거래 시그널 테이블
*/
import React, { useState } from 'react';
import type { BacktestSignal } from '../../utils/backendApi';
import { repairUtf8Mojibake } from '../../utils/textEncoding';
import { SectionTitle } from '../shared/analysisDashboardUi';
const SIG_LABEL: Record<string, string> = {
BUY: '매수',
SELL: '매도',
SHORT_ENTRY: '공매도',
SHORT_EXIT: '공매도청산',
PARTIAL_SELL: '분할매도',
};
const SIG_COLOR: Record<string, string> = {
BUY: 'brd-sig-buy',
SELL: 'brd-sig-sell',
SHORT_ENTRY: 'brd-neg',
SHORT_EXIT: 'brd-pos',
PARTIAL_SELL: 'brd-warn',
};
const fmtDate = (ts: number) => {
const d = new Date(ts * 1000);
return `${d.getFullYear()}.${String(d.getMonth() + 1).padStart(2, '0')}.${String(d.getDate()).padStart(2, '0')}`;
};
interface Props {
signals: BacktestSignal[];
/** true — 전체 표시, 접기 버튼 없음 */
expanded?: boolean;
className?: string;
}
export default function BacktestSignalTable({ signals, expanded = false, className }: Props) {
const [sigExpanded, setSigExpanded] = useState(expanded);
const showAll = expanded || sigExpanded;
const sigLimit = showAll ? signals.length : 8;
return (
<div className={`brd-card brd-card--full brd-card--sig-panel${className ? ` ${className}` : ''}`}>
<SectionTitle
icon="📋"
title="거래 시그널"
right={<span className="brd-section-count">{signals.length}</span>}
/>
{signals.length === 0 ? (
<div className="brd-empty-msg"> .</div>
) : (
<>
<div className="brd-sig-scroll">
<table className="brd-sig-table">
<thead>
<tr>
<th style={{ width: 36 }}>#</th>
<th></th>
<th></th>
<th style={{ textAlign: 'right' }}></th>
<th style={{ textAlign: 'center', width: 50 }}>#</th>
</tr>
</thead>
<tbody>
{signals.slice(0, sigLimit).map((s, i) => (
<tr key={i} className={i % 2 === 0 ? 'brd-sig-even' : ''}>
<td style={{ textAlign: 'center', color: 'var(--text3)' }}>{i + 1}</td>
<td style={{ fontVariantNumeric: 'tabular-nums' }}>{fmtDate(s.time)}</td>
<td>
<span className={`brd-sig-badge ${SIG_COLOR[s.type] ?? ''}`}>
{repairUtf8Mojibake(SIG_LABEL[s.type] ?? s.type)}
</span>
</td>
<td style={{ textAlign: 'right', fontVariantNumeric: 'tabular-nums', fontWeight: 600 }}>
{Math.round(s.price).toLocaleString()}
</td>
<td style={{ textAlign: 'center', color: 'var(--text3)' }}>{s.barIndex}</td>
</tr>
))}
</tbody>
</table>
</div>
{!expanded && signals.length > 8 && (
<button type="button" className="brd-expand-btn" onClick={() => setSigExpanded(v => !v)}>
{sigExpanded ? '▲ 접기' : `▼ 전체 보기 (${signals.length}건)`}
</button>
)}
</>
)}
</div>
);
}