FastAPI-based scraper for commodity ticker prices (HO, CL, RB futures) and competitor oil pricing from NewEnglandOil. Includes cron-driven scraping, PostgreSQL storage, and REST endpoints for price retrieval. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
73 lines
2.2 KiB
Python
73 lines
2.2 KiB
Python
from fastapi import APIRouter, Depends, HTTPException
|
|
from sqlalchemy.orm import Session
|
|
from typing import List
|
|
import logging
|
|
|
|
from app.database import get_db
|
|
from app.models import TickerPrice
|
|
from app.priceticker.scraper import fetch_ticker_data
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
router = APIRouter(
|
|
prefix="/scraper/priceticker",
|
|
tags=["Price Ticker"]
|
|
)
|
|
|
|
@router.post("/update")
|
|
async def update_prices(db: Session = Depends(get_db)):
|
|
"""
|
|
Trigger an immediate update of stock/commodity prices.
|
|
"""
|
|
logger.info("Triggering ticker update...")
|
|
data = fetch_ticker_data()
|
|
|
|
if not data:
|
|
raise HTTPException(status_code=500, detail="Failed to fetch ticker data")
|
|
|
|
try:
|
|
saved_records = []
|
|
for item in data:
|
|
record = TickerPrice(
|
|
symbol=item["symbol"],
|
|
price_decimal=item["price"],
|
|
currency=item["currency"],
|
|
change_decimal=item["change"],
|
|
percent_change_decimal=item["percent_change"],
|
|
timestamp=item["timestamp"]
|
|
)
|
|
db.add(record)
|
|
saved_records.append(record)
|
|
|
|
db.commit()
|
|
return {"status": "success", "updated": len(saved_records)}
|
|
|
|
except Exception as e:
|
|
db.rollback()
|
|
logger.error(f"Database error saving tickers: {e}")
|
|
raise HTTPException(status_code=500, detail=f"Database error: {str(e)}")
|
|
|
|
@router.get("/latest")
|
|
async def get_latest_prices(db: Session = Depends(get_db)):
|
|
"""
|
|
Get the most recent price for each ticker symbol.
|
|
"""
|
|
# Subquery to find the latest timestamp for each symbol
|
|
# This is a bit complex in pure ORM, so we might do it simply for now:
|
|
# 1. Get list of distinct symbols we care about
|
|
# 2. Query latest for each
|
|
|
|
results = []
|
|
# We know the symbols we care about: HO=F, CL=F, RB=F
|
|
TARGET_SYMBOLS = ["HO=F", "CL=F", "RB=F"]
|
|
|
|
for symbol in TARGET_SYMBOLS:
|
|
latest = db.query(TickerPrice).filter(
|
|
TickerPrice.symbol == symbol
|
|
).order_by(TickerPrice.timestamp.desc()).first()
|
|
|
|
if latest:
|
|
results.append(latest.to_dict())
|
|
|
|
return results
|