import { normalizeStartCandleType } from './strategyStartNodes'; import { resolveVirtualTargetNames } from './virtualTargetNames'; import { getUiPreferences, patchUiPreferences } from './uiPreferencesDb'; /** 가상투자 대상 종목·세션 설정 (DB ui_preferences + per-market live settings) */ export interface VirtualTargetItem { market: string; strategyId: number | null; /** 종목별 전략 평가 분봉 (gc_live_strategy_settings.candle_type) */ candleType?: string; koreanName?: string; englishName?: string; /** 투자대상 고정 — ON 이면 목록·추세검색에서 삭제 불가 (gc_live_strategy_settings.is_pinned) */ pinned?: boolean; } export interface VirtualSessionConfig { globalStrategyId: number | null; executionType: 'CANDLE_CLOSE' | 'REALTIME_TICK'; /** LONG_ONLY = 보유 자산 기준, SIGNAL_ONLY = 순수 지표 기준 */ positionMode: 'LONG_ONLY' | 'SIGNAL_ONLY'; running: boolean; } /** 카드 표시: summary=이퀄라이저·신호등·푸터만, detail=지표 테이블 포함 전체 */ export type VirtualCardViewMode = 'summary' | 'detail'; function defaultSession(): VirtualSessionConfig { return { globalStrategyId: null, executionType: 'CANDLE_CLOSE', positionMode: 'LONG_ONLY', running: false, }; } function normalizeTargets(items: VirtualTargetItem[]): VirtualTargetItem[] { return items.map(t => { const { koreanName, englishName } = resolveVirtualTargetNames( t.market, t.koreanName, t.englishName, ); return { ...t, koreanName, englishName }; }); } export function loadVirtualTargets(): VirtualTargetItem[] { const raw = getUiPreferences().virtual?.targets; if (!raw?.length) return []; return normalizeTargets(raw); } export function saveVirtualTargets(items: VirtualTargetItem[]): void { patchUiPreferences({ virtual: { targets: items } }); notifyVirtualSessionChanged(); } export function loadVirtualSession(): VirtualSessionConfig { const parsed = getUiPreferences().virtual?.session; if (!parsed) return defaultSession(); return { globalStrategyId: parsed.globalStrategyId ?? null, executionType: parsed.executionType === 'REALTIME_TICK' ? 'REALTIME_TICK' : 'CANDLE_CLOSE', positionMode: parsed.positionMode === 'SIGNAL_ONLY' ? 'SIGNAL_ONLY' : 'LONG_ONLY', running: parsed.running === true, }; } export function saveVirtualSession(cfg: VirtualSessionConfig): void { patchUiPreferences({ virtual: { session: cfg } }); notifyVirtualSessionChanged(); } export const VIRTUAL_SESSION_CHANGED_EVENT = 'gc_virtual_session_changed'; export function notifyVirtualSessionChanged(): void { window.dispatchEvent(new CustomEvent(VIRTUAL_SESSION_CHANGED_EVENT)); } export function loadVirtualCardViewMode(): VirtualCardViewMode { const mode = getUiPreferences().virtual?.cardViewMode; return mode === 'detail' ? 'detail' : 'summary'; } export function saveVirtualCardViewMode(mode: VirtualCardViewMode): void { patchUiPreferences({ virtual: { cardViewMode: mode } }); } /** 카드 시간봉 드롭다운 기본값 — 저장값 → 스냅샷 → 1m */ export function resolveTargetCandleType( item: Pick, snapshotTimeframe?: string | null, ): string { if (item.candleType) return normalizeStartCandleType(item.candleType); const raw = snapshotTimeframe?.split(',')[0]?.trim(); if (raw) return normalizeStartCandleType(raw); return '1m'; }