fix: 매수 차단·백테스트 왜곡 유발한 버그 5종 수정
수개월간 매수 0건 + 백테스트가 손실로 보이던 근본 원인들을 수정. - ADX 발산(mean_reversion_strategy, run_backtest): Wilder 평활에 /period 누락으로 ADX가 100 초과 발산 → 실서비스 SIDEWAYS 게이트(ADX<20) 영구 무력화. 공식 복원(표준 Wilder와 대수적으로 동일 검증). - 백테스트 워밍업(run_backtest): 국면판정 220봉을 start_date부터 세서 14개월 미만 백테스트의 ~90%가 강제 BEAR → 가짜 손실. start_date 340일 전부터 프리로드하고 성과는 sim_start_date부터만 집계. CAGR 분모도 워밍업 제외한 실제 거래일로 수정. → 최근1년 -0.33%→+6.95%, 가산성 회복. - ML HOLD 게이트(trade_executor): 신뢰도 무관 매수 차단 → 데이터 부족으로 ML이 실패(conf=0)한 HOLD까지 모든 매수를 막던 것을 conf>=0.6 조건부로. - 빈 Redis 추천 캐시(swing/scheduler): 빈 캐시를 '히트'로 처리해 DB 폴백을 건너뛰던 것을 recommendations_by_rule 비면 DB 폴백하도록. - alembic 로깅(env.py, main.py): lifespan의 alembic upgrade가 fileConfig로 앱 로거를 꺼 startup 이후 로그 전멸 → 스킵(스키마는 create_all 담당). 검증: code-verifier 통과(실전 경로 CONFIRMED 버그 없음), walk-forward 6/9구간 양(+)·과적합 아님(조건부 견고). 서바이버십 편향은 별도 이슈로 검증 진행 중. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HBmzf1HDnvFHLraJ8eaaKJ
This commit is contained in:
@@ -147,19 +147,17 @@ async def lifespan(app: FastAPI):
|
||||
logger.error(traceback.format_exc())
|
||||
raise
|
||||
|
||||
# ── Alembic 자동 마이그레이션 (서버 이전 시 DB 스키마 자동 동기화) ──────
|
||||
try:
|
||||
from alembic.config import Config as AlembicConfig
|
||||
from alembic import command as alembic_command
|
||||
import os
|
||||
alembic_ini = os.path.join(os.path.dirname(os.path.dirname(__file__)), "alembic.ini")
|
||||
if os.path.exists(alembic_ini):
|
||||
alembic_cfg = AlembicConfig(alembic_ini)
|
||||
alembic_cfg.set_main_option("script_location", os.path.join(os.path.dirname(os.path.dirname(__file__)), "alembic"))
|
||||
alembic_command.upgrade(alembic_cfg, "head")
|
||||
logger.info("✅ Alembic migration completed (upgrade head)")
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ Alembic migration 실패 (non-critical): {e}")
|
||||
# ── Alembic 자동 마이그레이션: 의도적으로 비활성화 ────────────────────────
|
||||
# [FIX] alembic_command.upgrade()를 lifespan에서 호출하면 두 가지 문제가 있었다:
|
||||
# (1) env.py가 이벤트 루프 내부에서 asyncio.run()을 호출 → 항상 실패
|
||||
# ("asyncio.run() cannot be called from a running event loop"). 즉 수개월간
|
||||
# 실제 마이그레이션이 한 번도 동작하지 않았다.
|
||||
# (2) 그 실패 이전에 env.py 모듈 로딩 시 fileConfig()가 alembic.ini의 root 로거
|
||||
# 설정(level=WARN)으로 앱 로깅을 덮어써, startup 이후 모든 INFO 로그(스케줄러
|
||||
# 사이클/진입 로그 등)가 침묵 → 매매 관측 불가의 원인.
|
||||
# 스키마는 위의 create_all()로 생성되며, 컬럼 변경 등 실제 마이그레이션은 배포 시
|
||||
# CLI(`alembic upgrade head`)로 수행한다. 따라서 여기서는 호출하지 않는다.
|
||||
logger.info("ℹ️ Alembic auto-migration skipped (schema via create_all; migrations run via CLI)")
|
||||
|
||||
# ── KRX 일봉 데이터 초기 수집 (DB 비어있을 때만 백그라운드 실행) ──────
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user