· 4 years ago · Aug 05, 2021, 02:04 AM
1import talib
2import threading
3from binance.client import Client
4from binance import ThreadedWebsocketManager
5from binance.enums import *
6import pandas as pd
7import time
8import numpy as np
9from enum import Enum
10######################
11
12class OrderTypes(Enum):
13 market = 'MARKET'
14 profit = 'TAKE_PROFIT'
15 loss = 'STOP_LOSS'
16########################
17
18class BinanceData:
19 trade_assets = ['BTCUSDT', 'ETHUSDT', 'BNBUSDT', 'NEOUSDT', 'LTCUSDT']
20
21 def __init__(self, api_key, secret_key, **kwargs):
22 '''
23 Класс взаимодействия с биржей через rest
24 ########################################
25
26 Возможные валютные пары для торговли:
27
28 ['BTCUSDT','ETHUSDT','BNBUSDT','NEOUSDT','LTCUSDT','QTUMUSDT','ADAUSDT','XRPUSDT','EOSUSDT','IOTAUSDT','XLMUSDT','ONTUSDT',
29 'TRXUSDT','ETCUSDT','VETUSDT','LINKUSDT','WAVESUSDT','BTTUSDT','ZILUSDT','ZRXUSDT','BATUSDT','XMRUSDT','ZECUSDT','IOSTUSDT',
30 'CELRUSDT','DASHUSDT','OMGUSDT','THETAUSDT','ENJUSDT','MATICUSDT','ATOMUSDT','ONEUSDT','FTMUSDT','ALGOUSDT','DOGEUSDT','ANKRUSDT',
31 'TOMOUSDT','CHZUSDT','BANDUSDT','XTZUSDT','RENUSDT','RVNUSDT','HBARUSDT','NKNUSDT','KAVAUSDT','RLCUSDT','BCHUSDT','OGNUSDT','BTSUSDT',
32 'COTIUSDT','SOLUSDT','CHRUSDT','STMXUSDT','KNCUSDT','LRCUSDT','COMPUSDT','SCUSDT','SNXUSDT','DGBUSDT','SXPUSDT','MKRUSDT','STORJUSDT',
33 'MANAUSDT','YFIUSDT','BALUSDT','SRMUSDT','CRVUSDT','SANDUSDT','OCEANUSDT','DOTUSDT','RSRUSDT','TRBUSDT','BZRXUSDT','SUSHIUSDT','YFIIUSDT',
34 'KSMUSDT','EGLDUSDT', 'RUNEUSDT', 'UNIUSDT', 'AVAXUSDT', 'ALPHAUSDT', 'AAVEUSDT', 'NEARUSDT', 'FILUSDT', 'AKROUSDT', 'XEMUSDT', 'SKLUSDT',
35 'GRTUSDT', '1INCHUSDT', 'REEFUSDT', 'LITUSDT', 'DODOUSDT', 'LINAUSDT']
36 '''
37 self.__dict__.update(kwargs)
38
39 self.binance_client = Client(api_key, secret_key)
40 self.df = self.get_candles()
41
42 def get_candles(self):
43 '''
44 Запрашивает свечи перед началом работы,
45 для рассчета индикаторов
46
47 '''
48
49 data = []
50
51 try:
52 for asset in self.trade_assets:
53 candles = self.binance_client.get_klines(symbol=asset,
54 interval=self.time_frame)
55 close_ = list()
56 for candle in candles:
57 close_.append(candle[4])
58 data.append(close_[-self.window_size:])
59 data = list(zip(*data))
60
61 return pd.DataFrame(data,columns=self.trade_assets)
62
63 except Exception:
64 print('Ограничение биржи на количество запросов, попробуйте позже')
65
66 def make_order(self,symbol,sid,quantity=None):
67 '''
68 Открывает сделки, включая стоп-лосс и тейк-профит
69
70 '''
71
72 kwargs = {'quantity':quantity, 'symbol':symbol, 'side':side}
73 try :
74 self.binance_client.futures_create_order(**kwargs,
75 type=OrderTypes.market)
76
77 self.binance_client.futures_create_order(**kwargs,
78 type=OrderTypes.profit)
79 self.binance_client.futures_create_order(**kwargs,
80 type=OrderTypes.loss)
81
82 except Exception as e:
83 print('ошибка создания ордера:', e.__str__())
84##############################################################################
85
86class BinanceManager(BinanceData,threading.Thread):
87 lock = threading.Lock()
88
89 def __init__(self,api_key = None ,secret_key = None,**kwargs):
90 '''
91 Основной класс, подключение к сокетам
92
93 '''
94 threading.Thread.__init__(self)
95 BinanceData.__init__(self, api_key, secret_key, **kwargs)
96
97 streams = list()
98
99 for asset in self.trade_assets:
100 s = asset.lower()
101 stream = f'{s}@kline_'+self.time_frame
102 streams.append(stream)
103
104
105 binance_websocket = ThreadedWebsocketManager(api_key=api_key,
106 api_secret=secret_key)
107 binance_websocket.start()
108
109 binance_websocket.start_multiplex_socket(callback=self.call_back,
110 streams=streams)
111
112 def call_back(self,message, candle=dict()):
113 '''
114 Прием свечей с сокета
115
116 '''
117 data = message['data']
118 symbol = data['s']
119 kline = data['k']
120 is_close, close_= kline['x'], kline['c']
121
122 if len(candle) == len(self.trade_assets):
123 self.lock.acquire()
124
125 try:
126 self.df = self.df.append(candle, ignore_index = True)
127 candle.clear()
128
129 finally:
130 self.lock.release()
131
132 if is_close:
133 candle[symbol] = close_
134
135 def run(self):
136 '''
137 Логика и открытие сделок
138
139 '''
140 session_params = {'debug': True, 'alive': False,'ticker': None,
141 'quantity': None,'side': None}
142
143 time.sleep(0.1)
144
145 while True:
146 self.lock.acquire()
147
148 try:
149 self.df = self.df.tail(self.window_size)
150 self.df = self.df.reset_index(drop = True)
151
152
153 if session_params['debug']:
154 print(self.df.tail())
155 else:
156
157 for col in self.df:
158 arr = np.array(self.df[col])
159 macd, signal, hist = talib.MACD(arr.astype(float),
160 **self.macd_periods)
161
162 if session_params['alive']:
163
164 self.binance_client.futures_cancel_all_open_orders()
165 session_params['alive'] = False
166
167 else:
168
169 if hist[-2] > 0 and hist[-1] < 0:
170 print('sell',col)
171
172 self.make_order(col,'SELL')
173 session_params['alive'] = True
174
175 elif hist[-2] < 0 and hist[-1] > 0:
176 print('buy',col)
177
178 self.make_order(col,'BUY')
179 session_params['alive'] = True
180
181 finally:
182 self.lock.release()
183 time.sleep(0.1)
184
185 time.sleep(self.frame_sec)
186
187#################################################################
188
189class TradeParams:
190 INTERVALS = ['1m','3m','5m','15m','30m','1h','2h','4h','6h','8h','12h','1d','3d','1w','1M']
191 ###########################################################################################
192
193 TIMEFRAME = '1m' # Период свечей
194 FRAMEINSEC = 60.0 # Частота обновления в секундах
195 WINDOWSIZE = 40 # Количество хранящихся свечей
196 FASTPERIOD = 8 # Период быстрой скользящей
197 SLOWPERIOD = 28 # Период медленной скользящей
198 SIGNALPERIOD = 9 # Период осцилятора
199
200 assert WINDOWSIZE > max(FASTPERIOD,SLOWPERIOD,SIGNALPERIOD), 'увеличьте WINDOWSIZE'
201 assert TIMEFRAME in INTERVALS, 'выберите другой интервал'
202
203def main():
204 MACDPERIODS = {'fastperiod':TradeParams.FASTPERIOD,
205 'slowperiod':TradeParams.SLOWPERIOD,
206 'signalperiod':TradeParams.SIGNALPERIOD}
207
208 MacdBot = BinanceManager(time_frame = TradeParams.TIMEFRAME,
209 frame_sec = TradeParams.FRAMEINSEC,
210 window_size = TradeParams.WINDOWSIZE,
211 macd_periods = MACDPERIODS)
212 MacdBot.start()
213
214
215if __name__ == "__main__":
216 main()
217