Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
AI4Finance-Foundation
GitHub Repository: AI4Finance-Foundation/FinRL
Path: blob/master/finrl/meta/preprocessor/ibkrdownloader.py
732 views
1
"""Contains methods and classes to collect data from
2
interactive broker API
3
"""
4
5
from __future__ import annotations
6
7
import math
8
from datetime import datetime
9
10
import pandas as pd
11
from ib_insync import *
12
13
14
class ibkrdownloader:
15
"""Provides methods for retrieving daily stock data from
16
IBKR API
17
18
Attributes
19
----------
20
start_date : str
21
start date of the data (modified from neofinrl_config.py)
22
end_date : str
23
end date of the data (modified from neofinrl_config.py)
24
ticker_list : list
25
a list of stock tickers (modified from neofinrl_config.py)
26
interval: str
27
ime period of one bar. Must be one of:
28
'1 secs', '5 secs', '10 secs' 15 secs', '30 secs',
29
'1 min', '2 mins', '3 mins', '5 mins', '10 mins', '15 mins',
30
'20 mins', '30 mins',
31
'1 hour', '2 hours', '3 hours', '4 hours', '8 hours',
32
'1 day', '1 week', '1 month'.
33
34
Methods
35
-------
36
fetch_data()
37
Fetches data from IBKR API
38
"""
39
40
def __init__(
41
self,
42
start_date: str,
43
end_date: str,
44
ticker_list: list,
45
interval="1 day",
46
host="127.0.0.1",
47
port=7497,
48
clientId=999,
49
) -> None:
50
self.start_date = start_date
51
self.end_date = end_date
52
self.ticker_list = ticker_list
53
self.interval = interval
54
self.host = host
55
self.port = port
56
self.clientId = clientId
57
58
def createContract(self, ticker):
59
contract = Stock(ticker, "SMART", "USD")
60
return contract
61
62
def connect2ibkr(self):
63
self.ib = IB()
64
self.ib.connect(self.host, self.port, clientId=self.clientId)
65
66
def calculate_duration(self, start_date_str, end_date_str):
67
start_date = datetime.strptime(start_date_str, "%Y-%m-%d")
68
end_date = datetime.strptime(end_date_str, "%Y-%m-%d")
69
70
duration_days = (end_date - start_date).days
71
72
return duration_days
73
74
def fetch_data(self) -> pd.DataFrame:
75
"""Fetches data from IBKR API
76
Parameters
77
----------
78
79
Returns
80
-------
81
`pd.DataFrame`
82
7 columns: A date, open, high, low, close, volume and tick symbol
83
for the specified stock ticker
84
"""
85
# Download and save the data in a pandas DataFrame:
86
self.connect2ibkr()
87
data_df = pd.DataFrame()
88
duration = self.calculate_duration(self.start_date, self.end_date)
89
if duration > 365:
90
duration = f"{math.ceil(duration / 365)} Y"
91
else:
92
duration = f"{duration} D"
93
94
end_date_time = datetime.strptime(self.end_date, "%Y-%m-%d")
95
for tic in self.ticker_list:
96
contract = self.createContract(tic)
97
self.ib.qualifyContracts(contract)
98
bars = self.ib.reqHistoricalData(
99
contract,
100
endDateTime=end_date_time,
101
durationStr=duration,
102
barSizeSetting=self.interval,
103
whatToShow="TRADES",
104
useRTH=False,
105
formatDate=1,
106
)
107
temp_df = util.df(bars)
108
print(f"************* {tic} *************")
109
temp_df["tic"] = [tic] * len(temp_df)
110
data_df = pd.concat([data_df, temp_df], ignore_index=True)
111
data_df = data_df[["date", "open", "high", "low", "close", "volume", "tic"]]
112
filter_df = data_df[data_df["date"] > pd.Timestamp(self.start_date).date()]
113
filter_df = filter_df.sort_values(by=["date", "tic"])
114
filter_df.index = filter_df["date"].factorize()[0]
115
116
self.disconnect()
117
return filter_df
118
119
def disconnect(self):
120
self.ib.disconnect()
121
122
def select_equal_rows_stock(self, df):
123
df_check = df.tic.value_counts()
124
df_check = pd.DataFrame(df_check).reset_index()
125
df_check.columns = ["tic", "counts"]
126
mean_df = df_check.counts.mean()
127
equal_list = list(df.tic.value_counts() >= mean_df)
128
names = df.tic.value_counts().index
129
select_stocks_list = list(names[equal_list])
130
df = df[df.tic.isin(select_stocks_list)]
131
return df
132
133
134
if __name__ == "__main__":
135
intr = ibkrdownloader(
136
"2023-01-01", "2023-04-12", ["AAPL", "MSFT", "CSCO", "WMT", "TSLA"]
137
)
138
try:
139
df = intr.fetch_data()
140
df.to_csv("data.csv", index=False)
141
except:
142
intr.disconnect()
143
144
intr.disconnect()
145
146