전략조건 상세설명 기능 추가
This commit is contained in:
+22
-25
@@ -1,4 +1,4 @@
|
||||
import React, { useState, useEffect, useCallback, useRef, useMemo } from 'react';
|
||||
import React, { useState, useEffect, useLayoutEffect, useCallback, useRef, useMemo } from 'react';
|
||||
import DrawingToolbar from './components/DrawingToolbar';
|
||||
import BottomBar from './components/BottomBar';
|
||||
import TradingChart from './components/TradingChart';
|
||||
@@ -70,7 +70,7 @@ import { BacktestHistoryPage } from './components/BacktestHistoryPage';
|
||||
import SettingsPage from './components/SettingsPage';
|
||||
import PaperTradingPage from './components/PaperTradingPage';
|
||||
import DashboardPage from './components/DashboardPage';
|
||||
import { loadPaperSummary, resetPaperAccount, loadActiveLiveStrategySettings } from './utils/backendApi';
|
||||
import { loadPaperSummary, resetPaperAccount, loadActiveLiveStrategySettings, expandLiveStrategySubscriptions } from './utils/backendApi';
|
||||
import ChartLegendBar from './components/ChartLegendBar';
|
||||
import RightSidePanel from './components/RightSidePanel';
|
||||
import {
|
||||
@@ -697,16 +697,14 @@ function App() {
|
||||
// ── 실시간 전략 체크 (전역 설정 + DB 관심종목 = 체크 대상) ─────────────────
|
||||
const [showLivePanel, setShowLivePanel] = useState(false);
|
||||
const [liveStrategies, setLiveStrategies] = useState<{id:number;name:string}[]>([]);
|
||||
const [liveCandleType, setLiveCandleType] = useState('1m');
|
||||
const [liveStrategyCandleTypes, setLiveStrategyCandleTypes] = useState<string[] | undefined>();
|
||||
|
||||
useEffect(() => {
|
||||
if (!appSettingsLoaded) return;
|
||||
loadLiveStrategySettings(symbol)
|
||||
.then(s => {
|
||||
if (s?.candleType) setLiveCandleType(s.candleType);
|
||||
})
|
||||
.catch(() => { /* 기본 1m 유지 */ });
|
||||
}, [symbol, appSettingsLoaded]);
|
||||
.then(s => setLiveStrategyCandleTypes(s.strategyCandleTypes))
|
||||
.catch(() => { /* optional */ });
|
||||
}, [symbol, appSettingsLoaded, appDefaults.liveStrategyId]);
|
||||
|
||||
const liveStrategySettings: LiveStrategySettingsDto = useMemo(() => ({
|
||||
market: symbol,
|
||||
@@ -714,8 +712,8 @@ function App() {
|
||||
isLiveCheck: appDefaults.liveStrategyCheck ?? false,
|
||||
executionType: appDefaults.liveExecutionType ?? 'CANDLE_CLOSE',
|
||||
positionMode: appDefaults.livePositionMode ?? 'LONG_ONLY',
|
||||
candleType: liveCandleType,
|
||||
}), [symbol, appDefaults, liveCandleType]);
|
||||
strategyCandleTypes: liveStrategyCandleTypes,
|
||||
}), [symbol, appDefaults, liveStrategyCandleTypes]);
|
||||
|
||||
/** 실시간 체크 ON + 전략 선택 시 STOMP 구독 대상 (관심종목 + 현재 차트 종목) */
|
||||
const monitoredMarkets = useMemo(() => {
|
||||
@@ -727,13 +725,12 @@ function App() {
|
||||
|
||||
const [marketSubscriptions, setMarketSubscriptions] = useState<{ market: string; candleType: string }[]>([]);
|
||||
|
||||
/** STOMP 구독 목록 — API 로드 전에도 관심종목 기준으로 바로 구독 (연결 끊김 방지) */
|
||||
/** STOMP 구독 목록 — API 로드 전에도 관심종목 × 1m 폴백 구독 */
|
||||
const liveStompSubscriptions = useMemo(() => {
|
||||
if (!appDefaults.liveStrategyCheck || !appDefaults.liveStrategyId) return [];
|
||||
if (marketSubscriptions.length > 0) return marketSubscriptions;
|
||||
const ct = liveCandleType || '1m';
|
||||
return monitoredMarkets.map(m => ({ market: m, candleType: ct }));
|
||||
}, [appDefaults.liveStrategyCheck, appDefaults.liveStrategyId, marketSubscriptions, monitoredMarkets, liveCandleType]);
|
||||
return monitoredMarkets.map(m => ({ market: m, candleType: '1m' }));
|
||||
}, [appDefaults.liveStrategyCheck, appDefaults.liveStrategyId, marketSubscriptions, monitoredMarkets]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!appDefaults.liveStrategyCheck) {
|
||||
@@ -741,11 +738,9 @@ function App() {
|
||||
return;
|
||||
}
|
||||
loadActiveLiveStrategySettings()
|
||||
.then(list => setMarketSubscriptions(
|
||||
list.map(s => ({ market: s.market, candleType: s.candleType ?? '1m' })),
|
||||
))
|
||||
.then(list => setMarketSubscriptions(expandLiveStrategySubscriptions(list)))
|
||||
.catch(() => { /* liveStompSubscriptions 가 monitoredMarkets 폴백 사용 */ });
|
||||
}, [appDefaults.liveStrategyCheck, monitoredMarkets.join(',')]);
|
||||
}, [appDefaults.liveStrategyCheck, appDefaults.liveStrategyId, monitoredMarkets.join(',')]);
|
||||
|
||||
const handleLiveSettingsChange = useCallback((saved: LiveStrategySettingsDto) => {
|
||||
saveAppDef({
|
||||
@@ -754,12 +749,12 @@ function App() {
|
||||
liveExecutionType: saved.executionType,
|
||||
livePositionMode: saved.positionMode,
|
||||
});
|
||||
if (saved.candleType) setLiveCandleType(saved.candleType);
|
||||
if (saved.strategyCandleTypes) {
|
||||
setLiveStrategyCandleTypes(saved.strategyCandleTypes);
|
||||
}
|
||||
if (appDefaults.liveStrategyCheck && saved.isLiveCheck) {
|
||||
loadActiveLiveStrategySettings()
|
||||
.then(list => setMarketSubscriptions(
|
||||
list.map(s => ({ market: s.market, candleType: s.candleType ?? '1m' })),
|
||||
))
|
||||
.then(list => setMarketSubscriptions(expandLiveStrategySubscriptions(list)))
|
||||
.catch(() => { /* 폴백 유지 */ });
|
||||
}
|
||||
}, [saveAppDef, appDefaults.liveStrategyCheck]);
|
||||
@@ -983,8 +978,8 @@ function App() {
|
||||
const barsMarket = useUpbit ? upbitBarsMarket : symbol;
|
||||
barsMarketRef.current = barsMarket;
|
||||
|
||||
/** 종목·타임프레임 전환 시 이전 틱 버퍼 폐기 */
|
||||
useEffect(() => {
|
||||
/** 종목·타임프레임 전환 시 이전 틱 버퍼 폐기 (paint 전에 실행) */
|
||||
useLayoutEffect(() => {
|
||||
pendingRealtimeBarRef.current = null;
|
||||
}, [symbol, timeframe]);
|
||||
|
||||
@@ -1981,12 +1976,14 @@ function App() {
|
||||
onManagerReady={mgr => {
|
||||
managerRef.current = mgr;
|
||||
const pending = pendingRealtimeBarRef.current;
|
||||
if (pending && bars.length > 0) {
|
||||
if (pending && barsMarketRef.current === symbol && bars.length > 0) {
|
||||
pendingRealtimeBarRef.current = null;
|
||||
const last = bars[bars.length - 1];
|
||||
if (last && pending.time === last.time) mgr.updateBar(pending);
|
||||
else if (!last || pending.time > last.time) void mgr.appendBar(pending);
|
||||
else mgr.updateBar({ ...pending, time: last.time });
|
||||
} else {
|
||||
pendingRealtimeBarRef.current = null;
|
||||
}
|
||||
mgr.setSeriesPriceLabelsEnabled(chartSeriesPriceLabels);
|
||||
const wrapper = document.querySelector('.chart-wrapper') as HTMLElement | null;
|
||||
|
||||
Reference in New Issue
Block a user