first commit
Some checks failed
Deploy / lint (push) Failing after 7s
Deploy / test (push) Has been skipped
Deploy / deploy (push) Has been skipped

This commit is contained in:
Dennis Thiessen
2026-02-20 17:31:01 +01:00
commit 61ab24490d
160 changed files with 17034 additions and 0 deletions

63
app/providers/alpaca.py Normal file
View File

@@ -0,0 +1,63 @@
"""Alpaca Markets OHLCV provider using the alpaca-py SDK."""
from __future__ import annotations
import asyncio
import logging
from datetime import date
from alpaca.data.historical import StockHistoricalDataClient
from alpaca.data.requests import StockBarsRequest
from alpaca.data.timeframe import TimeFrame
from app.exceptions import ProviderError, RateLimitError
from app.providers.protocol import OHLCVData
logger = logging.getLogger(__name__)
class AlpacaOHLCVProvider:
"""Fetches daily OHLCV bars from Alpaca Markets Data API."""
def __init__(self, api_key: str, api_secret: str) -> None:
if not api_key or not api_secret:
raise ProviderError("Alpaca API key and secret are required")
self._client = StockHistoricalDataClient(api_key, api_secret)
async def fetch_ohlcv(
self, ticker: str, start_date: date, end_date: date
) -> list[OHLCVData]:
"""Fetch daily OHLCV bars for *ticker* between *start_date* and *end_date*."""
try:
request = StockBarsRequest(
symbol_or_symbols=ticker,
timeframe=TimeFrame.Day,
start=start_date,
end=end_date,
)
# alpaca-py's client is synchronous — run in a thread
bars = await asyncio.to_thread(self._client.get_stock_bars, request)
results: list[OHLCVData] = []
bar_set = bars.get(ticker, []) if hasattr(bars, "get") else getattr(bars, "data", {}).get(ticker, [])
for bar in bar_set:
results.append(
OHLCVData(
ticker=ticker,
date=bar.timestamp.date(),
open=float(bar.open),
high=float(bar.high),
low=float(bar.low),
close=float(bar.close),
volume=int(bar.volume),
)
)
return results
except Exception as exc:
msg = str(exc).lower()
if "rate" in msg and "limit" in msg:
raise RateLimitError(f"Alpaca rate limit hit for {ticker}") from exc
logger.error("Alpaca provider error for %s: %s", ticker, exc)
raise ProviderError(f"Alpaca provider error for {ticker}: {exc}") from exc