from fastapi import APIRouter, Depends, HTTPException, Query from pathlib import Path import pandas as pd import logging from typing import List, Dict, Any import json from quote_db import QuoteDatabase from quote_service import QuoteService from quote_contracts import ( FetchQuoteRequest, FetchQuoteResponse, ListSymbolsRequest, ListSymbolsResponse, ListDatesRequest, ListDatesResponse, ListSessionRequest, ListSessionResponse, IngestRequest, IngestResponse, FetchBrokersResponse, FetchDataResponse, BrokersSymbolsResponse, IngestAllRequest, IngestAllResponse, # QuoteDataRecord ) router = APIRouter() def get_db(): db = QuoteDatabase("quotes.db") try: yield db finally: db.conn.close() def get_service(db: QuoteDatabase = Depends(get_db)): return QuoteService(db=db) @router.post("/ingestall", response_model = IngestAllResponse) def ingest_archives(request: IngestAllRequest, service: QuoteService = Depends(get_service)): return service.ingest_archives_from_folder(request) @router.post("/ingest", response_model=IngestResponse) def ingest_quotes(request: IngestRequest, service: QuoteService = Depends(get_service)): return service.ingest_archive(request) @router.get("/data") async def get_data( broker_a: str = Query(...), symbol_a: str = Query(...), broker_b: str = Query(...), symbol_b: str = Query(...), service: QuoteService = Depends(get_service) ): df_a, df_b, last_data_points, markable_records = service.get_data(broker_a, symbol_a, broker_b, symbol_b) combined_data = pd.concat([df_a, df_b], ignore_index=True) if not df_a.empty or not df_b.empty else pd.DataFrame() dataset_source = combined_data.to_dict(orient='records') if not combined_data.empty else [] records: List[Dict[str, Any]] = [] timestamps = set() for record in dataset_source: timestamp = record["timestamp"] if timestamp not in timestamps: records.append({ "askA": record["ask"] if record["broker"] == broker_a else None, "bidA": record["bid"] if record["broker"] == broker_a else None, "midlineA": record["midline"] if record["broker"] == broker_a else None, "spreadA": record["spread"] if record["broker"] == broker_a else None, "directionA": record["direction"] if record["broker"] == broker_a else None, "askB": record["ask"] if record["broker"] == broker_b else None, "bidB": record["bid"] if record["broker"] == broker_b else None, "midlineB": record["midline"] if record["broker"] == broker_b else None, "spreadB": record["spread"] if record["broker"] == broker_b else None, "directionB": record["direction"] if record["broker"] == broker_b else None, "timestamp": timestamp }) timestamps.add(timestamp) response_data = { "records": records, "brokerA": broker_a, "symbolA": symbol_a, "brokerB": broker_b, "symbolB": symbol_b, "lastDataPoints": last_data_points, "markableRecords": markable_records } print(f"Response data size: {len(response_data['records'])} records, lastDataPoints: {len(last_data_points)}, markableRecords: {len(markable_records)}") print(f"Response data sample: {json.dumps(response_data, default=str)[:500]}...") return response_data @router.get("/brokers", response_model=FetchBrokersResponse) def get_all_brokers(service: QuoteService = Depends(get_service)): return service.get_all_brokers() @router.post("/symbols", response_model=ListSymbolsResponse) def get_symbols(request: ListSymbolsRequest, service: QuoteService = Depends(get_service)): return service.get_symbols(request) @router.post("/dates", response_model=ListDatesResponse) def get_dates(request: ListDatesRequest, service: QuoteService = Depends(get_service)): return service.get_dates(request) @router.post("/sessions", response_model=ListSessionResponse) def get_sessions(request: ListSessionRequest, service: QuoteService = Depends(get_service)): return service.get_sessions(request) @router.post("/quotes", response_model=FetchQuoteResponse) def get_quotes(request: FetchQuoteRequest, service: QuoteService = Depends(get_service)): return service.get_quotes(request) @router.get("/brokers&symbols", response_model=BrokersSymbolsResponse) def get_brokers_and_symbols(service: QuoteService = Depends(get_service)): return service.get_brokers_and_symbols()