fix: 백테스트 시그널 타임스탬프를 봉 시작 시각으로 정렬

시그널 time을 ta4j Bar.endTime(봉 종료)으로 저장하면
차트 캔들 time(봉 시작)과 1봉 어긋나 마커가 다음 캔들에 표시됨.
IndicatorService·실시간 평가와 동일하게 barStartEpoch를 사용한다.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Macbook
2026-06-11 21:34:57 +09:00
parent b34bdda073
commit 280c187021
@@ -181,7 +181,7 @@ public class BacktestingService {
for (int i = 0; i < barCount; i++) { for (int i = 0; i < barCount; i++) {
double closePrice = getPrice(series, req.getBars(), i, cfg.getEntryPriceType()); double closePrice = getPrice(series, req.getBars(), i, cfg.getEntryPriceType());
double exitPrice = getPrice(series, req.getBars(), i, cfg.getExitPriceType()); double exitPrice = getPrice(series, req.getBars(), i, cfg.getExitPriceType());
long time = series.getBar(i).getEndTime().getEpochSecond(); long time = barStartEpoch(series, i);
// ── SIGNAL_ONLY 모드: 포지션·자금 상태 무관, 조건 충족 시마다 전체 시그널 생성 ── // ── SIGNAL_ONLY 모드: 포지션·자금 상태 무관, 조건 충족 시마다 전체 시그널 생성 ──
if (signalOnly) { if (signalOnly) {
@@ -458,6 +458,12 @@ public class BacktestingService {
.build(); .build();
} }
/** 차트·캔들 API 와 동일 — 봉 시작 시각(epoch sec). ta4j Bar.endTime 은 종료 시각. */
private static long barStartEpoch(BarSeries series, int index) {
var bar = series.getBar(index);
return bar.getEndTime().getEpochSecond() - bar.getTimePeriod().getSeconds();
}
// ── 개별 Criterion 계산 헬퍼 ───────────────────────────────────────────── // ── 개별 Criterion 계산 헬퍼 ─────────────────────────────────────────────
private double enterPosition(PortfolioLedger ledger, boolean useLedger, private double enterPosition(PortfolioLedger ledger, boolean useLedger,