debug: 백테스팅 실행 시 파라미터·시그널 생성 상세 로그 추가
인디케이터 파라미터 로드 현황, positionMode, 생성된 시그널 수를 INFO 레벨로 출력하여 서버에서 정확한 진단 가능하도록 한다. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -88,6 +88,14 @@ public class BacktestingService {
|
||||
}
|
||||
// 요청에 포함된 파라미터가 있으면 DB 값 위에 덮어씀 (요청값 우선)
|
||||
Map<String, Map<String, Object>> params = mergeIndicatorParams(dbParams, req.getIndicatorParams());
|
||||
log.info("[Backtest] 인디케이터 파라미터 로드 — deviceId={}, dbParams키={}, reqParams키={}, 최종키={}",
|
||||
req.getDeviceId(),
|
||||
dbParams.keySet(),
|
||||
req.getIndicatorParams() != null ? req.getIndicatorParams().keySet() : "null",
|
||||
params.keySet());
|
||||
if (params.containsKey("Stochastic")) {
|
||||
log.info("[Backtest] Stochastic 파라미터: {}", params.get("Stochastic"));
|
||||
}
|
||||
if (params.isEmpty()) {
|
||||
log.warn("[Backtest] 인디케이터 파라미터 없음 — deviceId={}, 지표 기본값 사용 가능성 있음", req.getDeviceId());
|
||||
}
|
||||
@@ -153,6 +161,8 @@ public class BacktestingService {
|
||||
// positionMode: LONG_ONLY(기본) | SIGNAL_ONLY(포지션 락 우회)
|
||||
String posMode = cfg.getPositionMode() != null ? cfg.getPositionMode() : "LONG_ONLY";
|
||||
boolean signalOnly = "SIGNAL_ONLY".equals(posMode);
|
||||
log.info("[Backtest] 실행 시작 — strategyId={}, bars={}, timeframe={}, positionMode={}, signalOnly={}",
|
||||
req.getStrategyId(), series.getBarCount(), req.getTimeframe(), posMode, signalOnly);
|
||||
|
||||
double initCap = cfg.getInitialCapital() != null ? cfg.getInitialCapital().doubleValue() : 10_000_000.0;
|
||||
double tradeSizePct = cfg.getTradeSizeValue() != null ? cfg.getTradeSizeValue().doubleValue() / 100.0 : 1.0;
|
||||
@@ -175,15 +185,19 @@ public class BacktestingService {
|
||||
|
||||
// ── SIGNAL_ONLY 모드: 포지션·자금 상태 무관, 조건 충족 시마다 전체 시그널 생성 ──
|
||||
if (signalOnly) {
|
||||
if (entryRule.isSatisfied(i)) {
|
||||
boolean entrySatisfied = entryRule.isSatisfied(i);
|
||||
boolean exitSatisfied = exitRule.isSatisfied(i);
|
||||
if (entrySatisfied) {
|
||||
double effEntry = applySlippage(closePrice, cfg, true);
|
||||
String buyType = "SHORT".equals(direction) ? "SHORT_ENTRY" : "BUY";
|
||||
signals.add(buildFillSignal(time, buyType, effEntry, i, 1.0));
|
||||
log.debug("[Backtest:SIGNAL_ONLY] BUY @ bar={} price={}", i, effEntry);
|
||||
}
|
||||
if (exitRule.isSatisfied(i)) {
|
||||
if (exitSatisfied) {
|
||||
double effExit = applySlippage(exitPrice, cfg, false);
|
||||
String sellType = "SHORT".equals(direction) ? "SHORT_EXIT" : "SELL";
|
||||
signals.add(buildFillSignal(time, sellType, effExit, i, 1.0));
|
||||
log.debug("[Backtest:SIGNAL_ONLY] SELL @ bar={} price={}", i, effExit);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -248,6 +262,11 @@ public class BacktestingService {
|
||||
if (useLedger) ledger.markToMarket(closePrice);
|
||||
}
|
||||
|
||||
long buyCnt = signals.stream().filter(s -> "BUY".equals(s.type()) || "SHORT_ENTRY".equals(s.type())).count();
|
||||
long sellCnt = signals.stream().filter(s -> "SELL".equals(s.type()) || "SHORT_EXIT".equals(s.type())).count();
|
||||
log.info("[Backtest] 완료 — strategyId={}, bars={}, 생성시그널={}개 (매수={}, 매도={}), positionMode={}",
|
||||
req.getStrategyId(), barCount, signals.size(), buyCnt, sellCnt, posMode);
|
||||
|
||||
double lastMarkPrice = barCount > 0
|
||||
? series.getBar(barCount - 1).getClosePrice().doubleValue() : 0.0;
|
||||
double finalEquity = resolveFinalEquity(ledger, useLedger, cfg, initCap, equity, inPosition,
|
||||
|
||||
Reference in New Issue
Block a user