def get_price(s3_client: S3Client, s3_bucket: str, ticker: str, trading_day: arrow.arrow.Arrow, stack_calls: int = 0) -> Optional[float]: """ Returns the adjusted close for a ticker on the date. If trading_day is not a valid trading day on the NYSE, the most recent day, up to `trading_day` is used. """ stack_calls += 1 max_stack_calls = 50 if stack_calls > max_stack_calls: raise RuntimeError( f"stack_calls exceeded max_stack_calls: {max_stack_calls} for {ticker} on {trading_day.format('YYYY-MM-DD')}" ) while not is_valid_trading_day(trading_day): trading_day = trading_day.shift(days=-1) df = get_eod_prices(s3_client, s3_bucket, trading_day) price = None try: price = df.loc[ticker]["adjusted_close"] except KeyError: # unable to get price for given ticker. Rewind day until we retrieve valid price price = get_price(s3_client, s3_bucket, ticker, trading_day.shift(days=-1), stack_calls) return price
def calculate_lookback_window(now: arrow.arrow.Arrow, lookback_months: int) -> LookbackPeriod: """ Calculate lookback period for momentum. start period defined as the first day of the month, 13 months ago, enabling us to get initial value to compare """ start_period = now.shift(months=-lookback_months).replace(day=1) # end period excludes the most recent full month, (exclusive) end_period = now.shift(months=-1).replace(day=1) return LookbackPeriod(start_period, end_period)
def _is_forex_trading_time(self, now: arrow.arrow.Arrow) -> bool: weekday = now.isoweekday() date = now.format('YYYY-MM-DD') if weekday <= 4: return True elif weekday == 5: if now < arrow.get(f'{date} 22:00'): return True elif weekday == 6: return False elif weekday == 7: if now >= arrow.get(f'{date} 21:00'): return True return False
def is_valid_trading_day(trading_day: arrow.arrow.Arrow) -> bool: """Decides if a given trading day is valid and returns a boolean.""" trading_day_formatted = trading_day.format("YYYY-MM-DD") is_valid = False nyse = ec.get_calendar("NYSE") nasdaq = ec.get_calendar("NASDAQ") if nyse.is_session(trading_day_formatted) and nasdaq.is_session( trading_day_formatted): is_valid = True return is_valid
def _is_A_shares_trading_time(self, now: arrow.arrow.Arrow) -> bool: weekday = now.isoweekday() date = now.format('YYYY-MM-DD') if self.env.sys_frequency == 'D': if weekday <= 5: return True else: if weekday <= 5: left_1 = arrow.get(f'{date} 09:30') right_1 = arrow.get(f'{date} 11:30') left_2 = arrow.get(f'{date} 13:00') right_2 = arrow.get(f'{date} 15:00') if left_1 < now < right_1 or left_2 < now < right_2: return True return False
def get_time_diff(arrow_time_obj: arrow.arrow.Arrow, granularity=['day', 'hour', 'minute']): return arrow_time_obj.humanize(only_distance=True, locale='zh', granularity=granularity)