import logging
import time
from datetime import datetime
from enum import Enum
import pytz
from govuk_bank_holidays.bank_holidays import BankHolidays
from tradingbot.Components.Utils import Utils
[docs]class TimeAmount(Enum):
"""Types of amount of time to wait for
"""
SECONDS = 0
NEXT_MARKET_OPENING = 1
[docs]class TimeProvider:
"""Class that handle functions dependents on actual time
such as wait, sleep or compute date/time operations
"""
def __init__(self) -> None:
logging.debug("TimeProvider __init__")
[docs] def is_market_open(self, timezone: str) -> bool:
"""
Return True if the market is open, false otherwise
- **timezone**: string representing the timezone
"""
tz = pytz.timezone(timezone)
now_time = datetime.now(tz=tz).strftime("%H:%M")
return BankHolidays().is_work_day(datetime.now(tz=tz)) and Utils.is_between(
str(now_time), ("07:55", "16:35")
)
[docs] def get_seconds_to_market_opening(self, from_time: datetime) -> float:
"""Return the amount of seconds from now to the next market opening,
taking into account UK bank holidays and weekends"""
today_opening = datetime(
year=from_time.year,
month=from_time.month,
day=from_time.day,
hour=8,
minute=0,
second=0,
microsecond=0,
)
if from_time < today_opening and BankHolidays().is_work_day(from_time.date()):
nextMarketOpening = today_opening
else:
# Get next working day
nextWorkDate = BankHolidays().get_next_work_day(date=from_time.date())
nextMarketOpening = datetime(
year=nextWorkDate.year,
month=nextWorkDate.month,
day=nextWorkDate.day,
hour=8,
minute=0,
second=0,
microsecond=0,
)
# Calculate the delta from from_time to the next market opening
return (nextMarketOpening - from_time).total_seconds()
[docs] def wait_for(self, time_amount_type: TimeAmount, amount: float = -1.0) -> None:
"""Wait for the specified amount of time.
An TimeAmount type can be specified
"""
if time_amount_type is TimeAmount.NEXT_MARKET_OPENING:
amount = self.get_seconds_to_market_opening(datetime.now())
elif time_amount_type is TimeAmount.SECONDS:
if amount < 0:
raise ValueError("Invalid amount of time to wait for")
logging.info("Wait for {0:.2f} hours...".format(amount / 3600))
time.sleep(amount)