refactor: GT·시뮬·운영 3축 정리 및 hybrid 실거래 정합

Phase C/dry-run·미사용 모듈·재생성 HTML을 제거하고, 운영 체결을
sim_causal_hybrid와 동일한 hybrid 로직으로 통합한다.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
xavis
2026-06-03 23:50:28 +09:00
parent a16c942be4
commit d7848df6f7
85 changed files with 177180 additions and 196131 deletions

View File

@@ -17,6 +17,11 @@ import numpy as np
import os
from config import *
from deepcoin.data.candle_intervals import (
candle_api_segment,
interval_display_label,
pagination_step,
)
class Monitor(HTS):
"""WLD 코인 데이터·지표·시장 상태 출력."""
@@ -303,27 +308,14 @@ class Monitor(HTS):
) -> pd.DataFrame | None:
base = BITHUMB_API_URL.rstrip("/")
count = BITHUMB_API_CANDLE_COUNT
segment = candle_api_segment(interval)
for attempt in range(retries):
try:
path = f"/v1/candles/{segment}"
if to is None:
if interval >= DAILY_INTERVAL_MIN:
url = f"{base}/v1/candles/days?market=KRW-{symbol}&count={count}"
else:
url = (
f"{base}/v1/candles/minutes/{interval}"
f"?market=KRW-{symbol}&count={count}"
)
url = f"{base}{path}?market=KRW-{symbol}&count={count}"
else:
if interval >= DAILY_INTERVAL_MIN:
url = (
f"{base}/v1/candles/days?market=KRW-{symbol}"
f"&count={count}&to={to}"
)
else:
url = (
f"{base}/v1/candles/minutes/{interval}"
f"?market=KRW-{symbol}&count={count}&to={to}"
)
url = f"{base}{path}?market=KRW-{symbol}&count={count}&to={to}"
headers = {"accept": "application/json"}
response = requests.get(url, headers=headers)
json_data = json.loads(response.text)
@@ -383,10 +375,10 @@ class Monitor(HTS):
print(f" API 추가 데이터 없음 (수집 {len(data)}봉)")
break
if verbose and (step == 1 or step % 5 == 0 or len(data) >= bong_count):
label = "일봉" if interval >= 1440 else f"{interval}"
label = interval_display_label(interval)
print(f" [{label}] 요청 {step}회 — 누적 {len(data)}/{bong_count}")
time.sleep(MONITOR_SLEEP_BETWEEN_CHUNKS_SEC)
to = to - relativedelta(minutes=interval * MONITOR_API_CHUNK_BARS)
to = to - pagination_step(interval, MONITOR_API_CHUNK_BARS)
if data is None or data.empty:
return pd.DataFrame()
data = data.set_index("datetime")
@@ -407,6 +399,12 @@ class Monitor(HTS):
Returns:
LIMIT에 넣을 최대 행 수.
"""
from config import MONTH_INTERVAL_MIN, WEEK_INTERVAL_MIN
if interval == WEEK_INTERVAL_MIN:
return max(lookback_days // 7 + 10, DB_ROW_MIN_DAILY_BARS)
if interval == MONTH_INTERVAL_MIN:
return max(lookback_days // 30 + 6, DB_ROW_MIN_DAILY_BARS)
if interval >= DAILY_INTERVAL_MIN:
return max(
lookback_days + DB_ROW_DAILY_PADDING_DAYS,
@@ -425,7 +423,7 @@ class Monitor(HTS):
"""
API로 받은 봉을 coins.db에 증분 INSERT합니다 (01_download.append_data와 동일).
dry-run·05·06·live_eval이 load_frames_from_db 할 때마다 최신 봉이 쌓입니다.
05·06·live_eval이 load_frames_from_db 할 때마다 최신 봉이 쌓입니다.
Returns:
(추가 행 수, 스킵 행 수)
@@ -520,9 +518,10 @@ class Monitor(HTS):
self, symbol: str, interval: int, db_max_rows: int | None = None
) -> pd.DataFrame:
"""
WLD 시세: API 최신 봉 + coins.db 과거 봉 + 1분봉 최신 1개를 합칩니다.
WLD 시세: API 최신 봉 + coins.db 과거 봉 합칩니다.
MONITOR_PERSIST_CANDLES=1 이면 API 청크를 즉시 coins.db에 INSERT합니다.
1분봉은 다운로드·병합하지 않습니다.
"""
data = self.get_coin_data(symbol, interval)
if data is None or data.empty:
@@ -530,11 +529,6 @@ class Monitor(HTS):
self.persist_api_candles_to_db(symbol, interval, data)
data_1 = self.get_coin_data(symbol, interval=1)
if data_1 is not None and not data_1.empty:
data_1 = data_1.copy()
data_1.at[data_1.index[-1], "Volume"] = data_1["Volume"].iloc[-1] * 60
row_limit = DB_READ_LIMIT_DEFAULT if db_max_rows is None else int(db_max_rows)
saved_data = self.read_candles_from_db(
symbol, interval, max_rows=row_limit
@@ -542,8 +536,6 @@ class Monitor(HTS):
parts = [data]
if saved_data is not None and not saved_data.empty:
parts.append(saved_data)
if data_1 is not None and not data_1.empty:
parts.append(data_1.iloc[[-1]])
merged = pd.concat(parts, ignore_index=True)
merged["datetime"] = pd.to_datetime(merged["datetime"], format="%Y-%m-%d %H:%M:%S")