매매시그널 실행조건 화면 공용 적용
This commit is contained in:
@@ -5,6 +5,7 @@
|
||||
import React, { useState, useEffect, useCallback } from 'react';
|
||||
import type { Theme } from '../types';
|
||||
import {
|
||||
loadBacktestSettings,
|
||||
saveLiveStrategySettings,
|
||||
type LiveStrategySettingsDto,
|
||||
} from '../utils/backendApi';
|
||||
@@ -1347,6 +1348,15 @@ const StrategyPanel: React.FC<StrategyPanelProps> = ({
|
||||
},
|
||||
);
|
||||
const [liveSaving, setLiveSaving] = useState(false);
|
||||
const [backtestPositionMode, setBacktestPositionMode] = useState<'LONG_ONLY' | 'SIGNAL_ONLY'>('LONG_ONLY');
|
||||
|
||||
useEffect(() => {
|
||||
void loadBacktestSettings().then(s => {
|
||||
if (s?.positionMode === 'SIGNAL_ONLY' || s?.positionMode === 'LONG_ONLY') {
|
||||
setBacktestPositionMode(s.positionMode);
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (liveSettingsProp) setLiveSettings(liveSettingsProp);
|
||||
@@ -1354,7 +1364,12 @@ const StrategyPanel: React.FC<StrategyPanelProps> = ({
|
||||
|
||||
const persistLive = useCallback(async (patch: Partial<LiveStrategySettingsDto>) => {
|
||||
if (virtualDriven) return;
|
||||
const next: LiveStrategySettingsDto = { ...liveSettings, ...patch, market: liveMarket };
|
||||
const next: LiveStrategySettingsDto = {
|
||||
...liveSettings,
|
||||
...patch,
|
||||
market: liveMarket,
|
||||
positionMode: backtestPositionMode,
|
||||
};
|
||||
if (next.isLiveCheck && next.strategyId != null) {
|
||||
const synced = await syncStrategyTimeframesFromLayoutIfNeeded(next.strategyId);
|
||||
if (!synced) return;
|
||||
@@ -1370,7 +1385,7 @@ const StrategyPanel: React.FC<StrategyPanelProps> = ({
|
||||
} finally {
|
||||
setLiveSaving(false);
|
||||
}
|
||||
}, [liveSettings, liveMarket, onClearLiveMarkers, onLiveSettingsChange, virtualDriven]);
|
||||
}, [liveSettings, liveMarket, onClearLiveMarkers, onLiveSettingsChange, virtualDriven, backtestPositionMode]);
|
||||
|
||||
const isOn = liveSettings.isLiveCheck;
|
||||
const execType = liveSettings.executionType;
|
||||
@@ -1502,38 +1517,18 @@ const StrategyPanel: React.FC<StrategyPanelProps> = ({
|
||||
|
||||
<SettingRow
|
||||
className="stg-row--block"
|
||||
label="포지션 종속성 모드"
|
||||
desc="매도 시그널 발생 조건을 선택합니다. LONG_ONLY: 매수 이력이 있을 때만 매도 허용. SIGNAL_ONLY: 포지션 없이도 지표 규칙 충족 시 즉시 매도 시그널."
|
||||
label="시그널 모드"
|
||||
desc="백테스트 설정의 포지션 종속성 모드와 동일하게 적용됩니다. 변경은 설정 → 백테스트 설정에서 하세요."
|
||||
>
|
||||
<div className={`stg-radio-row${!isOn ? ' stg-radio-row--disabled' : ''}`}>
|
||||
<label className="stg-radio-option stg-radio-option--blue">
|
||||
<input
|
||||
type="radio"
|
||||
name="stg-pos-mode"
|
||||
value="LONG_ONLY"
|
||||
checked={(liveSettings.positionMode ?? 'LONG_ONLY') === 'LONG_ONLY'}
|
||||
disabled={!isOn}
|
||||
onChange={() => persistLive({ positionMode: 'LONG_ONLY' })}
|
||||
/>
|
||||
<span className="stg-radio-option-text">
|
||||
<strong>보유 자산 기준 (Long-Only)</strong>
|
||||
<span>매수 이력 있을 때만 매도 허용</span>
|
||||
</span>
|
||||
</label>
|
||||
<label className="stg-radio-option stg-radio-option--orange">
|
||||
<input
|
||||
type="radio"
|
||||
name="stg-pos-mode"
|
||||
value="SIGNAL_ONLY"
|
||||
checked={liveSettings.positionMode === 'SIGNAL_ONLY'}
|
||||
disabled={!isOn}
|
||||
onChange={() => persistLive({ positionMode: 'SIGNAL_ONLY' })}
|
||||
/>
|
||||
<span className="stg-radio-option-text">
|
||||
<strong>순수 지표 기준 (Signal-Only)</strong>
|
||||
<span>포지션 무관, 지표 충족 시 즉시 매도</span>
|
||||
</span>
|
||||
</label>
|
||||
<div style={{
|
||||
padding: '8px 10px', borderRadius: 6,
|
||||
background: 'rgba(63,126,245,0.08)', border: '1px solid rgba(63,126,245,0.2)',
|
||||
fontSize: 12, color: 'var(--text2)',
|
||||
opacity: isOn ? 1 : 0.55,
|
||||
}}>
|
||||
{backtestPositionMode === 'LONG_ONLY'
|
||||
? '보유 자산 기준 (Long-Only) — 매수 이력 있을 때만 매도 허용'
|
||||
: '순수 지표 기준 (Signal-Only) — 포지션 무관, 지표 충족 시 즉시 매도'}
|
||||
</div>
|
||||
</SettingRow>
|
||||
</SettingSection>
|
||||
|
||||
Reference in New Issue
Block a user