일목균형표 수정

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
@@ -9,6 +9,11 @@ import {
isVirtualTargetAddAllowed,
virtualTargetLimitMessage,
} from '../../utils/virtualTargetLimits';
import {
defaultStrategyOptionLabel,
parseTargetStrategySelectValue,
targetStrategySelectValue,
} from '../../utils/virtualTargetStrategy';
interface Props {
targets: VirtualTargetItem[];
@@ -72,7 +77,7 @@ const VirtualLeftTargetPanel: React.FC<Props> = ({
...targets,
{
market,
strategyId: globalStrategyId,
strategyId: null,
koreanName: names.koreanName,
englishName: names.englishName,
},
@@ -192,15 +197,19 @@ const VirtualLeftTargetPanel: React.FC<Props> = ({
<span className="vtd-target-strategy-label"></span>
<select
className="vtd-target-strategy-select"
value={item.strategyId ?? globalStrategyId ?? ''}
value={targetStrategySelectValue(item)}
onChange={e => {
const v = e.target.value;
onTargetStrategyChange(item.market, v ? Number(v) : null);
onTargetStrategyChange(
item.market,
parseTargetStrategySelectValue(e.target.value),
);
}}
>
<option value=""> </option>
<option value={targetStrategySelectValue({ strategyId: null })}>
{defaultStrategyOptionLabel(globalStrategyId, strategies)}
</option>
{strategies.map(s => (
<option key={s.id} value={s.id}>{s.name}</option>
<option key={s.id} value={String(s.id)}>{s.name}</option>
))}
</select>
</div>
@@ -42,6 +42,7 @@ interface Props {
theme?: Theme;
chartRealtimeSource?: ChartRealtimeSource;
chartSeriesPriceLabels?: boolean;
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
chartLiveReceiveHighlight?: boolean;
ticker?: TickerData;
}
@@ -68,6 +69,7 @@ const VirtualTargetCard: React.FC<Props> = ({
theme = 'dark',
chartRealtimeSource = 'BACKEND_STOMP',
chartSeriesPriceLabels = true,
chartPaneSeparator,
chartLiveReceiveHighlight = true,
ticker,
}) => {
@@ -174,6 +176,7 @@ const VirtualTargetCard: React.FC<Props> = ({
running={running}
chartRealtimeSource={chartRealtimeSource}
chartSeriesPriceLabels={chartSeriesPriceLabels}
chartPaneSeparator={chartPaneSeparator}
chartTimeframe={chartTimeframe}
/>
) : (
@@ -31,6 +31,7 @@ interface Props {
chartRealtimeSource?: ChartRealtimeSource;
/** 차트 설정 — 지표 가격축 라벨·설명 */
chartSeriesPriceLabels?: boolean;
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
/** 전체보기 분할 pane — 캔버스 높이 100% */
fillHeight?: boolean;
/** 카드 푸터 평가 분봉과 동기화 */
@@ -46,6 +47,7 @@ const VirtualTargetCardChart: React.FC<Props> = ({
running = false,
chartRealtimeSource = 'BACKEND_STOMP',
chartSeriesPriceLabels = true,
chartPaneSeparator,
fillHeight = false,
chartTimeframe,
}) => {
@@ -217,6 +219,7 @@ const VirtualTargetCardChart: React.FC<Props> = ({
volumeVisible={false}
showHoverToolbar={false}
seriesPriceLabelsEnabled={chartSeriesPriceLabels}
paneSeparatorOptions={chartPaneSeparator}
/>
</div>
@@ -3,6 +3,11 @@ import type { StrategyDto } from '../../utils/backendApi';
import type { VirtualIndicatorSnapshot } from '../../hooks/useVirtualIndicatorSnapshots';
import { formatUpdatedTime } from '../../utils/virtualSignalMetrics';
import { STRATEGY_CANDLE_TYPE_OPTIONS } from '../../utils/strategyStartNodes';
import {
defaultStrategyOptionLabel,
parseTargetStrategySelectValue,
targetStrategySelectValue,
} from '../../utils/virtualTargetStrategy';
interface Props {
snapshot: VirtualIndicatorSnapshot | undefined;
@@ -31,15 +36,16 @@ const VirtualTargetCardFoot: React.FC<Props> = ({
<select
className="vtd-card-foot-select"
aria-label="투자전략"
value={strategyId ?? globalStrategyId ?? ''}
value={targetStrategySelectValue({ strategyId })}
onChange={e => {
const v = e.target.value;
onStrategyChange?.(v ? Number(v) : null);
onStrategyChange?.(parseTargetStrategySelectValue(e.target.value));
}}
>
<option value=""> </option>
<option value={targetStrategySelectValue({ strategyId: null })}>
{defaultStrategyOptionLabel(globalStrategyId, strategies)}
</option>
{strategies.map(s => (
<option key={s.id} value={s.id}>{s.name}</option>
<option key={s.id} value={String(s.id)}>{s.name}</option>
))}
</select>
</label>
@@ -35,6 +35,7 @@ interface Props {
theme?: Theme;
chartRealtimeSource?: ChartRealtimeSource;
chartSeriesPriceLabels?: boolean;
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
chartLiveReceiveHighlight?: boolean;
ticker?: TickerData;
}
@@ -58,6 +59,7 @@ const VirtualTargetFocusView: React.FC<Props> = ({
theme = 'dark',
chartRealtimeSource = 'BACKEND_STOMP',
chartSeriesPriceLabels = true,
chartPaneSeparator,
chartLiveReceiveHighlight = true,
ticker,
}) => {
@@ -114,6 +116,7 @@ const VirtualTargetFocusView: React.FC<Props> = ({
running={running}
chartRealtimeSource={chartRealtimeSource}
chartSeriesPriceLabels={chartSeriesPriceLabels}
chartPaneSeparator={chartPaneSeparator}
fillHeight
chartTimeframe={chartTimeframe}
/>
@@ -13,6 +13,7 @@ import {
import type { VirtualLiveStatus } from '../../hooks/useVirtualTargetLiveStatus';
import type { VirtualIndicatorSnapshot } from '../../hooks/useVirtualIndicatorSnapshots';
import type { TickerData } from '../../hooks/useMarketTicker';
import { resolveVirtualTargetStrategyId } from '../../utils/virtualTargetStrategy';
interface Props {
targets: VirtualTargetItem[];
@@ -28,6 +29,7 @@ interface Props {
theme?: Theme;
chartRealtimeSource?: ChartRealtimeSource;
chartSeriesPriceLabels?: boolean;
chartPaneSeparator?: import('../../types/chartPaneSeparator').ChartPaneSeparatorOptions;
chartLiveReceiveHighlight?: boolean;
tickers?: Map<string, TickerData>;
viewMode: VirtualCardViewMode;
@@ -44,6 +46,7 @@ const VirtualTargetGrid: React.FC<Props> = ({
theme = 'dark',
chartRealtimeSource = 'BACKEND_STOMP',
chartSeriesPriceLabels = true,
chartPaneSeparator,
chartLiveReceiveHighlight = true,
tickers,
viewMode,
@@ -111,7 +114,7 @@ const VirtualTargetGrid: React.FC<Props> = ({
{focusMarket && focusTarget ? (
<VirtualTargetFocusView
market={focusTarget.market}
strategy={strategies.find(s => s.id === (focusTarget.strategyId ?? session.globalStrategyId))}
strategy={strategies.find(s => s.id === resolveVirtualTargetStrategyId(focusTarget, session.globalStrategyId))}
strategies={strategies}
strategyId={focusTarget.strategyId}
globalStrategyId={session.globalStrategyId}
@@ -127,13 +130,14 @@ const VirtualTargetGrid: React.FC<Props> = ({
theme={theme}
chartRealtimeSource={chartRealtimeSource}
chartSeriesPriceLabels={chartSeriesPriceLabels}
chartPaneSeparator={chartPaneSeparator}
chartLiveReceiveHighlight={chartLiveReceiveHighlight}
ticker={tickers?.get(focusTarget.market)}
/>
) : (
<div className={`vtd-grid vtd-grid--${viewMode}`}>
{targets.map(t => {
const strat = strategies.find(s => s.id === (t.strategyId ?? session.globalStrategyId));
const strat = strategies.find(s => s.id === resolveVirtualTargetStrategyId(t, session.globalStrategyId));
return (
<VirtualTargetCard
key={t.market}
@@ -158,6 +162,7 @@ const VirtualTargetGrid: React.FC<Props> = ({
theme={theme}
chartRealtimeSource={chartRealtimeSource}
chartSeriesPriceLabels={chartSeriesPriceLabels}
chartPaneSeparator={chartPaneSeparator}
chartLiveReceiveHighlight={chartLiveReceiveHighlight}
ticker={tickers?.get(t.market)}
/>