매매시 현재가 적용

This commit is contained in:
Macbook
2026-06-23 00:12:23 +09:00
parent 351c5600b8
commit 6e86ec7ecb
16 changed files with 221 additions and 79 deletions
@@ -18,7 +18,7 @@ const FIELD_META: Partial<Record<keyof BacktestSettingsDto, FieldMeta>> = {
tradeExecutionMode: {
label: '매매 체결 방식',
description:
'시그널·체결가 산출 방식입니다.\n• 백테스트 엔진: 슬리피지, 손절/익절, 진입/청산가 반영. 실제 수익률 분석에 가깝습니다.\n• 조건 스캔: 봉 종가·DSL 충족 기준. 차트 마커·조건 패널과 동일합니다.',
'시그널·체결가 산출 방식입니다.\n• 백테스트 엔진: 슬리피지, 손절/익절, 진입/청산가 반영. 실제 수익률 분석에 가깝습니다.\n• 조건 스캔: 현재가·DSL 충족 기준. 차트 마커·조건 패널과 동일합니다.',
},
positionMode: {
label: '시그널 생성 방식',
@@ -53,12 +53,12 @@ const FIELD_META: Partial<Record<keyof BacktestSettingsDto, FieldMeta>> = {
entryPriceType: {
label: '진입 가격 기준',
description:
'매수 신호 발생 시 어느 가격에 진입하는지 결정합니다.\n• CLOSE(종가): 신호 발생 봉의 종가로 즉시 진입. 구현이 단순하지만 후행성(look-ahead bias) 우려가 있습니다.\n• NEXT_OPEN(다음봉 시가): 신호 다음 봉 시가에 진입. 실제 트레이딩과 가장 유사한 현실적 시뮬레이션입니다.',
'매수 신호 발생 시 어느 가격에 진입하는지 결정합니다.\n• CURRENT(현재가): 신호 발생 시점의 현재가로 즉시 진입.\n• NEXT_OPEN(다음봉 시가): 신호 다음 봉 시가에 진입. 실제 트레이딩과 가장 유사한 현실적 시뮬레이션입니다.',
},
exitPriceType: {
label: '청산 가격 기준',
description:
'매도 신호 발생 시 어느 가격에 청산하는지 결정합니다.\n• CLOSE(종가): 신호 발생 봉의 종가로 즉시 청산합니다.\n• NEXT_OPEN(다음봉 시가): 신호 다음 봉 시가에 청산. 야간 갭 하락 등 실제 리스크를 반영합니다.',
'매도 신호 발생 시 어느 가격에 청산하는지 결정합니다.\n• CURRENT(현재가): 신호 발생 시점의 현재가로 즉시 청산합니다.\n• NEXT_OPEN(다음봉 시가): 신호 다음 봉 시가에 청산. 야간 갭 하락 등 실제 리스크를 반영합니다.',
},
positionDirection: {
label: '포지션 방향',
@@ -151,7 +151,7 @@ const SECTIONS: SettingSection[] = [
key: 'tradeExecutionMode', type: 'select',
opts: [
{ value: 'BACKTEST_ENGINE', label: '백테스트 엔진 (슬리피지·리스크 반영)' },
{ value: 'SCAN_SIGNALS', label: '조건 스캔 (봉 종가·DSL 충족)' },
{ value: 'SCAN_SIGNALS', label: '조건 스캔 (현재가·DSL 충족)' },
],
},
],
@@ -203,11 +203,11 @@ const SECTIONS: SettingSection[] = [
fields: [
{
key: 'entryPriceType', type: 'select',
opts: [{ value:'CLOSE', label:'가 (Close)' }, { value:'NEXT_OPEN', label:'다음봉 시가 (Next Open)' }],
opts: [{ value:'CURRENT', label:'현재가 (Current)' }, { value:'NEXT_OPEN', label:'다음봉 시가 (Next Open)' }],
},
{
key: 'exitPriceType', type: 'select',
opts: [{ value:'CLOSE', label:'가 (Close)' }, { value:'NEXT_OPEN', label:'다음봉 시가 (Next Open)' }],
opts: [{ value:'CURRENT', label:'현재가 (Current)' }, { value:'NEXT_OPEN', label:'다음봉 시가 (Next Open)' }],
},
{
key: 'positionDirection', type: 'select',
@@ -233,19 +233,19 @@ export const BacktestSettingsPanel: React.FC<BacktestSettingsPanelProps> = ({
<BtSection title="거래 가격 기준">
<BtGrid>
<BtField label="진입 가격 기준" desc="매수 신호 시 진입 가격. 종가 즉시 진입 또는 다음 봉 시가 진입.">
<BtField label="진입 가격 기준" desc="매수 신호 시 진입 가격. 현재가(시그널 시점) 또는 다음 봉 시가.">
<select className="stg-select stg-select--wide"
value={cfg.entryPriceType}
onChange={e => field('entryPriceType', e.target.value as 'CLOSE' | 'NEXT_OPEN')}>
<option value="CLOSE"> (Close)</option>
value={cfg.entryPriceType === 'CLOSE' ? 'CURRENT' : cfg.entryPriceType}
onChange={e => field('entryPriceType', e.target.value as 'CURRENT' | 'NEXT_OPEN')}>
<option value="CURRENT"> (Current)</option>
<option value="NEXT_OPEN"> (Next Open)</option>
</select>
</BtField>
<BtField label="청산 가격 기준" desc="매도 신호 시 청산 가격. 종가 즉시 청산 또는 다음 봉 시가 청산.">
<BtField label="청산 가격 기준" desc="매도 신호 시 청산 가격. 현재가(시그널 시점) 또는 다음 봉 시가.">
<select className="stg-select stg-select--wide"
value={cfg.exitPriceType}
onChange={e => field('exitPriceType', e.target.value as 'CLOSE' | 'NEXT_OPEN')}>
<option value="CLOSE"> (Close)</option>
value={cfg.exitPriceType === 'CLOSE' ? 'CURRENT' : cfg.exitPriceType}
onChange={e => field('exitPriceType', e.target.value as 'CURRENT' | 'NEXT_OPEN')}>
<option value="CURRENT"> (Current)</option>
<option value="NEXT_OPEN"> (Next Open)</option>
</select>
</BtField>
+4 -4
View File
@@ -1419,8 +1419,8 @@ export interface BacktestSettingsDto {
commissionType: 'LINEAR' | 'ZERO';
commissionRate: number;
slippageRate: number;
entryPriceType: 'CLOSE' | 'NEXT_OPEN';
exitPriceType: 'CLOSE' | 'NEXT_OPEN';
entryPriceType: 'CURRENT' | 'CLOSE' | 'NEXT_OPEN';
exitPriceType: 'CURRENT' | 'CLOSE' | 'NEXT_OPEN';
positionDirection: 'LONG' | 'SHORT' | 'BOTH';
tradeSizeType: 'CAPITAL_PCT' | 'FIXED_AMOUNT';
tradeSizeValue: number;
@@ -1447,8 +1447,8 @@ export const DEFAULT_BACKTEST_SETTINGS: BacktestSettingsDto = {
commissionType: 'LINEAR',
commissionRate: 0.0015,
slippageRate: 0.0005,
entryPriceType: 'CLOSE',
exitPriceType: 'CLOSE',
entryPriceType: 'CURRENT',
exitPriceType: 'CURRENT',
positionDirection: 'LONG',
tradeSizeType: 'CAPITAL_PCT',
tradeSizeValue: 100,
@@ -432,7 +432,7 @@ export function buildStrategyEvaluationReportModel(opts: {
'분석 기간 전체 캔들 기준으로, 최초 매수 이전 매도·최종 매도 이후 매수 시그널은 제외했습니다. '
+ '매도는 보유 물량 전량 매도로 가정합니다. '
+ (opts.tradeExecutionMode === 'SCAN_SIGNALS'
? '체결가: 조건 스캔(봉 종가·DSL 충족).'
? '체결가: 조건 스캔(현재가·DSL 충족).'
: '체결가: 백테스트 설정(슬리피지·손절/익절·진입/청산가) 반영.'),
};
}
+2 -2
View File
@@ -14,8 +14,8 @@ export const TRADE_EXECUTION_MODE_OPTIONS: {
},
{
value: 'SCAN_SIGNALS',
label: '조건 스캔 (봉 종가·DSL 충족)',
desc: '차트 마커·조건 패널과 동일. 봉 종가 기준 이상적 체결.',
label: '조건 스캔 (현재가·DSL 충족)',
desc: '차트 마커·조건 패널과 동일. 시그널 시점 현재가 기준 체결.',
},
];