Phase C dry-run·문서화·DB 증분 저장 및 운영 env 동기화

- 1분봉 다운로드 제외, MONITOR_PERSIST로 05/06 수집 시 coins.db INSERT
- Phase C paper_fires 로그·07 모의 리포트, hybrid 시뮬 산출물·reference 문서 갱신
- .env Phase C(LIVE=0), bootstrap dotenv override=True

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
dsyoon
2026-06-01 23:32:47 +09:00
parent 3cbfa40aab
commit b9ee241d14
19 changed files with 877 additions and 333 deletions

View File

@@ -37,7 +37,7 @@ from deepcoin.matching.position_sizing import (
from deepcoin.paths import resolve_ground_truth_file
from deepcoin.ops.alert_message import build_rule_alert_message
from deepcoin.ops.monitor import Monitor
from deepcoin.paths import LIVE_TRADES_LOG
from deepcoin.paths import LIVE_TRADES_LOG, PAPER_FIRES_LOG
class LiveTrader(Monitor):
@@ -87,6 +87,35 @@ class LiveTrader(Monitor):
with LIVE_TRADES_LOG.open("a", encoding="utf-8") as f:
f.write(json.dumps(record, ensure_ascii=False) + "\n")
def _append_paper_fire(
self,
hit: dict[str, Any],
planned_krw: float,
would_trade: bool,
skip_reason: str = "",
order_log: dict[str, Any] | None = None,
) -> None:
"""
Phase C dry-run: 모든 발화·스킵 사유·모의 금액을 paper_fires.jsonl에 기록.
금요일 `07_phase_c_paper_report.py`로 forward 수익률(참고) 집계.
"""
PAPER_FIRES_LOG.parent.mkdir(parents=True, exist_ok=True)
row = {
"ts": datetime.now().isoformat(timespec="seconds"),
"signal_dt": hit.get("dt"),
"rule_id": hit.get("rule_id"),
"side": hit.get("side"),
"close": float(hit.get("close") or 0),
"planned_krw": round(float(planned_krw), 0),
"would_trade": bool(would_trade),
"skip_reason": skip_reason or "",
"live_enabled": bool(LIVE_TRADING_ENABLED),
"order_message": (order_log or {}).get("message", ""),
}
with PAPER_FIRES_LOG.open("a", encoding="utf-8") as f:
f.write(json.dumps(row, ensure_ascii=False) + "\n")
def _can_trade(self, rule_id: str, planned_krw: float | None = None) -> tuple[bool, str]:
"""
일·쿨다운·손실 한도 검사.
@@ -283,6 +312,9 @@ class LiveTrader(Monitor):
if hit["side"] == "buy" and hit["rule_id"] not in self._approved_rules:
print(f" [{hit['side']}] {rid} @ {hit['dt']}")
print(" skip: EV/WF 미통과 규칙")
self._append_paper_fire(
hit, 0.0, False, "EV/WF 미통과 규칙"
)
continue
planned = (
self._resolve_buy_amount_krw(hit)
@@ -293,11 +325,14 @@ class LiveTrader(Monitor):
print(f" [{hit['side']}] {rid} @ {hit['dt']}")
if not ok:
print(f" skip: {reason}")
self._append_paper_fire(hit, planned, False, reason)
continue
if hit["side"] == "buy" and planned <= 0:
print(" skip: 매수금액 0")
self._append_paper_fire(hit, 0.0, False, "매수금액 0")
continue
log = self._execute_order(hit)
self._append_paper_fire(hit, planned, True, "", log)
self._append_log(log)
print(f" order: {log['message']} ok={log['ok']}")
msg = build_rule_alert_message(hit, balances)