This commit is contained in:
Giulio De Pasquale 2025-10-15 19:03:28 +01:00
parent 9fa0e61cbb
commit a06dcab7f9

102
paperone/client.py Normal file
View File

@ -0,0 +1,102 @@
from datetime import datetime, timedelta
from .taapi import TaapiClient
from typing import List, Dict
import yfinance as yf
import pandas as pd
from dataclasses import dataclass
@dataclass
class TickerData:
name: str
date: datetime
open: float
close: float
low: float
high: float
avg: float
volume: int
@dataclass
class TimeSeriesFeatures:
"""Holds time-series data for a ticker with multiple lookback windows"""
ticker: str
target_date: datetime
current_day: TickerData
vix_current: TickerData
past_30d: List[TickerData] # Previous 30 trading days
class Client:
def __init__(self, taapi_key: str):
self._taapi = TaapiClient(taapi_key)
@staticmethod
def ticker_data_for(ticker: str, date: datetime) -> TickerData | None:
# Set end date to next day to ensure we get the target date
start_date = date.strftime("%Y-%m-%d")
end_date = (date + timedelta(days=1)).strftime("%Y-%m-%d")
try:
data = yf.download(
ticker,
start=start_date,
end=end_date,
auto_adjust=True,
progress=False,
)
if data.empty:
return None
row = data.iloc[0]
open_price = (
float(row["Open"].iloc[0])
if isinstance(row["Open"], pd.Series)
else float(row["Open"])
)
high = (
float(row["High"].iloc[0])
if isinstance(row["High"], pd.Series)
else float(row["High"])
)
low = (
float(row["Low"].iloc[0])
if isinstance(row["Low"], pd.Series)
else float(row["Low"])
)
close = (
float(row["Close"].iloc[0])
if isinstance(row["Close"], pd.Series)
else float(row["Close"])
)
volume = (
int(row["Volume"].iloc[0])
if isinstance(row["Volume"], pd.Series)
else int(row["Volume"])
if "Volume" in row
else 0
)
# Calculate average price
avg = (high + low) / 2.0
return TickerData(
name=ticker,
date=date,
open=round(open_price, 2),
high=round(high, 2),
low=round(low, 2),
close=round(close, 2),
avg=round(avg, 2),
volume=volume,
)
except Exception as e:
print(f"Error fetching data for {ticker} on {start_date}: {str(e)}")
return None