diff --git a/lotto/app/main.py b/lotto/app/main.py index f6e9497..0e8c024 100644 --- a/lotto/app/main.py +++ b/lotto/app/main.py @@ -47,6 +47,7 @@ from .weight_evolver import ( from .routers import curator as curator_router from .routers import briefing as briefing_router from .routers import review as review_router +from .routers import backtest as backtest_router from .jobs.grade_weekly_review import run_for_latest as grade_run_for_latest app = FastAPI() @@ -54,6 +55,7 @@ install_access_log(app) app.include_router(curator_router.router) app.include_router(briefing_router.router) app.include_router(review_router.router) +app.include_router(backtest_router.router) scheduler = BackgroundScheduler(timezone=os.getenv("TZ", "Asia/Seoul")) ALL_URL = os.getenv("LOTTO_ALL_URL", "https://smok95.github.io/lotto/results/all.json") diff --git a/lotto/app/routers/backtest.py b/lotto/app/routers/backtest.py new file mode 100644 index 0000000..6206d2f --- /dev/null +++ b/lotto/app/routers/backtest.py @@ -0,0 +1,30 @@ +from fastapi import APIRouter, BackgroundTasks, Query +from .. import backtest, db + +router = APIRouter(prefix="/api/lotto/backtest", tags=["backtest"]) + + +@router.get("/track-record") +def track_record(): + return backtest.track_record() + + +@router.get("/calibration") +def calibration(weeks: int = Query(52, ge=1, le=520)): + return {"history": db.get_calibration_history(limit=weeks)} + + +@router.get("/review/{draw_no}") +def review(draw_no: int): + return backtest.build_review_payload(draw_no) + + +@router.post("/run-forward") +def run_forward(draw_no: int = Query(...), k: int = 5000, pool_n: int = 20000): + return backtest.run_forward_purchase(draw_no=draw_no, k=k, pool_n=pool_n) + + +@router.post("/backfill") +def backfill(background_tasks: BackgroundTasks, batch: int = 50, sample_m: int = 2000): + background_tasks.add_task(backtest.backfill_calibration, batch, sample_m) + return {"ok": True, "message": f"backfill 시작 (batch={batch})"} diff --git a/lotto/tests/test_backtest_api.py b/lotto/tests/test_backtest_api.py new file mode 100644 index 0000000..40daf6c --- /dev/null +++ b/lotto/tests/test_backtest_api.py @@ -0,0 +1,23 @@ +import os, sys, tempfile + +# _shared lives in web-backend/_shared; add the parent dir so it can be found +sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "..")) + +from fastapi.testclient import TestClient + +def _client(monkeypatch): + tmp = tempfile.mkdtemp() + from app import db + monkeypatch.setattr(db, "DB_PATH", os.path.join(tmp, "lotto.db")) + db.init_db() + from app.main import app + return TestClient(app), db + +def test_backtest_endpoints(monkeypatch): + client, db = _client(monkeypatch) + r = client.get("/api/lotto/backtest/track-record") + assert r.status_code == 200 + assert "by_strategy" in r.json() + r2 = client.get("/api/lotto/backtest/calibration?weeks=4") + assert r2.status_code == 200 + assert isinstance(r2.json().get("history"), list)