2
2
import logging
3
3
import pandas as pd
4
4
5
- import requests
6
- import logging
7
- import pandas as pd
8
-
9
5
10
6
class ThetaDataStocksHistorical :
11
7
def __init__ (self , log_level : int = logging .WARNING , use_df : bool = False ) -> None :
8
+ """
9
+ Initialize the ThetaDataStocksHistorical class.
10
+
11
+ Parameters:
12
+ log_level (int): The logging level to use. Defaults to logging.WARNING.
13
+ use_df (bool): Whether to return results as pandas DataFrames. Defaults to False.
14
+
15
+ This constructor sets up logging and initializes the use_df attribute.
16
+ """
12
17
self .use_df = use_df
13
18
14
19
# Configure logging
@@ -29,6 +34,20 @@ def __init__(self, enable_logging: bool = False, use_df: bool = True) -> None:
29
34
self .logger = logging .getLogger (__name__ )
30
35
31
36
def send_request (self , endpoint : str , params : dict ) -> dict | None :
37
+ """
38
+ Send a GET request to the specified endpoint with the given parameters.
39
+
40
+ Args:
41
+ endpoint (str): The API endpoint to send the request to.
42
+ params (dict): A dictionary of query parameters to include in the request.
43
+
44
+ Returns:
45
+ dict | None: The JSON response from the API if successful, or None if an error occurs.
46
+
47
+ This method handles the HTTP request, logging, and error handling for all API calls.
48
+ It uses a base URL of 'http://127.0.0.1:25510'.
49
+ If logging is enabled, it logs the request details and the outcome of the request.
50
+ """
32
51
url = f"http://127.0.0.1:25510{ endpoint } "
33
52
headers = {"Accept" : "application/json" }
34
53
response = None
@@ -52,6 +71,36 @@ def send_request(self, endpoint: str, params: dict) -> dict | None:
52
71
def get_eod_report (
53
72
self , symbol : str , start_date : str , end_date : str
54
73
) -> pd .DataFrame | dict | None :
74
+ """
75
+ Get end-of-day report for a given symbol and date range.
76
+
77
+ The returned data includes the following columns:
78
+ - ms_of_day: Milliseconds since midnight for the start of the interval
79
+ - ms_of_day2: Milliseconds since midnight for the end of the interval
80
+ - open: Opening price for the interval
81
+ - high: Highest price during the interval
82
+ - low: Lowest price during the interval
83
+ - close: Closing price for the interval
84
+ - volume: Total trading volume during the interval
85
+ - count: Number of trades during the interval
86
+ - bid_size: Size of the best bid
87
+ - bid_exchange: Exchange code for the best bid
88
+ - bid: Best bid price
89
+ - bid_condition: Condition code for the best bid
90
+ - ask_size: Size of the best ask
91
+ - ask_exchange: Exchange code for the best ask
92
+ - ask: Best ask price
93
+ - ask_condition: Condition code for the best ask
94
+ - date: Date of the data point
95
+
96
+ Args:
97
+ symbol (str): The stock symbol
98
+ start_date (str): Start date in 'YYYYMMDD' format
99
+ end_date (str): End date in 'YYYYMMDD' format
100
+
101
+ Returns:
102
+ pd.DataFrame | dict | None: DataFrame or dict of EOD data, or None if request fails
103
+ """
55
104
# Check if dates have the correct format
56
105
if not (
57
106
self ._is_valid_date_format (start_date )
@@ -84,6 +133,30 @@ def _is_valid_date_format(self, date_string: str) -> bool:
84
133
def get_quotes (
85
134
self , symbol : str , start_date : str , end_date : str , interval : str = "900000"
86
135
) -> pd .DataFrame | dict | None :
136
+ """
137
+ Get quotes for a given symbol and date range.
138
+
139
+ The returned data includes the following columns:
140
+ - ms_of_day: Milliseconds since midnight
141
+ - bid_size: Size of the best bid
142
+ - bid_exchange: Exchange code for the best bid
143
+ - bid: Best bid price
144
+ - bid_condition: Condition code for the best bid
145
+ - ask_size: Size of the best ask
146
+ - ask_exchange: Exchange code for the best ask
147
+ - ask: Best ask price
148
+ - ask_condition: Condition code for the best ask
149
+ - date: Date of the data point
150
+
151
+ Args:
152
+ symbol (str): The stock symbol
153
+ start_date (str): Start date in 'YYYYMMDD' format
154
+ end_date (str): End date in 'YYYYMMDD' format
155
+ interval (str): Interval in milliseconds (default: "900000")
156
+
157
+ Returns:
158
+ pd.DataFrame | dict | None: DataFrame or dict of quote data, or None if request fails
159
+ """
87
160
if self .enable_logging :
88
161
self .logger .info (
89
162
f"Getting quotes for { symbol } from { start_date } to { end_date } "
@@ -107,6 +180,28 @@ def get_quotes(
107
180
def get_ohlc (
108
181
self , symbol : str , start_date : str , end_date : str , interval : str = "900000"
109
182
) -> pd .DataFrame | dict | None :
183
+ """
184
+ Get OHLC (Open, High, Low, Close) data for a given symbol and date range.
185
+
186
+ The returned data includes the following columns:
187
+ - ms_of_day: Milliseconds since midnight
188
+ - open: Opening price
189
+ - high: Highest price
190
+ - low: Lowest price
191
+ - close: Closing price
192
+ - volume: Trading volume
193
+ - count: Number of trades
194
+ - date: Date of the data point
195
+
196
+ Args:
197
+ symbol (str): The stock symbol
198
+ start_date (str): Start date in 'YYYYMMDD' format
199
+ end_date (str): End date in 'YYYYMMDD' format
200
+ interval (str): Interval in milliseconds (default: "900000")
201
+
202
+ Returns:
203
+ pd.DataFrame | dict | None: DataFrame or dict of OHLC data, or None if request fails
204
+ """
110
205
if self .enable_logging :
111
206
self .logger .info (
112
207
f"Getting OHLC for { symbol } from { start_date } to { end_date } "
@@ -121,7 +216,16 @@ def get_ohlc(
121
216
response = self .send_request (endpoint , params )
122
217
123
218
if response and self .use_df :
124
- columns = response ["header" ]["format" ]
219
+ columns = [
220
+ "ms_of_day" ,
221
+ "open" ,
222
+ "high" ,
223
+ "low" ,
224
+ "close" ,
225
+ "volume" ,
226
+ "count" ,
227
+ "date" ,
228
+ ]
125
229
data = response ["response" ]
126
230
return pd .DataFrame (data , columns = columns )
127
231
else :
@@ -130,6 +234,34 @@ def get_ohlc(
130
234
def get_trades (
131
235
self , symbol : str , start_date : str , end_date : str
132
236
) -> pd .DataFrame | dict | None :
237
+ """
238
+ Get historical trade data for a given symbol and date range.
239
+
240
+ The returned data includes the following columns:
241
+ - ms_of_day: Milliseconds since midnight
242
+ - sequence: Sequence number of the trade
243
+ - ext_condition1: Extended trading condition 1
244
+ - ext_condition2: Extended trading condition 2
245
+ - ext_condition3: Extended trading condition 3
246
+ - ext_condition4: Extended trading condition 4
247
+ - condition: Trading condition
248
+ - size: Trade size
249
+ - exchange: Exchange where the trade occurred
250
+ - price: Trade price
251
+ - condition_flags: Condition flags
252
+ - price_flags: Price flags
253
+ - volume_type: Volume type
254
+ - records_back: Number of records back
255
+ - date: Date of the trade
256
+
257
+ Args:
258
+ symbol (str): The stock symbol
259
+ start_date (str): Start date in 'YYYYMMDD' format
260
+ end_date (str): End date in 'YYYYMMDD' format
261
+
262
+ Returns:
263
+ pd.DataFrame | dict | None: DataFrame or dict of trade data, or None if request fails
264
+ """
133
265
if self .enable_logging :
134
266
self .logger .info (
135
267
f"Getting trades for { symbol } from { start_date } to { end_date } "
@@ -152,6 +284,43 @@ def get_trades(
152
284
def get_trade_quote (
153
285
self , symbol : str , start_date : str , end_date : str
154
286
) -> pd .DataFrame | dict | None :
287
+ """
288
+ Get historical trade and quote data for a given symbol and date range.
289
+
290
+ The returned data includes the following columns:
291
+ - ms_of_day: Milliseconds since midnight for the trade
292
+ - sequence: Sequence number of the trade
293
+ - ext_condition1: Extended trading condition 1
294
+ - ext_condition2: Extended trading condition 2
295
+ - ext_condition3: Extended trading condition 3
296
+ - ext_condition4: Extended trading condition 4
297
+ - condition: Trading condition
298
+ - size: Trade size
299
+ - exchange: Exchange where the trade occurred
300
+ - price: Trade price
301
+ - condition_flags: Condition flags
302
+ - price_flags: Price flags
303
+ - volume_type: Volume type
304
+ - records_back: Number of records back
305
+ - ms_of_day2: Milliseconds since midnight for the quote
306
+ - bid_size: Size of the NBBO bid
307
+ - bid_exchange: Exchange of the NBBO bid
308
+ - bid: NBBO bid price
309
+ - bid_condition: Condition of the NBBO bid
310
+ - ask_size: Size of the NBBO ask
311
+ - ask_exchange: Exchange of the NBBO ask
312
+ - ask: NBBO ask price
313
+ - ask_condition: Condition of the NBBO ask
314
+ - date: Date of the trade and quote
315
+
316
+ Args:
317
+ symbol (str): The stock symbol
318
+ start_date (str): Start date in 'YYYYMMDD' format
319
+ end_date (str): End date in 'YYYYMMDD' format
320
+
321
+ Returns:
322
+ pd.DataFrame | dict | None: DataFrame or dict of trade and quote data, or None if request fails
323
+ """
155
324
if self .enable_logging :
156
325
self .logger .info (
157
326
f"Getting trade quotes for { symbol } from { start_date } to { end_date } "
@@ -174,6 +343,24 @@ def get_trade_quote(
174
343
def get_splits (
175
344
self , symbol : str , start_date : str , end_date : str
176
345
) -> pd .DataFrame | dict | None :
346
+ """
347
+ Get stock split data for a given symbol and date range.
348
+
349
+ The returned data includes the following columns:
350
+ - ms_of_day: Milliseconds since midnight
351
+ - split_date: Date of the stock split
352
+ - before_shares: Number of shares before the split
353
+ - after_shares: Number of shares after the split
354
+ - date: Date of the record
355
+
356
+ Args:
357
+ symbol (str): The stock symbol
358
+ start_date (str): Start date in 'YYYYMMDD' format
359
+ end_date (str): End date in 'YYYYMMDD' format
360
+
361
+ Returns:
362
+ pd.DataFrame | dict | None: DataFrame or dict of stock split data, or None if request fails
363
+ """
177
364
if self .enable_logging :
178
365
self .logger .info (
179
366
f"Getting splits for { symbol } from { start_date } to { end_date } "
@@ -196,6 +383,28 @@ def get_splits(
196
383
def get_dividends (
197
384
self , symbol : str , start_date : str , end_date : str
198
385
) -> pd .DataFrame | dict | None :
386
+ """
387
+ Get dividend data for a given symbol and date range.
388
+
389
+ The returned data includes the following columns:
390
+ - ms_of_day: Milliseconds since midnight
391
+ - ex_date: Ex-dividend date
392
+ - record_date: Record date for the dividend
393
+ - payment_date: Date when the dividend is paid
394
+ - ann_date: Announcement date of the dividend
395
+ - dividend_amount: Amount of the dividend
396
+ - undefined: Undefined column
397
+ - less_amount: Less amount (if applicable)
398
+ - date: Date of the record
399
+
400
+ Args:
401
+ symbol (str): The stock symbol
402
+ start_date (str): Start date in 'YYYYMMDD' format
403
+ end_date (str): End date in 'YYYYMMDD' format
404
+
405
+ Returns:
406
+ pd.DataFrame | dict | None: DataFrame or dict of dividend data, or None if request fails
407
+ """
199
408
if self .enable_logging :
200
409
self .logger .info (
201
410
f"Getting dividends for { symbol } from { start_date } to { end_date } "
@@ -220,7 +429,7 @@ def get_dividends(
220
429
221
430
if __name__ == "__main__" :
222
431
# Toggle example cases
223
- run_apple_eod_example = False
432
+ run_apple_eod_example = False
224
433
run_microsoft_quotes_example = False
225
434
run_google_ohlc_example = False
226
435
run_tesla_trades_example = False
@@ -284,7 +493,9 @@ def get_dividends(
284
493
285
494
# Example 5: Get trade quotes for AMZN
286
495
if run_amazon_trade_quote_example :
287
- amazon_trade_quotes = historical_data .get_trade_quote ("AMZN" , "20240101" , "20240102" )
496
+ amazon_trade_quotes = historical_data .get_trade_quote (
497
+ "AMZN" , "20240101" , "20240102"
498
+ )
288
499
if amazon_trade_quotes is None :
289
500
historical_data .logger .warning ("Failed to get Amazon Trade Quotes data" )
290
501
elif amazon_trade_quotes .empty :
0 commit comments