vnpy实现一个简单EMA双均线策略并回测
""" 简单EMA策略. """ from vnpy.app.cta_strategy.template import CtaTemplate from typing import Any from vnpy.trader.object import BarData, Interval, TickData, TradeData, OrderData from vnpy.trader.utility import BarGenerator, ArrayManager from datetime import datetime from vnpy.app.cta_strategy.backtesting import BacktestingEngine import talib class BitquantEmaStrategy(CtaTemplate): short_ema = 15 long_ema = 50 short_ema_values = 0.0 long_ema_values = 0.0 parameters = ["short_ema", "long_ema"] variables = ['short_ema_values', 'long_ema_values'] def __init__( self, cta_engine: Any, strategy_name: str, vt_symbol: str, setting: dict): super(BitquantEmaStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) # self.bg = BarGenerator(self.on_bar, window=15, on_window_bar=self.on_5min_bar, interval=Interval.MINUTE) # 这里注意要从这个函数进去 # utility.py self.window_bar.volume += float(bar.volume) #这里要改为float 因为成交量可以是小数的 self.bg = BarGenerator(self.on_bar, window=1, on_window_bar=self.on_hour_bar, interval=Interval.HOUR) self.am = ArrayManager(200) def on_init(self): print("on init") self.load_bar(3) def on_start(self): """ Callback when strategy is started. """ print("on_start strategy") def on_tick(self, tick: TickData): pass def on_bar(self, bar: BarData): self.bg.update_bar(bar) def on_5min_bar(self, bar: BarData): print(bar) def on_15min_bar(self, bar: BarData): pass def on_hour_bar(self, bar: BarData): # print(bar) self.cancel_all() # 先撤单 # self.cancel_order() self.am.update_bar(bar) if not self.am.inited: return self.short_ema_values = talib.EMA(self.am.close, timeperiod=self.short_ema) # series self.long_ema_values = talib.EMA(self.am.close_array, timeperiod=self.long_ema) # series if self.short_ema_values[-1] > self.long_ema_values[-1] and self.short_ema_values[-2] < self.long_ema_values[-2]: trend_status = 1 elif self.short_ema_values[-1] < self.long_ema_values[-1] and self.short_ema_values[-2] > self.long_ema_values[-2]: trend_status = -1 else: trend_status = 0 if self.pos == 0: # 没有仓位 if trend_status == 1: self.buy(bar.close_price+2, 1) # 做多 elif trend_status == -1: self.short(bar.close_price-2,1) # 做空 elif self.pos > 0: # 有多有仓位 if trend_status == -1: self.sell(bar.close_price, abs(self.pos)) # 先平多头仓位,再反手开空 self.short(bar.close_price, 1) # 做空一个BTC. elif self.pos < 0: # 有空头的仓位 if trend_status == 1: self.cover(bar.close_price, abs(self.pos)) # 先平空头仓位, 然后反手开多 self.buy(bar.close_price, 1) def on_trade(self, trade: TradeData): pass def on_order(self, order: OrderData): pass if __name__ == '__main__': # 回测引擎初始化 # 注意要从这里进去把股票计算的240天改为数字货币的365天(计算年化收益) # backtesting.py annual_return = total_return / total_days * 240 engine = BacktestingEngine() # 设置交易对产品的参数 engine.set_parameters( vt_symbol="XBTUSD.BITMEX", # 交易的标的 interval=Interval.MINUTE, start=datetime(2018, 1, 1), # 开始时间 rate=7.5 / 10000, # 手续费 slippage=0.5, # 交易滑点 size=1, # 合约乘数 pricetick=0.5, # 8500.5 8500.01 capital=100000, # 初始资金 end=datetime(2018, 6, 1) # 结束时间 ) # 添加策略 engine.add_strategy(BitquantEmaStrategy, {}) # 加载 engine.load_data() # 运行回测 engine.run_backtesting() # 统计结果 engine.calculate_result() # 计算策略的统计指标 Sharp ratio, drawdown engine.calculate_statistics() # 绘制图表 # engine.show_chart()
优化开仓仓位和止盈止损
""" 简单EMA策略. """ from vnpy.app.cta_strategy.template import CtaTemplate from typing import Any from vnpy.trader.object import BarData, Interval, TickData, TradeData, OrderData, Direction, Offset from vnpy.trader.utility import BarGenerator, ArrayManager from datetime import datetime from vnpy.app.cta_strategy.backtesting import BacktestingEngine from vnpy.app.cta_strategy.base import StopOrder import talib class BitquantEmaStrategy(CtaTemplate): short_ema = 15 long_ema = 50 trade_money = 100000 short_ema_values = 0.0 long_ema_values = 0.0 long_entry = 0 short_entry = 0 parameters = ["short_ema", "long_ema", "trade_money"] variables = ['short_ema_values', 'long_ema_values'] def __init__( self, cta_engine: Any, strategy_name: str, vt_symbol: str, setting: dict): super(BitquantEmaStrategy, self).__init__(cta_engine, strategy_name, vt_symbol, setting) # self.bg = BarGenerator(self.on_bar, window=15, on_window_bar=self.on_5min_bar, interval=Interval.MINUTE) self.bg = BarGenerator(self.on_bar, window=1, on_window_bar=self.on_hour_bar, interval=Interval.HOUR) self.am = ArrayManager(200) def on_init(self): print("on init") self.load_bar(3) def on_start(self): """ Callback when strategy is started. """ print("on_start strategy") def on_tick(self, tick: TickData): pass def on_bar(self, bar: BarData): self.bg.update_bar(bar) def on_5min_bar(self, bar: BarData): print(bar) def on_15min_bar(self, bar: BarData): pass def on_hour_bar(self, bar: BarData): # print(bar) self.cancel_all() # 先撤单 # self.cancel_order() self.am.update_bar(bar) if not self.am.inited: return self.short_ema_values = talib.EMA(self.am.close, timeperiod=self.short_ema) # series self.long_ema_values = talib.EMA(self.am.close_array, timeperiod=self.long_ema) # series if self.short_ema_values[-1] > self.long_ema_values[-1] and self.short_ema_values[-2] < self.long_ema_values[-2]: trend_status = 1 elif self.short_ema_values[-1] < self.long_ema_values[-1] and self.short_ema_values[-2] > self.long_ema_values[-2]: trend_status = -1 else: trend_status = 0 if self.pos == 0: # 没有仓位 if trend_status == 1: self.buy(bar.close_price, self.trade_money/bar.close_price) # 做多 elif trend_status == -1: self.short(bar.close_price, self.trade_money/bar.close_price) # 做空 elif self.pos > 0: # 有多有仓位 if trend_status == -1: self.sell(bar.close_price, abs(self.pos)) # 先平多头仓位,再反手开空 self.short(bar.close_price, self.trade_money/bar.close_price) # 做空按照开仓的资金来计算 else: self.sell(self.long_entry * (1-0.01), abs(self.pos), stop=True) # 停止单. # self.sell(self.long_entry * (1+0.06), abs(self.pos)) # 止盈. elif self.pos < 0: # 有空头的仓位 if trend_status == 1: self.cover(bar.close_price, abs(self.pos)) # 先平空头仓位, 然后反手开多 self.buy(bar.close_price, self.trade_money/bar.close_price) #做多按照开仓的资金来计算 else: # self.cover(self.short_entry * (1-0.06), abs(self.pos)) self.cover(self.short_entry*(1+0.01), abs(self.pos), stop=True) def on_trade(self, trade: TradeData): if self.pos != 0: if trade.direction == Direction.LONG and trade.offset == Offset.OPEN: self.long_entry = trade.price elif trade.direction == Direction.SHORT and trade.offset == Offset.OPEN: self.short_entry = trade.price def on_order(self, order: OrderData): pass def on_stop_order(self, stop_order: StopOrder): pass if __name__ == '__main__': # 回测引擎初始化 engine = BacktestingEngine() # 设置交易对产品的参数 engine.set_parameters( vt_symbol="XBTUSD.BITMEX", # 交易的标的 interval=Interval.MINUTE, start=datetime(2018, 1, 1), # 开始时间 rate=7.5 / 10000, # 手续费 slippage=0.5, # 交易滑点 size=1, # 合约乘数 pricetick=0.5, # 8500.5 8500.01 capital=100000, # 初始资金 # end=datetime(2018, 6, 1) # 结束时间 ) # 添加策略 engine.add_strategy(BitquantEmaStrategy, {}) # 加载 engine.load_data() # 运行回测 engine.run_backtesting() # 统计结果 engine.calculate_result() # 计算策略的统计指标 Sharp ratio, drawdown engine.calculate_statistics() # 绘制图表 engine.show_chart()