164 lines
5.4 KiB
TypeScript
164 lines
5.4 KiB
TypeScript
import React from 'react';
|
|
import type { StrategyDto } from '../../utils/backendApi';
|
|
import type { VirtualSessionConfig, VirtualCardViewMode } from '../../utils/virtualTradingStorage';
|
|
import type { VirtualCardDisplayMode } from './VirtualTargetCard';
|
|
import VirtualGridLayoutPicker from './VirtualGridLayoutPicker';
|
|
import type { TradeNotificationGridPresetId } from '../../utils/tradeNotificationGridPresets';
|
|
|
|
interface SessionProps {
|
|
session: Pick<VirtualSessionConfig, 'globalStrategyId' | 'executionType' | 'positionMode' | 'running'>;
|
|
strategies: StrategyDto[];
|
|
onStrategyChange: (strategyId: number | null) => void;
|
|
onExecutionTypeChange: (type: VirtualSessionConfig['executionType']) => void;
|
|
onPositionModeChange: (mode: VirtualSessionConfig['positionMode']) => void;
|
|
onStart: () => void;
|
|
onStop: () => void;
|
|
paperAutoTradeEnabled?: boolean;
|
|
onPaperAutoTradeEnabled?: (enabled: boolean) => void;
|
|
paperTradingEnabled?: boolean;
|
|
}
|
|
|
|
interface ViewProps {
|
|
session: Pick<VirtualSessionConfig, 'running'>;
|
|
viewMode: VirtualCardViewMode;
|
|
onViewModeChange: (mode: VirtualCardViewMode) => void;
|
|
globalDisplayMode?: VirtualCardDisplayMode;
|
|
onGlobalDisplayModeChange?: (mode: VirtualCardDisplayMode) => void;
|
|
showSignalChartToggle?: boolean;
|
|
gridPreset?: TradeNotificationGridPresetId;
|
|
onGridPresetChange?: (preset: TradeNotificationGridPresetId) => void;
|
|
showGridLayoutPicker?: boolean;
|
|
}
|
|
|
|
export const VirtualSessionHeaderControls: React.FC<SessionProps> = ({
|
|
session,
|
|
strategies,
|
|
onStrategyChange,
|
|
onExecutionTypeChange,
|
|
onPositionModeChange,
|
|
onStart,
|
|
onStop,
|
|
paperAutoTradeEnabled = false,
|
|
onPaperAutoTradeEnabled,
|
|
paperTradingEnabled = true,
|
|
}) => (
|
|
<div className="vtd-header-session vtd-header-session--compact">
|
|
<select
|
|
className="vtd-header-select vtd-header-select--strategy"
|
|
aria-label="투자전략"
|
|
value={session.globalStrategyId ?? ''}
|
|
onChange={e => {
|
|
const v = e.target.value;
|
|
onStrategyChange(v ? Number(v) : null);
|
|
}}
|
|
>
|
|
<option value="">전략 선택</option>
|
|
{strategies.map(s => (
|
|
<option key={s.id} value={s.id}>{s.name}</option>
|
|
))}
|
|
</select>
|
|
|
|
<select
|
|
className="vtd-header-select vtd-header-select--narrow"
|
|
aria-label="실행방식"
|
|
value={session.executionType}
|
|
onChange={e => onExecutionTypeChange(e.target.value as VirtualSessionConfig['executionType'])}
|
|
>
|
|
<option value="CANDLE_CLOSE">봉 마감 직후</option>
|
|
<option value="REALTIME_TICK">실시간 틱</option>
|
|
</select>
|
|
|
|
<select
|
|
className="vtd-header-select vtd-header-select--narrow"
|
|
aria-label="시그널 모드"
|
|
value={session.positionMode}
|
|
onChange={e => onPositionModeChange(e.target.value as VirtualSessionConfig['positionMode'])}
|
|
>
|
|
<option value="LONG_ONLY">보유 자산 기준</option>
|
|
<option value="SIGNAL_ONLY">순수 지표 기준</option>
|
|
</select>
|
|
|
|
<select
|
|
className="vtd-header-select vtd-header-select--narrow"
|
|
aria-label="자동매매"
|
|
title={
|
|
!paperTradingEnabled
|
|
? '설정 › 가상투자에서 가상매매를 활성화하세요'
|
|
: undefined
|
|
}
|
|
value={paperAutoTradeEnabled ? 'on' : 'off'}
|
|
disabled={!paperTradingEnabled || !onPaperAutoTradeEnabled}
|
|
onChange={e => onPaperAutoTradeEnabled?.(e.target.value === 'on')}
|
|
>
|
|
<option value="off">자동매매 OFF</option>
|
|
<option value="on">자동매매 ON</option>
|
|
</select>
|
|
|
|
<div className="vtd-session-actions vtd-session-actions--compact">
|
|
<button
|
|
type="button"
|
|
className="bps-btn vtd-session-btn vtd-session-btn--start"
|
|
disabled={session.running}
|
|
onClick={onStart}
|
|
title="가상투자 시작"
|
|
>
|
|
시작
|
|
</button>
|
|
<button
|
|
type="button"
|
|
className="bps-btn bps-btn--danger vtd-session-btn"
|
|
disabled={!session.running}
|
|
onClick={onStop}
|
|
title="가상투자 종료"
|
|
>
|
|
종료
|
|
</button>
|
|
</div>
|
|
</div>
|
|
);
|
|
|
|
export const VirtualViewHeaderControls: React.FC<ViewProps> = ({
|
|
session,
|
|
viewMode,
|
|
onViewModeChange,
|
|
globalDisplayMode = 'signal',
|
|
onGlobalDisplayModeChange,
|
|
showSignalChartToggle = true,
|
|
gridPreset = '2x2',
|
|
onGridPresetChange,
|
|
showGridLayoutPicker = true,
|
|
}) => (
|
|
<div className="vtd-header-view vtd-header-view--compact">
|
|
{showGridLayoutPicker && onGridPresetChange && (
|
|
<VirtualGridLayoutPicker
|
|
value={gridPreset}
|
|
onChange={onGridPresetChange}
|
|
disabled={!showSignalChartToggle}
|
|
/>
|
|
)}
|
|
{showSignalChartToggle && onGlobalDisplayModeChange && (
|
|
<select
|
|
className="vtd-header-select vtd-header-select--narrow"
|
|
aria-label="신호 또는 차트"
|
|
value={globalDisplayMode}
|
|
onChange={e => onGlobalDisplayModeChange(e.target.value as VirtualCardDisplayMode)}
|
|
>
|
|
<option value="signal">신호</option>
|
|
<option value="chart">차트</option>
|
|
</select>
|
|
)}
|
|
<select
|
|
className="vtd-header-select vtd-header-select--narrow"
|
|
aria-label="카드 표시 방식"
|
|
value={viewMode}
|
|
onChange={e => onViewModeChange(e.target.value as VirtualCardViewMode)}
|
|
>
|
|
<option value="summary">요약표시</option>
|
|
<option value="detail">상세표시</option>
|
|
</select>
|
|
{session.running && (
|
|
<span className="vtd-grid-live" title="3초마다 갱신">실시간</span>
|
|
)}
|
|
</div>
|
|
);
|