def run(self): """ ˜ Function to run the bot """ if self.hyperopt: logger.info(f"Bot Mode : Hyperopt") self.params_search() return elif self.stub_test: logger.info(f"Bot Mode : Stub") self.exchange = BitMexStub() elif self.back_test: logger.info(f"Bot Mode : Back test") self.exchange = BitMexBackTest() else: logger.info(f"Bot Mode : Trade") self.exchange = BitMex(demo=self.test_net) self.exchange.ohlcv_len = self.ohlcv_len() self.exchange.on_update(self.bin_size, self.strategy) logger.info(f"Starting Bot") logger.info(f"Strategy : {type(self).__name__}") logger.info(f"Balance : {self.exchange.get_balance()}") self.exchange.show_result()
def test_fetch_ohlcv_11m(self): ohlcv_len = 100 bin_size = '11m' bitmex = BitMex(threading=False) end_time = datetime.now(timezone.utc) start_time = end_time - ohlcv_len * delta(bin_size) d1 = bitmex.fetch_ohlcv(bin_size, start_time, end_time) print(f"{d1}")
def run(self): if self.hyperopt: raise Exception( "Trading View Strategy dose not support hyperopt Mode.") elif self.back_test: raise Exception( "Trading View Strategy dose not support backtest Mode.") elif self.stub_test: # if you want to use binance futures # self.exchange = BinanceFuturesStub(account=self.account, pair=self.pair) self.exchange = BitMexStub(account=self.account, pair=self.pair) logger.info(f"Bot Mode : Stub") else: # if you want to use binance #self.exchange = BinanceFutures(account=self.account, pair=self.pair, demo=self.test_net) self.exchange = BitMex(account=self.account, pair=self.pair, demo=self.test_net) logger.info(f"Bot Mode : Trade") logger.info(f"Starting Bot") logger.info(f"Strategy : {type(self).__name__}") logger.info(f"Balance : {self.exchange.get_balance()}") notify(f"Starting Bot\n" f"Strategy : {type(self).__name__}\n" f"Balance : {self.exchange.get_balance()/100000000} XBT") self.subscriber.on_message(self.__on_message)
def on_update(self, bin_size, strategy): """ Register function of strategy. :param strategy: """ def __override_strategy(open, close, high, low, volume): new_open_orders = [] if self.get_position_size() > 0 and low[-1] > self.get_trail_price(): self.set_trail_price(low[-1]) if self.get_position_size() < 0 and high[-1] < self.get_trail_price(): self.set_trail_price(high[-1]) for _, order in enumerate(self.open_orders): id = order["id"] long = order["long"] qty = order["qty"] limit = order["limit"] stop = order["stop"] post_only = order["post_only"] if limit > 0 and stop > 0: if (long and high[-1] > stop and close[-1] < limit) or (not long and low[-1] < stop and close[-1] > limit): self.commit(id, long, qty, limit, False) continue elif (long and high[-1] > stop) or (not long and low[-1] < stop): new_open_orders.append( {"id": id, "long": long, "qty": qty, "limit": limit, "stop": 0}) continue elif limit > 0: if (long and low[-1] < limit) or (not long and high[-1] > limit): self.commit(id, long, qty, limit, False) continue elif stop > 0: if (long and high[-1] > stop) or (not long and low[-1] < stop): self.commit(id, long, qty, stop, False) continue new_open_orders.append(order) self.open_orders = new_open_orders strategy(open, close, high, low, volume) self.eval_exit() BitMex.on_update(self, bin_size, __override_strategy)
def __init__(self, account, pair, threading=True): """ constructor :account: :pair: :param threading: """ BitMex.__init__(self, account, pair, threading=threading) # Pair self.pair = pair # Balance all time high self.balance_ath = self.balance # Current Pos Size self.position_size = 0 # Current AVG Price self.position_avg_price = 0 # Current Order Count self.order_count = 0 # Current Winning Count self.win_count = 0 # Current Lose Count self.lose_count = 0 # Win Profit self.win_profit = 0 # Lose Loss self.lose_loss = 0 #Drawdown from peak self.drawdown = 0 # Max Loss Rate self.max_draw_down = 0 # max drawdown for the session self.max_draw_down_session = 0 # max drawdown session % self.max_draw_down_session_perc = 0 # orders self.open_orders = [] # Warmup long and short entry lists for tp_next_candle option for sltp() self.isLongEntry = [False, False] self.isShortEntry = [False,False] self.order_log = open("orders.csv", "w") self.order_log.write("time,type,id,price,quantity,av_price,position,pnl,balance,drawdown\n") #header
def run(self): """ ˜ Function to run the bot """ if self.hyperopt: logger.info(f"Bot Mode : Hyperopt") self.params_search() return elif self.stub_test: logger.info(f"Bot Mode : Stub") if self.exchange_arg == "binance": self.exchange = BinanceFuturesStub(account=self.account, pair=self.pair) elif self.exchange_arg == "bitmex": self.exchange = BitMexStub(account=self.account, pair=self.pair) else: logger.info(f"--exchange argument missing or invalid") return elif self.back_test: logger.info(f"Bot Mode : Back test") if self.exchange_arg == "binance": self.exchange = BinanceFuturesBackTest(account=self.account, pair=self.pair) elif self.exchange_arg == "bitmex": self.exchange = BitMexBackTest(account=self.account, pair=self.pair) else: logger.info(f"--exchange argument missing or invalid") return else: logger.info(f"Bot Mode : Trade") if self.exchange_arg == "binance": self.exchange = BinanceFutures(account=self.account, pair=self.pair, demo=self.test_net) elif self.exchange_arg == "bitmex": self.exchange = BitMex(account=self.account, pair=self.pair, demo=self.test_net) else: logger.info(f"--exchange argument missing or invalid") return self.exchange.ohlcv_len = self.ohlcv_len() self.exchange.on_update(self.bin_size, self.strategy) logger.info(f"Starting Bot") logger.info(f"Strategy : {type(self).__name__}") logger.info(f"Balance : {self.exchange.get_balance()}") notify(f"Starting Bot\n" f"Strategy : {type(self).__name__}\n" f"Balance : {self.exchange.get_balance()}") self.exchange.show_result()
def objective(args): logger.info(f"Params : {args}") try: self.params = args self.exchange = BitMexBackTest() self.exchange.on_update(self.bin_size, self.strategy) profit_factor = self.exchange.win_profit / self.exchange.lose_loss logger.info(f"Profit Factor : {profit_factor}") ret = {'status': STATUS_OK, 'loss': 1 / profit_factor} except Exception as e: ret = {'status': STATUS_FAIL} return ret
def objective(args): logger.info(f"Params : {args}") try: if self.exchange_arg == "bitmex": self.params = args self.exchange = BitMexBackTest(account=self.account, pair=self.pair) self.exchange.on_update(self.bin_size, self.strategy) profit_factor = self.exchange.win_profit / self.exchange.lose_loss logger.info(f"Profit Factor : {profit_factor}") ret = {'status': STATUS_OK, 'loss': 1 / profit_factor} if self.exchange_arg == 'binance': self.params = args self.exchange = BinanceFuturesBackTest( account=self.account, pair=self.pair) self.exchange.on_update(self.bin_size, self.strategy) profit_factor = self.exchange.win_profit / self.exchange.lose_loss logger.info(f"Profit Factor : {profit_factor}") ret = {'status': STATUS_OK, 'loss': 1 / profit_factor} except Exception as e: ret = {'status': STATUS_FAIL} return ret
def __init__(self, threading=True): """ constructor :param threading: """ BitMex.__init__(self, threading=threading)
class Bot: params = {} exchange = None bin_size = '1h' periods = 20 test_net = False back_test = False stub_test = False hyperopt = False def __init__(self, bin_size): """ constructor :param bin_size: time_frame :param periods: period """ self.bin_size = bin_size def options(self): """ Function to obtain value for searching for a parameter. """ pass def ohlcv_len(self): """ The length of the OHLC to the strategy """ return 100 def input(self, title, type, defval): """ function to get param :param title: title of the parm :param defval: default value :return value """ p = {} if self.params is None else self.params if title in p: return type(p[title]) else: return defval def strategy(self, open, close, high, low, volume): """ Strategy function, when creating a bot please inherit this and implement this fn. :param open: open price :param close: close price :param high: high price :param low: low price :param volume: volume """ pass def params_search(self): """ ˜ function to search params """ def objective(args): logger.info(f"Params : {args}") try: self.params = args self.exchange = BitMexBackTest() self.exchange.on_update(self.bin_size, self.strategy) profit_factor = self.exchange.win_profit / self.exchange.lose_loss logger.info(f"Profit Factor : {profit_factor}") ret = {'status': STATUS_OK, 'loss': 1 / profit_factor} except Exception as e: ret = {'status': STATUS_FAIL} return ret trials = Trials() best_params = fmin(objective, self.options(), algo=tpe.suggest, trials=trials, max_evals=200) logger.info(f"Best params is {best_params}") logger.info( f"Best profit factor is {1/trials.best_trial['result']['loss']}") def run(self): """ ˜ Function to run the bot """ if self.hyperopt: logger.info(f"Bot Mode : Hyperopt") self.params_search() return elif self.stub_test: logger.info(f"Bot Mode : Stub") self.exchange = BitMexStub() elif self.back_test: logger.info(f"Bot Mode : Back test") self.exchange = BitMexBackTest() else: logger.info(f"Bot Mode : Trade") self.exchange = BitMex(demo=self.test_net) self.exchange.ohlcv_len = self.ohlcv_len() self.exchange.on_update(self.bin_size, self.strategy) logger.info(f"Starting Bot") logger.info(f"Strategy : {type(self).__name__}") logger.info(f"Balance : {self.exchange.get_balance()}") self.exchange.show_result() def stop(self): """ ˜ Function that stops the bot and cancel all trades. """ if self.exchange is None: return logger.info(f"Stopping Bot") self.exchange.stop() self.exchange.cancel_all() sys.exit()
def on_update(self, bin_size, strategy): """ Register function of strategy. :param strategy: """ def __override_strategy(action, open, close, high, low, volume): new_open_orders = [] self.OHLC = { 'open': open, 'high': high, 'low': low, 'close': close } if self.get_position_size() > 0 and low[-1] > self.get_trail_price(): self.set_trail_price(low[-1]) if self.get_position_size() < 0 and high[-1] < self.get_trail_price(): self.set_trail_price(high[-1]) index=0 while(True): if index < len(self.open_orders): order = self.open_orders[index] index += 1 else: break id = order["id"] long = order["long"] qty = order["qty"] limit = order["limit"] stop = order["stop"] post_only = order["post_only"] reduce_only = order["reduce_only"] callback = order["callback"] if reduce_only == True and (self.position_size == 0 or (long and self.get_position_size() > 0) or (not long and self.get_position_size() < 0)): new_open_orders.append({"id": id, "long": long, "qty": qty, "limit": limit, "stop": 0, "post_only": post_only, "reduce_only": reduce_only, "callback": callback}) continue if limit > 0 and stop > 0: if (long and high[-1] > stop and close[-1] < limit) or (not long and low[-1] < stop and close[-1] > limit): self.commit(id, long, qty, limit, True, callback) continue elif (long and high[-1] > stop) or (not long and low[-1] < stop): new_open_orders.append({"id": id, "long": long, "qty": qty, "limit": limit, "stop": 0, "post_only": post_only, "reduce_only": reduce_only, "callback": callback}) continue elif limit > 0: if (long and low[-1] < limit) or (not long and high[-1] > limit): self.commit(id, long, qty, limit, True, callback) continue elif stop > 0: if (long and high[-1] > stop) or (not long and low[-1] < stop): self.commit(id, long, qty, stop, True, callback) continue new_open_orders.append(order) self.open_orders = new_open_orders self.eval_exit() self.eval_sltp() strategy(action, open, close, high, low, volume) BitMex.on_update(self, bin_size, __override_strategy)
class Bot: # Parameters params = {} # Account account = None # Exchange exchange_arg = None # Time Frame bin_size = '1h' # Pair pair = 'BTCUSDT' # Periods periods = 20 # Run on test net? test_net = False # Back test? back_test = False # Stub Test(paper trading)? stub_test = False # Parameter optimization? hyperopt = False # Session Persistence session = Session() # session = type("Session", (object,), {})() session_file = None session_file_name = None def __init__(self, bin_size): """ constructor :param bin_size: time_frame :param periods: period """ self.bin_size = bin_size def __del__(self): self.stop() def get_session(self): return self.session def set_session(self, session): self.session.load(session) def options(self): """ Function to get values for parameter optimization """ pass def ohlcv_len(self): """ The length of the OHLC to the strategy """ return 100 def input(self, title, type, defval): """ function to get param :param title: title of the parm :param defval: default value :return value """ p = {} if self.params is None else self.params if title in p: return type(p[title]) else: return defval def strategy(self, open, close, high, low, volume): """ Strategy function, when creating a bot please inherit and implement this fn. :param open: open price :param close: close price :param high: high price :param low: low price :param volume: volume """ pass def params_search(self): """ ˜ function to search params """ def objective(args): logger.info(f"Params : {args}") try: if self.exchange_arg == "bitmex": self.params = args self.exchange = BitMexBackTest(account=self.account, pair=self.pair) self.exchange.on_update(self.bin_size, self.strategy) profit_factor = self.exchange.win_profit / self.exchange.lose_loss logger.info(f"Profit Factor : {profit_factor}") ret = {'status': STATUS_OK, 'loss': 1 / profit_factor} if self.exchange_arg == 'binance': self.params = args self.exchange = BinanceFuturesBackTest( account=self.account, pair=self.pair) self.exchange.on_update(self.bin_size, self.strategy) profit_factor = self.exchange.win_profit / self.exchange.lose_loss logger.info(f"Profit Factor : {profit_factor}") ret = {'status': STATUS_OK, 'loss': 1 / profit_factor} except Exception as e: ret = {'status': STATUS_FAIL} return ret trials = Trials() best_params = fmin(objective, self.options(), algo=tpe.suggest, trials=trials, max_evals=200) logger.info(f"Best params is {best_params}") logger.info( f"Best profit factor is {1/trials.best_trial['result']['loss']}") def run(self): """ ˜ Function to run the bot """ if self.hyperopt: logger.info(f"Bot Mode : Hyperopt") self.params_search() return elif self.stub_test: logger.info(f"Bot Mode : Stub") if self.exchange_arg == "binance": self.exchange = BinanceFuturesStub(account=self.account, pair=self.pair) elif self.exchange_arg == "bitmex": self.exchange = BitMexStub(account=self.account, pair=self.pair) else: logger.info(f"--exchange argument missing or invalid") return elif self.back_test: logger.info(f"Bot Mode : Back test") if self.exchange_arg == "binance": self.exchange = BinanceFuturesBackTest(account=self.account, pair=self.pair) elif self.exchange_arg == "bitmex": self.exchange = BitMexBackTest(account=self.account, pair=self.pair) else: logger.info(f"--exchange argument missing or invalid") return else: logger.info(f"Bot Mode : Trade") if self.exchange_arg == "binance": self.exchange = BinanceFutures(account=self.account, pair=self.pair, demo=self.test_net) elif self.exchange_arg == "bitmex": self.exchange = BitMex(account=self.account, pair=self.pair, demo=self.test_net) else: logger.info(f"--exchange argument missing or invalid") return self.exchange.ohlcv_len = self.ohlcv_len() self.exchange.on_update(self.bin_size, self.strategy) logger.info(f"Starting Bot") logger.info(f"Strategy : {type(self).__name__}") logger.info(f"Balance : {self.exchange.get_balance()}") notify(f"Starting Bot\n" f"Strategy : {type(self).__name__}\n" f"Balance : {self.exchange.get_balance()}") self.exchange.show_result() def stop(self): """ ˜ Function that stops the bot and cancel all trades. """ if self.exchange is None: return logger.info(f"Stopping Bot") if self.session_file != None: self.session_file.truncate(0) self.session_file.seek(0) # pickle.dump(self.session, self.session_file) json.dump(self.session, self.session_file, default=vars, indent=True) # self.session_file.write(jsonpickle.encode(self.session)) self.session_file.close() logger.info(f"Saved Session to {self.session_file_name}") self.exchange.stop() self.exchange.cancel_all() sys.exit(0)
def test_entry_cancel(self): bitmex = BitMex() bitmex.demo = True # close current orders bitmex.close_all() price = bitmex.get_market_price() # TEST: CANCELLATION id = "Long" bitmex.entry(id, True, 1, limit=price - 1000) assert bitmex.get_open_order(id) is not None bitmex.cancel(id) assert bitmex.get_open_order(id) is None # TEST: UPDATE ORDER id = "Long" bitmex.entry(id, True, 1, limit=price - 1000) order = bitmex.get_open_order(id) assert order["orderQty"] == 1 assert order["price"] == price - 1000 bitmex.entry(id, True, 2, limit=price - 900) order = bitmex.get_open_order(id) assert order["orderQty"] == 2 assert order["price"] == price - 900 bitmex.cancel(id) assert bitmex.get_open_order(id) is None
def test_fetch_ohlc_2h(self): bitmex = BitMex(threading=False) end_time = datetime.now(timezone.utc) start_time = end_time - 5 * timedelta(hours=2) source = bitmex.fetch_ohlcv('2h', start_time, end_time) assert len(source) > 1
def test_fetch_ohlcv_5m(self): bitmex = BitMex(threading=False) end_time = datetime.now(timezone.utc) start_time = end_time - 5 * timedelta(minutes=5) source = bitmex.fetch_ohlcv('5m', start_time, end_time) assert len(source) > 1