feat: Pattern Lab — historical backtest engine for pattern discovery

- Remove all built-in patterns (no proof of legitimacy); seed_builtin_patterns is now a no-op
- DB: add backtest_lab_runs table + backtest_hits/runs_count columns on patterns
- services/pattern_lab.py: build_historical_context (yfinance + RSI/MA200),
  run_ai_backtest (GPT-4o as historical analyst), evaluate_outcomes (actual moves at T+horizon)
- routers/pattern_lab.py: POST /run, POST /evaluate/{id}, GET /runs, DELETE /runs/{id},
  POST /save-pattern (promotes hit pattern to library with reliability counters)
- PatternLab.tsx: 34 preset events 2015-2025 (macro/geo/credit/fx/commodities/volatility/tech),
  3-panel layout — preset selector + wizard + run history, market data table,
  AI pattern cards with hit/miss outcome display, Save to Library button
- useApi.ts: usePatternLabRuns, useRunPatternLab, useEvaluatePatternLab, useSaveLabPattern, useDeleteLabRun
- Sidebar + App.tsx: /pattern-lab route + FlaskConical nav link

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OpenSquared
2026-06-22 17:55:48 +02:00
parent a68a08d9af
commit cbf989502c
8 changed files with 1148 additions and 31 deletions

View File

@@ -1,6 +1,7 @@
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from routers import market_data, geopolitical, options, backtest, ai, portfolio, config, patterns, journal, cycle as cycle_router, profiles as profiles_router, reasoning as reasoning_router, knowledge as knowledge_router, options_vol as options_vol_router, analytics as analytics_router, risk as risk_router
from routers import pattern_lab as pattern_lab_router
from routers import logs as logs_router
from routers import var as var_router
from routers import reports as reports_router
@@ -117,6 +118,7 @@ app.include_router(logs_router.router)
app.include_router(var_router.router)
app.include_router(reports_router.router)
app.include_router(institutional_router.router)
app.include_router(pattern_lab_router.router)
@app.get("/")