class TestIndicator(unittest.TestCase): def setUp(self): self.symbol = "eth_usdt" self.digits = 6 self.interval = kl.KLINE_INTERVAL_1DAY self.display_count = 10 exchange_name = ex.BINANCE_SPOT_EXCHANGE_NAME self.md = DBMD(exchange_name) self.md.tick_time = datetime(2019, 1, 1, 8) self.klines = self.md.get_klines(self.symbol, self.interval, 150 + self.display_count) self.klines_df = pd.DataFrame(self.klines, columns=self.md.get_kline_column_names()) self.closeseat = self.md.get_kline_seat_close() self.highseat = self.md.get_kline_seat_high() self.lowseat = self.md.get_kline_seat_low() self.closekey = ex.get_kline_key_close(exchange_name) self.highkey = ex.get_kline_key_high(exchange_name) self.lowkey = ex.get_kline_key_low(exchange_name) self.count = 5000 self.steps = 1 self.td = kl.get_interval_timedelta( kl.KLINE_INTERVAL_1MINUTE) * self.steps def tearDown(self): pass def test_ma(self): print_test_title("ma") period = 55 kls = self.klines ma_key = ti.MA(kls, self.closekey, period) print(" ti mas: ", [ round(kl[ma_key], self.digits) for kl in kls[-self.display_count:] ]) tas = talib.MA(self.klines_df[self.closekey], period) print("TA-Lib mas: ", [round(a, self.digits) for a in tas][-self.display_count:]) for i in range(-self.display_count, 0): self.assertTrue(abs(kls[i][ma_key] - tas.values[i]) < 0.01) def test_ema(self): print_test_title("ema") period = 55 kls = self.klines ema_key = ti.EMA(kls, self.closekey, period) print(" ti emas: ", [ round(kl[ema_key], self.digits) for kl in kls[-self.display_count:] ]) tas = talib.EMA(self.klines_df[self.closekey], period) print("TA-Lib emas: ", [round(a, self.digits) for a in tas][-self.display_count:]) for i in range(-self.display_count, 0): self.assertTrue(abs(kls[i][ema_key] - tas.values[i]) < 0.01) def test_bias(self): print_test_title("bias") period_s = 21 period_l = 55 kls = self.klines ema_s_key = ti.EMA(kls, self.closekey, period_s) ta_semas = talib.EMA(self.klines_df[self.closekey], period_s) print(" ti semas(%d): %s" % (period_s, [ round(kl[ema_s_key], self.digits) for kl in kls[-self.display_count:] ])) print("TA-Lib semas(%d): %s" % (period_s, [round(a, self.digits) for a in ta_semas][-self.display_count:])) for i in range(-self.display_count, 0): self.assertTrue(abs(kls[i][ema_s_key] - ta_semas.values[i]) < 0.01) ema_l_key = ti.EMA(kls, self.closekey, period_l) ta_lemas = talib.EMA(self.klines_df[self.closekey], period_l) print(" ti lemas(%d): %s" % (period_l, [ round(kl[ema_l_key], self.digits) for kl in kls[-self.display_count:] ])) print("TA-Lib lemas(%d): %s" % (period_l, [round(a, self.digits) for a in ta_lemas][-self.display_count:])) for i in range(-self.display_count, 0): self.assertTrue(abs(kls[i][ema_l_key] - ta_lemas.values[i]) < 0.01) bias_sl_key = ti.BIAS_EMA(kls, self.closekey, period_s, period_l) ta_biases = ic.pd_biases(ta_semas, ta_lemas) print(" ti biases(%d, %d): %s" % (period_s, period_l, [ round(kl[bias_sl_key], self.digits) for kl in kls[-self.display_count:] ])) print("TA-Lib biases(%d, %d): %s" % (period_s, period_l, [round(a, self.digits) for a in ta_biases][-self.display_count:])) for i in range(-self.display_count, 0): self.assertTrue( abs(kls[i][bias_sl_key] - ta_biases.values[i]) < 0.01) def test_rsi(self): print_test_title("rsi") kls = self.klines rsi_key = ti.RSI(kls, self.closekey) ta_rsis = talib.RSI(self.klines_df[self.closekey]) print(" ti rsis: ", [ round(kl[rsi_key], self.digits) for kl in kls[-self.display_count:] ]) print("TA-Lib rsis: ", [round(a, self.digits) for a in ta_rsis][-self.display_count:]) for i in range(-self.display_count, 0): self.assertTrue(abs(kls[i][rsi_key] - ta_rsis.values[i]) < 0.01) def test_macd(self): print_test_title("macd") kls = self.klines dif_key, signal_key, hist_key = ti.MACD(kls, self.closekey) difs, signals, hists = talib.MACD(self.klines_df[self.closekey]) print(" ti macd difs: ", [ round(kl[dif_key], self.digits) for kl in kls[-self.display_count:] ]) print("TA-Lib macd difs: ", [round(a, self.digits) for a in difs][-self.display_count:]) print(" ti macd signals: ", [ round(kl[signal_key], self.digits) for kl in kls[-self.display_count:] ]) print("TA-Lib macd signals: ", [round(a, self.digits) for a in signals][-self.display_count:]) print(" ti macd hists: ", [ round(kl[hist_key], self.digits) for kl in kls[-self.display_count:] ]) print("TA-Lib macd hists: ", [round(a, self.digits) for a in hists][-self.display_count:]) for i in range(-self.display_count, 0): self.assertTrue(abs(kls[i][dif_key] - difs.values[i]) < 0.01) self.assertTrue(abs(kls[i][signal_key] - signals.values[i]) < 0.01) self.assertTrue(abs(kls[i][hist_key] - hists.values[i]) < 0.01) def perf_macd(self): for i in range(self.count): kls = self.md.get_klines(self.symbol, self.interval, 150 + self.display_count) dif_key, signal_key, hist_key = ti.MACD(kls, self.closekey) kls_df = pd.DataFrame(kls, columns=self.md.get_kline_column_names()) difs, signals, hists = talib.MACD(kls_df[self.closekey]) i = -1 self.assertTrue(abs(kls[i][dif_key] - difs.values[i]) < 0.01) self.assertTrue(abs(kls[i][signal_key] - signals.values[i]) < 0.01) self.assertTrue(abs(kls[i][hist_key] - hists.values[i]) < 0.01) self.md.tick_time += self.td def test_kd(self): print_test_title("kd") period = 9 kls = self.klines kkey, dkey = ti.KD(kls, self.closekey, self.highkey, self.lowkey, period) ''' kls_df = self.klines_df slowk, slowd = talib.STOCH(high=kls_df[self.highkey], low=kls_df[self.lowkey], close=kls_df[self.closekey], fastk_period=period, slowk_period=3, slowk_matype=0, slowd_period=3, slowd_matype=0) ''' kds = ic.py_kdj(kls, self.highseat, self.lowseat, self.closeseat) print( " ti kd ks: ", [round(kl[kkey], self.digits) for kl in kls[-self.display_count:]]) #print("TA-Lib kd ks: ", [round(k, self.digits) for k in slowk][-self.display_count:]) print("indicator kd ks: ", [round(kd[1], self.digits) for kd in kds[-self.display_count:]]) print( " ti kd ds: ", [round(kl[dkey], self.digits) for kl in kls[-self.display_count:]]) #print("TA-Lib kd ds: ", [round(d, self.digits) for d in slowd][-self.display_count:]) print("indicator kd ds: ", [round(kd[2], self.digits) for kd in kds[-self.display_count:]]) for i in range(-self.display_count, 0): #self.assertTrue(abs(kls[i][kkey] - slowk.values[i]) < 0.01) #self.assertTrue(abs(kls[i][dkey] - slowd.values[i]) < 0.01) self.assertTrue(abs(kls[i][kkey] - kds[i][1]) < 0.01) self.assertTrue(abs(kls[i][dkey] - kds[i][2]) < 0.01) def _test_atr(self): name = "atr" period = 14 print_test_title(name) kls = self.klines ti_key = ti._ATR(kls, self.highkey, self.lowkey, self.closekey, period) tas = talib.ATR(self.klines_df[self.highkey], self.klines_df[self.lowkey], self.klines_df[self.closekey], timeperiod=period) print(" ti %ss: %s" % (name, [ round(kl[ti_key], self.digits) for kl in kls[-self.display_count:] ])) print("TA-Lib %ss: %s" % (name, [round(a, self.digits) for a in tas][-self.display_count:])) for i in range(-self.display_count, 0): self.assertTrue(abs(kls[i][ti_key] - tas.values[i]) < 0.01) def test_trix(self): name = "trix" print_test_title(name) period = 30 kls = self.klines ti_key = ti.TRIX(kls, self.closekey, period) tas = talib.TRIX(self.klines_df[self.closekey], timeperiod=period) print(" ti %ss: %s" % (name, [ round(kl[ti_key], self.digits) for kl in kls[-self.display_count:] ])) print("TA-Lib %ss: %s" % (name, [round(a, self.digits) for a in tas][-self.display_count:])) for i in range(-self.display_count, 0): self.assertTrue(abs(kls[i][ti_key] - tas.values[i]) < 0.01)
class TestIndicator(unittest.TestCase): def setUp(self): self.symbol = "eth_usdt" self.digits = 4 self.interval = kl.KLINE_INTERVAL_1DAY self.display_count = 10 exchange_name = ex.BINANCE_SPOT_EXCHANGE_NAME self.md = DBMD(exchange_name) self.md.tick_time = datetime(2019, 1, 1, 8) self.klines = self.md.get_klines(self.symbol, self.interval, 150 + self.display_count) self.klines_df = pd.DataFrame(self.klines, columns=self.md.get_kline_column_names()) self.closeseat = self.md.get_kline_seat_close() self.closekey = ex.get_kline_key_close(exchange_name) self.count = 5000 self.steps = 1 self.td = kl.get_interval_timedelta( kl.KLINE_INTERVAL_1MINUTE) * self.steps def tearDown(self): pass def _test_rsi(self): print("") py_rsis = ic.py_rsis(self.klines, self.closeseat) ta_rsis = talib.RSI(self.klines_df[self.closekey]) #print(" X-Lib rsis: ", [round(a, 6) for a in py_rsis][-self.display_count:]) #print("TA-Lib rsis: ", [round(a, 6) for a in ta_rsis][-self.display_count:]) for i in range(-self.display_count, 0): #self.assertEqual(py_rsis[i], ta_rsis[i]) self.assertTrue(abs(py_rsis[i] - ta_rsis.values[i]) < 0.01) def test_ema(self): print("test ema") period = 55 pys = ic.py_emas(self.klines, self.closeseat, period) tas = talib.EMA(self.klines_df[self.closekey], period) closes = [c for c in pd.to_numeric(self.klines_df[self.closekey])] xtis = xti.EMA(closes, period) #kl_xtis = xti.EMA_KL(self.klines, self.closeseat, period) print(" ic emas: ", [round(a, 6) for a in pys][-self.display_count:]) print("TA-Lib emas: ", [round(a, 6) for a in tas][-self.display_count:]) print(" X-Lib emas: ", [round(a, 6) for a in xtis][-self.display_count:]) #print(" X-Lib kl emas: ", [round(a, 6) for a in kl_xtis][-self.display_count:]) for i in range(-self.display_count, 0): #self.assertEqual(pys[i], tas[i]) self.assertTrue(abs(pys[i] - tas.values[i]) < 0.01) self.assertTrue(abs(xtis[i] - tas.values[i]) < 0.01) #self.assertTrue(abs(kl_xtis[i] - tas.values[i]) < 0.01) def _test_bias(self): print("") period_s = 21 period_l = 55 semas = ic.py_emas(self.klines, self.closeseat, period_s) ta_semas = talib.EMA(self.klines_df[self.closekey], period_s) print(" X-Lib semas(%d): %s" % (period_s, [round(a, self.digits) for a in semas][-self.display_count:])) print("TA-Lib semas(%d): %s" % (period_s, [round(a, self.digits) for a in ta_semas][-self.display_count:])) for i in range(-self.display_count, 0): self.assertTrue(abs(semas[i] - ta_semas.values[i]) < 0.01) lemas = ic.py_emas(self.klines, self.closeseat, period_l) ta_lemas = talib.EMA(self.klines_df[self.closekey], period_l) print(" X-Lib lemas(%d): %s" % (period_l, [round(a, self.digits) for a in lemas][-self.display_count:])) print("TA-Lib lemas(%d): %s" % (period_l, [round(a, self.digits) for a in ta_lemas][-self.display_count:])) for i in range(-self.display_count, 0): self.assertTrue(abs(lemas[i] - ta_lemas.values[i]) < 0.01) biases = ic.py_biases(semas, lemas) ta_biases = ic.pd_biases(ta_semas, ta_lemas) print(" X-Lib biases(%d, %d): %s" % (period_s, period_l, [round(a, 4) for a in biases][-self.display_count:])) print("TA-Lib biases(%d, %d): %s" % (period_s, period_l, [round(a, 4) for a in ta_biases][-self.display_count:])) for i in range(-self.display_count, 0): self.assertTrue(abs(biases[i] - ta_biases.values[i]) < 0.01) def _test_nbias(self): print("") period = 55 closes = [float(k[self.closeseat]) for k in self.klines] print(" closes: ", [round(a, self.digits) for a in closes][-self.display_count:]) emas = ic.py_emas(self.klines, self.closeseat, period) ta_emas = talib.EMA(self.klines_df[self.closekey], period) print(" X-Lib emas(%d): %s" % (period, [round(a, self.digits) for a in emas][-self.display_count:])) print("TA-Lib emas(%d): %s" % (period, [round(a, self.digits) for a in ta_emas][-self.display_count:])) for i in range(-self.display_count, 0): self.assertTrue(abs(emas[i] - ta_emas.values[i]) < 0.01) nbiases = ic.py_biases(closes, emas) ta_nbiases = ic.pd_biases(pd.to_numeric(self.klines_df[self.closekey]), ta_emas) print(" X-Lib nbiases(%d): %s" % (period, [round(a, 4) for a in nbiases][-self.display_count:])) print("TA-Lib nbiases(%d): %s" % (period, [round(a, 4) for a in ta_nbiases][-self.display_count:])) for i in range(-self.display_count, 0): self.assertTrue(abs(nbiases[i] - ta_nbiases.values[i]) < 0.01) def _test_perf_xlib_rsi(self): for i in range(self.count): klines = self.md.get_klines(self.symbol, self.interval, 150 + self.display_count) py_rsis = ic.py_rsis(klines, self.closeseat) py_rsis = [round(a, 3) for a in py_rsis][-self.display_count:] self.md.tick_time += self.td def _test_perf_talib_rsi(self): for i in range(self.count): klines = self.md.get_klines(self.symbol, self.interval, 150 + self.display_count) klines_df = pd.DataFrame(klines, columns=self.md.get_kline_column_names()) ta_rsis = talib.RSI(klines_df[self.closekey]) ta_rsis = [round(a, 3) for a in ta_rsis][-self.display_count:] self.md.tick_time += self.td def perf_py_ema(self): period = 55 for i in range(self.count): klines = self.md.get_klines(self.symbol, self.interval, 150 + self.display_count) emas = ic.py_emas(self.klines, self.closeseat, period) self.md.tick_time += self.td def perf_xlib_ema(self): period = 55 for i in range(self.count): klines = self.md.get_klines(self.symbol, self.interval, 150 + self.display_count) closes = [float(k[self.closeseat]) for k in klines] emas = xti.EMA(closes, period) self.md.tick_time += self.td def perf_xlib_ema_kl(self): period = 55 for i in range(self.count): klines = self.md.get_klines(self.symbol, self.interval, 150 + self.display_count) #emas = xti.EMA_KL(self.klines, self.closeseat, period) self.md.tick_time += self.td
class BackTest(Engine): """回测引擎""" def __init__(self, instance_id, exchange_name, config, value=10000, *symbols): super().__init__(instance_id, config, value) self.md = DBMD(exchange_name) self.orders = [] def now(self): return self.md.tick_time def get_balances(self, *coins): """ 获取账户余额,回测默认1个亿,哈哈 """ coin_balances = [] for coin in coins: balance = xq.create_balance(coin, "100000000", "0") coin_balances.append(balance) if len(coin_balances) <= 0: return elif len(coin_balances) == 1: return coin_balances[0] else: return tuple(coin_balances) def get_position(self, symbol, cur_price): """ 获取持仓信息 """ if len(self.orders) > 0: if self.orders[-1]["action"] == bl.OPEN_POSITION: if "high" not in self.orders[ -1] or self.orders[-1]["high"] < cur_price: self.orders[-1]["high"] = cur_price self.orders[-1]["high_time"] = self.now().timestamp() if "low" not in self.orders[ -1] or self.orders[-1]["low"] > cur_price: self.orders[-1]["low"] = cur_price self.orders[-1]["low_time"] = self.now().timestamp() return self._get_position(symbol, self.orders, cur_price) def send_order_limit(self, direction, action, symbol, pst_rate, cur_price, limit_price, amount, stop_loss_price, rmk): """ 提交委托,回测默认以当前价全部成交 """ # order_id = uuid.uuid1() order_id = "" self.orders.append({ "create_time": self.now().timestamp(), "instance_id": self.instance_id, "symbol": symbol, "direction": direction, "action": action, "pst_rate": pst_rate, "type": xq.ORDER_TYPE_LIMIT, "market_price": cur_price, "price": limit_price, "amount": amount, "stop_loss_price": stop_loss_price, "status": xq.ORDER_STATUS_CLOSE, "order_id": order_id, "cancle_amount": 0, "deal_amount": amount, "deal_value": amount * cur_price, "rmk": rmk, }) return order_id def cancle_orders(self, symbol): """ 撤掉本策略的所有挂单委托 """ pass def run(self, strategy, start_time, end_time): """ run """ total_tick_start = datetime.now() self.md.tick_time = start_time tick_count = 0 while self.md.tick_time < end_time: self.log_info("tick_time: %s" % self.md.tick_time.strftime("%Y-%m-%d %H:%M:%S")) tick_start = datetime.now() strategy.on_tick() tick_end = datetime.now() self.log_info("tick cost: %s \n\n" % (tick_end - tick_start)) tick_count += 1 self.md.tick_time += timedelta(seconds=strategy.config["sec"]) progress = (self.md.tick_time - start_time).total_seconds() / ( end_time - start_time).total_seconds() sys.stdout.write(" tick: %s, cost: %s, progress: %d%% \r" % ( self.md.tick_time.strftime("%Y-%m-%d %H:%M:%S"), tick_end - total_tick_start, progress * 100, )) sys.stdout.flush() total_tick_end = datetime.now() print("\n total tick count: %d cost: %s" % (tick_count, total_tick_end - total_tick_start)) def chart(self, symbol, start_time, end_time, args): interval = self.config["kline"]["interval"] display_count = int((end_time - start_time).total_seconds() / xq.get_interval_seconds(interval)) print("display_count: %s" % display_count) klines = self.md.get_klines(symbol, interval, 150 + display_count) self.display(args, symbol, self.orders, klines, display_count)
help='exchange') parser.add_argument('-s', help='symbol (btc_usdt)') parser.add_argument('-i', help='interval') parser.add_argument('-r', help='time range') parser.add_argument('-di', help='display indicators,egg: macd,kdj,MACD,KDJ,RSI') add_argument_overlap_studies(parser) args = parser.parse_args() # print(args) if not (args.r and args.i and args.s and args.di and args.e): parser.print_help() exit(1) interval = args.i start_time, end_time = ts.parse_date_range(args.r) display_count = int((end_time - start_time).total_seconds() / xq.get_interval_seconds(interval)) print("display_count: %s" % display_count) md = DBMD(args.e) md.tick_time = datetime.now() pre_count = 150 klines = md.get_klines(args.s, interval, pre_count + display_count, start_time - xq.get_timedelta(interval, pre_count)) show(args, klines, md.kline_column_names, display_count, ts.parse_ic_keys(args.di))