Files
goldenChart/frontend/src/utils/virtualTradingStorage.ts
T

110 lines
3.3 KiB
TypeScript

import { normalizeStartCandleType } from './strategyStartNodes';
/** 가상투자 대상 종목·세션 설정 localStorage */
export interface VirtualTargetItem {
market: string;
strategyId: number | null;
/** 종목별 전략 평가 분봉 (gc_live_strategy_settings.candle_type) */
candleType?: string;
koreanName?: string;
englishName?: string;
}
export interface VirtualSessionConfig {
globalStrategyId: number | null;
executionType: 'CANDLE_CLOSE' | 'REALTIME_TICK';
/** LONG_ONLY = 보유 자산 기준, SIGNAL_ONLY = 순수 지표 기준 */
positionMode: 'LONG_ONLY' | 'SIGNAL_ONLY';
running: boolean;
}
const TARGETS_KEY = 'gc_virtual_targets_v1';
const SESSION_KEY = 'gc_virtual_session_v1';
const CARD_VIEW_KEY = 'gc_virtual_card_view_v1';
/** 카드 표시: summary=이퀄라이저·신호등·푸터만, detail=지표 테이블 포함 전체 */
export type VirtualCardViewMode = 'summary' | 'detail';
export function loadVirtualTargets(): VirtualTargetItem[] {
try {
const raw = localStorage.getItem(TARGETS_KEY);
if (!raw) return [];
const parsed = JSON.parse(raw) as VirtualTargetItem[];
return Array.isArray(parsed) ? parsed : [];
} catch {
return [];
}
}
export function saveVirtualTargets(items: VirtualTargetItem[]): void {
try {
localStorage.setItem(TARGETS_KEY, JSON.stringify(items));
notifyVirtualSessionChanged();
} catch { /* ignore */ }
}
export function loadVirtualSession(): VirtualSessionConfig {
try {
const raw = localStorage.getItem(SESSION_KEY);
if (!raw) return defaultSession();
const parsed = JSON.parse(raw) as Partial<VirtualSessionConfig>;
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,
};
} catch {
return defaultSession();
}
}
export function saveVirtualSession(cfg: VirtualSessionConfig): void {
try {
localStorage.setItem(SESSION_KEY, JSON.stringify(cfg));
notifyVirtualSessionChanged();
} catch { /* ignore */ }
}
export const VIRTUAL_SESSION_CHANGED_EVENT = 'gc_virtual_session_changed';
export function notifyVirtualSessionChanged(): void {
window.dispatchEvent(new CustomEvent(VIRTUAL_SESSION_CHANGED_EVENT));
}
function defaultSession(): VirtualSessionConfig {
return {
globalStrategyId: null,
executionType: 'CANDLE_CLOSE',
positionMode: 'LONG_ONLY',
running: false,
};
}
export function loadVirtualCardViewMode(): VirtualCardViewMode {
try {
const raw = localStorage.getItem(CARD_VIEW_KEY);
return raw === 'detail' ? 'detail' : 'summary';
} catch {
return 'summary';
}
}
export function saveVirtualCardViewMode(mode: VirtualCardViewMode): void {
try {
localStorage.setItem(CARD_VIEW_KEY, mode);
} catch { /* ignore */ }
}
/** 카드 시간봉 드롭다운 기본값 — 저장값 → 스냅샷 → 1m */
export function resolveTargetCandleType(
item: Pick<VirtualTargetItem, 'candleType'>,
snapshotTimeframe?: string | null,
): string {
if (item.candleType) return normalizeStartCandleType(item.candleType);
const raw = snapshotTimeframe?.split(',')[0]?.trim();
if (raw) return normalizeStartCandleType(raw);
return '1m';
}