Files
goldenChart/frontend/src/utils/strategyEvaluationBarSignals.ts
T
2026-06-12 15:22:48 +09:00

53 lines
1.7 KiB
TypeScript

import type { BacktestSignal } from './backendApi';
import { normalizeEpochSecOptional } from './backtestUiUtils';
export interface BarSignalHighlight {
buy: boolean;
sell: boolean;
}
const isBuySignalType = (type: BacktestSignal['type']): boolean =>
type === 'BUY' || type === 'SHORT_EXIT';
const isSellSignalType = (type: BacktestSignal['type']): boolean =>
type === 'SELL' || type === 'SHORT_ENTRY' || type === 'PARTIAL_SELL';
function signalMatchesBar(
signal: BacktestSignal,
barIndex: number,
barTimeSec: number,
): boolean {
if (signal.barIndex === barIndex) return true;
const signalTime = normalizeEpochSecOptional(signal.time);
const barTime = normalizeEpochSecOptional(barTimeSec);
if (signalTime > 0 && barTime > 0 && signalTime === barTime) return true;
return false;
}
/** 선택 봉에 백테스트 매매 시그널이 있는지 (차트 마커와 동일 기준) */
export function resolveBarSignalHighlight(
signals: BacktestSignal[],
barTimeSec: number | null | undefined,
barIndex?: number | null,
): BarSignalHighlight {
if (signals.length === 0) {
return { buy: false, sell: false };
}
if (barIndex == null || barIndex < 0) {
if (barTimeSec == null) return { buy: false, sell: false };
const t = normalizeEpochSecOptional(barTimeSec);
const atBar = signals.filter(s => normalizeEpochSecOptional(s.time) === t);
return {
buy: atBar.some(s => isBuySignalType(s.type)),
sell: atBar.some(s => isSellSignalType(s.type)),
};
}
const barTime = barTimeSec ?? 0;
const atBar = signals.filter(s => signalMatchesBar(s, barIndex, barTime));
return {
buy: atBar.some(s => isBuySignalType(s.type)),
sell: atBar.some(s => isSellSignalType(s.type)),
};
}