feat: Pattern Lab Discover + fix history run display

Fix: history runs now always show results — create synthetic selected preset
from run data when no matching preset found (was broken for custom events).
Also force mode='events' and reset matchResults on history load.

Discover tab: new "Discover" panel in left sidebar (AI knowledge search).
- GPT-4o generates 6 matching events from a free-text query (date, assets, hint)
- Confidence score + category badge per event
- Click → pre-fills experiment form exactly like a preset → ready to Run
- Backend: POST /api/pattern-lab/discover (DiscoverRequest, sorted by confidence)
- Frontend: useDiscoverEvents hook + DiscoveredEvent type + Discover UI with
  Enter-to-search, spinner, empty states

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OpenSquared
2026-06-22 21:36:00 +02:00
parent a2315c3b78
commit 78c60d5254
3 changed files with 238 additions and 52 deletions

View File

@@ -49,6 +49,11 @@ class FindMatchingRequest(BaseModel):
pattern_index: int
class DiscoverRequest(BaseModel):
query: str
n: int = 6
class InstrumentScanRequest(BaseModel):
ticker: str
instrument_name: str
@@ -270,6 +275,57 @@ def evaluate_instrument_run(run_id: str):
return {"run_id": run_id, "outcomes": outcomes}
@router.post("/discover")
async def discover_events(req: DiscoverRequest):
"""Use GPT-4o to generate historical/recent event suggestions matching the query."""
from openai import AsyncOpenAI
key = get_config("openai_api_key") or ""
if not key:
raise HTTPException(400, "OpenAI API key not configured")
client = AsyncOpenAI(api_key=key)
prompt = f"""You are a financial markets research expert specialized in geopolitical and macro events.
Query: "{req.query}"
Identify {req.n} specific real events (2000-2025) that match this query and are relevant for options/derivatives trading analysis.
Prioritize events with clear market impact and dateable start points.
Return ONLY valid JSON:
{{
"events": [
{{
"label": "Concise event name",
"date": "YYYY-MM-DD",
"category": "geopolitical|macro|volatility|commodities|fx_macro|credit",
"horizon_days": 60,
"assets": ["TICKER1", "TICKER2", "TICKER3"],
"hint": "2-3 sentence market context for a trader: what happened, why it matters, key dynamics.",
"confidence": 90
}}
]
}}
Rules:
- Use valid Yahoo Finance tickers (SPY, GLD, USO, EURUSD=X, BTC-USD, etc.)
- horizon_days: typical holding period to capture the event's full market impact
- confidence: 0-100, how well-documented and dateable this event is
- Diversify dates and instruments across the {req.n} results"""
resp = await client.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}],
response_format={"type": "json_object"},
temperature=0.3,
timeout=30,
)
result = json.loads(resp.choices[0].message.content)
events = result.get("events", [])
# Sort by confidence desc
events.sort(key=lambda e: e.get("confidence", 0), reverse=True)
return {"events": events, "source": "ai", "query": req.query}
@router.post("/find-matching")
async def find_matching_pattern(req: FindMatchingRequest):
"""Ask GPT-4o-mini if this lab pattern matches / counter-scenario an existing library pattern."""