from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from db import SessionLocal from models.bid import Bid as BidModel from models.auth import User from pydantic import BaseModel from datetime import datetime, timezone from zoneinfo import ZoneInfo from typing import List, Optional router = APIRouter() MARKET_TIMEZONES = { "ISONE": ZoneInfo("America/New_York"), "NYISO": ZoneInfo("America/New_York"), "MISO": ZoneInfo("America/Chicago"), } def get_db(): db = SessionLocal() try: yield db finally: db.close() class BidBase(BaseModel): timestamp: datetime quantity: float price: float user_id: ( int # In production the user_id should be obtained from the authenticated user ) market: str class BidCreate(BidBase): pass class BidResponse(BidBase): id: int status: str pnl: Optional[float] class Config: from_attributes = True @router.get("/", response_model=List[BidResponse]) def get_bids(db: Session = Depends(get_db)): return db.query(BidModel).all() @router.post("/", response_model=BidResponse) def submit_bid(bid: BidCreate, db: Session = Depends(get_db)): if bid.market not in MARKET_TIMEZONES: raise HTTPException( status_code=400, detail=f"Invalid market. Supported markets: {list(MARKET_TIMEZONES.keys())}", ) market_tz = MARKET_TIMEZONES[bid.market] now = datetime.now(market_tz) bid_timestamp_local = bid.timestamp.astimezone(market_tz) bid_day = bid_timestamp_local.date() today = now.date() print(f"Received bid for {bid_day} at {bid.timestamp} ({bid.market})") if bid.timestamp < now: raise HTTPException(status_code=400, detail="Cannot submit bids in the past.") cutoff_time = now.replace(hour=11, minute=0, second=0, microsecond=0) if bid_day == today: if now > cutoff_time: raise HTTPException( status_code=400, detail="Cannot submit bids for today after 11AM local time.", ) start_of_hour = bid.timestamp.replace(minute=0, second=0, microsecond=0) end_of_hour = start_of_hour.replace(minute=59, second=59, microsecond=999999) bid_count = ( db.query(BidModel) .filter( BidModel.timestamp >= start_of_hour, BidModel.timestamp <= end_of_hour, BidModel.market == bid.market, ) .count() ) if bid_count >= 10: raise HTTPException( status_code=400, detail="Cannot submit more than 10 bids for this hour in this market.", ) db_bid = BidModel( timestamp=bid.timestamp, quantity=bid.quantity, price=bid.price, user_id=bid.user_id, market=bid.market, status="Submitted", pnl=None, ) db.add(db_bid) db.commit() db.refresh(db_bid) return db_bid