매매실행 방식 설정 추가

This commit is contained in:
Macbook
2026-06-20 09:59:18 +09:00
parent fd63c101e5
commit 8bf157137a
12 changed files with 195 additions and 21 deletions
@@ -15,6 +15,11 @@ interface FieldMeta {
}
const FIELD_META: Partial<Record<keyof BacktestSettingsDto, FieldMeta>> = {
tradeExecutionMode: {
label: '매매 체결 방식',
description:
'시그널·체결가 산출 방식입니다.\n• 백테스트 엔진: 슬리피지, 손절/익절, 진입/청산가 반영. 실제 수익률 분석에 가깝습니다.\n• 조건 스캔: 봉 종가·DSL 충족 기준. 차트 마커·조건 패널과 동일합니다.',
},
positionMode: {
label: '시그널 생성 방식',
description:
@@ -139,6 +144,18 @@ interface SettingSection {
}
const SECTIONS: SettingSection[] = [
{
title: '⚡ 매매 체결 방식',
fields: [
{
key: 'tradeExecutionMode', type: 'select',
opts: [
{ value: 'BACKTEST_ENGINE', label: '백테스트 엔진 (슬리피지·리스크 반영)' },
{ value: 'SCAN_SIGNALS', label: '조건 스캔 (봉 종가·DSL 충족)' },
],
},
],
},
{
title: '🎯 시그널 생성 방식',
fields: [
@@ -9,6 +9,7 @@ import {
saveBacktestSettings,
} from '../utils/backendApi';
import { ANALYSIS_METHOD_OPTIONS } from '../utils/analysisMethodLabels';
import { TRADE_EXECUTION_MODE_OPTIONS } from '../utils/tradeExecutionMode';
// ── 백테스팅 전용 UI 컴포넌트 ───────────────────────────────────────────────
@@ -107,6 +108,36 @@ export const BacktestSettingsPanel: React.FC<BacktestSettingsPanelProps> = ({
</BtGrid>
</BtSection>
<BtSection title="매매 체결 방식">
<BtGrid>
<BtField
label="시그널 · 체결가 산출"
desc="전략평가·백테스팅·분석 레포트에 공통 적용됩니다."
full
>
<select
className="stg-select stg-select--wide"
value={cfg.tradeExecutionMode ?? 'BACKTEST_ENGINE'}
onChange={e => field('tradeExecutionMode', e.target.value as 'SCAN_SIGNALS' | 'BACKTEST_ENGINE')}
>
{TRADE_EXECUTION_MODE_OPTIONS.map(o => (
<option key={o.value} value={o.value}>{o.label}</option>
))}
</select>
</BtField>
</BtGrid>
<p className="stg-bt-hint">
{(cfg.tradeExecutionMode ?? 'BACKTEST_ENGINE') === 'SCAN_SIGNALS'
? TRADE_EXECUTION_MODE_OPTIONS[1].desc
: TRADE_EXECUTION_MODE_OPTIONS[0].desc}
</p>
{(cfg.tradeExecutionMode ?? 'BACKTEST_ENGINE') === 'SCAN_SIGNALS' && (
<p className="stg-bt-hint stg-bt-hint--warn">
모드: 슬리피지·/··/(NEXT_OPEN) . .
</p>
)}
</BtSection>
<BtSection title="투자분석 방식">
<BtGrid>
<BtField
@@ -56,6 +56,7 @@ import {
padEvaluationSignalCount,
} from '../utils/strategyEvaluationReport';
import { resolveEvaluationCommissionRate } from '../utils/strategyEvaluationSignals';
import { normalizeTradeExecutionMode, tradeExecutionModeLabel } from '../utils/tradeExecutionMode';
import { BACKTEST_DISPLAY_BAR_COUNT, resolveEvaluationBarSlice } from '../utils/backtestWarmup';
import type { StrategyEvaluationWindowMeta } from './strategyEvaluation/StrategyEvaluationChart';
import StrategyEvaluationAiVerifyPanel from './strategyEvaluation/StrategyEvaluationAiVerifyPanel';
@@ -452,6 +453,11 @@ function StrategyEvaluationPageInner({ theme = 'dark' }: Props) {
[backtestSettings],
);
const tradeExecutionMode = useMemo(
() => normalizeTradeExecutionMode(backtestSettings?.tradeExecutionMode),
[backtestSettings],
);
const analysisSummary = useMemo(() => {
if (!selectedStrategy) return null;
return buildStrategyEvaluationToolbarSummary(backtestSignals, {
@@ -749,6 +755,7 @@ function StrategyEvaluationPageInner({ theme = 'dark' }: Props) {
firstBarClose: evalBars[0]?.close,
lastBarClose: evalBars[evalBars.length - 1]?.close,
commissionRate: evaluationCommissionRate,
tradeExecutionMode,
});
if (gen !== reportGenRef.current) return;
if (!model) {
@@ -779,6 +786,7 @@ function StrategyEvaluationPageInner({ theme = 'dark' }: Props) {
bars,
evalWindowMeta.evaluationBarCount,
evaluationCommissionRate,
tradeExecutionMode,
]);
return (
@@ -819,7 +827,7 @@ function StrategyEvaluationPageInner({ theme = 'dark' }: Props) {
{selectedStrategy && analysisSummary && !signalScanRunning && (
<span
className="seval-analysis-summary"
title="일괄매수(최초 전액) · 분할매수(40/30/잔여) · 레포트와 동일 필터 기준"
title={`${tradeExecutionModeLabel(tradeExecutionMode)} · 일괄매수(최초 전액) · 분할매수(40/30/잔여) · 레포트와 동일 필터 기준`}
>
<span className="seval-analysis-item">
:<strong>{padEvaluationSignalCount(analysisSummary.buyCount)}</strong>