def test_case(self): """ 策略: 多空市价开仓且当根bar成交 买入点:[bt1, bt2, bt3] 当天卖出点:[st1, st2] """ class DemoStrategy(Strategy): def __init__(self, name): super(DemoStrategy, self).__init__(name) self.cashes = [] self.equities = [] def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): curtime = ctx.datetime[0].time() if curtime in [bt1, bt2, bt3]: ctx.buy(0, 1) ctx.short(0, 2) else: if curtime == st1: assert(ctx.pos('long') == 3 and '持仓测试失败!') ctx.sell(0, 2) assert(ctx.pos('short') == 6 and '持仓测试失败!') ctx.cover(0, 4) elif curtime == st2: assert(ctx.pos('long') == 1 and '持仓测试失败!') ctx.sell(0, 1) assert(ctx.pos('short') == 2 and '持仓测试失败!') ctx.cover(0, 2) self.cashes.append(ctx.cash()) self.equities.append(ctx.equity()) def test(self, test): target, cashes, open_equities, open_cashes, dts =\ market_trade_closed_curbar(source, capital, lmg, smg, multi) for i, hd in enumerate(profile.all_holdings()): test.assertTrue(hd['datetime'] == dts[i], '模拟器测试失败!') test.assertAlmostEqual(hd['equity'], target[i]) test.assertAlmostEqual(hd['cash'], cashes[i]) for i in range(0, len(self.cashes)): test.assertAlmostEqual(self.equities[i], open_equities[i]) test.assertAlmostEqual(self.cashes[i], open_cashes[i]) set_symbols(['future.TEST-1.Minute']) c1 = DemoStrategy('C1') profile = add_strategy([c1], {'capital': capital}) run() c1.test(self)
def test_case(self): """ 策略: 多空市价开仓且当根bar成交 买入点:[bt1, bt2, bt3] 当天卖出点:[st1, st2] """ class DemoStrategy(Strategy): def __init__(self, name): super(DemoStrategy, self).__init__(name) self.cashes = [] self.equities = [] def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): curtime = ctx.datetime[0].time() if curtime in [bt1, bt2, bt3]: ctx.buy(0, 1) ctx.short(0, 2) else: if curtime == st1: assert (ctx.pos('long') == 3 and '持仓测试失败!') ctx.sell(0, 2) assert (ctx.pos('short') == 6 and '持仓测试失败!') ctx.cover(0, 4) elif curtime == st2: assert (ctx.pos('long') == 1 and '持仓测试失败!') ctx.sell(0, 1) assert (ctx.pos('short') == 2 and '持仓测试失败!') ctx.cover(0, 2) self.cashes.append(ctx.cash()) self.equities.append(ctx.equity()) def test(self, test): target, cashes, open_equities, open_cashes, dts =\ market_trade_closed_curbar(source, capital, lmg, smg, multi) for i, hd in enumerate(profile.all_holdings()): test.assertTrue(hd['datetime'] == dts[i], '模拟器测试失败!') test.assertAlmostEqual(hd['equity'], target[i]) test.assertAlmostEqual(hd['cash'], cashes[i]) for i in range(0, len(self.cashes)): test.assertAlmostEqual(self.equities[i], open_equities[i]) test.assertAlmostEqual(self.cashes[i], open_cashes[i]) set_symbols(['future.TEST-1.Minute']) c1 = DemoStrategy('C1') profile = add_strategy([c1], {'capital': capital}) run() c1.test(self)
def test_case(self): on_bar_timestep = [] on_symbol_timestep = [] class DemoStrategy(Strategy): def on_init(self, ctx): """初始化数据""" return def on_symbol(self, ctx): on_symbol_timestep.append("%s %s %s %s" % (ctx.pcontract, ctx.strategy, ctx.datetime, ctx.curbar)) def on_bar(self, ctx): t = ctx['oneday.TEST-1.Minute'] on_bar_timestep.append("%s %s %s" % (t.pcontract, t.datetime, t.curbar)) t = ctx['TWODAY.TEST-5.Second'] on_bar_timestep.append("%s %s %s" % (t.pcontract, t.datetime, t.curbar)) set_symbols(['TWODAY.TEST-5.Second', 'oneday.TEST-1.Minute']) add_strategy([DemoStrategy('A1'), DemoStrategy('A2')]) add_strategy([DemoStrategy('B1'), DemoStrategy('B2')]) run() # on_symbol fname = os.path.join(os.getcwd(), 'data', 'diffPeriodOnSymbol.txt') with open(fname) as f: lines = [line.rstrip('\n') for line in f] assert(len(lines) > 0) count = 0 for line in lines: if line.startswith("*"): continue self.assertTrue(on_symbol_timestep[count] == line, "on_symbol时间对齐失败") count += 1 # on_bar fname = os.path.join(os.getcwd(), 'data', 'diffPeriodOnBar.txt') lines = [line.rstrip('\n') for line in open(fname)] assert(len(lines) > 0) count = 0 for line in lines: if line.startswith("*"): continue self.assertTrue(on_bar_timestep[count] == line, "on_bar时间对齐失败") count += 1 logger.info('on_symbol, on_bar 时间对齐测试成功!')
def test_case(self): class DemoStrategy(Strategy): def on_init(self, ctx): """初始化数据""" return def on_bar(self, ctx): assert(ctx.open == ctx['TWODAY.TEST-5.Second'].open) assert(ctx.close == ctx['TWODAY.TEST-5.Second'].close) assert(ctx.high == ctx['TWODAY.TEST-5.Second'].high) assert(ctx.low == ctx['TWODAY.TEST-5.Second'].low) set_symbols(['TWODAY.TEST-5.Second', 'TWODAY.TEST-1.Minute']) add_strategy([DemoStrategy('A1')]) logger.info("默认合约测试成功!") run()
def test_case4(self): """ 测试市价成交 """ cashes0 = [] class DemoStrategy(Strategy): def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): curtime = ctx.datetime[0].time() if curtime in [bt1, bt2, bt3]: ctx.buy(0, 1) ctx.short(0, 2) else: if curtime == st1: assert (ctx.pos('long') == 3 and '持仓测试失败!') ctx.sell(0, 2) assert (ctx.pos('short') == 6 and '持仓测试失败!') ctx.cover(0, 4) elif curtime == st2: assert (ctx.pos('long') == 1 and '持仓测试失败!') ctx.sell(0, 1) assert (ctx.pos('short') == 2 and '持仓测试失败!') ctx.cover(0, 2) cashes0.append(ctx.test_cash()) set_symbols(['future.TEST-1.Minute']) profile = add_strategy([DemoStrategy('C1')], {'capital': capital}) run() lmg = Contract.long_margin_ratio('future.TEST') multi = Contract.volume_multiple('future.TEST') smg = Contract.short_margin_ratio('future.TEST') target, cashes, dts = holdings_buy_short_maked_market( source, capital, lmg, smg, multi) self.assertTrue(len(cashes0) == len(cashes), 'cash接口测试失败!') for i, hd in enumerate(profile.all_holdings()): self.assertTrue(hd['datetime'] == dts[i], '模拟器测试失败!') self.assertAlmostEqual(hd['equity'], target[i]) for i in range(0, len(cashes0) - 1): # 最后一根强平了无法比较 self.assertAlmostEqual(cashes0[i], cashes[i])
def test_case5(self): """ 测试跨合约交易的持仓, 资金 """ cashes0 = [] class DemoStrategy(Strategy): def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): curtime = ctx.datetime[0].time() if curtime in [bt1, bt2, bt3]: ctx.buy(ctx.close, 1) # 默认future.TEST ctx.short(ctx['future2.TEST-1.Minute'].close, 2, 'future2.TEST') else: if curtime == st1: for pos in ctx.all_positions(): if str(pos.contract) == 'FUTURE.TEST': assert (pos.quantity == 3) assert (pos.closable == 3) assert (pos.direction == Direction.LONG) else: assert (pos.quantity == 6) assert (pos.closable == 6) assert (pos.direction == Direction.SHORT) assert (ctx.pos('long', 'future.TEST') == 3 and '持仓测试失败!') ctx.sell(ctx.close, 2) assert (ctx.pos('short', 'future2.TEST') == 6 and '持仓测试失败!') ctx.cover(ctx['future2.TEST-1.Minute'].close, 4, 'future2.TEST') elif curtime == st2: assert (ctx.pos('long', 'future.TEST') == 1 and '跨合约持仓测试失败!') ctx.sell(ctx.close, 1, 'future.TEST') assert (ctx.pos('short', 'future2.TEST') == 2 and '持仓测试失败!') ctx.cover(ctx['future2.TEST-1.Minute'].close, 2, 'future2.TEST') cashes0.append(ctx.test_cash()) set_symbols(['future.TEST-1.Minute', 'future2.TEST-1.Minute']) profile = add_strategy([DemoStrategy('D1')], {'capital': capital}) run() fname = os.path.join(os.getcwd(), 'data', '1MINUTE', 'TEST', 'FUTURE2.csv') source2 = pd.read_csv(fname, parse_dates=True, index_col=0) lmg = Contract.long_margin_ratio('future.TEST') multi = Contract.volume_multiple('future.TEST') # 确保资金够用,所以不影响 target1, cashes1, dts = buy_closed_curbar(source, capital / 2, lmg, multi) # 期货 multi = Contract.volume_multiple('future2.TEST') smg = Contract.short_margin_ratio('future2.TEST') target2, cashes2, dts = holdings_short_maked_curbar( source2, capital / 2, smg, multi) target = [x + y for x, y in zip(target1, target2)] cashes = [x + y for x, y in zip(cashes1, cashes2)] self.assertTrue(len(cashes0) == len(cashes), 'cash接口测试失败!') for i in range(0, len(cashes0) - 1): # 最后一根强平了无法比较 self.assertAlmostEqual(cashes0[i], cashes[i]) for i, hd in enumerate(profile.all_holdings()): self.assertTrue(hd['datetime'] == dts[i], 'all_holdings接口测试失败!') self.assertAlmostEqual(hd['equity'], target[i])
def test_case(self): """ 测试: 1) 可平仓位。ctx.pos() 2) profile.all_holdings 每根bar收盘时间的价格撮合。 3) 都头买卖。ctx.buy, ctx.sell """ # @TODO 持仓过夜,不卖,累加仓位。 # @todo profile # signals 盈利 # @TODO deals DemoStrategy2 t_cashes0, t_cashes1 = [], [] t_ocashes0 = [] t_oequity0 = [] t_equity0 = [] class DemoStrategy1(Strategy): """ 限价只买多头仓位的策略 """ def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): curtime = ctx.datetime[0].time() if curtime in [bt1, bt2, bt3]: ctx.buy(ctx.close, 1) else: if curtime == st1: assert (ctx.pos() == 3 and '持仓测试失败!') ctx.sell(ctx.close, 2) elif curtime == st2: assert (ctx.pos() == 1 and '持仓测试失败!') ctx.sell(ctx.close, 1) ## 前一根的交易信号在当前价格撮合后的可用资金 t_ocashes0.append(ctx.cash()) t_oequity0.append(ctx.equity()) t_cashes0.append(ctx.test_cash()) t_equity0.append(ctx.test_equity()) class DemoStrategy2(Strategy): """ 限价买多卖空的策略 """ def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): curtime = ctx.datetime[0].time() if curtime in [bt1, bt2, bt3]: ctx.buy(ctx.close, 1) ctx.short(ctx.close, 2) else: if curtime == st1: assert (ctx.pos() == 3 and '默认持仓查询测试失败!') ctx.sell(ctx.close, 2) assert (ctx.pos('short') == 6 and '持仓测试失败!') ctx.cover(ctx.close, 4) elif curtime == st2: assert (ctx.pos('long') == 1 and '持仓测试失败!') ctx.sell(ctx.close, 1) assert (ctx.pos('short') == 2 and '持仓测试失败!') ctx.cover(ctx.close, 2) t_cashes1.append(ctx.test_cash()) class DemoStrategy3(Strategy): """ 测试平仓未成交时的持仓,撤单后的持仓,撤单。 """ def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): if ctx.curbar == 1: ctx.short(138, 1) ctx.short(138, 1) ctx.buy(ctx.close, 1) elif ctx.curbar == 3: # 保证下一根撤单成功, 而非当前这根。 assert (len(ctx.open_orders) == 2) ctx.cancel(ctx.open_orders[0]) assert (len(ctx.open_orders) == 2 and '撤单测试失败') elif ctx.curbar == 4: assert (len(ctx.open_orders) == 1 and '撤单测试失败!') elif ctx.curbar == 5: assert (ctx.pos() == 1) ctx.sell(300, 1) # 下无法成交的平仓,测试持仓。 elif ctx.curbar == 7: assert (ctx.pos() == 0 and '持仓测试失败!') assert (len(ctx.open_orders) == 2 and '撤单测试失败!') order = list( filter(lambda x: x.side == TradeSide.PING, ctx.open_orders))[0] ctx.cancel(order) elif ctx.curbar == 8: assert (len(ctx.open_orders) == 1 and '撤单测试失败!') assert (ctx.pos() == 1 and '持仓测试失败!') if ctx.curbar > 1 and ctx.datetime[0].date( ) != ctx.datetime[1].date(): assert (len(ctx.open_orders) == 0 and '隔夜订单清空测试失败') set_symbols(['future.TEST-1.Minute']) profile = add_strategy( [DemoStrategy1('A1'), DemoStrategy2('A2'), DemoStrategy3('A3')], { 'capital': capital, 'ratio': [0.3, 0.3, 0.4] }) run() # 绘制k线,交易信号线 #from quantdigger.digger import finance, plotting #plotting.plot_strategy(profile.data(), deals=profile.deals(0)) # all_holdings, cash() all_holdings = profile.all_holdings() all_holdings0 = profile.all_holdings(0) all_holdings1 = profile.all_holdings(1) all_holdings2 = profile.all_holdings(2) self.assertTrue( len(source) > 0 and len(source) == len(all_holdings), '模拟器测试失败!') lmg = Contract.long_margin_ratio('future.TEST') multi = Contract.volume_multiple('future.TEST') smg = Contract.short_margin_ratio('future.TEST') s_equity0, s_cashes0, s_oequity0, s_ocashes0, dts = buy_closed_curbar1( source, capital * 0.3, lmg, multi) for i in range(len(dts)): self.assertAlmostEqual(t_equity0[i], s_equity0[i]) self.assertAlmostEqual(t_oequity0[i], s_oequity0[i]) self.assertAlmostEqual(t_ocashes0[i], s_ocashes0[i]) self.assertAlmostEqual(t_cashes0[i], s_cashes0[i]) for i, hd in enumerate(all_holdings0): self.assertAlmostEqual(hd['equity'], s_equity0[i]) self.assertAlmostEqual(hd['cash'], s_cashes0[i]) self.assertTrue(hd['datetime'] == dts[i], 'all_holdings接口测试失败!') # 最后一根强平了无法比较, 可以通过Profile的all_holding去比较 for i in range(0, len(t_cashes0) - 1): self.assertAlmostEqual(t_cashes0[i], s_cashes0[i]) # 确保资金够用,所以不影响 e0, c0, dts = buy_closed_curbar(source, capital * 0.3 / 2, lmg, multi) e1, c1, dts = holdings_short_maked_curbar(source, capital * 0.3 / 2, smg, multi) s_equity1 = [x + y for x, y in zip(e0, e1)] s_cashes1 = [x + y for x, y in zip(c0, c1)] self.assertTrue(len(t_cashes1) == len(s_cashes1), 'cash接口测试失败!') for i, hd in enumerate(profile.all_holdings(1)): self.assertTrue(hd['datetime'] == dts[i], 'all_holdings接口测试失败!') self.assertAlmostEqual(hd['equity'], s_equity1[i]) # 最后一根强平了无法比较, 可以通过Profile的all_holding去比较 for i in range(0, len(t_cashes1) - 1): self.assertAlmostEqual(t_cashes1[i], s_cashes1[i]) for i in range(0, len(profile.all_holdings())): hd = all_holdings[i] hd0 = all_holdings0[i] hd1 = all_holdings1[i] hd2 = all_holdings2[i] self.assertTrue( hd['cash'] == hd0['cash'] + hd1['cash'] + hd2['cash'], 'all_holdings接口测试失败!') self.assertTrue( hd['commission'] == hd0['commission'] + hd1['commission'] + hd2['commission'], 'all_holdings接口测试失败!') self.assertTrue( hd['equity'] == hd0['equity'] + hd1['equity'] + hd2['equity'], 'all_holdings接口测试失败!') # holding hd0 = profile.holding(0) hd1 = profile.holding(1) hd2 = profile.holding(2) hd = profile.holding() self.assertTrue( hd0['equity'] + hd1['equity'] + hd2['equity'] == hd['equity'], 'holdings接口测试失败!') self.assertTrue(hd0['cash'] + hd1['cash'] + hd2['cash'] == hd['cash'], 'holdings接口测试失败!') self.assertTrue( hd0['commission'] + hd1['commission'] + hd2['commission'] == hd['commission'], 'holdings接口测试失败!') self.assertTrue( hd0['history_profit'] + hd1['history_profit'] + hd2['history_profit'] == hd['history_profit'], 'holdings接口测试失败!') hd0last = profile.all_holdings(0)[-1] self.assertTrue(hd0last['equity'] == hd0['equity'], 'holdings接口测试失败!') self.assertTrue(hd0last['cash'] == hd0['cash'], 'holdings接口测试失败!') self.assertTrue(hd0last['commission'] == hd0['commission'], 'holdings接口测试失败!') self.assertTrue( len(profile.all_holdings()) == len(s_equity0) and len(s_equity0) > 0, 'holdings接口测试失败!')
def test_case2(self): """ 测试限价的延迟成交, 与是否是期货还是股票无关。 测试延迟成交的资金占用 """ buy_entries, sell_entries = [], [] short_entries, cover_entries = [], [] cashes0, cashes1, cashes2 = [], [], [] class DemoStrategyBuy(Strategy): """ 只开多头仓位的策略 """ def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): if ctx.datetime[0] in buy_entries: ctx.buy(ctx.low - OFFSET, 1) # 确保在下一根Bar成交 # 默认多头 elif ctx.pos() > 0 and ctx.datetime[0].time() == st1: ctx.sell(ctx.close, ctx.pos()) cashes0.append(ctx.test_cash()) class DemoStrategyShort(Strategy): """ 只开空头仓位的策略 """ def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): if ctx.datetime[0] in short_entries: ctx.short(ctx.high + OFFSET, 1) elif ctx.pos('short') > 0 and ctx.datetime[0].time() == st1: ctx.cover(ctx.close, ctx.pos('short')) cashes1.append(ctx.test_cash()) class DemoStrategySell(Strategy): """ 只开多头仓位的策略 """ def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): if ctx.datetime[0].time() == bt1: ctx.buy(ctx.close, 1) elif ctx.pos('long') > 0 and ctx.datetime[0] in sell_entries: ctx.sell(ctx.high + OFFSET, ctx.pos()) elif ctx.pos('long') > 0 and ctx.datetime[0].time() == st3: ctx.sell(ctx.close, ctx.pos()) cashes2.append(ctx.test_cash()) class DemoStrategyCover(Strategy): def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): if ctx.datetime[0].time() == bt1: ctx.short(ctx.close, 1) elif ctx.pos('short') > 0 and ctx.datetime[0] in cover_entries: ctx.cover(ctx.low - OFFSET, ctx.pos('short')) elif ctx.pos('short') > 0 and ctx.datetime[0].time() == st3: ctx.cover(ctx.close, ctx.pos('short')) set_symbols(['future.TEST-1.Minute']) profile = add_strategy([ DemoStrategyBuy('B1'), DemoStrategySell('B2'), DemoStrategyShort('B3'), DemoStrategyCover('B4') ], { 'capital': capital, 'ratio': [0.25, 0.25, 0.25, 0.25] }) buy_entries, sell_entries, short_entries, cover_entries = entries_maked_nextbar( source) run() # buy lmg = Contract.long_margin_ratio('future.TEST') multi = Contract.volume_multiple('future.TEST') smg = Contract.short_margin_ratio('future.TEST') target, cashes, dts = holdings_buy_maked_nextbar( source, buy_entries, capital / 4, lmg, multi) self.assertTrue( len(profile.all_holdings(0)) == len(target) and len(target) > 0, '模拟器测试失败!') for i, hd in enumerate(profile.all_holdings(0)): self.assertTrue(hd['datetime'] == dts[i], '模拟器测试失败!') self.assertAlmostEqual(hd['equity'], target[i]) for i in range(0, len(cashes0) - 1): # 最后一根强平了无法比较 self.assertAlmostEqual(cashes0[i], cashes[i]) # short target, cashes, dts = holdings_short_maked_nextbar( source, short_entries, capital / 4, smg, multi) self.assertTrue( len(profile.all_holdings(2)) == len(target) and len(target) > 0, '模拟器测试失败!') for i, hd in enumerate(profile.all_holdings(2)): self.assertTrue(hd['datetime'] == dts[i], '模拟器测试失败!') self.assertAlmostEqual(hd['equity'], target[i]) for i in range(0, len(cashes1) - 1): self.assertAlmostEqual(cashes1[i], cashes[i]) ## sell target, cashes, dts = holdings_sell_maked_nextbar( source, sell_entries, capital / 4, lmg, multi) self.assertTrue( len(profile.all_holdings(1)) == len(target) and len(target) > 0, '模拟器测试失败!') for i, hd in enumerate(profile.all_holdings(1)): self.assertTrue(hd['datetime'] == dts[i], '模拟器测试失败!') self.assertAlmostEqual(hd['equity'], target[i]) self.assertAlmostEqual(hd['cash'], cashes[i]) for i in range(0, len(cashes2) - 1): self.assertAlmostEqual(cashes2[i], cashes[i]) # cover target, cashes, dts = holdings_cover_maked_nextbar( source, cover_entries, capital / 4, smg, multi) self.assertTrue( len(profile.all_holdings(3)) == len(target) and len(target) > 0, '模拟器测试失败!') for i, hd in enumerate(profile.all_holdings(3)): self.assertTrue(hd['datetime'] == dts[i], '模拟器测试失败!') self.assertAlmostEqual(hd['equity'], target[i]) self.assertAlmostEqual(hd['cash'], cashes[i]) #from quantdigger.digger import plotting #plotting.plot_strategy(profile.data(), deals=profile.deals(0)) ## @TODO 模拟器make_market的运行次数 return
def test_case(self): """ 案例:两个策略组合,每个策略组合下分别有两个策略,每个组合运行于两个周期合约中。 测试:on_bar, on_symbol, on_exit 的运行频次,数据和策略遍历的粗粒度测试; ctx.prontract, ctx.strategy """ on_exit = { 'strategy': [], } on_bar = { 'strategy': [], } on_symbol = { 'combination': set(), 'step_num': 0 } class DemoStrategy(Strategy): def on_init(self, ctx): """初始化数据""" return def on_symbol(self, ctx): # six.print_(ctx.strategy, ctx.pcontract) on_symbol['combination'].add((str(ctx.pcontract), ctx.strategy)) on_symbol['step_num'] += 1 def on_bar(self, ctx): on_bar['strategy'].append(ctx.strategy) def on_exit(self, ctx): on_exit['strategy'].append(ctx.strategy) set_symbols(['BB.TEST-1.Minute', 'AA.TEST-1.Minute']) add_strategy([DemoStrategy('A1'), DemoStrategy('A2')]) add_strategy([DemoStrategy('B1'), DemoStrategy('B2')]) run() fname = os.path.join(os.getcwd(), 'data', '1MINUTE', 'TEST', 'BB.csv') blen = len(pd.read_csv(fname)) fname = os.path.join(os.getcwd(), 'data', '1MINUTE', 'TEST', 'AA.csv') alen = len(pd.read_csv(fname)) sample = set([ ('BB.TEST-1.MINUTE', 'A1'), ('BB.TEST-1.MINUTE', 'A2'), ('AA.TEST-1.MINUTE', 'A1'), ('AA.TEST-1.MINUTE', 'A2'), ('BB.TEST-1.MINUTE', 'B1'), ('BB.TEST-1.MINUTE', 'B2'), ('AA.TEST-1.MINUTE', 'B1'), ('AA.TEST-1.MINUTE', 'B2') ]) self.assertTrue(alen > 0 and blen > 0) # 测试on_symbol self.assertTrue(on_symbol['combination'] == sample, "on_symbol测试失败!") self.assertTrue(on_symbol['step_num'] == alen * 4 + blen * 4, "on_symbol测试失败!") self.assertTrue(['A1', 'A2', 'B1', 'B2'] * max(blen, alen) == on_bar['strategy'], 'on_bar测试失败!') self.assertTrue(['A1', 'A2', 'B1', 'B2'] == on_exit['strategy'], 'on_exit测试失败!') logger.info('-- 策略on_xxx主函数测试成功 --')
def test_case(self): profile = None class DemoStrategy1(Strategy): """ 限价只买多头仓位的策略 """ def __init__(self, name): super(DemoStrategy1, self).__init__(name) self.open_cash = [] self.open_equity = [] def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): curtime = ctx.datetime[0].time() if curtime in [bt1, bt2, bt3]: ctx.buy(ctx.close, 1) else: if curtime == st1: assert (ctx.pos() == 3 and '持仓测试失败!') ctx.sell(ctx.close, 2) elif curtime == st2: assert (ctx.pos() == 1 and '持仓测试失败!') ctx.sell(ctx.close, 1) # 前一根的交易信号在当前价格撮合后的可用资金 self.open_cash.append(ctx.cash()) self.open_equity.append(ctx.equity()) def test(self, test): close_equity, close_cash, open_equity, open_cashes, dts = trade_closed_curbar( source, capital * 0.3, lmg, smg, multi, 1) for i, hd in enumerate(profile.all_holdings(0)): test.assertAlmostEqual(self.open_equity[i], open_equity[i]) test.assertAlmostEqual(self.open_cash[i], open_cashes[i]) test.assertAlmostEqual(hd['equity'], close_equity[i]) test.assertAlmostEqual(hd['cash'], close_cash[i]) test.assertTrue(hd['datetime'] == dts[i], 'all_holdings接口测试失败!') test.assertTrue( len(profile.all_holdings()) == len(close_equity) and len(close_equity) > 0, 'holdings接口测试失败!') class DemoStrategy2(Strategy): """ 限价买多卖空的策略 """ def __init__(self, name): super(DemoStrategy2, self).__init__(name) self.open_cash = [] self.open_equity = [] def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): curtime = ctx.datetime[0].time() if curtime in [bt1, bt2, bt3]: ctx.buy(ctx.close, 1) ctx.short(ctx.close, 1) else: if curtime == st1: assert (ctx.pos() == 3 and '默认持仓查询测试失败!') ctx.sell(ctx.close, 2) assert (ctx.pos('short') == 3 and '持仓测试失败!') ctx.cover(ctx.close, 2) elif curtime == st2: assert (ctx.pos('long') == 1 and '持仓测试失败!') ctx.sell(ctx.close, 1) assert (ctx.pos('short') == 1 and '持仓测试失败!') ctx.cover(ctx.close, 1) self.open_cash.append(ctx.cash()) self.open_equity.append(ctx.equity()) def test(self, test): # 确保资金够用,所以不影响 e0, c0, oe0, oc0, dts = trade_closed_curbar( source, capital * 0.3 / 2, lmg, smg, multi, 1) e1, c1, oe1, oc1, dts = trade_closed_curbar( source, capital * 0.3 / 2, lmg, smg, multi, -1) close_equity = [x + y for x, y in zip(e0, e1)] close_cash = [x + y for x, y in zip(c0, c1)] open_equity = [x + y for x, y in zip(oe0, oe1)] open_cash = [x + y for x, y in zip(oc0, oc1)] test.assertTrue( len(close_equity) == len(profile.all_holdings(1))) for i in range(len(close_equity)): hd = profile.all_holdings(1)[i] test.assertAlmostEqual(self.open_equity[i], open_equity[i]) test.assertAlmostEqual(self.open_cash[i], open_cash[i]) test.assertAlmostEqual(hd['equity'], close_equity[i]) test.assertAlmostEqual(hd['cash'], close_cash[i]) test.assertTrue(hd['datetime'] == dts[i], 'all_holdings接口测试失败!') test.assertTrue( len(profile.all_holdings()) == len(close_equity) and len(close_equity) > 0, 'holdings接口测试失败!') class DemoStrategy3(Strategy): def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): if ctx.curbar == 1: ctx.short(138, 1) ctx.short(138, 1) ctx.buy(ctx.close, 1) # 保证测单动作不会在当前时间点生效,而是从下一个时间点开始。 if ctx.curbar == 3: assert (len(ctx.open_orders) == 2) ctx.cancel(ctx.open_orders[0]) assert (len(ctx.open_orders) == 2 and '撤单测试失败') elif ctx.curbar == 4: assert (len(ctx.open_orders) == 1 and '撤单测试失败!') # 测试可平仓位和所有仓位不同。 if ctx.curbar == 5: assert (ctx.pos() == 1) ctx.sell(300, 1) # 下无法成交的平仓,测试持仓。 elif ctx.curbar == 7: assert (len(ctx.all_positions()) == 1 and '持仓测试失败!') assert (ctx.pos() == 0 and '持仓测试失败!') assert (len(ctx.open_orders) == 2 and '撤单测试失败!') order = list( filter(lambda x: x.side == TradeSide.PING, ctx.open_orders))[0] ctx.cancel(order) elif ctx.curbar == 8: assert (len(ctx.open_orders) == 1 and '撤单测试失败!') assert (ctx.pos() == 1 and '持仓测试失败!') # 隔夜未成交订单自动清空。 if ctx.curbar == 9: ctx.sell(300, 1) elif ctx.curbar == 10: assert (ctx.pos() == 0 and '持仓测试失败!') elif ctx.curbar > 1 and ctx.datetime[0].date( ) != ctx.datetime[1].date(): assert (ctx.pos() == 1 and '隔夜未成交订单清空测试失败') assert (len(ctx.open_orders) == 0 and '隔夜未成交订单清空测试失败') set_symbols(['future.TEST-1.Minute']) s1 = DemoStrategy1('A1') s2 = DemoStrategy2('A2') s3 = DemoStrategy3('A3') profile = add_strategy([s1, s2, s3], { 'capital': capital, 'ratio': [0.3, 0.3, 0.4] }) run() # 绘制k线,交易信号线 # from quantdigger.digger import finance, plotting # plotting.plot_strategy(profile.data(), deals=profile.deals(0)) all_holdings = profile.all_holdings() self.assertTrue( len(source) > 0 and len(source) == len(all_holdings), '模拟器测试失败!') self.assertAlmostEqual(lmg, 0.4) self.assertAlmostEqual(smg, 0.4) self.assertAlmostEqual(multi, 3) s1.test(self) s2.test(self) # test all_holdings for i in range(0, len(profile.all_holdings())): hd = all_holdings[i] hd0 = profile.all_holdings(0)[i] hd1 = profile.all_holdings(1)[i] hd2 = profile.all_holdings(2)[i] self.assertTrue( hd['cash'] == hd0['cash'] + hd1['cash'] + hd2['cash'], 'all_holdings接口测试失败!') self.assertTrue( hd['commission'] == hd0['commission'] + hd1['commission'] + hd2['commission'], 'all_holdings接口测试失败!') self.assertTrue( hd['equity'] == hd0['equity'] + hd1['equity'] + hd2['equity'], 'all_holdings接口测试失败!')
def test_case(self): """ 测试跨合约交易的持仓, 资金, 持仓""" class DemoStrategy(Strategy): def __init__(self, name): super(DemoStrategy, self).__init__(name) self.cashes = [] self.equities = [] def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): curtime = ctx.datetime[0].time() if curtime in [bt1, bt2, bt3]: ctx.buy(ctx.close, 1) # 默认future.TEST ctx.short(ctx['future2.TEST-1.Minute'].close, 1, 'future2.TEST') else: if curtime == st1: for pos in ctx.all_positions(): if str(pos.contract) == 'FUTURE.TEST': assert(pos.quantity == 3) assert(pos.closable == 3) assert(pos.direction == Direction.LONG) else: assert(pos.quantity == 3) assert(pos.closable == 3) assert(pos.direction == Direction.SHORT) assert(ctx.pos('long', 'future.TEST') == 3 and '持仓测试失败!') ctx.sell(ctx.close, 2) assert(ctx.pos('short', 'future2.TEST') == 3 and '持仓测试失败!') ctx.cover(ctx['future2.TEST-1.Minute'].close, 2, 'future2.TEST') elif curtime == st2: assert(ctx.pos('long', 'future.TEST') == 1 and '跨合约持仓测试失败!') ctx.sell(ctx.close, 1, 'future.TEST') assert(ctx.pos('short', 'future2.TEST') == 1 and '持仓测试失败!') ctx.cover(ctx['future2.TEST-1.Minute'].close, 1, 'future2.TEST') self.cashes.append(ctx.cash()) self.equities.append(ctx.equity()) def test(self, test): fname = os.path.join(os.getcwd(), 'data', '1MINUTE', 'TEST', 'FUTURE2.csv') source2 = pd.read_csv(fname, parse_dates=True, index_col=0) global smg, multi target1, cashes1, t1, c1, dts = trade_closed_curbar(source, capital / 2, lmg, smg, multi, 1) # 期货 multi = Contract.volume_multiple('future2.TEST') smg = Contract.short_margin_ratio('future2.TEST') target2, cashes2, t2, c2, dts = trade_closed_curbar(source2, capital / 2, lmg, smg, multi, -1) target = [x + y for x, y in zip(target1, target2)] cashes = [x + y for x, y in zip(cashes1, cashes2)] open_equities = [x + y for x, y in zip(t1, t2)] open_cashes = [x + y for x, y in zip(c1, c2)] test.assertTrue(len(self.cashes) == len(cashes), 'cash接口测试失败!') for i in range(0, len(self.cashes) - 1): # 最后一根强平了无法比较 test.assertAlmostEqual(self.cashes[i], open_cashes[i]) test.assertAlmostEqual(self.equities[i], open_equities[i]) for i, hd in enumerate(profile.all_holdings()): test.assertTrue(hd['datetime'] == dts[i], 'all_holdings接口测试失败!') test.assertAlmostEqual(hd['equity'], target[i]) test.assertAlmostEqual(hd['cash'], cashes[i]) set_symbols(['future.TEST-1.Minute', 'future2.TEST-1.Minute']) d1 = DemoStrategy('D1') profile = add_strategy([d1], {'capital': capital}) run() d1.test(self)
def test_case2(self): """ 测试限价的延迟成交, 与是否是期货还是股票无关。 测试延迟成交的资金占用 """ buy_entries, sell_entries = [], [] short_entries, cover_entries = [], [] class DemoStrategyBuy(Strategy): """ 只开多头仓位的策略 """ def __init__(self, name): super(DemoStrategyBuy, self).__init__(name) self.cashes = [] self.equities = [] def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): if ctx.datetime[0] in buy_entries: ctx.buy(ctx.low - OFFSET, 1) # 确保在下一根Bar成交 # 默认多头 elif ctx.pos() > 0 and ctx.datetime[0].time() == st1: ctx.sell(ctx.close, ctx.pos()) self.cashes.append(ctx.cash()) self.equities.append(ctx.equity()) def test(self, test): equities, cashes, open_equities, open_cashes, dts =\ in_closed_nextbar(source, buy_entries, capital / 4, lmg, smg, multi, 1) test.assertTrue(len(profile.all_holdings(0)) == len(equities) and len(equities) > 0, '模拟器测试失败!') for i, hd in enumerate(profile.all_holdings(0)): test.assertTrue(hd['datetime'] == dts[i], '模拟器测试失败!') test.assertAlmostEqual(hd['equity'], equities[i]) test.assertAlmostEqual(hd['cash'], cashes[i]) for i in range(0, len(self.equities)): test.assertAlmostEqual(self.equities[i], open_equities[i]) for i in range(0, len(self.cashes)): test.assertAlmostEqual(self.cashes[i], open_cashes[i]) class DemoStrategyShort(Strategy): """ 只开空头仓位的策略 """ def __init__(self, name): super(DemoStrategyShort, self).__init__(name) self.cashes = [] self.equities = [] def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): if ctx.datetime[0] in short_entries: ctx.short(ctx.high + OFFSET, 1) elif ctx.pos('short') > 0 and ctx.datetime[0].time() == st1: ctx.cover(ctx.close, ctx.pos('short')) self.cashes.append(ctx.cash()) self.equities.append(ctx.equity()) def test(self, test): # short equities, cashes, open_equities, open_cashes, dts =\ in_closed_nextbar(source, short_entries, capital / 4, lmg, smg, multi, -1) test.assertTrue(len(profile.all_holdings(2)) == len(equities) and len(equities) > 0, '模拟器测试失败!') for i, hd in enumerate(profile.all_holdings(2)): test.assertTrue(hd['datetime'] == dts[i], '模拟器测试失败!') test.assertAlmostEqual(hd['equity'], equities[i]) test.assertAlmostEqual(hd['cash'], cashes[i]) for i in range(0, len(self.equities)): test.assertAlmostEqual(self.equities[i], open_equities[i]) test.assertAlmostEqual(self.cashes[i], open_cashes[i]) class DemoStrategySell(Strategy): """ 只开多头仓位的策略 """ def __init__(self, name): super(DemoStrategySell, self).__init__(name) self.cashes = [] self.equities = [] def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): if ctx.datetime[0].time() == bt1: ctx.buy(ctx.close, 1) elif ctx.pos('long') > 0 and ctx.datetime[0] in sell_entries: ctx.sell(ctx.high + OFFSET, ctx.pos()) elif ctx.pos('long') > 0 and ctx.datetime[0].time() == st3: ctx.sell(ctx.close, ctx.pos()) self.cashes.append(ctx.cash()) self.equities.append(ctx.equity()) def test(self, test): target, cashes, open_equities, open_cashes, dts =\ out_closed_nextbar(source, sell_entries, capital / 4, lmg, smg, multi, 1) test.assertTrue(len(profile.all_holdings(1)) == len(target) and len(target) > 0, '模拟器测试失败!') for i, hd in enumerate(profile.all_holdings(1)): test.assertTrue(hd['datetime'] == dts[i], '模拟器测试失败!') test.assertAlmostEqual(hd['equity'], target[i]) test.assertAlmostEqual(hd['cash'], cashes[i]) for i in range(0, len(self.cashes)): test.assertAlmostEqual(self.equities[i], open_equities[i]) test.assertAlmostEqual(self.cashes[i], open_cashes[i]) class DemoStrategyCover(Strategy): def __init__(self, name): super(DemoStrategyCover, self).__init__(name) self.cashes = [] self.equities = [] def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): if ctx.datetime[0].time() == bt1: ctx.short(ctx.close, 1) elif ctx.pos('short') > 0 and ctx.datetime[0] in cover_entries: ctx.cover(ctx.low - OFFSET, ctx.pos('short')) elif ctx.pos('short') > 0 and ctx.datetime[0].time() == st3: ctx.cover(ctx.close, ctx.pos('short')) self.cashes.append(ctx.cash()) self.equities.append(ctx.equity()) def test(self, test): target, cashes, open_equities, open_cashes, dts =\ out_closed_nextbar(source, cover_entries, capital / 4, lmg, smg, multi, -1) test.assertTrue(len(profile.all_holdings(3)) == len(target) and len(target) > 0, '模拟器测试失败!') for i, hd in enumerate(profile.all_holdings(3)): test.assertTrue(hd['datetime'] == dts[i], '模拟器测试失败!') test.assertAlmostEqual(hd['equity'], target[i]) test.assertAlmostEqual(hd['cash'], cashes[i]) for i in range(0, len(self.cashes)): test.assertAlmostEqual(self.equities[i], open_equities[i]) test.assertAlmostEqual(self.cashes[i], open_cashes[i]) set_symbols(['future.TEST-1.Minute']) b1 = DemoStrategyBuy('B1') b2 = DemoStrategySell('B2') b3 = DemoStrategyShort('B3') b4 = DemoStrategyCover('B4') profile = add_strategy([b1, b2, b3, b4], {'capital': capital, 'ratio': [0.25, 0.25, 0.25, 0.25]}) buy_entries, sell_entries, short_entries, cover_entries = entries_maked_nextbar(source) run() b1.test(self) b2.test(self) b3.test(self) b4.test(self) return
def test_case(self): close, open, dt, high, low, volume = [], [], [], [], [], [] open3, dt3 = [], [] operator_test = [] user_vars = { 'curbar_list': [], 'numseries': [], 'numseries3': [], 'dtseries': [], } class DemoStrategy(Strategy): def on_init(self, ctx): """初始化数据""" ctx.ma3 = MA(ctx.close, 3) ctx.numseries = NumberSeries() ctx.dtseries = DateTimeSeries() ctx.curbar_list = [] def on_symbol(self, ctx): # @TODO * / operator_test.append(ctx.open - 0 == ctx.open[0]) operator_test.append(ctx.close - 0 == ctx.close[0]) operator_test.append(ctx.high + 0 == ctx.high[0]) operator_test.append(ctx.low + 0 == ctx.low[0]) operator_test.append(ctx.volume + 0 == ctx.volume[0]) open.append(ctx.open[0]) close.append(ctx.close[0]) high.append(ctx.high[0]) low.append(ctx.low[0]) volume.append(int(ctx.volume[0])) dt.append(ctx.datetime[0]) open3.append(ctx.open[3]) dt3.append(ctx.datetime[3]) if ctx.curbar >= 100 and ctx.curbar < 300: ctx.numseries.update(100) ctx.dtseries.update(datetime.datetime(1000, 1, 1)) elif ctx.curbar >= 300: ctx.dtseries.update(datetime.datetime(3000, 1, 1)) ctx.numseries.update(300) ctx.curbar_list.append(ctx.curbar) user_vars['numseries3'].append(ctx.numseries[3]) user_vars['numseries'].append(ctx.numseries[0]) user_vars['dtseries'].append(ctx.dtseries[0]) user_vars['curbar_list'] = ctx.curbar_list set_symbols(['BB.TEST-1.Minute']) add_strategy([DemoStrategy('A1')]) run() # 序列变量默认值 self.assertTrue(NumberSeries.DEFAULT_VALUE == 0.0, "默认值测试失败") self.assertTrue(DateTimeSeries.DEFAULT_VALUE == datetime.datetime(1980, 1, 1), "默认值测试失败") self.assertTrue(all(operator_test), "类型转化错误!") # 系统序列变量测试 target = pd.DataFrame({ 'open': open, 'close': close, 'high': high, 'low': low, 'volume': volume }) target.index = dt target = target.loc[:, ['open', 'close', 'high', 'low', 'volume']] fname = os.path.join(os.getcwd(), 'data', '1MINUTE', 'TEST', 'BB.csv') source = pd.read_csv(fname, parse_dates=True, index_col=0) self.assertTrue(source.equals(target), "系统时间序列变量正测试出错") fname = os.path.join(os.getcwd(), 'data', '1MINUTE', 'TEST', 'CC.csv') source = pd.read_csv(fname, parse_dates=True, index_col=0) self.assertFalse(source.equals(target), "系统时间序列变量反测试出错") # ctx.curbar,用户普通变量测试 for i in range(0, len(user_vars['curbar_list'])): self.assertTrue(i + 1 == user_vars['curbar_list'][i]) self.assertTrue(len(user_vars['numseries'])==len(open) and len(open)>0, '系列变量长度不一致') logger.info('-- 用户普通变量测试成功 --') logger.info('-- curbar测试成功 --') # 用户序列变量 numseries = user_vars['numseries'] dtseries = user_vars['dtseries'] dt1980 = datetime.datetime(1980, 1, 1) dt1000 = datetime.datetime(1000, 1, 1) dt3000 = datetime.datetime(3000, 1, 1) for i in range(0, len(numseries)): # 用户序列变量自动追加测试成功 if i < 99: self.assertTrue(numseries[i] == NumberSeries.DEFAULT_VALUE, '用户数字序列变量测试失败!') self.assertTrue(dtseries[i] == dt1980, '用户时间序列变量测试失败!') elif i >= 99 and i < 299: self.assertTrue(numseries[i] == 100, '用户数字序列变量测试失败!') self.assertTrue(dtseries[i] == dt1000, '用户时间序列变量测试失败!') elif i >= 299: self.assertTrue(numseries[i] == 300, '用户数字序列变量测试失败!') self.assertTrue(dtseries[i] == dt3000, '用户时间序列变量测试失败!') # 序列变量回溯测试 for i in range(0, len(open)): if i - 3 >= 0: self.assertTrue(open3[i] == open[i - 3], "系统序列变量回溯测试失败!") self.assertTrue(dt3[i] == dt[i - 3], "系统序列变量回溯测试失败!") self.assertTrue(user_vars['numseries3'][i] == numseries[i - 3], "用户序列变量回溯测试失败!") else: self.assertTrue(open3[i] == NumberSeries.DEFAULT_VALUE, "系统序列变量回溯测试失败!") self.assertTrue(user_vars['numseries3'][i] == NumberSeries.DEFAULT_VALUE, "用户序列变量回溯测试失败!") self.assertTrue(dt3[i] == DateTimeSeries.DEFAULT_VALUE, "系统序列时间变量回溯测试失败!") logger.info('-- 序列变量测试成功 --')
ctx.sell(ctx.close, ctx.pos()) return def on_exit(self, ctx): return if __name__ == '__main__': import timeit start = timeit.default_timer() set_config({'source': 'csv'}) set_symbols(['BB.SHFE-1.Day']) profile = add_strategy([DemoStrategy('A1'), DemoStrategy2('A2')], {'capital': 50000.0, 'ratio': [0.5, 0.5]}) run() stop = timeit.default_timer() print("运行耗时: %d秒" % ((stop - start))) # 绘制k线,交易信号线 from quantdigger.digger import finance, plotting s = 0 # 绘制策略A1, 策略A2, 组合的资金曲线 curve0 = finance.create_equity_curve(profile.all_holdings(0)) curve1 = finance.create_equity_curve(profile.all_holdings(1)) curve = finance.create_equity_curve(profile.all_holdings()) plotting.plot_strategy(profile.data(), profile.technicals(0), profile.deals(0), curve0.equity.values, profile.marks(0)) # 绘制净值曲线 plotting.plot_curves([curve.networth])
def test_case(self): profile = None class DemoStrategy1(Strategy): """ 限价只买多头仓位的策略 """ def __init__(self, name): super(DemoStrategy1, self).__init__(name) self.open_cash = [] self.open_equity = [] def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): curtime = ctx.datetime[0].time() if curtime in [bt1, bt2, bt3]: ctx.buy(ctx.close, 1) else: if curtime == st1: assert(ctx.pos() == 3 and '持仓测试失败!') ctx.sell(ctx.close, 2) elif curtime == st2: assert(ctx.pos() == 1 and '持仓测试失败!') ctx.sell(ctx.close, 1) # 前一根的交易信号在当前价格撮合后的可用资金 self.open_cash.append(ctx.cash()) self.open_equity.append(ctx.equity()) def test(self, test): close_equity, close_cash, open_equity, open_cashes, dts = trade_closed_curbar(source, capital * 0.3, lmg, smg, multi, 1) for i, hd in enumerate(profile.all_holdings(0)): test.assertAlmostEqual(self.open_equity[i], open_equity[i]) test.assertAlmostEqual(self.open_cash[i], open_cashes[i]) test.assertAlmostEqual(hd['equity'], close_equity[i]) test.assertAlmostEqual(hd['cash'], close_cash[i]) test.assertTrue(hd['datetime'] == dts[i], 'all_holdings接口测试失败!') test.assertTrue(len(profile.all_holdings()) == len(close_equity) and len(close_equity) > 0, 'holdings接口测试失败!') class DemoStrategy2(Strategy): """ 限价买多卖空的策略 """ def __init__(self, name): super(DemoStrategy2, self).__init__(name) self.open_cash = [] self.open_equity = [] def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): curtime = ctx.datetime[0].time() if curtime in [bt1, bt2, bt3]: ctx.buy(ctx.close, 1) ctx.short(ctx.close, 1) else: if curtime == st1: assert(ctx.pos() == 3 and '默认持仓查询测试失败!') ctx.sell(ctx.close, 2) assert(ctx.pos('short') == 3 and '持仓测试失败!') ctx.cover(ctx.close, 2) elif curtime == st2: assert(ctx.pos('long') == 1 and '持仓测试失败!') ctx.sell(ctx.close, 1) assert(ctx.pos('short') == 1 and '持仓测试失败!') ctx.cover(ctx.close, 1) self.open_cash.append(ctx.cash()) self.open_equity.append(ctx.equity()) def test(self, test): # 确保资金够用,所以不影响 e0, c0, oe0, oc0, dts = trade_closed_curbar(source, capital * 0.3 / 2, lmg, smg, multi, 1) e1, c1, oe1, oc1, dts = trade_closed_curbar(source, capital * 0.3 / 2, lmg, smg, multi, -1) close_equity = [x + y for x, y in zip(e0, e1)] close_cash = [x + y for x, y in zip(c0, c1)] open_equity = [x + y for x, y in zip(oe0, oe1)] open_cash = [x + y for x, y in zip(oc0, oc1)] test.assertTrue(len(close_equity) == len(profile.all_holdings(1))) for i in range(len(close_equity)): hd = profile.all_holdings(1)[i] test.assertAlmostEqual(self.open_equity[i], open_equity[i]) test.assertAlmostEqual(self.open_cash[i], open_cash[i]) test.assertAlmostEqual(hd['equity'], close_equity[i]) test.assertAlmostEqual(hd['cash'], close_cash[i]) test.assertTrue(hd['datetime'] == dts[i], 'all_holdings接口测试失败!') test.assertTrue(len(profile.all_holdings()) == len(close_equity) and len(close_equity) > 0, 'holdings接口测试失败!') class DemoStrategy3(Strategy): def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): if ctx.curbar == 1: ctx.short(138, 1) ctx.short(138, 1) ctx.buy(ctx.close, 1) # 保证测单动作不会在当前时间点生效,而是从下一个时间点开始。 if ctx.curbar == 3: assert(len(ctx.open_orders) == 2) ctx.cancel(ctx.open_orders[0]) assert(len(ctx.open_orders) == 2 and '撤单测试失败') elif ctx.curbar == 4: assert(len(ctx.open_orders) == 1 and '撤单测试失败!') # 测试可平仓位和所有仓位不同。 if ctx.curbar == 5: assert(ctx.pos() == 1) ctx.sell(300, 1) # 下无法成交的平仓,测试持仓。 elif ctx.curbar == 7: assert(len(ctx.all_positions()) == 1 and '持仓测试失败!') assert(ctx.pos() == 0 and '持仓测试失败!') assert(len(ctx.open_orders) == 2 and '撤单测试失败!') order = list(filter(lambda x: x.side == TradeSide.PING, ctx.open_orders))[0] ctx.cancel(order) elif ctx.curbar == 8: assert(len(ctx.open_orders) == 1 and '撤单测试失败!') assert(ctx.pos() == 1 and '持仓测试失败!') # 隔夜未成交订单自动清空。 if ctx.curbar == 9: ctx.sell(300, 1) elif ctx.curbar == 10: assert(ctx.pos() == 0 and '持仓测试失败!') elif ctx.curbar > 1 and ctx.datetime[0].date() != ctx.datetime[1].date(): assert(ctx.pos() == 1 and '隔夜未成交订单清空测试失败') assert(len(ctx.open_orders) == 0 and '隔夜未成交订单清空测试失败') set_symbols(['future.TEST-1.Minute']) s1 = DemoStrategy1('A1') s2 = DemoStrategy2('A2') s3 = DemoStrategy3('A3') profile = add_strategy([s1, s2, s3], { 'capital': capital, 'ratio': [0.3, 0.3, 0.4] }) run() # 绘制k线,交易信号线 # from quantdigger.digger import finance, plotting # plotting.plot_strategy(profile.data(), deals=profile.deals(0)) all_holdings = profile.all_holdings() self.assertTrue(len(source) > 0 and len(source) == len(all_holdings), '模拟器测试失败!') self.assertAlmostEqual(lmg, 0.4) self.assertAlmostEqual(smg, 0.4) self.assertAlmostEqual(multi, 3) s1.test(self) s2.test(self) # test all_holdings for i in range(0, len(profile.all_holdings())): hd = all_holdings[i] hd0 = profile.all_holdings(0)[i] hd1 = profile.all_holdings(1)[i] hd2 = profile.all_holdings(2)[i] self.assertTrue(hd['cash'] == hd0['cash'] + hd1['cash'] + hd2['cash'], 'all_holdings接口测试失败!') self.assertTrue(hd['commission'] == hd0['commission'] + hd1['commission'] + hd2['commission'], 'all_holdings接口测试失败!') self.assertTrue(hd['equity'] == hd0['equity'] + hd1['equity'] + hd2['equity'], 'all_holdings接口测试失败!')
def test_case2(self): """ 测试限价的延迟成交, 与是否是期货还是股票无关。 测试延迟成交的资金占用 """ buy_entries, sell_entries = [], [] short_entries, cover_entries = [], [] class DemoStrategyBuy(Strategy): """ 只开多头仓位的策略 """ def __init__(self, name): super(DemoStrategyBuy, self).__init__(name) self.cashes = [] self.equities = [] def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): if ctx.datetime[0] in buy_entries: ctx.buy(ctx.low - OFFSET, 1) # 确保在下一根Bar成交 # 默认多头 elif ctx.pos() > 0 and ctx.datetime[0].time() == st1: ctx.sell(ctx.close, ctx.pos()) self.cashes.append(ctx.cash()) self.equities.append(ctx.equity()) def test(self, test): equities, cashes, open_equities, open_cashes, dts =\ in_closed_nextbar(source, buy_entries, capital / 4, lmg, smg, multi, 1) test.assertTrue( len(profile.all_holdings(0)) == len(equities) and len(equities) > 0, '模拟器测试失败!') for i, hd in enumerate(profile.all_holdings(0)): test.assertTrue(hd['datetime'] == dts[i], '模拟器测试失败!') test.assertAlmostEqual(hd['equity'], equities[i]) test.assertAlmostEqual(hd['cash'], cashes[i]) for i in range(0, len(self.equities)): test.assertAlmostEqual(self.equities[i], open_equities[i]) for i in range(0, len(self.cashes)): test.assertAlmostEqual(self.cashes[i], open_cashes[i]) class DemoStrategyShort(Strategy): """ 只开空头仓位的策略 """ def __init__(self, name): super(DemoStrategyShort, self).__init__(name) self.cashes = [] self.equities = [] def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): if ctx.datetime[0] in short_entries: ctx.short(ctx.high + OFFSET, 1) elif ctx.pos('short') > 0 and ctx.datetime[0].time() == st1: ctx.cover(ctx.close, ctx.pos('short')) self.cashes.append(ctx.cash()) self.equities.append(ctx.equity()) def test(self, test): # short equities, cashes, open_equities, open_cashes, dts =\ in_closed_nextbar(source, short_entries, capital / 4, lmg, smg, multi, -1) test.assertTrue( len(profile.all_holdings(2)) == len(equities) and len(equities) > 0, '模拟器测试失败!') for i, hd in enumerate(profile.all_holdings(2)): test.assertTrue(hd['datetime'] == dts[i], '模拟器测试失败!') test.assertAlmostEqual(hd['equity'], equities[i]) test.assertAlmostEqual(hd['cash'], cashes[i]) for i in range(0, len(self.equities)): test.assertAlmostEqual(self.equities[i], open_equities[i]) test.assertAlmostEqual(self.cashes[i], open_cashes[i]) class DemoStrategySell(Strategy): """ 只开多头仓位的策略 """ def __init__(self, name): super(DemoStrategySell, self).__init__(name) self.cashes = [] self.equities = [] def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): if ctx.datetime[0].time() == bt1: ctx.buy(ctx.close, 1) elif ctx.pos('long') > 0 and ctx.datetime[0] in sell_entries: ctx.sell(ctx.high + OFFSET, ctx.pos()) elif ctx.pos('long') > 0 and ctx.datetime[0].time() == st3: ctx.sell(ctx.close, ctx.pos()) self.cashes.append(ctx.cash()) self.equities.append(ctx.equity()) def test(self, test): target, cashes, open_equities, open_cashes, dts =\ out_closed_nextbar(source, sell_entries, capital / 4, lmg, smg, multi, 1) test.assertTrue( len(profile.all_holdings(1)) == len(target) and len(target) > 0, '模拟器测试失败!') for i, hd in enumerate(profile.all_holdings(1)): test.assertTrue(hd['datetime'] == dts[i], '模拟器测试失败!') test.assertAlmostEqual(hd['equity'], target[i]) test.assertAlmostEqual(hd['cash'], cashes[i]) for i in range(0, len(self.cashes)): test.assertAlmostEqual(self.equities[i], open_equities[i]) test.assertAlmostEqual(self.cashes[i], open_cashes[i]) class DemoStrategyCover(Strategy): def __init__(self, name): super(DemoStrategyCover, self).__init__(name) self.cashes = [] self.equities = [] def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): if ctx.datetime[0].time() == bt1: ctx.short(ctx.close, 1) elif ctx.pos('short') > 0 and ctx.datetime[0] in cover_entries: ctx.cover(ctx.low - OFFSET, ctx.pos('short')) elif ctx.pos('short') > 0 and ctx.datetime[0].time() == st3: ctx.cover(ctx.close, ctx.pos('short')) self.cashes.append(ctx.cash()) self.equities.append(ctx.equity()) def test(self, test): target, cashes, open_equities, open_cashes, dts =\ out_closed_nextbar(source, cover_entries, capital / 4, lmg, smg, multi, -1) test.assertTrue( len(profile.all_holdings(3)) == len(target) and len(target) > 0, '模拟器测试失败!') for i, hd in enumerate(profile.all_holdings(3)): test.assertTrue(hd['datetime'] == dts[i], '模拟器测试失败!') test.assertAlmostEqual(hd['equity'], target[i]) test.assertAlmostEqual(hd['cash'], cashes[i]) for i in range(0, len(self.cashes)): test.assertAlmostEqual(self.equities[i], open_equities[i]) test.assertAlmostEqual(self.cashes[i], open_cashes[i]) set_symbols(['future.TEST-1.Minute']) b1 = DemoStrategyBuy('B1') b2 = DemoStrategySell('B2') b3 = DemoStrategyShort('B3') b4 = DemoStrategyCover('B4') profile = add_strategy([b1, b2, b3, b4], { 'capital': capital, 'ratio': [0.25, 0.25, 0.25, 0.25] }) buy_entries, sell_entries, short_entries, cover_entries = entries_maked_nextbar( source) run() b1.test(self) b2.test(self) b3.test(self) b4.test(self) return
def test_case(self): class DemoStrategy1(Strategy): """ 限价只买多头仓位的策略 """ def on_init(self, ctx): self._cashes = {} self._equities = {} ctx.tobuy = False ctx.tosell = False def on_symbol(self, ctx): """""" weekday = ctx.datetime[0].weekday() if weekday == 0: ctx.tobuy = True elif weekday == 4: ctx.tosell = True def on_bar(self, ctx): if ctx['600522'].tobuy: ctx.buy(ctx['600522'].close, 1, symbol='600522.SH') if ctx['600522'].tosell and ctx.pos(symbol='600522.SH')>0: ctx.sell(ctx['600522'].close, ctx.pos(symbol='600522.SH'), '600522.SH') ctx['600522'].tobuy = False ctx['600522'].tosell = False self._cashes[ctx.datetime[0]] = ctx.cash() self._equities[ctx.datetime[0]] = ctx.equity() def test(self, test, profile): lmg = Contract.long_margin_ratio('600522.SH') multi = Contract.volume_multiple('600522.SH') test.assertTrue(lmg == 1) test.assertTrue(multi == 1) fname = os.path.join(os.getcwd(), 'data', '1DAY', 'SH', '600522.csv') source = pd.read_csv(fname, parse_dates=True, index_col=0) equities, cashes, open_equities, open_cashes, dts = \ buy_monday_sell_friday(source, capital * 0.3, lmg, multi) count = 0 all_holdings0 = profile.all_holdings(0) for i, hd in enumerate(all_holdings0): dt = hd['datetime'] if dt in cashes: test.assertAlmostEqual(hd['cash'], cashes[dt]) test.assertAlmostEqual(hd['equity'], equities[dt]) test.assertAlmostEqual(self._cashes[dt], open_cashes[dt]) test.assertAlmostEqual(self._equities[dt], open_equities[dt]) count += 1 else: # 两支股票的混合,总数据长度和source不一样。 test.assertAlmostEqual(all_holdings0[i - 1]['cash'], hd['cash']) test.assertAlmostEqual(all_holdings0[i - 1]['equity'], hd['equity']) test.assertTrue(count == len(dts)) class DemoStrategy2(Strategy): """ 选股,并且时间没对齐的日线数据。 """ def __init__(self, name): super(DemoStrategy2, self).__init__(name) self.tobuys = [] self.tosells = [] self._cashes = {} self._equities = {} def on_symbol(self, ctx): """""" weekday = ctx.datetime[0].weekday() if weekday == 0: self.tobuys.append(ctx.symbol) elif weekday == 4: self.tosells.append(ctx.symbol) def on_bar(self, ctx): """初始化数据""" for symbol in self.tobuys: ctx.buy(ctx[symbol].close, 1, symbol) for symbol in self.tosells: if ctx.pos(symbol=symbol) > 0: ctx.sell(ctx[symbol].close, ctx.pos(symbol=symbol), symbol) self._equities[ctx.datetime[0]] = ctx.equity() self._cashes[ctx.datetime[0]] = ctx.cash() self.tobuys = [] self.tosells = [] def test(self, test, profile): fname = os.path.join(os.getcwd(), 'data', '1DAY', 'SH', '600521.csv') source = pd.read_csv(fname, parse_dates=True, index_col=0) fname = os.path.join(os.getcwd(), 'data', '1DAY', 'SH', '600522.csv') source2 = pd.read_csv(fname, parse_dates=True, index_col=0) equities0, cashes0, open_equities0, open_cashes0, dts = \ buy_monday_sell_friday(source, capital * 0.3 / 2, 1, 1) equities1, cashes1, open_equities1, open_cashes1, dts = \ buy_monday_sell_friday(source2, capital * 0.3 / 2, 1, 1) last_equity0 = 0 last_equity1 = 0 last_cash0 = 0 last_cash1 = 0 for i, hd in enumerate(profile.all_holdings(1)): dt = hd['datetime'] equity = 0 cash = 0 open_equity = 0 open_cash = 0 if dt in equities0: equity = equities0[dt] cash = cashes0[dt] open_equity = open_equities0[dt] open_cash = open_cashes0[dt] last_equity0 = equities0[dt] last_cash0 = cashes0[dt] else: equity += last_equity0 cash += last_cash0 open_equity += last_equity0 open_cash += last_cash0 if dt in equities1: equity += equities1[dt] cash += cashes1[dt] last_equity1 = equities1[dt] last_cash1 = cashes1[dt] open_equity += open_equities1[dt] open_cash += open_cashes1[dt] else: equity += last_equity1 cash += last_cash1 open_equity += last_equity1 open_cash += last_cash1 test.assertAlmostEqual(hd['equity'], equity) test.assertAlmostEqual(hd['cash'], cash) test.assertAlmostEqual(self._equities[dt], open_equity) test.assertAlmostEqual(self._cashes[dt], open_cash) class DemoStrategy3(Strategy): """ 测试平仓未成交时的持仓,撤单后的持仓,撤单。 """ def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): return set_symbols(['600521', '600522']) b1 = DemoStrategy1('B1') b2 = DemoStrategy2('B2') b3 = DemoStrategy3('B3') profile = add_strategy([b1, b2, b3], { 'capital': capital, 'ratio': [0.3, 0.3, 0.4] } ) run() b1.test(self, profile) b2.test(self, profile)
def test_case(self): """ 测试跨合约交易的持仓, 资金, 持仓""" class DemoStrategy(Strategy): def __init__(self, name): super(DemoStrategy, self).__init__(name) self.cashes = [] self.equities = [] def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): curtime = ctx.datetime[0].time() if curtime in [bt1, bt2, bt3]: ctx.buy(ctx.close, 1) # 默认future.TEST ctx.short(ctx['future2.TEST-1.Minute'].close, 1, 'future2.TEST') else: if curtime == st1: for pos in ctx.all_positions(): if str(pos.contract) == 'FUTURE.TEST': assert (pos.quantity == 3) assert (pos.closable == 3) assert (pos.direction == Direction.LONG) else: assert (pos.quantity == 3) assert (pos.closable == 3) assert (pos.direction == Direction.SHORT) assert (ctx.pos('long', 'future.TEST') == 3 and '持仓测试失败!') ctx.sell(ctx.close, 2) assert (ctx.pos('short', 'future2.TEST') == 3 and '持仓测试失败!') ctx.cover(ctx['future2.TEST-1.Minute'].close, 2, 'future2.TEST') elif curtime == st2: assert (ctx.pos('long', 'future.TEST') == 1 and '跨合约持仓测试失败!') ctx.sell(ctx.close, 1, 'future.TEST') assert (ctx.pos('short', 'future2.TEST') == 1 and '持仓测试失败!') ctx.cover(ctx['future2.TEST-1.Minute'].close, 1, 'future2.TEST') self.cashes.append(ctx.cash()) self.equities.append(ctx.equity()) def test(self, test): fname = os.path.join(os.getcwd(), 'data', '1MINUTE', 'TEST', 'FUTURE2.csv') source2 = pd.read_csv(fname, parse_dates=True, index_col=0) global smg, multi target1, cashes1, t1, c1, dts = trade_closed_curbar( source, capital / 2, lmg, smg, multi, 1) # 期货 multi = Contract.volume_multiple('future2.TEST') smg = Contract.short_margin_ratio('future2.TEST') target2, cashes2, t2, c2, dts = trade_closed_curbar( source2, capital / 2, lmg, smg, multi, -1) target = [x + y for x, y in zip(target1, target2)] cashes = [x + y for x, y in zip(cashes1, cashes2)] open_equities = [x + y for x, y in zip(t1, t2)] open_cashes = [x + y for x, y in zip(c1, c2)] test.assertTrue(len(self.cashes) == len(cashes), 'cash接口测试失败!') for i in range(0, len(self.cashes) - 1): # 最后一根强平了无法比较 test.assertAlmostEqual(self.cashes[i], open_cashes[i]) test.assertAlmostEqual(self.equities[i], open_equities[i]) for i, hd in enumerate(profile.all_holdings()): test.assertTrue(hd['datetime'] == dts[i], 'all_holdings接口测试失败!') test.assertAlmostEqual(hd['equity'], target[i]) test.assertAlmostEqual(hd['cash'], cashes[i]) set_symbols(['future.TEST-1.Minute', 'future2.TEST-1.Minute']) d1 = DemoStrategy('D1') profile = add_strategy([d1], {'capital': capital}) run() d1.test(self)
def test_case(self): lmg = Contract.long_margin_ratio('stock.TEST') multi = Contract.volume_multiple('stock.TEST') smg = Contract.short_margin_ratio('stock.TEST') profile = None class DemoStrategy1(Strategy): """ 限价只买多头仓位的策略 """ def on_init(self, ctx): """初始化数据""" self.cashes = [] self.equities = [] def on_bar(self, ctx): curtime = ctx.datetime[0].time() if curtime in [bt1, bt2, bt3]: ctx.buy(ctx.close, 1) elif ctx.pos() >= 2 and curtime == st1: ctx.sell(ctx.close, 2) elif ctx.pos() >= 1 and curtime == st2: ctx.sell(ctx.close, 1) self.cashes.append(ctx.cash()) self.equities.append(ctx.equity()) def test(self, test): equities, cashes, open_equities, open_casheses, dts =\ trade_closed_curbar(source, capital * 0.3, lmg, smg, multi, 1) test.assertTrue(len(self.cashes) == len(cashes), 'cash接口测试失败!') for i in range(0, len(self.cashes)): test.assertAlmostEqual(self.cashes[i], open_casheses[i]) test.assertAlmostEqual(self.equities[i], open_equities[i]) for i, hd in enumerate(profile.all_holdings(0)): test.assertTrue(hd['datetime'] == dts[i], 'all_holdings接口测试失败!') test.assertAlmostEqual(hd['equity'], equities[i]) test.assertAlmostEqual(hd['cash'], cashes[i]) class DemoStrategy2(Strategy): """ 限价买多卖空的策略 """ def on_init(self, ctx): """初始化数据""" self.cashes = [] def on_bar(self, ctx): curtime = ctx.datetime[0].time() if curtime in [bt1, bt2, bt3]: ctx.buy(ctx.close, 1) ctx.short(ctx.close, 1) elif curtime == st1: if ctx.pos() >= 3: assert(ctx.pos() == 3 and '默认持仓查询测试失败!') ctx.sell(ctx.close, 2) if ctx.pos('short') >= 3: assert(ctx.pos('short') == 3 and '默认持仓查询测试失败!') ctx.cover(ctx.close, 2) elif curtime == st2: if ctx.pos() >= 1: ctx.sell(ctx.close, 1) if ctx.pos('short') >= 1: ctx.cover(ctx.close, 1) self.cashes.append(ctx.test_cash()) def test(self, test): e0, c0, oe0, oc0, dts = trade_closed_curbar(source, capital * 0.3 / 2, lmg, smg, multi, 1) e1, c1, oe1, oc1, dts = trade_closed_curbar(source, capital * 0.3 / 2, lmg, smg, multi, -1) equities = [x + y for x, y in zip(e0, e1)] cashes = [x + y for x, y in zip(c0, c1)] for i, hd in enumerate(profile.all_holdings(1)): test.assertTrue(hd['datetime'] == dts[i], 'all_holdings接口测试失败!') test.assertAlmostEqual(hd['equity'], equities[i]) test.assertTrue(len(self.cashes) == len(cashes), 'cash接口测试失败!') for i in range(0, len(self.cashes) - 1): # 最后一根强平了无法比较 test.assertAlmostEqual(self.cashes[i], cashes[i]) class DemoStrategy3(Strategy): def on_init(self, ctx): """初始化数据""" pass def on_bar(self, ctx): return set_symbols(['stock.TEST-1.Minute']) a1 = DemoStrategy1('A1') a2 = DemoStrategy2('A2') a3 = DemoStrategy3('A3') profile = add_strategy([a1, a2, a3], { 'capital': capital, 'ratio': [0.3, 0.3, 0.4] }) run() a1.test(self) a2.test(self) all_holdings = profile.all_holdings() self.assertTrue(len(source) > 0 and len(source) == len(all_holdings), '模拟器测试失败!') for i in range(0, len(profile.all_holdings())): hd = all_holdings[i] hd0 = profile.all_holdings(0)[i] hd1 = profile.all_holdings(1)[i] hd2 = profile.all_holdings(2)[i] self.assertTrue(hd['cash'] == hd0['cash'] + hd1['cash'] + hd2['cash'], 'all_holdings接口测试失败!') self.assertTrue(hd['commission'] == hd0['commission'] + hd1['commission'] + hd2['commission'], 'all_holdings接口测试失败!') self.assertTrue(hd['equity'] == hd0['equity'] + hd1['equity'] + hd2['equity'], 'all_holdings接口测试失败!')
def on_exit(self, ctx): return if __name__ == '__main__': import timeit start = timeit.default_timer() set_config({'source': 'csv'}) set_symbols(['BB.SHFE-1.Day']) profile = add_strategy( [DemoStrategy('A1'), DemoStrategy2('A2')], { 'capital': 50000.0, 'ratio': [0.5, 0.5] }) run() stop = timeit.default_timer() print("运行耗时: %d秒" % ((stop - start))) # 绘制k线,交易信号线 from quantdigger.digger import finance, plotting s = 0 # 绘制策略A1, 策略A2, 组合的资金曲线 curve0 = finance.create_equity_curve(profile.all_holdings(0)) curve1 = finance.create_equity_curve(profile.all_holdings(1)) curve = finance.create_equity_curve(profile.all_holdings()) plotting.plot_strategy(profile.data(), profile.technicals(0), profile.deals(0), curve0.equity.values, profile.marks(0)) # 绘制净值曲线 plotting.plot_curves([curve.networth])
def test_case(self): """ 测试: * 指标变量 1) 指标变量和数值间的运算。 ctx.ma2 - 0 2) 指标变量回溯 ctx.ma2[3] 3) 单值和多值测试 """ close, open, ma, ma3, tech_operator = [], [], [], [], [] boll = { 'upper': [], 'middler': [], 'lower': [] } boll3 = { 'upper': [], 'middler': [], 'lower': [] } class DemoStrategy(Strategy): def on_init(self, ctx): """初始化数据""" ctx.ma = MA(ctx.close, 2) ctx.boll = BOLL(ctx.close, 2) def on_symbol(self, ctx): if ctx.curbar>=2: # @todo + * / tech_operator.append(ctx.ma - 0 == ctx.ma[0]) ma3.append(ctx.ma[3]) ma.append(ctx.ma[0]) close.append(ctx.close[0]) open.append(ctx.open[0]) boll['upper'].append(float(ctx.boll['upper'])) boll['middler'].append(ctx.boll['middler'][0]) boll['lower'].append(ctx.boll['lower'][0]) boll3['upper'].append(ctx.boll['upper'][3]) boll3['middler'].append(ctx.boll['middler'][3]) boll3['lower'].append(ctx.boll['lower'][3]) assert(isinstance(ctx.boll['lower'], NumberSeries)) assert(isinstance(ctx.ma, MA)) set_symbols(['BB.TEST-1.Minute']) add_strategy([DemoStrategy('A1')]) run() # 单值指标运算和回溯测试 source_ma = talib.SMA(np.asarray(close), 2) self.assertTrue(all(tech_operator), "指标运算错误!") self.assertFalse(ma[0] == ma[0], "指标NaN值测试失败!") for source, target in zip(source_ma[1:], ma[1:]): self.assertTrue(target == source, "单值指标计算测试失败!") for source, target in zip(ma[1:], ma3[4:]): self.assertTrue(target == source, "单值指标回溯测试失败!") for nan in ma3[:4]: self.assertFalse(nan == nan, "单值指标回溯NaN值测试失败!") logger.info('-- 单值指标测试成功 --') # 多值指标运算和回溯测试 upper, middler, lower = talib.BBANDS(np.asarray(close), 2, 2, 2) ta_boll = { 'upper': upper, 'middler': middler, 'lower': lower } for v in ['upper', 'lower', 'middler']: self.assertFalse(boll[v][0] == boll[v][0], "多值指标NaN值测试失败!") for source, target in zip(ta_boll[v][1:], boll[v][1:]): self.assertTrue(target == source, "多值指标计算测试失败!") for nan in boll3[v][:4]: self.assertFalse(nan == nan, "多值指标回溯NaN值测试失败!") for source, target in zip(boll[v][1:], boll3[v][4:]): self.assertTrue(target == source, "多值指标回溯测试失败!") logger.info('-- 多值指标测试成功 --') logger.info('***** 指标测试成功 *****\n')