ВЫГРУЗКА ДАННЫХ С БИРЖИ BINANCE
Для обучения сетей и бэктеста нам потребуется исторические данные по разным инструментам. Конечно все эти данные можно найти и скачать в открытом доступе, так же на github можно найти множество различных грабберов для сбора этих данных с разных бирж. Можно не изобретать велосипед, а можно изобрести, так что пишем свой класс для сбора данных.
Что должно быть на выходе ? На выходе я хочу вызвать метод, передать в него: тип, инструмент, таймфрейм и интервал с и по какие даты и время собрать инфу. И в последствии выполнения должен сформироваться csv файл, с которым в дальнейшем я смогу работать.
Создадим новый файл LoadHistory.py и подключим нужные библиотеки
LoadHistory.pyimport json import math import pandas as pd import requests import time from datetime import datetime
Создадим класс с конструктором и пропишем в нем некие константы с которыми будем взаимодействовать
class LoadHistoryData: # ТИП: Спот или Фьючерсы MARKET = { "SPOT": "https://api.binance.com/api/v3", "FUTURE": "https://fapi.binance.com/fapi/v1" } # ТАЙМФРЕЙМ TF = { "1m": 1, "5m": 5, "15m": 15, "30m": 30, "1h": 60, "4h": 240, "1d": 1440 } # Переменные для работы _limit = None _limit_max = None _request_count = None _market = None _t_d, _f_d = None, None _t, _f, _tf, _sym = None, None, None, None def __init__(self): pass # Функция загрузки данных def load(self): pass
Наполним конструктор смысловой нагрузкой. При создании класса будем передавать тип, это может быть либо фьючерсный рынок либо спотовый, полное наименование инструмента, таймфрейм, дата и время начала и окончания данных.
def __init__(self, market, sym, tf, f, t): self._sym = sym self._tf = tf self._market = market # Максимальное кол-во баров у спота и фьюча разное self._limit_max = 1000 if market == 'SPOT' else 1500 # Обрабатываем и конвертируем дату начала self._t = datetime.strptime(t, '%Y-%m-%d %H:%M:%S') self._t_d = str(datetime.strftime(self._t, '_%Y%m%d_%H%M_')) self._t = int(datetime.timestamp(self._t)) # Обрабатываем и конвертируем дату окончания self._f = datetime.strptime(f, '%Y-%m-%d %H:%M:%S') self._f_d = str(datetime.strftime(self._f, '_%Y%m%d_%H%M')) self._f = int(datetime.timestamp(self._f)) # Рассчитываем кол-во баров необходимых для закрытия переданных дат self._limit = int((self._t - self._f) / (self.TF[self._tf] * 60)) # Рассчитывем кол-во запросов исходя из максимального кол-ва баров self._request_count = math.ceil(self._limit / self._limit_max)
Так же напишем код для основного метода загрузки
def load(self): payload={} headers = {'Content-Type': 'application/json'} data = list() cur_limit = self._limit_max if self._request_count > 1 else self._limit cur_f = self._f cur_t = self._f + cur_limit * (self.TF[self._tf] * 60) for r in range(0, self._request_count): url = "{}/klines?symbol={}&interval={}&limit={}&startTime={}&endTime={}".format( self.MARKET[self._market], self._sym, self._tf, cur_limit, "{}000".format(cur_f), "{}000".format(cur_t) ) self._limit -= self._limit_max cur_limit = cur_limit if self._limit >= self._limit_max else self._limit cur_f = cur_t cur_t = cur_t + cur_limit * (self.TF[self._tf] * 60) response = requests.request("GET", url, headers=headers, data=payload) if response.status_code == 200: d = json.loads(response.text) data.extend(d) # Сделаем паузу, чтобы не грузить биржу time.sleep(1.5) # Произведем постобработку списка for item in data: item[0] = int(str(item[0])[:-3]) item.pop(11) item.pop(6) # Создадим датафрейм и присвоим имена колонок df = pd.DataFrame(data, columns=[ 'Open time', 'Open', 'High', 'Low', 'Close', 'Volume', 'Quote asset volume', 'Number of trades', 'Taker buy base asset volume', 'Taker buy quote asset volume' ]) # Сформируем имя для csv файла и сохраним его nafullnameme = self._market[:-5] + '_' + self._sym + '_' + self._tf + '_' + self._f_d + '_' + self._t_d + '.csv' df.to_csv(nafullnameme, index=False)
Наш класс выгрузки данных готов! У вас должен получиться следующий код
import json import math import pandas as pd import requests import time from datetime import datetime class LoadHistoryData: # ТИП: Спот или Фьючерсы MARKET = { "SPOT": "https://api.binance.com/api/v3", "FUTURE": "https://fapi.binance.com/fapi/v1" } # ТАЙМФРЕЙМ TF = { "1m": 1, "5m": 5, "15m": 15, "30m": 30, "1h": 60, "4h": 240, "1d": 1440 } # Переменные для работы _limit = None _limit_max = None _request_count = None _market = None _t_d, _f_d = None, None _t, _f, _tf, _sym = None, None, None, None def __init__(self, market, sym, tf, f, t): self._sym = sym self._tf = tf self._market = market # Максимальное кол-во баров у спота и фьюча разное self._limit_max = 1000 if market == 'SPOT' else 1500 # Обрабатываем и конвертируем дату начала self._t = datetime.strptime(t, '%Y-%m-%d %H:%M:%S') self._t_d = str(datetime.strftime(self._t, '_%Y%m%d_%H%M_')) self._t = int(datetime.timestamp(self._t)) # Обрабатываем и конвертируем дату окончания self._f = datetime.strptime(f, '%Y-%m-%d %H:%M:%S') self._f_d = str(datetime.strftime(self._f, '_%Y%m%d_%H%M')) self._f = int(datetime.timestamp(self._f)) # Рассчитываем кол-во баров необходимых для закрытия переданных дат self._limit = int((self._t - self._f) / (self.TF[self._tf] * 60)) # Рассчитывем кол-во запросов исходя из максимального кол-ва баров self._request_count = math.ceil(self._limit / self._limit_max) # Функция загрузки данных def load(self): payload={} headers = {'Content-Type': 'application/json'} data = list() cur_limit = self._limit_max if self._request_count > 1 else self._limit cur_f = self._f cur_t = self._f + cur_limit * (self.TF[self._tf] * 60) for r in range(0, self._request_count): url = "{}/klines?symbol={}&interval={}&limit={}&startTime={}&endTime={}".format( self.MARKET[self._market], self._sym, self._tf, cur_limit, "{}000".format(cur_f), "{}000".format(cur_t) ) self._limit -= self._limit_max cur_limit = cur_limit if self._limit >= self._limit_max else self._limit cur_f = cur_t cur_t = cur_t + cur_limit * (self.TF[self._tf] * 60) response = requests.request("GET", url, headers=headers, data=payload) if response.status_code == 200: d = json.loads(response.text) data.extend(d) # Сделаем паузу, чтобы не грузить биржу time.sleep(1.5) # Произведем постобработку списка for item in data: item[0] = int(str(item[0])[:-3]) item.pop(11) item.pop(6) # Создадим датафрейм и присвоим имена колонок df = pd.DataFrame(data, columns=[ 'Open time', 'Open', 'High', 'Low', 'Close', 'Volume', 'Quote asset volume', 'Number of trades', 'Taker buy base asset volume', 'Taker buy quote asset volume' ]) # Сформируем имя для csv файла и сохраним его nafullnameme = self._market[:1] + '_' + self._sym + '_' + self._tf + '_' + self._f_d + '_' + self._t_d + '.csv' df.to_csv(nafullnameme, index=False)
Теперь, когда все готово, можно опробовать, что у нас получилось
market='SPOT' sym = 'BTCUSDT' tf = '1h' f = '2020-01-01 00:00:00' t = '2021-12-31 23:59:59' history = LoadHistoryData(market, sym, tf, f, t) history.load()
Наш скрипт сделает рассчеты и выполнит нужное кол-во запросов к бирже, за процессом можно наблюдать в консоле
В конце процесса в вашей папке сформируется csv файл
Откроем его и убедимся что все данные загружены. Сам вывод может отличаться от моего, в зависимости от вашего редактора кода и установленных модулей
На этом все! В следующих статьях с помощью данного класса мы будем формировать себе датасеты для обучения своих сететей.