From ad4d4bc2ddc40e6d0b6a3f511b747843775a89c4 Mon Sep 17 00:00:00 2001 From: Daniel Chew Date: Tue, 7 Nov 2023 15:01:09 +0900 Subject: [PATCH 1/4] add rates to calendar --- pythclient/calendar.py | 158 ++++++++++++++++++++++++++++++++++------- tests/test_calendar.py | 130 +++++++++++++++++++++++++++++++-- 2 files changed, 260 insertions(+), 28 deletions(-) diff --git a/pythclient/calendar.py b/pythclient/calendar.py index 3941113..9fbf7df 100644 --- a/pythclient/calendar.py +++ b/pythclient/calendar.py @@ -6,11 +6,12 @@ EQUITY_OPEN = datetime.time(9, 30, 0, tzinfo=NY_TZ) EQUITY_CLOSE = datetime.time(16, 0, 0, tzinfo=NY_TZ) -EQUITY_EARLY_CLOSE = datetime.time(13, 0, 0, tzinfo=NY_TZ) -# EQUITY_HOLIDAYS and EQUITY_EARLY_HOLIDAYS will need to be updated each year +NYSE_EARLY_CLOSE = datetime.time(13, 0, 0, tzinfo=NY_TZ) + +# NYSE_HOLIDAYS and NYSE_EARLY_HOLIDAYS will need to be updated each year # From https://www.nyse.com/markets/hours-calendars -EQUITY_HOLIDAYS = [ +NYSE_HOLIDAYS = [ datetime.datetime(2023, 1, 2, tzinfo=NY_TZ).date(), datetime.datetime(2023, 1, 16, tzinfo=NY_TZ).date(), datetime.datetime(2023, 2, 20, tzinfo=NY_TZ).date(), @@ -22,7 +23,7 @@ datetime.datetime(2023, 11, 23, tzinfo=NY_TZ).date(), datetime.datetime(2023, 12, 25, tzinfo=NY_TZ).date(), ] -EQUITY_EARLY_HOLIDAYS = [ +NYSE_EARLY_HOLIDAYS = [ datetime.datetime(2023, 7, 3, tzinfo=NY_TZ).date(), datetime.datetime(2023, 11, 24, tzinfo=NY_TZ).date(), ] @@ -36,6 +37,9 @@ datetime.datetime(2023, 12, 25, tzinfo=NY_TZ).date(), ] +RATES_OPEN = datetime.time(8, 0, 0, tzinfo=NY_TZ) +RATES_CLOSE = datetime.time(17, 0, 0, tzinfo=NY_TZ) + def is_market_open(asset_type: str, dt: datetime.datetime) -> bool: # make sure time is in NY timezone @@ -43,11 +47,11 @@ def is_market_open(asset_type: str, dt: datetime.datetime) -> bool: day, date, time = dt.weekday(), dt.date(), dt.time() if asset_type == "equity": - if date in EQUITY_HOLIDAYS or date in EQUITY_EARLY_HOLIDAYS: + if date in NYSE_HOLIDAYS or date in NYSE_EARLY_HOLIDAYS: if ( - date in EQUITY_EARLY_HOLIDAYS + date in NYSE_EARLY_HOLIDAYS and time >= EQUITY_OPEN - and time < EQUITY_EARLY_CLOSE + and time < NYSE_EARLY_CLOSE ): return True return False @@ -70,6 +74,19 @@ def is_market_open(asset_type: str, dt: datetime.datetime) -> bool: return True + if asset_type == "rates": + if date in NYSE_HOLIDAYS or date in NYSE_EARLY_HOLIDAYS: + if ( + date in NYSE_EARLY_HOLIDAYS + and time >= RATES_OPEN + and time < NYSE_EARLY_CLOSE + ): + return True + return False + if day < 5 and time >= RATES_OPEN and time < RATES_CLOSE: + return True + return False + # all other markets (crypto) return True @@ -112,6 +129,22 @@ def get_next_market_open(asset_type: str, dt: datetime.datetime) -> int: ) while is_market_open(asset_type, next_market_open): next_market_open += datetime.timedelta(days=1) + elif asset_type == "rates": + if time < RATES_OPEN: + next_market_open = dt.replace( + hour=RATES_OPEN.hour, + minute=RATES_OPEN.minute, + second=0, + microsecond=0, + ) + else: + next_market_open = dt.replace( + hour=RATES_OPEN.hour, + minute=RATES_OPEN.minute, + second=0, + microsecond=0, + ) + next_market_open += datetime.timedelta(days=1) else: return None @@ -127,11 +160,11 @@ def get_next_market_close(asset_type: str, dt: datetime.datetime) -> int: time = dt.time() if asset_type == "equity": - if dt.date() in EQUITY_EARLY_HOLIDAYS: - if time < EQUITY_EARLY_CLOSE: + if dt.date() in NYSE_EARLY_HOLIDAYS: + if time < NYSE_EARLY_CLOSE: next_market_close = dt.replace( - hour=EQUITY_EARLY_CLOSE.hour, - minute=EQUITY_EARLY_CLOSE.minute, + hour=NYSE_EARLY_CLOSE.hour, + minute=NYSE_EARLY_CLOSE.minute, second=0, microsecond=0, ) @@ -143,20 +176,35 @@ def get_next_market_close(asset_type: str, dt: datetime.datetime) -> int: microsecond=0, ) next_market_close += datetime.timedelta(days=1) - elif dt.date() in EQUITY_HOLIDAYS: - next_market_open = get_next_market_open( - asset_type, dt + datetime.timedelta(days=1) - ) - next_market_close = ( + elif dt.date() in NYSE_HOLIDAYS: + next_market_open = get_next_market_open(asset_type, dt) + next_market_open_date = ( datetime.datetime.fromtimestamp(next_market_open) .astimezone(NY_TZ) - .replace( - hour=EQUITY_CLOSE.hour, - minute=EQUITY_CLOSE.minute, - second=0, - microsecond=0, - ) + .date() ) + if next_market_open_date in NYSE_EARLY_HOLIDAYS: + next_market_close = ( + datetime.datetime.fromtimestamp(next_market_open) + .astimezone(NY_TZ) + .replace( + hour=NYSE_EARLY_CLOSE.hour, + minute=NYSE_EARLY_CLOSE.minute, + second=0, + microsecond=0, + ) + ) + else: + next_market_close = ( + datetime.datetime.fromtimestamp(next_market_open) + .astimezone(NY_TZ) + .replace( + hour=EQUITY_CLOSE.hour, + minute=EQUITY_CLOSE.minute, + second=0, + microsecond=0, + ) + ) else: next_market_close = dt.replace( hour=EQUITY_CLOSE.hour, @@ -167,9 +215,9 @@ def get_next_market_close(asset_type: str, dt: datetime.datetime) -> int: if time >= EQUITY_CLOSE: next_market_close += datetime.timedelta(days=1) - # while next_market_close.date() is in EQUITY_HOLIDAYS or weekend, add 1 day + # while next_market_close.date() is in NYSE_HOLIDAYS or weekend, add 1 day while ( - next_market_close.date() in EQUITY_HOLIDAYS + next_market_close.date() in NYSE_HOLIDAYS or next_market_close.weekday() >= 5 ): next_market_close += datetime.timedelta(days=1) @@ -185,6 +233,68 @@ def get_next_market_close(asset_type: str, dt: datetime.datetime) -> int: next_market_close += datetime.timedelta(days=1) while is_market_open(asset_type, next_market_close): next_market_close += datetime.timedelta(days=1) + elif asset_type == "rates": + if dt.date() in NYSE_EARLY_HOLIDAYS: + if time < NYSE_EARLY_CLOSE: + next_market_close = dt.replace( + hour=NYSE_EARLY_CLOSE.hour, + minute=NYSE_EARLY_CLOSE.minute, + second=0, + microsecond=0, + ) + else: + next_market_close = dt.replace( + hour=RATES_CLOSE.hour, + minute=RATES_CLOSE.minute, + second=0, + microsecond=0, + ) + next_market_close += datetime.timedelta(days=1) + elif dt.date() in NYSE_HOLIDAYS: + next_market_open = get_next_market_open(asset_type, dt) + next_market_open_date = ( + datetime.datetime.fromtimestamp(next_market_open) + .astimezone(NY_TZ) + .date() + ) + if next_market_open_date in NYSE_EARLY_HOLIDAYS: + next_market_close = ( + datetime.datetime.fromtimestamp(next_market_open) + .astimezone(NY_TZ) + .replace( + hour=NYSE_EARLY_CLOSE.hour, + minute=NYSE_EARLY_CLOSE.minute, + second=0, + microsecond=0, + ) + ) + else: + next_market_close = ( + datetime.datetime.fromtimestamp(next_market_open) + .astimezone(NY_TZ) + .replace( + hour=RATES_CLOSE.hour, + minute=RATES_CLOSE.minute, + second=0, + microsecond=0, + ) + ) + else: + next_market_close = dt.replace( + hour=RATES_CLOSE.hour, + minute=RATES_CLOSE.minute, + second=0, + microsecond=0, + ) + if time >= RATES_CLOSE: + next_market_close += datetime.timedelta(days=1) + + # while next_market_close.date() is in NYSE_HOLIDAYS or weekend, add 1 day + while ( + next_market_close.date() in NYSE_HOLIDAYS + or next_market_close.weekday() >= 5 + ): + next_market_close += datetime.timedelta(days=1) else: # crypto markets never close return None diff --git a/tests/test_calendar.py b/tests/test_calendar.py index de79857..413bbc0 100644 --- a/tests/test_calendar.py +++ b/tests/test_calendar.py @@ -12,7 +12,9 @@ EQUITY_CLOSE_WED_2023_6_21_17 = datetime.datetime(2023, 6, 21, 17, 0, 0, tzinfo=NY_TZ) EQUITY_CLOSE_SAT_2023_6_10_17 = datetime.datetime(2023, 6, 10, 17, 0, 0, tzinfo=NY_TZ) EQUITY_HOLIDAY_MON_2023_6_19 = datetime.datetime(2023, 6, 19, tzinfo=NY_TZ) -EQUITY_EARLY_CLOSE_OPEN_FRI_2023_11_24_14 = datetime.datetime(2023, 11, 24, 11, 0, 0, tzinfo=NY_TZ) +EQUITY_HOLIDAY_NEXT_DAY_EARLY_CLOSE_OPEN_THU_2023_11_23_9_30 = datetime.datetime(2023, 11, 23, 9, 30, 0, tzinfo=NY_TZ) +EQUITY_HOLIDAY_NEXT_DAY_EARLY_CLOSE_CLOSE_THU_2023_11_23_13 = datetime.datetime(2023, 11, 23, 13, 0, 0, tzinfo=NY_TZ) +EQUITY_EARLY_CLOSE_OPEN_FRI_2023_11_24_11 = datetime.datetime(2023, 11, 24, 11, 0, 0, tzinfo=NY_TZ) EQUITY_EARLY_CLOSE_CLOSE_FRI_2023_11_24_14 = datetime.datetime(2023, 11, 24, 14, 0, 0, tzinfo=NY_TZ) # Define constants for fx & metal market @@ -21,6 +23,16 @@ FX_METAL_CLOSE_SUN_2023_6_18_16 = datetime.datetime(2023, 6, 18, 16, 0, 0, tzinfo=NY_TZ) FX_METAL_HOLIDAY_SUN_2023_1_1 = datetime.datetime(2023, 1, 1, tzinfo=NY_TZ) +# Define constants for rates market +RATES_OPEN_WED_2023_6_21_12 = datetime.datetime(2023, 6, 21, 8, 0, 0, tzinfo=NY_TZ) +RATES_CLOSE_WED_2023_6_21_17 = datetime.datetime(2023, 6, 21, 17, 0, 0, tzinfo=NY_TZ) +RATES_CLOSE_SAT_2023_6_10_17 = datetime.datetime(2023, 6, 10, 17, 0, 0, tzinfo=NY_TZ) +RATES_HOLIDAY_MON_2023_6_19 = datetime.datetime(2023, 6, 19, tzinfo=NY_TZ) +RATES_HOLIDAY_NEXT_DAY_EARLY_CLOSE_OPEN_THU_2023_11_23_8 = datetime.datetime(2023, 11, 23, 8, 0, 0, tzinfo=NY_TZ) +RATES_HOLIDAY_NEXT_DAY_EARLY_CLOSE_CLOSE_THU_2023_11_23_13 = datetime.datetime(2023, 11, 23, 13, 0, 0, tzinfo=NY_TZ) +RATES_EARLY_CLOSE_OPEN_FRI_2023_11_24_11 = datetime.datetime(2023, 11, 24, 11, 0, 0, tzinfo=NY_TZ) +RATES_EARLY_CLOSE_CLOSE_FRI_2023_11_24_14 = datetime.datetime(2023, 11, 24, 14, 0, 0, tzinfo=NY_TZ) + # Define constants for cryptocurrency market CRYPTO_OPEN_WED_2023_6_21_12 = datetime.datetime(2023, 6, 21, 12, 0, 0, tzinfo=NY_TZ) CRYPTO_OPEN_SUN_2023_6_18_12 = datetime.datetime(2023, 6, 18, 12, 0, 0, tzinfo=NY_TZ) @@ -47,7 +59,7 @@ def test_is_market_open(): assert is_market_open("equity", EQUITY_HOLIDAY_MON_2023_6_19) == False # weekday, NYSE early close holiday - assert is_market_open("equity", EQUITY_EARLY_CLOSE_OPEN_FRI_2023_11_24_14) == True + assert is_market_open("equity", EQUITY_EARLY_CLOSE_OPEN_FRI_2023_11_24_11) == True assert is_market_open("equity", EQUITY_EARLY_CLOSE_CLOSE_FRI_2023_11_24_14) == False # fx & metal @@ -63,6 +75,23 @@ def test_is_market_open(): assert is_market_open("fx", FX_METAL_HOLIDAY_SUN_2023_1_1) == False assert is_market_open("metal", FX_METAL_HOLIDAY_SUN_2023_1_1) == False + # rates + # weekday, within rates market hours + assert is_market_open("rates", RATES_OPEN_WED_2023_6_21_12) == True + + # weekday, out of rates market hours + assert is_market_open("rates", RATES_CLOSE_WED_2023_6_21_17) == False + + # weekend, out of rates market hours + assert is_market_open("rates", RATES_CLOSE_SAT_2023_6_10_17) == False + + # weekday, NYSE holiday + assert is_market_open("rates", RATES_HOLIDAY_MON_2023_6_19) == False + + # weekday, NYSE early close holiday + assert is_market_open("rates", RATES_EARLY_CLOSE_OPEN_FRI_2023_11_24_11) == True + assert is_market_open("rates", RATES_EARLY_CLOSE_CLOSE_FRI_2023_11_24_14) == False + # crypto assert is_market_open("crypto", CRYPTO_OPEN_WED_2023_6_21_12) == True assert is_market_open("crypto", CRYPTO_OPEN_SUN_2023_6_18_12) == True @@ -93,9 +122,15 @@ def test_get_next_market_open(): == format_datetime_to_unix_timestamp(datetime.datetime(2023, 6, 20, 9, 30, 0, tzinfo=NY_TZ)) ) + # equity holiday next day early close holiday + assert ( + get_next_market_open("equity", EQUITY_HOLIDAY_NEXT_DAY_EARLY_CLOSE_OPEN_THU_2023_11_23_9_30) + == format_datetime_to_unix_timestamp(datetime.datetime(2023, 11, 24, 9, 30, 0, tzinfo=NY_TZ)) + ) + # equity early close holiday assert ( - get_next_market_open("equity", EQUITY_EARLY_CLOSE_OPEN_FRI_2023_11_24_14) + get_next_market_open("equity", EQUITY_EARLY_CLOSE_OPEN_FRI_2023_11_24_11) == format_datetime_to_unix_timestamp(datetime.datetime(2023, 11, 27, 9, 30, 0, tzinfo=NY_TZ)) ) assert ( @@ -142,6 +177,47 @@ def test_get_next_market_open(): == format_datetime_to_unix_timestamp(datetime.datetime(2023, 1, 2, 17, 0, 0, tzinfo=NY_TZ)) ) + # rates within market hours + assert ( + get_next_market_open("rates", RATES_OPEN_WED_2023_6_21_12) + == format_datetime_to_unix_timestamp(datetime.datetime(2023, 6, 22, 8, 0, 0, tzinfo=NY_TZ)) + ) + + # rates out of market hours + assert ( + get_next_market_open("rates", RATES_CLOSE_WED_2023_6_21_17) + == format_datetime_to_unix_timestamp(datetime.datetime(2023, 6, 22, 8, 0, 0, tzinfo=NY_TZ)) + ) + + # rates weekend + assert ( + get_next_market_open("rates", RATES_CLOSE_SAT_2023_6_10_17) + == format_datetime_to_unix_timestamp(datetime.datetime(2023, 6, 12, 8, 0, 0, tzinfo=NY_TZ)) + ) + + # rates holiday + assert ( + get_next_market_open("rates", RATES_HOLIDAY_MON_2023_6_19) + == format_datetime_to_unix_timestamp(datetime.datetime(2023, 6, 20, 8, 0, 0, tzinfo=NY_TZ)) + ) + + # rates holiday next day early close holiday + assert ( + get_next_market_open("rates", RATES_HOLIDAY_NEXT_DAY_EARLY_CLOSE_OPEN_THU_2023_11_23_8) + == format_datetime_to_unix_timestamp(datetime.datetime(2023, 11, 24, 8, 0, 0, tzinfo=NY_TZ)) + ) + + # rates early close holiday + assert ( + get_next_market_open("rates", RATES_EARLY_CLOSE_OPEN_FRI_2023_11_24_11) + == format_datetime_to_unix_timestamp(datetime.datetime(2023, 11, 27, 8, 0, 0, tzinfo=NY_TZ)) + ) + assert ( + get_next_market_open("rates", RATES_EARLY_CLOSE_CLOSE_FRI_2023_11_24_14) + == format_datetime_to_unix_timestamp(datetime.datetime(2023, 11, 27, 8, 0, 0, tzinfo=NY_TZ)) + ) + + # crypto assert get_next_market_open("crypto", CRYPTO_OPEN_WED_2023_6_21_12) == None assert get_next_market_open("crypto", CRYPTO_OPEN_SUN_2023_6_18_12) == None @@ -172,9 +248,15 @@ def test_get_next_market_close(): == format_datetime_to_unix_timestamp(datetime.datetime(2023, 6, 20, 16, 0, 0, tzinfo=NY_TZ)) ) + # equity holiday next day early close holiday + assert ( + get_next_market_close("equity", EQUITY_HOLIDAY_NEXT_DAY_EARLY_CLOSE_CLOSE_THU_2023_11_23_13) + == format_datetime_to_unix_timestamp(datetime.datetime(2023, 11, 24, 13, 0, 0, tzinfo=NY_TZ)) + ) + # equity early close holiday assert ( - get_next_market_close("equity", EQUITY_EARLY_CLOSE_OPEN_FRI_2023_11_24_14) + get_next_market_close("equity", EQUITY_EARLY_CLOSE_OPEN_FRI_2023_11_24_11) == format_datetime_to_unix_timestamp(datetime.datetime(2023, 11, 24, 13, 0, 0, tzinfo=NY_TZ)) ) assert ( @@ -222,6 +304,46 @@ def test_get_next_market_close(): == format_datetime_to_unix_timestamp(datetime.datetime(2023, 1, 6, 17, 0, 0, tzinfo=NY_TZ)) ) + # rates within market hours + assert ( + get_next_market_close("rates", RATES_OPEN_WED_2023_6_21_12) + == format_datetime_to_unix_timestamp(datetime.datetime(2023, 6, 21, 17, 0, 0, tzinfo=NY_TZ)) + ) + + # rates out of market hours + assert ( + get_next_market_close("rates", RATES_CLOSE_WED_2023_6_21_17) + == format_datetime_to_unix_timestamp(datetime.datetime(2023, 6, 22, 17, 0, 0, tzinfo=NY_TZ)) + ) + + # rates weekend + assert ( + get_next_market_close("rates", RATES_CLOSE_SAT_2023_6_10_17) + == format_datetime_to_unix_timestamp(datetime.datetime(2023, 6, 12, 17, 0, 0, tzinfo=NY_TZ)) + ) + + # rates holiday + assert ( + get_next_market_close("rates", RATES_HOLIDAY_MON_2023_6_19) + == format_datetime_to_unix_timestamp(datetime.datetime(2023, 6, 20, 17, 0, 0, tzinfo=NY_TZ)) + ) + + # rates holiday next day early close holiday + assert ( + get_next_market_close("rates", RATES_HOLIDAY_NEXT_DAY_EARLY_CLOSE_CLOSE_THU_2023_11_23_13) + == format_datetime_to_unix_timestamp(datetime.datetime(2023, 11, 24, 13, 0, 0, tzinfo=NY_TZ)) + ) + + # rates early close holiday + assert ( + get_next_market_close("rates", RATES_EARLY_CLOSE_OPEN_FRI_2023_11_24_11) + == format_datetime_to_unix_timestamp(datetime.datetime(2023, 11, 24, 13, 0, 0, tzinfo=NY_TZ)) + ) + assert ( + get_next_market_close("rates", RATES_EARLY_CLOSE_CLOSE_FRI_2023_11_24_14) + == format_datetime_to_unix_timestamp(datetime.datetime(2023, 11, 27, 17, 0, 0, tzinfo=NY_TZ)) + ) + # crypto assert get_next_market_close("crypto", CRYPTO_OPEN_WED_2023_6_21_12) == None assert get_next_market_close("crypto", CRYPTO_OPEN_SUN_2023_6_18_12) == None From 453479a084b77b38f7bef5c3cb1a165f45f4a5c8 Mon Sep 17 00:00:00 2001 From: Daniel Chew Date: Tue, 7 Nov 2023 15:07:50 +0900 Subject: [PATCH 2/4] add get_market_hours_clause --- pythclient/calendar.py | 57 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/pythclient/calendar.py b/pythclient/calendar.py index 9fbf7df..c70cb79 100644 --- a/pythclient/calendar.py +++ b/pythclient/calendar.py @@ -299,3 +299,60 @@ def get_next_market_close(asset_type: str, dt: datetime.datetime) -> int: return None return int(next_market_close.timestamp()) + + +def get_market_hours_clause(time_column_name): + us_equity_start_minute = EQUITY_OPEN.hour * 60 + EQUITY_OPEN.minute + us_equity_end_minute = EQUITY_CLOSE.hour * 60 + EQUITY_CLOSE.minute + nyse_early_end_minute = NYSE_EARLY_CLOSE.hour * 60 + NYSE_EARLY_CLOSE.minute + # for all equity, only include data from monday to friday (9:30am ET to 4pm ET) and exclude holidays + us_equity_clause = f""" + toDayOfWeek({time_column_name}) <= 5 + AND dateDiff('minute', date_trunc('day', {time_column_name}, '{NY_TZ}'), {time_column_name}, '{NY_TZ}') >= {us_equity_start_minute} + AND dateDiff('minute', date_trunc('day', {time_column_name}, '{NY_TZ}'), {time_column_name}, '{NY_TZ}') < {us_equity_end_minute} + AND toDate({time_column_name}) NOT IN ({','.join([f"toDate('{h.strftime('%Y-%m-%d')}')" for h in NYSE_HOLIDAYS])}) + AND ( + toDate({time_column_name}) NOT IN ({','.join([f"toDate('{h.strftime('%Y-%m-%d')}')" for h in NYSE_EARLY_HOLIDAYS])}) + OR ( + toDate({time_column_name}) IN ({','.join([f"toDate('{h.strftime('%Y-%m-%d')}')" for h in NYSE_EARLY_HOLIDAYS])}) + AND dateDiff('minute', date_trunc('day', {time_column_name}, '{NY_TZ}'), {time_column_name}, '{NY_TZ}') < {nyse_early_end_minute} + ) + ) + """ + + fx_metal_start_end_minute = ( + FX_METAL_OPEN_CLOSE_TIME.hour * 60 + FX_METAL_OPEN_CLOSE_TIME.minute + ) + + # for all fx and metal, only include data from sunday (after 5pm ET) to friday (before 5pm ET) + fx_metal_clause = f""" + ((toDayOfWeek({time_column_name}) <= 4) + OR ( + toDayOfWeek({time_column_name}) = 5 + AND dateDiff('minute', date_trunc('day', {time_column_name}, '{NY_TZ}'), {time_column_name}, '{NY_TZ}') < {fx_metal_start_end_minute} + ) + OR ( + toDayOfWeek({time_column_name}) = 7 + AND dateDiff('minute', date_trunc('day', {time_column_name}, '{NY_TZ}'), {time_column_name}, '{NY_TZ}') >= {fx_metal_start_end_minute} + )) + AND toDate({time_column_name}) NOT IN ({','.join([f"toDate('{h.strftime('%Y-%m-%d')}')" for h in FX_METAL_HOLIDAYS])}) + """ + + rates_start_minute = RATES_OPEN.hour * 60 + RATES_OPEN.minute + rates_end_minute = RATES_CLOSE.hour * 60 + RATES_CLOSE.minute + # for all rates, only include data from monday to friday (8:00am ET to 5pm ET) and exclude holidays + rates_clause = f""" + toDayOfWeek({time_column_name}) <= 5 + AND dateDiff('minute', date_trunc('day', {time_column_name}, '{NY_TZ}'), {time_column_name}, '{NY_TZ}') >= {rates_start_minute} + AND dateDiff('minute', date_trunc('day', {time_column_name}, '{NY_TZ}'), {time_column_name}, '{NY_TZ}') < {rates_end_minute} + AND toDate({time_column_name}) NOT IN ({','.join([f"toDate('{h.strftime('%Y-%m-%d')}')" for h in NYSE_HOLIDAYS])}) + AND ( + toDate({time_column_name}) NOT IN ({','.join([f"toDate('{h.strftime('%Y-%m-%d')}')" for h in NYSE_EARLY_HOLIDAYS])}) + OR ( + toDate({time_column_name}) IN ({','.join([f"toDate('{h.strftime('%Y-%m-%d')}')" for h in NYSE_EARLY_HOLIDAYS])}) + AND dateDiff('minute', date_trunc('day', {time_column_name}, '{NY_TZ}'), {time_column_name}, '{NY_TZ}') < {nyse_early_end_minute} + ) + ) + """ + + return f"""((symbol LIKE 'Equity.US.%' AND ({us_equity_clause})) OR ((symbol LIKE 'FX.%' OR symbol LIKE 'Metal.%') AND ({fx_metal_clause})) OR (symbol LIKE 'Rates.%' AND ({rates_clause})) OR symbol LIKE 'Crypto.%')""" From 4b7b2837576c8b3105e2e85e702c0414fff4fd74 Mon Sep 17 00:00:00 2001 From: Daniel Chew Date: Tue, 7 Nov 2023 15:11:28 +0900 Subject: [PATCH 3/4] bump --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index fc36bff..29350c8 100644 --- a/setup.py +++ b/setup.py @@ -7,7 +7,7 @@ setup( name='pythclient', - version='0.1.15', + version='0.1.16', packages=['pythclient'], author='Pyth Developers', author_email='contact@pyth.network', From 0289d4d1a81f2abc4fe6160147b7240cce864593 Mon Sep 17 00:00:00 2001 From: Daniel Chew Date: Tue, 7 Nov 2023 17:40:15 +0900 Subject: [PATCH 4/4] remove get_market_hours_clause --- pythclient/calendar.py | 57 ------------------------------------------ 1 file changed, 57 deletions(-) diff --git a/pythclient/calendar.py b/pythclient/calendar.py index c70cb79..9fbf7df 100644 --- a/pythclient/calendar.py +++ b/pythclient/calendar.py @@ -299,60 +299,3 @@ def get_next_market_close(asset_type: str, dt: datetime.datetime) -> int: return None return int(next_market_close.timestamp()) - - -def get_market_hours_clause(time_column_name): - us_equity_start_minute = EQUITY_OPEN.hour * 60 + EQUITY_OPEN.minute - us_equity_end_minute = EQUITY_CLOSE.hour * 60 + EQUITY_CLOSE.minute - nyse_early_end_minute = NYSE_EARLY_CLOSE.hour * 60 + NYSE_EARLY_CLOSE.minute - # for all equity, only include data from monday to friday (9:30am ET to 4pm ET) and exclude holidays - us_equity_clause = f""" - toDayOfWeek({time_column_name}) <= 5 - AND dateDiff('minute', date_trunc('day', {time_column_name}, '{NY_TZ}'), {time_column_name}, '{NY_TZ}') >= {us_equity_start_minute} - AND dateDiff('minute', date_trunc('day', {time_column_name}, '{NY_TZ}'), {time_column_name}, '{NY_TZ}') < {us_equity_end_minute} - AND toDate({time_column_name}) NOT IN ({','.join([f"toDate('{h.strftime('%Y-%m-%d')}')" for h in NYSE_HOLIDAYS])}) - AND ( - toDate({time_column_name}) NOT IN ({','.join([f"toDate('{h.strftime('%Y-%m-%d')}')" for h in NYSE_EARLY_HOLIDAYS])}) - OR ( - toDate({time_column_name}) IN ({','.join([f"toDate('{h.strftime('%Y-%m-%d')}')" for h in NYSE_EARLY_HOLIDAYS])}) - AND dateDiff('minute', date_trunc('day', {time_column_name}, '{NY_TZ}'), {time_column_name}, '{NY_TZ}') < {nyse_early_end_minute} - ) - ) - """ - - fx_metal_start_end_minute = ( - FX_METAL_OPEN_CLOSE_TIME.hour * 60 + FX_METAL_OPEN_CLOSE_TIME.minute - ) - - # for all fx and metal, only include data from sunday (after 5pm ET) to friday (before 5pm ET) - fx_metal_clause = f""" - ((toDayOfWeek({time_column_name}) <= 4) - OR ( - toDayOfWeek({time_column_name}) = 5 - AND dateDiff('minute', date_trunc('day', {time_column_name}, '{NY_TZ}'), {time_column_name}, '{NY_TZ}') < {fx_metal_start_end_minute} - ) - OR ( - toDayOfWeek({time_column_name}) = 7 - AND dateDiff('minute', date_trunc('day', {time_column_name}, '{NY_TZ}'), {time_column_name}, '{NY_TZ}') >= {fx_metal_start_end_minute} - )) - AND toDate({time_column_name}) NOT IN ({','.join([f"toDate('{h.strftime('%Y-%m-%d')}')" for h in FX_METAL_HOLIDAYS])}) - """ - - rates_start_minute = RATES_OPEN.hour * 60 + RATES_OPEN.minute - rates_end_minute = RATES_CLOSE.hour * 60 + RATES_CLOSE.minute - # for all rates, only include data from monday to friday (8:00am ET to 5pm ET) and exclude holidays - rates_clause = f""" - toDayOfWeek({time_column_name}) <= 5 - AND dateDiff('minute', date_trunc('day', {time_column_name}, '{NY_TZ}'), {time_column_name}, '{NY_TZ}') >= {rates_start_minute} - AND dateDiff('minute', date_trunc('day', {time_column_name}, '{NY_TZ}'), {time_column_name}, '{NY_TZ}') < {rates_end_minute} - AND toDate({time_column_name}) NOT IN ({','.join([f"toDate('{h.strftime('%Y-%m-%d')}')" for h in NYSE_HOLIDAYS])}) - AND ( - toDate({time_column_name}) NOT IN ({','.join([f"toDate('{h.strftime('%Y-%m-%d')}')" for h in NYSE_EARLY_HOLIDAYS])}) - OR ( - toDate({time_column_name}) IN ({','.join([f"toDate('{h.strftime('%Y-%m-%d')}')" for h in NYSE_EARLY_HOLIDAYS])}) - AND dateDiff('minute', date_trunc('day', {time_column_name}, '{NY_TZ}'), {time_column_name}, '{NY_TZ}') < {nyse_early_end_minute} - ) - ) - """ - - return f"""((symbol LIKE 'Equity.US.%' AND ({us_equity_clause})) OR ((symbol LIKE 'FX.%' OR symbol LIKE 'Metal.%') AND ({fx_metal_clause})) OR (symbol LIKE 'Rates.%' AND ({rates_clause})) OR symbol LIKE 'Crypto.%')"""