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
| import os
import datetime
import pytz
import pandas as pd
import ccxt
import click
from dateutil.relativedelta import relativedelta
from pathlib import Path
exchange = ccxt.binance(
{
"enableRateLimit": True, # 必须开启!防止被交易所封IP
"timeout": 15000 # 超时设为15秒
"proxies": {
"http": os.getenv("http_proxy"),
"https": os.getenv("https_proxy"),
}
}
)
def download(symbol: str, start=None, end=None, timeframe="1d", save_dir="."):
if end is None:
end = datetime.datetime.now(pytz.UTC)
else:
end = end.replace(tzinfo=pytz.UTC)
if start is None:
start = end - relativedelta(years=3)
else:
start = start.replace(tzinfo=pytz.UTC)
max_limit = 1000
since = start.timestamp()
end_time = int(end.timestamp() * 1e3)
# Create save directory if it doesn't exist
Path(save_dir).mkdir(parents=True, exist_ok=True)
absolute_path = os.path.join(
save_dir, f"{symbol.replace('/', '-')}_{timeframe}.csv"
)
ohlcvs = []
while True:
new_ohlcvs = exchange.fetch_ohlcv(
symbol, since=int(since * 1e3), timeframe=timeframe, limit=max_limit, params={"endTime": end_time }
)
if len(new_ohlcvs) == 0:
break
ohlcvs += new_ohlcvs
since = ohlcvs[-1][0]/1e3 + 1
print(f"下载进度:{datetime.datetime.fromtimestamp(ohlcvs[-1][0]/1e3)}\r", end="")
print()
data = pd.DataFrame(
ohlcvs, columns=["timestamp_ms", "open", "high", "low", "close", "volume"]
)
data.drop_duplicates(inplace=True)
data.set_index(
pd.DatetimeIndex(pd.to_datetime(data["timestamp_ms"], unit="ms", utc=True)),
inplace=True,
)
data.index.name = "datetime"
del data["timestamp_ms"]
data.to_csv(absolute_path)
print(f"Data saved to: {absolute_path}")
@click.command()
@click.option("--symbol", required=True, help="Trading symbol (e.g. BTC/USDT)")
@click.option("--start", type=click.DateTime(), help="Start date (YYYY-MM-DD)")
@click.option("--end", type=click.DateTime(), help="End date (YYYY-MM-DD)")
@click.option("--timeframe", default="1d", help="Timeframe for OHLCV data (1m, 5m, 15m, 1h, 1d, etc.)")
@click.option("--save-dir", default=".", help="Directory to save the CSV file")
def main(symbol, start, end, timeframe, save_dir):
"""Download OHLCV data from Binance"""
download(symbol=symbol, start=start, end=end, timeframe=timeframe, save_dir=save_dir)
if __name__ == "__main__":
main()
|