From fc10cf390797c28059f07f0ea9adbb6e618b7893 Mon Sep 17 00:00:00 2001 From: pvlasak <93707814+pvlasak@users.noreply.github.com> Date: Mon, 15 Jul 2024 09:46:17 +0200 Subject: [PATCH] Feature/cal days from pandas (#213) * new fetch_calendar_data function * new class Calendar * Revert common/model.py to the state before the last commit * dataframe transformation is making Timestamp objects in open and close columns naive before converting to dictionary. * typing for function arguments added. Function returns list of Calendar objects that have properties defined like strings. * else condition fixed * else condition returns directly an empty without declaring a list name --- v2realbot/utils/utils.py | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/v2realbot/utils/utils.py b/v2realbot/utils/utils.py index b82893d..2390f9f 100644 --- a/v2realbot/utils/utils.py +++ b/v2realbot/utils/utils.py @@ -20,7 +20,7 @@ from uuid import UUID from enum import Enum #from v2realbot.enums.enums import Order from v2realbot.common.model import Order as btOrder, TradeUpdate as btTradeUpdate -from alpaca.trading.models import Order, TradeUpdate +from alpaca.trading.models import Order, TradeUpdate, Calendar import numpy as np import pandas as pd from collections import deque @@ -35,6 +35,7 @@ import tempfile import shutil from filelock import FileLock import v2realbot.utils.config_handler as cfh +import pandas_market_calendars as mcal def validate_and_format_time(time_string): """ @@ -59,8 +60,32 @@ def validate_and_format_time(time_string): else: return None +def fetch_calendar_data(start: datetime, end: datetime) -> List[Calendar]: + """ + Fetches the trading schedule for the NYSE (New York Stock Exchange) between the specified start and end dates. + Args: + start (datetime): The start date for the trading schedule. + end (datetime): The end date for the trading schedule. + Returns: + List[Calendar]: A list of Calendar objects containing the trading dates and market open/close times. + Returns an empty list if no trading days are found within the specified range. + """ + nyse = mcal.get_calendar('NYSE') + schedule = nyse.schedule(start_date=start, end_date=end, tz='America/New_York') + if not schedule.empty: + schedule = (schedule.reset_index() + .rename(columns={"index": "date", "market_open": "open", "market_close": "close"}) + .assign(date=lambda day: day['date'].dt.date.astype(str), + open=lambda day: day['open'].dt.strftime('%H:%M'), + close=lambda day: day['close'].dt.strftime('%H:%M')) + .to_dict(orient="records")) + cal_dates = [Calendar(**record) for record in schedule] + return cal_dates + else: + return [] + #Alpaca Calendar wrapper with retry -def fetch_calendar_data(start, end, max_retries=5, backoff_factor=1): +def fetch_calendar_data_from_alpaca(start, end, max_retries=5, backoff_factor=1): """ Attempts to fetch calendar data with exponential backoff. Raises an exception if all retries fail.