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)
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? stub_test = False # parameter search? 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: 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") self.exchange.stop() self.exchange.cancel_all() sys.exit()
class Bot: # 파라메타 params = {} # 거래소 exchange = None # 봉단위 bin_size = '1h' # 봉기간 periods = 20 # ohlcv = 1440 ohlcv = 8000 # 테스트넷 옵션 test_net = False # 벡테스트 옵션 back_test = False # 스터브 옵션 stub_test = False # 하이퍼 옵션 hyperopt = False def __init__(self, bin_size): """ 컨스트럭터 :param bin_size: 봉단위 :param periods: 봉기간 """ self.bin_size = bin_size def options(self): """ 하이퍼옵션 파라메타탐색 값 취득 함수 """ pass def resolution(self): """ 봉기간 사이즈 """ return self.bin_size def ohlcv_len(self): """ strategy 전략함수에 넘기는 OHLC 길이 """ # return 100 return self.ohlcv def input(self, title, type, defval): """ 하이퍼옵션에 넘겨지는 파라메타 및 속성설정 :param title: 파라메타명 :param defval: 디폴트값 :return: 値 """ 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): """ 전략함수로 봇을 작성할때 이 함수를 오버라이드해서 사용 :param open: 시가 :param close: 종가 :param high: 고가 :param low: 저가 :param volume: 거래량 """ pass def params_search(self): """ ˜ 파라메타 탐색 함수 """ 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): """ ˜ 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"Resolution : {self.resolution()}") logger.info(f"Balance : {self.exchange.get_balance()}") notify(f"Starting Bot\n" f"Strategy : {type(self).__name__}\n" f"Resolution : {self.resolution()}\n" f"Balance : {self.exchange.get_balance()/100000000} XBT") self.exchange.show_result() def stop(self): """ ˜ Bot 정지 및 Open되어 있는 주문을 취소 """ if self.exchange is None: return logger.info(f"Stopping Bot") self.exchange.stop() self.exchange.cancel_all() sys.exit()
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): """ コンストラクタ。 :param bin_size: 時間足 :param periods: 期間 """ self.bin_size = bin_size def options(self): """ パレメータ探索用の値を取得する関数。 """ pass def ohlcv_len(self): """ 戦略にわたすOHLCの長さ """ return 100 def input(self, title, type, defval): """ パレメータを取得する関数。 :param title: パレメータ名 :param defval: デフォルト値 :return: 値 """ 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): """ 戦略関数。Botを作成する際は、この関数を継承して実装してください。 :param open: 始値 :param close: 終値 :param high: 高値 :param low: 安値 """ pass def params_search(self): """ ˜ パラメータ検索を行う関数。 """ 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): """ ˜ Botを起動する関数。 """ logger.info(f"Starting Bot") logger.info(f"Strategy : {type(self).__name__}") 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) self.exchange.show_result() def stop(self): """ ˜ Botを停止する関数。Openしている注文は、キャンセルする。 """ if self.exchange is None: return logger.info(f"Stopping Bot") self.exchange.stop() self.exchange.cancel_all() sys.exit()