Phase C/dry-run·미사용 모듈·재생성 HTML을 제거하고, 운영 체결을 sim_causal_hybrid와 동일한 hybrid 로직으로 통합한다. Co-authored-by: Cursor <cursoragent@cursor.com>
94 lines
2.7 KiB
Python
94 lines
2.7 KiB
Python
"""
|
|
봉 간격 상수·빗썸(Upbit 호환) 캔들 API 경로.
|
|
|
|
분봉·일봉 외 주봉(10080)·월봉(43200)은 DB 테이블명 `{symbol}_{interval}` 에 그대로 사용합니다.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from dateutil.relativedelta import relativedelta
|
|
|
|
from config import DAILY_INTERVAL_MIN, MONTH_INTERVAL_MIN, WEEK_INTERVAL_MIN
|
|
|
|
WM_INTERVALS: frozenset[int] = frozenset({WEEK_INTERVAL_MIN, MONTH_INTERVAL_MIN})
|
|
|
|
# 01_download·ops_sync 대상에서 제외 (DB 적재 안 함)
|
|
DOWNLOAD_EXCLUDED_INTERVALS: frozenset[int] = frozenset({1})
|
|
|
|
|
|
def is_excluded_from_download(interval: int) -> bool:
|
|
"""01_download·ops_sync에서 건너뛸 간격(1분봉 등)."""
|
|
return interval in DOWNLOAD_EXCLUDED_INTERVALS
|
|
|
|
|
|
def is_week_or_month(interval: int) -> bool:
|
|
"""주봉·월봉 여부."""
|
|
return interval in WM_INTERVALS
|
|
|
|
|
|
def candle_api_segment(interval: int) -> str:
|
|
"""
|
|
REST 경로 세그먼트 (minutes/{n} 제외).
|
|
|
|
Returns:
|
|
'weeks' | 'months' | 'days' | minutes/{interval}
|
|
"""
|
|
if interval == WEEK_INTERVAL_MIN:
|
|
return "weeks"
|
|
if interval == MONTH_INTERVAL_MIN:
|
|
return "months"
|
|
if interval >= DAILY_INTERVAL_MIN:
|
|
return "days"
|
|
return f"minutes/{interval}"
|
|
|
|
|
|
def interval_display_label(interval: int) -> str:
|
|
"""로그·UI용 라벨."""
|
|
if interval == WEEK_INTERVAL_MIN:
|
|
return "주봉"
|
|
if interval == MONTH_INTERVAL_MIN:
|
|
return "월봉"
|
|
if interval >= DAILY_INTERVAL_MIN:
|
|
return "일봉(1440)"
|
|
return f"{interval}분봉"
|
|
|
|
|
|
def pagination_step(interval: int, chunk_bars: int) -> relativedelta:
|
|
"""
|
|
get_coin_more_data 역순 수집 시 `to` 감소 단위.
|
|
|
|
Args:
|
|
interval: 봉 간격(분 표기).
|
|
chunk_bars: API 1회 최대 봉 수(겹침 청크).
|
|
|
|
Returns:
|
|
relativedelta.
|
|
"""
|
|
if interval == WEEK_INTERVAL_MIN:
|
|
return relativedelta(weeks=chunk_bars)
|
|
if interval == MONTH_INTERVAL_MIN:
|
|
return relativedelta(months=chunk_bars)
|
|
return relativedelta(minutes=interval * chunk_bars)
|
|
|
|
|
|
def bars_for_months(interval: int, months: int, *, extra_days: int = 0) -> int:
|
|
"""
|
|
N개월치 예상 봉 수(여유 포함).
|
|
|
|
Args:
|
|
interval: 봉 간격.
|
|
months: 보관·적재 개월 수.
|
|
extra_days: 일봉 계열 여유 일수.
|
|
|
|
Returns:
|
|
API 요청 목표 봉 수.
|
|
"""
|
|
if interval == WEEK_INTERVAL_MIN:
|
|
return int(months * 30 / 7) + max(extra_days // 7, 5)
|
|
if interval == MONTH_INTERVAL_MIN:
|
|
return months + max(extra_days // 30, 2)
|
|
if interval >= DAILY_INTERVAL_MIN:
|
|
return months * 30 + extra_days
|
|
bars_per_day = (24 * 60) // interval
|
|
return months * 30 * bars_per_day + 200
|