feat(vol_breakout): 15m 현물 롱 라이브·모니터·cron 운영 추가
vol_breakout 멀티종목 tick, vol_live HTML 모니터, 마감 봉만 저장하는 캔들 다운로드, 텔레그램 체결 알림, cron/watch 감시 스크립트 및 테스트를 포함한다. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
59
src/bithumb/data/candle_bars.py
Normal file
59
src/bithumb/data/candle_bars.py
Normal file
@@ -0,0 +1,59 @@
|
||||
"""캔들 봉 마감 판별."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
from bithumb.api.bithumb import parse_kst_datetime
|
||||
|
||||
|
||||
def bar_close_time(bar_open: datetime, interval_min: int) -> datetime:
|
||||
"""봉 시작 시각 기준 마감 시각(KST naive)을 반환한다."""
|
||||
return bar_open + timedelta(minutes=interval_min)
|
||||
|
||||
|
||||
def is_closed_candle(
|
||||
bar_open: datetime,
|
||||
interval_min: int,
|
||||
*,
|
||||
now: datetime | None = None,
|
||||
) -> bool:
|
||||
"""해당 봉이 마감되었는지 여부."""
|
||||
ref = now or datetime.now()
|
||||
return ref >= bar_close_time(bar_open, interval_min)
|
||||
|
||||
|
||||
def only_closed_candles(
|
||||
rows: list[tuple],
|
||||
interval_min: int,
|
||||
*,
|
||||
now: datetime | None = None,
|
||||
) -> list[tuple]:
|
||||
"""미마감 봉을 제외한 OHLCV 행만 반환한다.
|
||||
|
||||
Args:
|
||||
rows: ``(ymdhms, open, high, low, close, volume)`` 튜플 리스트.
|
||||
interval_min: 분 단위 인터벌.
|
||||
now: 기준 시각(KST). None이면 ``datetime.now()``.
|
||||
|
||||
Returns:
|
||||
마감된 봉만 포함한 리스트(입력 순서 유지).
|
||||
"""
|
||||
if not rows:
|
||||
return []
|
||||
ref = now or datetime.now()
|
||||
closed: list[tuple] = []
|
||||
for row in rows:
|
||||
bar_open = parse_kst_datetime(str(row[0]))
|
||||
if is_closed_candle(bar_open, interval_min, now=ref):
|
||||
closed.append(row)
|
||||
return closed
|
||||
|
||||
|
||||
def last_closed_bar_open(now: datetime, interval_min: int) -> datetime:
|
||||
"""기준 시각에서 가장 최근 마감된 봉의 시작 시각."""
|
||||
minute = (now.minute // interval_min) * interval_min
|
||||
current_start = now.replace(minute=minute, second=0, microsecond=0)
|
||||
if is_closed_candle(current_start, interval_min, now=now):
|
||||
return current_start
|
||||
return current_start - timedelta(minutes=interval_min)
|
||||
Reference in New Issue
Block a user