feat: instrument picker + Pattern Lab instrument scan mode

- instruments.ts: 90 IB-options-tradable instruments in 12 categories
  (US Indices, Europe, Asia, EM, Sectors, Forex, Bonds, Metals, Energy,
   Agriculture, Crypto, Volatility) — EUR/CHF, Cotton, etc. all included

- PatternExplorer: replace text input in Instrument Lens with categorised
  grid picker (category pill filters + search + custom ticker fallback)

- PatternLab: add Instrument Scan tab alongside Event Presets
  - Pick any instrument from the shared categorised picker
  - Set period (start/end date) + horizon per pattern
  - AI scans the full period: identifies 4-6 key pattern instances each with
    their own entry date, expected move, strategy
  - 'Evaluate outcomes' fetches actual price at T+horizon per pattern
  - 'Save pattern' promotes any instance to the Pattern Library

- backend/services/pattern_lab.py: run_instrument_scan() + evaluate_instrument_outcomes()
  (per-pattern analysis_date vs shared date in event mode)
- backend/routers/pattern_lab.py: POST /instrument-scan + POST /evaluate-instrument/{id}
- useApi.ts: useInstrumentScan + useEvaluateInstrumentScan hooks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
OpenSquared
2026-06-22 18:20:22 +02:00
parent cbf989502c
commit 303ecc2a3a
6 changed files with 850 additions and 80 deletions

View File

@@ -1007,3 +1007,22 @@ export const useDeleteLabRun = () => {
onSuccess: () => qc.invalidateQueries({ queryKey: ['pattern-lab-runs'] }),
})
}
export const useInstrumentScan = () => {
const qc = useQueryClient()
return useMutation({
mutationFn: (body: {
ticker: string; instrument_name: string;
start_date: string; end_date: string; horizon_days: number;
}) => api.post('/pattern-lab/instrument-scan', body).then(r => r.data),
onSuccess: () => qc.invalidateQueries({ queryKey: ['pattern-lab-runs'] }),
})
}
export const useEvaluateInstrumentScan = () => {
const qc = useQueryClient()
return useMutation({
mutationFn: (run_id: string) => api.post(`/pattern-lab/evaluate-instrument/${run_id}`, {}).then(r => r.data),
onSuccess: () => qc.invalidateQueries({ queryKey: ['pattern-lab-runs'] }),
})
}