import React, { useEffect, useState } from 'react'; import { loadStrategies, loadLiveStrategySettings, type LiveStrategySettingsDto, type PaperSummaryDto, type StrategyDto, } from '../../utils/backendApi'; import { loadVirtualSession } from '../../utils/virtualTradingStorage'; import { fmtKrw } from '../TradeOrderPanel'; import PaperSplitPanel from './PaperSplitPanel'; interface Props { market: string; summary: PaperSummaryDto | null; paperAutoTradeEnabled?: boolean; onMarketSelect?: (market: string) => void; } const PaperLeftStrategyTab: React.FC = ({ market, summary, paperAutoTradeEnabled = false, onMarketSelect, }) => { const [strategies, setStrategies] = useState([]); const [settings, setSettings] = useState(null); const [virtualRunning, setVirtualRunning] = useState(() => loadVirtualSession().running); useEffect(() => { loadStrategies().then(setStrategies).catch(() => setStrategies([])); }, []); useEffect(() => { const refreshVirtual = () => setVirtualRunning(loadVirtualSession().running); window.addEventListener('gc_virtual_session_changed', refreshVirtual); window.addEventListener('storage', refreshVirtual); return () => { window.removeEventListener('gc_virtual_session_changed', refreshVirtual); window.removeEventListener('storage', refreshVirtual); }; }, []); useEffect(() => { let cancelled = false; loadLiveStrategySettings(market) .then(s => { if (!cancelled) setSettings(s); }) .catch(() => { if (!cancelled) { setSettings({ market, strategyId: null, isLiveCheck: false, executionType: 'CANDLE_CLOSE', positionMode: 'LONG_ONLY', }); } }); return () => { cancelled = true; }; }, [market, virtualRunning]); const selected = strategies.find(s => s.id === settings?.strategyId); const execLabel = settings?.executionType === 'REALTIME_TICK' ? '실시간 틱 (3초)' : '봉 마감 직후'; const top = ( <>
{summary ? fmtKrw(summary.totalAsset) : '—'} KRW
= 0 ? 'up' : 'down'}`}> {summary ? `${(summary.totalReturnPct ?? 0) >= 0 ? '+' : ''}${summary.totalReturnPct.toFixed(2)}%` : '—'}

실시간 전략·체크 대상 종목은 가상투자 화면에서 설정합니다. {virtualRunning ? ' (세션 실행 중)' : ''}

{settings?.isLiveCheck && selected && (

{market.replace(/^KRW-/, '')}: {selected.name} · {execLabel}

)}

{paperAutoTradeEnabled ? '자동매매 ON — 가상투자 Match 시 가상 계좌 자동 체결' : '자동매매 OFF — 가상투자 타이틀바에서 변경'}

); const bottom = ( {(summary?.positions ?? []).length === 0 ? ( ) : summary!.positions.map(p => { const code = p.symbol.replace(/^KRW-/, ''); const up = (p.profitLoss ?? 0) >= 0; return ( onMarketSelect?.(p.symbol)} > ); })}
자산수량손익
보유 없음
{code} {p.quantity.toFixed(4)} {p.profitLoss != null ? `${up ? '+' : ''}${fmtKrw(p.profitLoss)}` : '—'}
); return ( ); }; export default PaperLeftStrategyTab;