매매 시그널 디테일 팝업 기능 적용

This commit is contained in:
Macbook
2026-06-10 21:13:53 +09:00
parent bf5554d375
commit 0ff1992b64
19 changed files with 1507 additions and 58 deletions
+54
View File
@@ -51,3 +51,57 @@ export async function loadAnalysisCandles(
return data.sort((a, b) => a.time - b.time);
}
/** 시그널 발생 봉 기준 좌우 N개 캔들 (기본 ±5) */
export const SIGNAL_SNAPSHOT_CONTEXT_BARS = 5;
/** 화면에 표시할 봉 수 (±context) */
export const SIGNAL_SNAPSHOT_VISIBLE_BARS = SIGNAL_SNAPSHOT_CONTEXT_BARS * 2 + 1;
/** CCI·RSI 등 보조지표 계산용 선행 워밍업 봉 (표시 범위와 별도) */
const SIGNAL_SNAPSHOT_WARMUP_BARS = 50;
function findNearestBarIndex(bars: OHLCVBar[], candleTimeSec: number): number {
if (bars.length === 0) return -1;
let bestIdx = 0;
let bestDist = Math.abs(bars[0].time - candleTimeSec);
for (let i = 1; i < bars.length; i++) {
const dist = Math.abs(bars[i].time - candleTimeSec);
if (dist < bestDist) {
bestDist = dist;
bestIdx = i;
}
}
return bestIdx;
}
export async function loadSignalSnapshotCandles(
market: string,
timeframe: Timeframe,
candleTimeSec: number,
contextBars = SIGNAL_SNAPSHOT_CONTEXT_BARS,
): Promise<OHLCVBar[]> {
const barSec = timeframeToBarSeconds(timeframe);
const normalizedCandle = normalizeEpochSec(candleTimeSec);
const wantVisible = contextBars * 2 + 1;
const toTimeSec = normalizedCandle + barSec * (contextBars + 2);
const fetchCount = Math.max(wantVisible + SIGNAL_SNAPSHOT_WARMUP_BARS + 10, 60);
const raw = await loadAnalysisCandles(market, timeframe, toTimeSec, fetchCount);
if (raw.length === 0) return raw;
let idx = raw.findIndex(b => b.time === normalizedCandle);
if (idx < 0) idx = findNearestBarIndex(raw, normalizedCandle);
if (idx < 0) return raw.slice(-wantVisible);
const start = Math.max(0, idx - contextBars - SIGNAL_SNAPSHOT_WARMUP_BARS);
const end = Math.min(raw.length, idx + contextBars + 1);
return raw.slice(start, end);
}
function timeframeToBarSeconds(timeframe: string): number {
const map: Record<string, number> = {
'1m': 60, '3m': 180, '5m': 300, '10m': 600, '15m': 900, '30m': 1800,
'1h': 3600, '4h': 14400, '1D': 86400, '1W': 604800, '1M': 2592000,
};
return map[timeframe] ?? 180;
}