hybrid DD tier와 Option C 2차(+1000%) 검증을 추가하고 실거래 사이징을 정합한다.

인과 GT leg 엔진·drawdown tier·train 캘리브레이션, Phase 2 Go/No-Go 및 시뮬 리포트를 반영한다.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
xavis
2026-06-01 16:09:18 +09:00
parent 9b00ef34c6
commit d385456867
21 changed files with 3315 additions and 1178 deletions

View File

@@ -11,6 +11,7 @@ from pathlib import Path
from typing import Any
from config import (
CHART_LOOKBACK_DAYS,
COIN_NAME,
LIVE_COOLDOWN_MIN,
LIVE_DAILY_KRW_MAX,
@@ -18,11 +19,14 @@ from config import (
LIVE_MAX_TRADES_PER_DAY,
LIVE_ORDER_KRW,
LIVE_TRADING_ENABLED,
MATCH_PRIMARY_INTERVAL,
SYMBOL,
TRADING_FEE_RATE,
)
from deepcoin.data.mtf_bb import load_frames_from_db
from deepcoin.ground_truth.ground_truth import load_ground_truth
from deepcoin.matching.live_eval import evaluate_live_rules
from deepcoin.matching.live_sizing import LivePositionState, live_sizing_enabled
from deepcoin.matching.load_rules import load_monitor_rules
from deepcoin.matching.position_sizing import (
compute_buy_amount_krw,
@@ -52,6 +56,8 @@ class LiveTrader(Monitor):
self._gt_trades: list[dict] = []
self._large_legs: set[int] = set()
self._approved_rules: set[str] = set()
self._position_state = LivePositionState.load()
self._ohlc_df = None
self._load_sizing_context()
def _load_sizing_context(self) -> None:
@@ -104,10 +110,20 @@ class LiveTrader(Monitor):
return False, f"규칙 쿨다운({LIVE_COOLDOWN_MIN}분)"
return True, ""
def _load_ohlc_df(self) -> None:
"""drawdown tier용 3m OHLC 캐시."""
try:
frames = load_frames_from_db(self, SYMBOL, lookback_days=CHART_LOOKBACK_DAYS)
self._ohlc_df = frames.get(MATCH_PRIMARY_INTERVAL)
except Exception:
self._ohlc_df = None
def _resolve_buy_amount_krw(self, hit: dict[str, Any]) -> float:
"""
총자산·현금·EV/WF·leg 티어로 매수 원화 산출.
GT_SIGNAL_CAUSAL=1 이면 시뮬 sim_tier_enhanced와 동일 인과 tier·weight.
Args:
hit: evaluate_live_rules 항목.
@@ -127,6 +143,18 @@ class LiveTrader(Monitor):
qty = float(sym.get("balance") or 0)
except Exception:
return 0.0
if live_sizing_enabled():
if self._ohlc_df is None:
self._load_ohlc_df()
return self._position_state.plan_buy_amount_krw(
hit["dt"],
price,
cash,
qty,
self._ohlc_df,
enhanced=False,
fee_rate=TRADING_FEE_RATE,
)
scale = live_buy_asset_pct_scale(
rid,
hit["dt"],
@@ -200,18 +228,31 @@ class LiveTrader(Monitor):
if qty <= 0:
record["message"] = "보유 없음"
else:
gross = qty * price
record["amount_krw"] = round(gross, 0)
ok = self.sellCoinMarket(SYMBOL, int(price), qty)
record["ok"] = bool(ok)
record["message"] = f"sell qty={qty}" if ok else "sell failed"
if record["ok"] and live_sizing_enabled():
fee = gross * TRADING_FEE_RATE
self._position_state.record_sell(
gross, fee, full_close=True
)
self._position_state.save()
else:
record["message"] = f"unknown side {side}"
except Exception as exc:
record["message"] = str(exc)
if record["ok"]:
self._day_spent_krw += amount_krw
spent = float(record.get("amount_krw") or amount_krw)
self._day_spent_krw += spent
self._day_trades += 1
self._rule_last_unix[hit["rule_id"]] = time.time()
if live_sizing_enabled() and side == "buy":
fee = spent * TRADING_FEE_RATE
self._position_state.record_buy(hit["dt"], price, spent, fee)
self._position_state.save()
return record
def run_once(self) -> None: