일목균형표 수정

This commit is contained in:
Macbook
2026-05-27 23:36:48 +09:00
parent 9cee6387c3
commit 8cc0d1c88c
73 changed files with 2256 additions and 334 deletions
+23 -6
View File
@@ -55,6 +55,10 @@ import {
} from '../utils/virtualLiveStrategySync';
import { pinStrategyEvaluationTimeframes } from '../utils/strategyTimeframePin';
import { persistVirtualTargetPinned } from '../utils/virtualTargetMutations';
import {
coalesceTargetsToDefaultStrategy,
resolveVirtualTargetStrategyId,
} from '../utils/virtualTargetStrategy';
import { virtualTargetLimitMessage } from '../utils/virtualTargetLimits';
import '../styles/virtualTradingDashboard.css';
@@ -100,6 +104,7 @@ const VirtualTradingPage: React.FC<Props> = ({
const chartRealtimeSource = (appChartDefaults.chartRealtimeSource
?? 'BACKEND_STOMP') as ChartRealtimeSource;
const chartSeriesPriceLabels = appChartDefaults.chartSeriesPriceLabels;
const chartPaneSeparator = appChartDefaults.chartPaneSeparator;
const chartLiveReceiveHighlight = appChartDefaults.chartLiveReceiveHighlight;
const virtualTargetMaxCount = appChartDefaults.virtualTargetMaxCount;
@@ -136,6 +141,13 @@ const VirtualTradingPage: React.FC<Props> = ({
useEffect(() => { saveVirtualTargets(targets); }, [targets]);
useEffect(() => { saveVirtualSession(session); }, [session]);
/** 예전 데이터: 종목 strategyId에 전역 ID가 복사된 경우 → 기본 전략 따름(null) */
useEffect(() => {
if (session.globalStrategyId == null) return;
setTargets(prev => coalesceTargetsToDefaultStrategy(prev, session.globalStrategyId));
}, [session.globalStrategyId]);
useEffect(() => { saveVirtualCardViewMode(viewMode); }, [viewMode]);
const strategyNames = useMemo(
@@ -160,7 +172,7 @@ const VirtualTradingPage: React.FC<Props> = ({
const targetRefs = useMemo(() =>
targets.map(t => ({
market: t.market,
strategyId: t.strategyId ?? session.globalStrategyId,
strategyId: resolveVirtualTargetStrategyId(t, session.globalStrategyId),
})),
[targets, session.globalStrategyId]);
@@ -302,22 +314,24 @@ const VirtualTradingPage: React.FC<Props> = ({
setTargets(prev => prev.map(t =>
t.market === market ? { ...t, strategyId } : t,
));
if (!session.running || !strategyId) return;
if (!session.running) return;
const effectiveId = resolveVirtualTargetStrategyId({ strategyId }, session.globalStrategyId);
if (effectiveId == null) return;
try {
await saveLiveStrategySettings({
market,
strategyId,
strategyId: effectiveId,
isLiveCheck: true,
executionType: session.executionType,
positionMode: session.positionMode,
skipWatchlistSync: true,
skipGlobalTemplate: true,
});
await pinStrategyEvaluationTimeframes(market, strategyId);
await pinStrategyEvaluationTimeframes(market, effectiveId);
} catch {
window.alert('종목 전략 변경 저장에 실패했습니다.');
}
}, [session, targets]);
}, [session]);
const handleTargetCandleTypeChange = useCallback(async (market: string, candleType: string) => {
const normalized = normalizeStartCandleType(candleType);
@@ -326,7 +340,9 @@ const VirtualTradingPage: React.FC<Props> = ({
));
if (!session.running) return;
const target = targets.find(t => t.market === market);
const strategyId = target?.strategyId ?? session.globalStrategyId;
const strategyId = target
? resolveVirtualTargetStrategyId(target, session.globalStrategyId)
: session.globalStrategyId;
if (!strategyId) return;
try {
await saveLiveStrategySettings({
@@ -469,6 +485,7 @@ const VirtualTradingPage: React.FC<Props> = ({
theme={theme}
chartRealtimeSource={chartRealtimeSource}
chartSeriesPriceLabels={chartSeriesPriceLabels}
chartPaneSeparator={chartPaneSeparator}
chartLiveReceiveHighlight={chartLiveReceiveHighlight}
tickers={tickers}
viewMode={viewMode}