-
Notifications
You must be signed in to change notification settings - Fork 852
/
Copy pathib_trading_hours.py
143 lines (113 loc) · 4.35 KB
/
ib_trading_hours.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import datetime
from ib_insync import ContractDetails as ibContractDetails
from sysdata.config.private_directory import get_full_path_for_private_config
from sysobjects.production.trading_hours.trading_hours import (
tradingHours,
listOfTradingHours,
)
from syscore.fileutils import does_filename_exist
from sysdata.config.production_config import get_production_config
from sysdata.production.trading_hours import read_trading_hours
IB_CONFIG_TRADING_HOURS_FILE = "sysbrokers.IB.ib_config_trading_hours.yaml"
PRIVATE_CONFIG_TRADING_HOURS_FILE = get_full_path_for_private_config(
"private_config_trading_hours.yaml"
)
def get_saved_trading_hours():
if does_filename_exist(PRIVATE_CONFIG_TRADING_HOURS_FILE):
return read_trading_hours(PRIVATE_CONFIG_TRADING_HOURS_FILE)
else:
return read_trading_hours(IB_CONFIG_TRADING_HOURS_FILE)
def get_trading_hours_from_contract_details(
ib_contract_details: ibContractDetails,
) -> listOfTradingHours:
try:
time_zone_id = ib_contract_details.timeZoneId
time_zone_adjustment = get_time_difference(time_zone_id)
trading_hours_string = ib_contract_details.tradingHours
list_of_open_times = parse_trading_hours_string(
trading_hours_string, adjustment_hours=time_zone_adjustment
)
except Exception as e:
raise e
return list_of_open_times
NO_ADJUSTMENTS = 0, 0
CLOSED_ALL_DAY = object()
def parse_trading_hours_string(
trading_hours_string: str,
adjustment_hours: int = 0,
) -> listOfTradingHours:
day_by_day = trading_hours_string.split(";")
list_of_open_times = [
parse_trading_for_day(string_for_day, adjustment_hours=adjustment_hours)
for string_for_day in day_by_day
]
list_of_open_times = [
open_time for open_time in list_of_open_times if open_time is not CLOSED_ALL_DAY
]
list_of_open_times = listOfTradingHours(list_of_open_times)
return list_of_open_times
def parse_trading_for_day(
string_for_day: str, adjustment_hours: int = 0
) -> tradingHours:
start_and_end = string_for_day.split("-")
if len(start_and_end) == 1:
# closed
return CLOSED_ALL_DAY
start_phrase = start_and_end[0]
end_phrase = start_and_end[1]
# Doesn't deal with DST. We will be conservative and only trade 1 hour
# after and 1 hour before
adjust_start = 1
adjust_end = -1
start_dt = parse_phrase(
start_phrase, adjustment_hours=adjustment_hours, additional_adjust=adjust_start
)
end_dt = parse_phrase(
end_phrase, adjustment_hours=adjustment_hours, additional_adjust=adjust_end
)
return tradingHours(start_dt, end_dt)
def parse_phrase(
phrase: str, adjustment_hours: int = 0, additional_adjust: int = 0
) -> datetime.datetime:
total_adjustment = adjustment_hours + additional_adjust
original_time = datetime.datetime.strptime(phrase, "%Y%m%d:%H%M")
adjustment = datetime.timedelta(hours=total_adjustment)
return original_time + adjustment
def get_GMT_offset_hours():
# this needs to be in private_config.YAML
# where are the defaults stored that needs to be
# GMT_offset_hours = 0
try:
production_config = get_production_config()
GMT_offset_hours = production_config.GMT_offset_hours
except:
raise Exception("Default is zero, have it in private_config")
return GMT_offset_hours
def get_time_difference(time_zone_id: str) -> int:
# Doesn't deal with DST. We will be conservative and only trade 1 hour
# after and 1 hour before
# confusingly, IB seem to have changed their time zone codes in 2020
# some of these are legacy codes which could be removed
time_diff_dict = {
"CST (Central Standard Time)": 6,
"MET (Middle Europe Time)": -1,
"EST (Eastern Standard Time)": 5,
"JST (Japan Standard Time)": -9,
"US/Eastern": 5,
"MET": -1,
"EST": 5,
"JST": -9,
"Japan": -9,
"US/Central": 6,
"GB-Eire": 0,
"Hongkong": -8,
"Australia/NSW": -11,
"": 0,
}
GMT_offset_hours = get_GMT_offset_hours()
for k, v in time_diff_dict.items():
time_diff_dict[k] = v + GMT_offset_hours
diff_hours = time_diff_dict.get(time_zone_id, None)
if diff_hours is None:
raise Exception("Time zone '%s' not found!" % time_zone_id)
return diff_hours