class SsrmBot: def __init__(self, symbol, min_amount, API_KEY, API_SECRET): self.symbol = symbol self.api_key = API_KEY self.api_secret = API_SECRET self.bclient = Client(api_key=self.api_key, api_secret=self.api_secret) self.bot_ping = True self.rsi_signal = None self.main_data = [] self.main_data_hour = [] self.trade = 0 # self.my_bid = 0 self.my_price = 0 self.status = False self.min_amount = min_amount * 50 self.amount = 0 self.main_direction = None self.new_side = None self.order = False self.order_id = False self.order_id_tp = False self.order_id_sl = False self.my_tp = 0 self.my_sl = 0 self.my_Stoch = False self.my_RSI = False self.binance_websocket_api_manager = None def new_data_1_min(self): print("New data 1 min START:") para = self.bclient.get_historical_klines( f"{self.symbol}usdt".upper(), Client.KLINE_INTERVAL_1MINUTE, "1 day ago UTC") self.main_data = para print("================== new_data_1_min") def new_data_1_hour(self): print("New data 1 hour START:") para = self.bclient.get_historical_klines(f"{self.symbol}usdt".upper(), Client.KLINE_INTERVAL_1HOUR, "2 days ago UTC") self.main_data_hour = para print("================== new_data_1_hour") def place_new_order(self): if self.main_direction == 1: self.new_side = "LONG" else: self.new_side = "SHORT" self.order = self.main_direction reponse = Orders.my_order_future( client=self.bclient, symbol=f"{self.symbol.upper()}USDT", side=self.main_direction, amount=round(self.amount, n_rools[self.symbol.upper()]["decimals"])) if reponse['error']: self.bot_ping = False logging.info(f"New order Error:\n {reponse}") bot_sendtext(f"New order Error:\n {reponse}") else: self.order_id = reponse['result']['orderId'] logging.info(f"New order:\n {reponse}") dbrools.insert_history_new(data=reponse) time.sleep(1) my_orders = self.bclient.futures_get_order( symbol=f"{self.symbol.upper()}USDT", orderId=self.order_id) self.my_price = float(my_orders['avgPrice']) if self.order == 1: self.my_sl = self.my_price / 1.009 self.my_tp = self.my_price * 1.022 else: self.my_sl = self.my_price * 1.009 self.my_tp = self.my_price / 1.022 data = { "symbol": f"{self.symbol} ({self.new_side})", "side": f"{self.new_side}", "amount": round(self.amount, n_rools[self.symbol.upper()]["decimals"]), "price": float( round(self.my_price, n_rools[self.symbol.upper()]['price'])), "direct": 'BUY', "result": 0, "date": f"{datetime.now().strftime('%d.%m.%Y')}" } dbrools.insert_history(data=data) bot_message = f"Added {self.symbol} ({self.new_side}), \n{round(self.amount, n_rools[self.symbol.upper()]['decimals'])}, \n{round(self.my_price, n_rools[self.symbol.upper()]['price'])},\n SL {round(self.my_sl, n_rools[self.symbol.upper()]['price'])} / TP {round(self.my_tp, n_rools[self.symbol.upper()]['price'])}" bot_sendtext(bot_message) print("\n", bot_message) self.place_tp_order() def place_tp_order(self): reponse = Orders.tp_future( client=self.bclient, symbol=f"{self.symbol.upper()}USDT", side=self.main_direction, price=str(round(self.my_tp, n_rools[self.symbol.upper()]['price'])), amount=round(self.amount, n_rools[self.symbol.upper()]["decimals"])) if reponse['error']: self.bot_ping = False logging.info(f"TP order Error:\n {reponse}") bot_sendtext(f"TP order Error:\n {reponse}") else: self.order_id_tp = reponse['result']['clientOrderId'] self.place_sl_order() def place_sl_order(self): reponse = Orders.sl_future( client=self.bclient, symbol=f"{self.symbol.upper()}USDT", side=self.main_direction, price=str(round(self.my_sl, n_rools[self.symbol.upper()]['price'])), amount=round(self.amount, n_rools[self.symbol.upper()]["decimals"])) if reponse['error']: self.bot_ping = False logging.info(f"TP order Error:\n {reponse}") bot_sendtext(f"TP order Error:\n {reponse}") else: self.order_id_sl = reponse['result']['clientOrderId'] def close_tp_order(self): bot_message = f"QUIT {self.symbol.upper()} ({self.new_side}), \n{round(self.amount, n_rools[self.symbol.upper()]['decimals'])}, \n{round(self.my_tp, n_rools[self.symbol.upper()]['price'])}, \n TAKE PROFIT" bot_sendtext(bot_message) print("\n", bot_message) data = { "symbol": f"{self.symbol} ({self.new_side})", "amount": round(self.amount, n_rools[self.symbol.upper()]['decimals']), "price": round(self.my_tp, n_rools[self.symbol.upper()]['price']), "direct": 'SELL', "result": 2, "date": f"{datetime.now().strftime('%d.%m.%Y')}" } dbrools.insert_history(data=data) self.bclient.futures_cancel_order(symbol=f"{self.symbol.upper()}USDT", origClientOrderId=self.order_id_sl) self.my_Stoch = False self.my_RSI = False self.order = False self.order_id = False def close_sl_order(self): bot_message = f"QUIT {self.symbol.upper()} ({self.new_side}), \n{round(self.amount, n_rools[self.symbol.upper()]['decimals'])}, \n{round(self.my_tp, n_rools[self.symbol.upper()]['price'])}, \n STOP LOSS" bot_sendtext(bot_message) print("\n", bot_message) data = { "symbol": f"{self.symbol} ({self.new_side})", "amount": round(self.amount, n_rools[self.symbol.upper()]['decimals']), "price": round(self.my_sl, n_rools[self.symbol.upper()]['price']), "direct": 'SELL', "result": 1, "date": f"{datetime.now().strftime('%d.%m.%Y')}" } dbrools.insert_history(data=data) self.bclient.futures_cancel_order(symbol=f"{self.symbol.upper()}USDT", origClientOrderId=self.order_id_tp) self.my_Stoch = False self.my_RSI = False self.order = False self.order_id = False def algorithm(self): if not self.order: df = pd.DataFrame(self.main_data, columns=[ 'timestamp', 'open', 'high', 'low', 'close', 'volume', 'close_time', 'quote_av', 'trades', 'tb_base_av', 'tb_quote_av', 'ignore' ]) df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms') df.set_index('timestamp', inplace=True) df['close'] = pd.to_numeric(df['close']) df['close'] = pd.to_numeric(df['close']) df["high"] = pd.to_numeric(df["high"]) df["low"] = pd.to_numeric(df["low"]) df['rsi'] = ta.RSI(df['close'].values, timeperiod=12) df["slowk"], df["slowd"] = ta.STOCH(df['high'].values, df['low'].values, df['close'].values, 14, 3, 0, 3, 0) df["macd"], df["line"], df["hist"] = ta.MACD(df['close'], fastperiod=12, slowperiod=26, signalperiod=9) if df["slowk"].iloc[-1] <= 20 and df["slowd"].iloc[-1] <= 20: self.my_Stoch = 1 elif df["slowk"].iloc[-1] >= 80 and df["slowd"].iloc[-1] >= 80: self.my_Stoch = 2 if self.my_Stoch == 1 and df["slowk"].iloc[-1] >= 80: self.my_Stoch = False elif self.my_Stoch == 2 and df["slowk"].iloc[-1] <= 20: self.my_Stoch = False if df["rsi"].iloc[-1] >= 50: self.my_RSI = 1 else: self.my_RSI = 2 if self.my_Stoch == 1 and self.my_RSI == 1: if df["hist"].iloc[-1] > 0 > df["hist"].iloc[ -2] and self.rsi_signal > 70: self.main_direction = self.my_RSI self.place_new_order() elif self.my_Stoch == 2 and self.my_RSI == 2: if df["hist"].iloc[-1] < 0 < df["hist"].iloc[ -2] and self.rsi_signal < 30: self.main_direction = self.my_RSI self.place_new_order() def algorithm_rsi(self): data = pd.DataFrame(self.main_data_hour, columns=[ 'timestamp', 'open', 'high', 'low', 'close', 'volume', 'close_time', 'quote_av', 'trades', 'tb_base_av', 'tb_quote_av', 'ignore' ]) data['timestamp'] = pd.to_datetime(data['timestamp'], unit='ms') data.set_index('timestamp', inplace=True) data['close'] = pd.to_numeric(data['close']) data["high"] = pd.to_numeric(data["high"]) data["low"] = pd.to_numeric(data["low"]) data.reset_index(inplace=True, drop=True) data["RSID"] = ta.RSI(data['close'].values, timeperiod=12) self.rsi_signal = data["RSID"].iloc[-1] def run(self): bot_sendtext(f"FUTURE START {self.symbol.upper()}USDT") self.binance_websocket_api_manager = BinanceWebSocketApiManager( exchange="binance.com-futures", output_default="dict") self.binance_websocket_api_manager.create_stream( ['kline_1m', 'kline_1h'], [f'{self.symbol}usdt'], stream_label="UnicornFy", output="UnicornFy") self.binance_websocket_api_manager.create_stream( ['trade'], [f'{self.symbol}usdt'], output="UnicornFy") self.binance_websocket_api_manager.create_stream( 'arr', '!userData', api_key=self.api_key, api_secret=self.api_secret, output="dict") while self.bot_ping: if self.status: self.status = False self.binance_websocket_api_manager.create_stream( ['kline_1m', 'kline_1h'], [f'{self.symbol}usdt'], stream_label="UnicornFy", output="UnicornFy") self.binance_websocket_api_manager.create_stream( ['trade'], [f'{self.symbol}usdt'], output="UnicornFy") self.binance_websocket_api_manager.create_stream( 'arr', '!userData', api_key=self.api_key, api_secret=self.api_secret, output="dict") print( f"PARSER RESTART at {datetime.now().strftime('%H:%M:%S')}") else: try: if self.binance_websocket_api_manager.is_manager_stopping( ): exit(0) self.status = True stream_buffer = self.binance_websocket_api_manager.pop_stream_data_from_stream_buffer( ) if stream_buffer: try: if "e" in stream_buffer: if stream_buffer['e'] == 'ACCOUNT_UPDATE': if stream_buffer['a']['P'][0][ 's'] == f'{self.symbol}usdt'.upper( ) and stream_buffer['a']['P'][0][ 'pa'] == "0": if self.order == 1: if self.trade >= self.my_price: self.close_tp_order() if self.trade < self.my_price: self.close_sl_order() elif self.order == 2: if self.trade > self.my_price: self.close_sl_order() if self.trade <= self.my_price: self.close_tp_order() elif stream_buffer['event_type'] == "trade": self.trade = float(stream_buffer['price']) self.amount = self.min_amount / self.trade else: if stream_buffer['kline']['interval'] == "1m": if stream_buffer[ 'event_time'] >= stream_buffer[ 'kline']['kline_close_time']: new_row = [ stream_buffer['kline'] ['kline_start_time'], stream_buffer['kline'] ['open_price'], stream_buffer['kline'] ['high_price'], stream_buffer['kline'] ['low_price'], stream_buffer['kline'] ['close_price'], stream_buffer['kline'] ['base_volume'], stream_buffer['kline'] ['kline_close_time'], None, None, None, None, None ] self.main_data.append(new_row) del self.main_data[0] self.algorithm() elif stream_buffer['kline'][ 'interval'] == "1h": if stream_buffer[ 'event_time'] >= stream_buffer[ 'kline']['kline_close_time']: new_row = [ stream_buffer['kline'] ['kline_start_time'], stream_buffer['kline'] ['open_price'], stream_buffer['kline'] ['high_price'], stream_buffer['kline'] ['low_price'], stream_buffer['kline'] ['close_price'], stream_buffer['kline'] ['base_volume'], stream_buffer['kline'] ['kline_close_time'], None, None, None, None, None ] self.main_data_hour.append(new_row) del self.main_data_hour[0] self.algorithm_rsi() time.sleep(0.1) except KeyError: print(f"Exception :\n {stream_buffer}") time.sleep(0.5) else: time.sleep(0.01) except Exception as exc: self.status = True traceback.print_exc() time.sleep(30)
class BinanceWrapperAPI(WrapperAPI): # (n) means that parameter is necessary def __init__(self, pair, target, precision): self.pair = pair self.precision = precision self.target = target self.client = Client(keys.binance_api_key, keys.binance_api_secret) def get_my_balance_coin(self, coin): balances = self.client.futures_account_balance() balance = find(lambda v: v['asset'] == coin, balances) return float(balance['withdrawAvailable']) if balance else 0 def get_mycoin(self): return self.get_my_balance_coin('USDT') def get_position_targ(self) -> Tuple[float, bool]: risks = self.client.futures_position_information(symbol=self.target) position = find(lambda v: v['symbol'] == self.pair, risks) amt = float(position['positionAmt']) return abs(amt), amt >= 0 def get_balance_interest(self): amount, _ = self.get_position_targ() return amount def buy_order(self, amount: float): return self.post_order_market("BUY", amount) def sell_order(self, amount: float): return self.post_order_market("SELL", amount) def post_order_market(self, side: str, quantity: float): try: res = self.client.futures_create_order( symbol=self.pair, side=side, type="MARKET", # positionSide=pside, quantity=roundt(quantity, self.precision)) return [True, res['orderId']] except BinanceAPIException as e: raise (e) return [False, e] def get_open_orders(self): return self.client.get_open_orders(symbol=self.pair) def get_position(self) -> Literal["none", "long", "shor"]: amount, posi = self.get_position_targ() if amount == 0: return 'none' return "long" if posi else "shor" def get_ask(self): return float(self.client.get_ticker(symbol=self.pair)['askPrice']) def get_bid(self): return float(self.client.get_ticker(symbol=self.pair)['bidPrice']) def get_order_status(self, id) -> Literal["COMP", "NEW", "EXPIRE"]: try: res = self.client.futures_get_order(symbol=self.pair, orderId=id) if res['status'] == "FILLED": return "COMP" # other: CANCELED, PARTIALLY_FILLED return "NEW" except BinanceAPIException as e: return "EXPIRE"