From a06dcab7f9d1b718ac5277cb7d4fb4cfcc8c6a6a Mon Sep 17 00:00:00 2001 From: Giulio De Pasquale Date: Wed, 15 Oct 2025 19:03:28 +0100 Subject: [PATCH] mbleh --- paperone/client.py | 102 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 paperone/client.py diff --git a/paperone/client.py b/paperone/client.py new file mode 100644 index 0000000..1a380e9 --- /dev/null +++ b/paperone/client.py @@ -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