forked from 51bitquant/howtrader
-
Notifications
You must be signed in to change notification settings - Fork 0
/
crawl_data.py
230 lines (182 loc) · 7.58 KB
/
crawl_data.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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
"""
use the binance api to crawl data then save into the sqlite database.
"""
import pandas as pd
import time
from datetime import datetime
import requests
import pytz
from howtrader.trader.database import get_database, BaseDatabase
from howtrader.trader.object import BarData, Interval, Exchange
from tzlocal import get_localzone_name
from threading import Thread
pd.set_option('expand_frame_repr', False)
BINANCE_SPOT_LIMIT = 1000
BINANCE_FUTURE_LIMIT = 1500
LOCAL_TZ = pytz.timezone(get_localzone_name())
database: BaseDatabase = get_database()
def generate_datetime(timestamp: float) -> datetime:
"""
:param timestamp:
:return:
"""
dt = datetime.fromtimestamp(timestamp / 1000)
dt = LOCAL_TZ.localize(dt)
return dt
def get_binance_data(symbol: str, exchange: str, start_time: str, end_time: str):
"""
crawl binance exchange data
:param symbol: BTCUSDT.
:param exchange: spot、usdt_future, inverse_future.
:param start_time: format :2020-1-1 or 2020-01-01 year-month-day
:param end_time: format: 2020-1-1 or 2020-01-01 year-month-day
:param gate_way the gateway name for binance is:BINANCE_SPOT, BINANCE_USDT, BINANCE_INVERSE
:return:
"""
api_url = ''
save_symbol = symbol
gateway = "BINANCE_USDT"
if exchange == 'spot':
print("spot")
limit = BINANCE_SPOT_LIMIT
save_symbol = symbol.lower()
gateway = 'BINANCE_SPOT'
api_url = f'https://api.binance.com/api/v3/klines?symbol={symbol}&interval=1m&limit={limit}'
elif exchange == 'usdt_future':
print('usdt_future')
limit = BINANCE_FUTURE_LIMIT
gateway = "BINANCE_USDT"
api_url = f'https://fapi.binance.com/fapi/v1/klines?symbol={symbol}&interval=1m&limit={limit}'
elif exchange == 'inverse_future':
print("inverse_future")
limit = BINANCE_FUTURE_LIMIT
gateway = "BINANCE_INVERSE"
f'https://dapi.binance.com/dapi/v1/klines?symbol={symbol}&interval=1m&limit={limit}'
else:
raise Exception('the exchange name should be one of :spot, usdt_future, inverse_future')
start_time = int(datetime.strptime(start_time, '%Y-%m-%d').timestamp() * 1000)
end_time = int(datetime.strptime(end_time, '%Y-%m-%d').timestamp() * 1000)
while True:
try:
print(start_time)
url = f'{api_url}&startTime={start_time}'
print(url)
datas = requests.get(url=url, timeout=10, proxies=proxies).json()
"""
[
[
1591258320000, // open time
"9640.7", // open price
"9642.4", // highest price
"9640.6", // lowest price
"9642.0", // close price(latest price if the kline is not close)
"206", // volume
1591258379999, // close time
"2.13660389", // turnover
48, // trade count
"119", // buy volume
"1.23424865", // buy turnover
"0" // ignore
]
"""
buf = []
for row in datas:
bar: BarData = BarData(
symbol=save_symbol,
exchange=Exchange.BINANCE,
datetime=generate_datetime(row[0]),
interval=Interval.MINUTE,
volume=float(row[5]),
turnover=float(row[7]),
open_price=float(row[1]),
high_price=float(row[2]),
low_price=float(row[3]),
close_price=float(row[4]),
gateway_name=gateway
)
buf.append(bar)
database.save_bar_data(buf)
# exit the loop, if close time is greater than the current time
if (datas[-1][0] > end_time) or datas[-1][6] >= (int(time.time() * 1000) - 60 * 1000):
break
start_time = datas[-1][0]
except Exception as error:
print(error)
time.sleep(10)
def download_spot(symbol):
"""
download binance spot data, config your start date and end date(format: year-month-day)
:return:
"""
t1 = Thread(target=get_binance_data, args=(symbol, 'spot', "2018-1-1", "2018-6-1"))
t2 = Thread(target=get_binance_data, args=(symbol, 'spot', "2018-6-1", "2018-12-1"))
t3 = Thread(target=get_binance_data, args=(symbol, 'spot', "2018-12-1", "2019-6-1"))
t4 = Thread(target=get_binance_data, args=(symbol, 'spot', "2019-6-1", "2019-12-1"))
t5 = Thread(target=get_binance_data, args=(symbol, 'spot', "2019-12-1", "2020-6-1"))
t6 = Thread(target=get_binance_data, args=(symbol, 'spot', "2020-6-1", "2020-12-1"))
t7 = Thread(target=get_binance_data, args=(symbol, 'spot', "2020-12-1", "2021-6-1"))
t8 = Thread(target=get_binance_data, args=(symbol, 'spot', "2021-6-1", "2021-12-1"))
t9 = Thread(target=get_binance_data, args=(symbol, 'spot', "2021-12-1", "2022-6-28"))
t1.start()
t2.start()
t3.start()
t4.start()
t5.start()
t6.start()
t7.start()
t8.start()
t9.start()
t1.join()
t2.join()
t3.join()
t4.join()
t5.join()
t6.join()
t7.join()
t8.join()
t9.join()
def download_future(symbol):
"""
download binance future data, config your start date and end date(format: year-month-day)
:return:
"""
t1 = Thread(target=get_binance_data, args=(symbol, 'usdt_future', "2020-1-1", "2020-6-1"))
t2 = Thread(target=get_binance_data, args=(symbol, 'usdt_future', "2020-6-1", "2020-12-1"))
t3 = Thread(target=get_binance_data, args=(symbol, 'usdt_future', "2020-12-1", "2021-6-1"))
t4 = Thread(target=get_binance_data, args=(symbol, 'usdt_future', "2021-6-1", "2021-12-1"))
t5 = Thread(target=get_binance_data, args=(symbol, 'usdt_future', "2021-12-1", "2022-6-28"))
t1.start()
t2.start()
t3.start()
t4.start()
t5.start()
t1.join()
t2.join()
t3.join()
t4.join()
t5.join()
if __name__ == '__main__':
"""
@important Note:
read the code before running it. the software crawl the binance data then save into the sqlite database.
you may need to change the start date and end date.
set the proxy_host and proxy_port: if you can directly connect to the binance exchange,
then set the proxy_host to None and proxy_port to empty string ""
you can use the command ping api.binance.com to check whether your network works
@重要提示:
如果你的网络不能直连binance.com交易所,你需要设置proxy_host 和 proxy_port, 具体的设置看你代理的主机和端口。如果能直连的话,
就设置proxy_host = None, proxy_port = ""
你可以在终端运行输入命令看看自己的网络能否连接交易所: ping api.binance.com
"""
# set your proxy_host
# 如果没有就设置为 None, 如果有就设置为你的代理主机如:127.0.0.1
proxy_host = "127.0.0.1"
# set it to your proxy_port
# 设置你的代理端口号如: 1087, 没有你修改为0,但是要保证你能访问api.binance.com这个主机。
proxy_port = 1087
proxies = None
if proxy_host and proxy_port:
proxy = f'http://{proxy_host}:{proxy_port}'
proxies = {'http': proxy, 'https': proxy}
download_future(symbol="BTCUSDT") # crawl usdt_future data. 下载合约的数据
download_spot(symbol="BTCUSDT") # crawl binance spot data.