2025-08-19 17:04:19 +01:00
|
|
|
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
|
|
|
from pathlib import Path
|
2025-09-12 18:33:32 +01:00
|
|
|
import pandas as pd
|
2025-08-19 17:04:19 +01:00
|
|
|
import logging
|
2025-09-12 18:33:32 +01:00
|
|
|
from typing import List, Dict, Any
|
|
|
|
|
import json
|
2025-08-19 17:04:19 +01:00
|
|
|
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,
|
2025-09-12 18:33:32 +01:00
|
|
|
BrokersSymbolsResponse, IngestAllRequest, IngestAllResponse,
|
|
|
|
|
# QuoteDataRecord
|
2025-08-19 17:04:19 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
|
2025-09-12 18:33:32 +01:00
|
|
|
@router.get("/data")
|
2025-08-19 17:04:19 +01:00
|
|
|
async def get_data(
|
|
|
|
|
broker_a: str = Query(...),
|
|
|
|
|
symbol_a: str = Query(...),
|
|
|
|
|
broker_b: str = Query(...),
|
|
|
|
|
symbol_b: str = Query(...),
|
2025-09-12 18:33:32 +01:00
|
|
|
|
|
|
|
|
|
2025-08-19 17:04:19 +01:00
|
|
|
service: QuoteService = Depends(get_service)
|
|
|
|
|
):
|
2025-09-12 18:33:32 +01:00
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
2025-08-19 17:04:19 +01:00
|
|
|
|
|
|
|
|
@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()
|