11"""Module that contains Theta Client class."""
2- import datetime
2+ from datetime import time
33import threading
44import time
55import traceback
2727from .terminal import check_download , launch_terminal
2828
2929_NOT_CONNECTED_MSG = "You must establish a connection first."
30- _VERSION = '0.9.2'
31- URL_BASE = "http://localhost:25510/"
30+ _VERSION = '0.9.3'
31+ URL_BASE = "http://127.0.0.1:25510/"
32+
3233
3334def _format_strike (strike : float ) -> int :
3435 """Round USD to the nearest tenth of a cent, acceptable by the terminal."""
@@ -40,6 +41,12 @@ def _format_date(dt: date) -> str:
4041 return dt .strftime ("%Y%m%d" )
4142
4243
44+ def ms_to_time (ms_of_day : int ) -> datetime .time :
45+ return datetime (year = 2000 , month = 1 , day = 1 , hour = int ((ms_of_day / (1000 * 60 * 60 )) % 24 ),
46+ minute = int (ms_of_day / (1000 * 60 )) % 60 , second = int ((ms_of_day / 1000 ) % 60 ),
47+ microsecond = (ms_of_day % 1000 ) * 1000 ).time ()
48+
49+
4350_pt_to_price_mul = [
4451 0 ,
4552 0.000000001 ,
@@ -89,6 +96,15 @@ def from_bytes(self, data: bytearray):
8996 date_raw = str (parse_int (view [28 :32 ]))
9097 self .date = date (year = int (date_raw [0 :4 ]), month = int (date_raw [4 :6 ]), day = int (date_raw [6 :8 ]))
9198
99+ def copy_from (self , other_trade ):
100+ self .ms_of_day = other_trade .ms_of_day
101+ self .sequence = other_trade .sequence
102+ self .size = other_trade .size
103+ self .condition = other_trade .condition
104+ self .price = other_trade .price
105+ self .exchange = other_trade .exchange
106+ self .date = other_trade .date
107+
92108 def to_string (self ) -> str :
93109 """String representation of a trade."""
94110 return 'ms_of_day: ' + str (self .ms_of_day ) + ' sequence: ' + str (self .sequence ) + ' size: ' + str (self .size ) + \
@@ -123,6 +139,16 @@ def from_bytes(self, data: bytearray):
123139 date_raw = str (parse_int (view [32 :36 ]))
124140 self .date = date (year = int (date_raw [0 :4 ]), month = int (date_raw [4 :6 ]), day = int (date_raw [6 :8 ]))
125141
142+ def copy_from (self , other_ohlcvc ):
143+ self .ms_of_day = other_ohlcvc .ms_of_day
144+ self .open = other_ohlcvc .open
145+ self .high = other_ohlcvc .high
146+ self .low = other_ohlcvc .low
147+ self .close = other_ohlcvc .close
148+ self .volume = other_ohlcvc .volume
149+ self .count = other_ohlcvc .count
150+ self .date = other_ohlcvc .date
151+
126152 def to_string (self ) -> str :
127153 """String representation of a trade."""
128154 return 'ms_of_day: ' + str (self .ms_of_day ) + ' open: ' + str (self .open ) + ' high: ' + str (self .high ) + \
@@ -162,6 +188,18 @@ def from_bytes(self, data: bytes):
162188 date_raw = str (parse_int (view [40 :44 ]))
163189 self .date = date (year = int (date_raw [0 :4 ]), month = int (date_raw [4 :6 ]), day = int (date_raw [6 :8 ]))
164190
191+ def copy_from (self , other_quote ):
192+ self .ms_of_day = other_quote .ms_of_day
193+ self .bid_size = other_quote .bid_size
194+ self .bid_exchange = other_quote .bid_exchange
195+ self .bid_price = other_quote .bid_price
196+ self .bid_condition = other_quote .bid_condition
197+ self .ask_size = other_quote .ask_size
198+ self .ask_exchange = other_quote .ask_exchange
199+ self .ask_price = other_quote .ask_price
200+ self .ask_condition = other_quote .ask_condition
201+ self .date = other_quote .date
202+
165203 def to_string (self ) -> str :
166204 """String representation of a quote."""
167205 return 'ms_of_day: ' + str (self .ms_of_day ) + ' bid_size: ' + str (self .bid_size ) + ' bid_exchange: ' + \
@@ -186,6 +224,10 @@ def from_bytes(self, data: bytearray):
186224 date_raw = str (parse_int (view [4 :8 ]))
187225 self .date = date (year = int (date_raw [0 :4 ]), month = int (date_raw [4 :6 ]), day = int (date_raw [6 :8 ]))
188226
227+ def copy_from (self , other_open_interest ):
228+ self .open_interest = other_open_interest .open_interest
229+ self .date = other_open_interest .date
230+
189231 def to_string (self ) -> str :
190232 """String representation of open interest."""
191233 return 'open_interest: ' + str (self .open_interest ) + ' date: ' + str (self .date )
@@ -239,15 +281,14 @@ def __init__(self):
239281 self .contract = Contract ()
240282 self .date = None
241283
242-
243284class ThetaClient :
244285 """A high-level, blocking client used to fetch market data. Instantiating this class
245286 runs a java background process, which is responsible for the heavy lifting of market
246287 data communication. Java 11 or higher is required to use this class."""
247288
248289 def __init__ (self , port : int = 11000 , timeout : Optional [float ] = 60 , launch : bool = True , jvm_mem : int = 0 ,
249290 username : str = "default" , passwd : str = "default" , auto_update : bool = True , use_bundle : bool = True ,
250- host : str = "localhost " , streaming_port : int = 10000 , stable : bool = True ):
291+ host : str = "127.0.0.1 " , streaming_port : int = 10000 , stable : bool = True ):
251292 """Construct a client instance to interface with market data. If no username and passwd fields are provided,
252293 the terminal will connect to thetadata servers with free data permissions.
253294
@@ -683,7 +724,7 @@ def get_hist_option_REST(
683724 end_fmt = _format_date (date_range .end )
684725 right_fmt = right .value
685726 use_rth_fmt = str (use_rth ).lower ()
686- url = f"http://localhost :25510/hist/option/{ req_fmt } "
727+ url = f"http://127.0.0.1 :25510/hist/option/{ req_fmt } "
687728 querystring = {"root" : root , "start_date" : start_fmt , "end_date" : end_fmt ,
688729 "strike" : strike_fmt , "exp" : exp_fmt , "right" : right_fmt ,
689730 "ivl" : interval_size , "rth" : use_rth_fmt }
@@ -774,7 +815,7 @@ def get_opt_at_time_REST(
774815 end_fmt = _format_date (date_range .end )
775816 right_fmt = right .value
776817
777- url = f"http://localhost :25510/at_time/option/{ req_fmt } "
818+ url = f"http://127.0.0.1 :25510/at_time/option/{ req_fmt } "
778819 querystring = {"root" : root , "start_date" : start_fmt , "end_date" : end_fmt , "strike" : strike_fmt ,
779820 "exp" : exp_fmt , "right" : right_fmt , "ivl" : ms_of_day }
780821 response = requests .get (url , params = querystring )
@@ -842,7 +883,7 @@ def get_stk_at_time_REST(
842883 start_fmt = _format_date (date_range .start )
843884 end_fmt = _format_date (date_range .end )
844885
845- url = f"http://localhost :25510/at_time/stock/{ req_fmt } "
886+ url = f"http://127.0.0.1 :25510/at_time/stock/{ req_fmt } "
846887 querystring = {"root" : root_fmt , "start_date" : start_fmt ,
847888 "end_date" : end_fmt , "ivl" : ms_of_day }
848889 response = requests .get (url , params = querystring )
@@ -916,7 +957,7 @@ def get_hist_stock_REST(
916957 start_fmt = _format_date (date_range .start )
917958 end_fmt = _format_date (date_range .end )
918959 use_rth_fmt = str (use_rth ).lower ()
919- url = f"http://localhost :25510/hist/stock/{ req_fmt } "
960+ url = f"http://127.0.0.1 :25510/hist/stock/{ req_fmt } "
920961 params = {"root" : root , "start_date" : start_fmt , "end_date" : end_fmt ,
921962 "ivl" : interval_size , "rth" : use_rth_fmt }
922963 response = requests .get (url , params = params )
@@ -956,7 +997,7 @@ def get_dates_stk_REST(self, root: str, req: StockReqType) -> pd.Series:
956997 """
957998 root_fmt = root .lower ()
958999 req_fmt = req .name .lower ()
959- url = f"http://localhost :25510/list/dates/stock/{ req_fmt } "
1000+ url = f"http://127.0.0.1 :25510/list/dates/stock/{ req_fmt } "
9601001 params = {'root' : root_fmt }
9611002 response = requests .get (url , params = params )
9621003 series = parse_list_REST (response , dates = True )
@@ -1016,7 +1057,7 @@ def get_dates_opt_REST(
10161057 strike_fmt = _format_strike (strike )
10171058 right = right .value
10181059 sec = SecType .OPTION .value .lower ()
1019- url = f"http://localhost :25510/list/dates/{ sec } /{ req } "
1060+ url = f"http://127.0.0.1 :25510/list/dates/{ sec } /{ req } "
10201061 params = {'root' : root , 'exp' : exp_fmt , 'strike' : strike_fmt , 'right' : right }
10211062 response = requests .get (url , params = params )
10221063 df = parse_list_REST (response , dates = True )
@@ -1067,7 +1108,7 @@ def get_dates_opt_bulk_REST(
10671108 req = req .name .lower ()
10681109 exp_fmt = _format_date (exp )
10691110 sec = SecType .OPTION .value .lower ()
1070- url = f"http://localhost :25510/list/dates/{ sec } /{ req } "
1111+ url = f"http://127.0.0.1 :25510/list/dates/{ sec } /{ req } "
10711112 params = {'root' : root , 'exp' : exp_fmt }
10721113 response = requests .get (url , params = params )
10731114 df = parse_list_REST (response , dates = True )
@@ -1100,7 +1141,7 @@ def get_expirations_REST(self, root: str) -> pd.Series:
11001141 :raises ResponseError: If the request failed.
11011142 :raises NoData: If there is no data available for the request.
11021143 """
1103- url = "http://localhost :25510/list/expirations"
1144+ url = "http://127.0.0.1 :25510/list/expirations"
11041145 params = {"root" : root }
11051146 response = requests .get (url , params = params )
11061147 df = parse_list_REST (response )
@@ -1164,7 +1205,7 @@ def get_strikes_REST(self, root: str, exp: date, date_range: DateRange = None,)
11641205 querystring = {"root" : root_fmt , "exp" : exp_fmt }
11651206 else :
11661207 querystring = {"root" : root_fmt , "exp" : exp_fmt }
1167- url = "http://localhost :25510/list/strikes"
1208+ url = "http://127.0.0.1 :25510/list/strikes"
11681209 response = requests .get (url , params = querystring )
11691210 ser = parse_list_REST (response )
11701211 ser = ser .divide (1000 )
@@ -1197,7 +1238,7 @@ def get_roots_REST(self, sec: SecType) -> pd.Series:
11971238 :raises ResponseError: If the request failed.
11981239 :raises NoData: If there is no data available for the request.
11991240 """
1200- url = "http://localhost :25510/list/roots"
1241+ url = "http://127.0.0.1 :25510/list/roots"
12011242 params = {'sec' : sec .value }
12021243 response = requests .get (url , params = params )
12031244 df = parse_list_REST (response )
@@ -1269,7 +1310,7 @@ def get_last_option_REST(
12691310 strike_fmt = _format_strike (strike )
12701311 exp_fmt = _format_date (exp )
12711312
1272- url = f"http://localhost :25510/snapshot/option/{ req_fmt } "
1313+ url = f"http://127.0.0.1 :25510/snapshot/option/{ req_fmt } "
12731314 querystring = {"root" : root_fmt , "strike" : strike_fmt , "exp" : exp_fmt , "right" : right_fmt }
12741315 response = requests .get (url , params = querystring )
12751316 df = parse_flexible_REST (response )
@@ -1324,7 +1365,7 @@ def get_last_stock_REST(
13241365 root_fmt = root .lower ()
13251366 req_fmt = req .name .lower ()
13261367
1327- url = f"http://localhost :25510/snapshot/option/{ req_fmt } "
1368+ url = f"http://127.0.0.1 :25510/snapshot/option/{ req_fmt } "
13281369 querystring = {"root" : root_fmt }
13291370 response = requests .get (url , params = querystring )
13301371 df = parse_flexible_REST (response )
0 commit comments