AkShare 策略示例

股票策略

BackTrader-基本策略

代码

下载和安装 BackTrader

  1. from datetime import datetime
  2. import backtrader as bt
  3. import matplotlib.pyplot as plt
  4. import akshare as ak
  5. plt.rcParams["font.sans-serif"] = ["SimHei"]
  6. plt.rcParams["axes.unicode_minus"] = False
  7. stock_hfq_df = ak.stock_zh_a_daily(symbol="sh600000", adjust="hfq") # 利用 AkShare 获取后复权数据
  8. class MyStrategy(bt.Strategy):
  9. """
  10. 主策略程序
  11. """
  12. params = (("maperiod", 20),) # 全局设定交易策略的参数
  13. def __init__(self):
  14. """
  15. 初始化函数
  16. """
  17. self.data_close = self.datas[0].close # 指定价格序列
  18. # 初始化交易指令、买卖价格和手续费
  19. self.order = None
  20. self.buy_price = None
  21. self.buy_comm = None
  22. # 添加移动均线指标
  23. self.sma = bt.indicators.SimpleMovingAverage(
  24. self.datas[0], period=self.params.maperiod
  25. )
  26. def next(self):
  27. """
  28. :return:
  29. :rtype:
  30. """
  31. if self.order: # 检查是否有指令等待执行,
  32. return
  33. # 检查是否持仓
  34. if not self.position: # 没有持仓
  35. if self.data_close[0] > self.sma[0]: # 执行买入条件判断:收盘价格上涨突破20日均线
  36. self.order = self.buy(size=100) # 执行买入
  37. else:
  38. if self.data_close[0] < self.sma[0]: # 执行卖出条件判断:收盘价格跌破20日均线
  39. self.order = self.sell(size=100) # 执行卖出
  40. cerebro = bt.Cerebro() # 初始化回测系统
  41. start_date = datetime(2000, 1, 1) # 回测开始时间
  42. end_date = datetime(2020, 4, 21) # 回测结束时间
  43. data = bt.feeds.PandasData(dataname=stock_hfq_df, fromdate=start_date, todate=end_date) # 加载数据
  44. cerebro.adddata(data) # 将数据传入回测系统
  45. cerebro.addstrategy(MyStrategy) # 将交易策略加载到回测系统中
  46. start_cash = 1000000
  47. cerebro.broker.setcash(start_cash) # 设置初始资本为 100000
  48. cerebro.broker.setcommission(commission=0.002) # 设置交易手续费为 0.2%
  49. cerebro.run() # 运行回测系统
  50. port_value = cerebro.broker.getvalue() # 获取回测结束后的总资金
  51. pnl = port_value - start_cash # 盈亏统计
  52. print(f"初始资金: {start_cash}\n回测期间:{start_date.strftime('%Y%m%d')}:{end_date.strftime('%Y%m%d')}")
  53. print(f"总资金: {round(port_value, 2)}")
  54. print(f"净收益: {round(pnl, 2)}")
  55. cerebro.plot(style='candlestick') # 画图

结果

  1. 初始资金: 1000000
  2. 回测期间:20000101:20200421
  3. 总资金: 1010238.65
  4. 净收益: 10238.65

可视化

https://jfds-1252952517.cos.ap-chengdu.myqcloud.com/akshare/readme/strategy/Figure_0.png

BackTrader-参数优化

代码

下载和安装 BackTrader

  1. import backtrader as bt
  2. import matplotlib.pyplot as plt
  3. import akshare as ak
  4. plt.rcParams["font.sans-serif"] = ["SimHei"] # 设置画图时的中文显示
  5. plt.rcParams["axes.unicode_minus"] = False # 设置画图时的负号显示
  6. class MyStrategy(bt.Strategy):
  7. """
  8. 主策略程序
  9. """
  10. params = (("maperiod", 20),
  11. ('printlog', False),) # 全局设定交易策略的参数, maperiod是 MA 均值的长度
  12. def __init__(self):
  13. """
  14. 初始化函数
  15. """
  16. self.data_close = self.datas[0].close # 指定价格序列
  17. # 初始化交易指令、买卖价格和手续费
  18. self.order = None
  19. self.buy_price = None
  20. self.buy_comm = None
  21. # 添加移动均线指标
  22. self.sma = bt.indicators.SimpleMovingAverage(
  23. self.datas[0], period=self.params.maperiod
  24. )
  25. def next(self):
  26. """
  27. 主逻辑
  28. """
  29. # self.log(f'收盘价, {data_close[0]}') # 记录收盘价
  30. if self.order: # 检查是否有指令等待执行,
  31. return
  32. # 检查是否持仓
  33. if not self.position: # 没有持仓
  34. # 执行买入条件判断:收盘价格上涨突破15日均线
  35. if self.data_close[0] > self.sma[0]:
  36. self.log("BUY CREATE, %.2f" % self.data_close[0])
  37. # 执行买入
  38. self.order = self.buy()
  39. else:
  40. # 执行卖出条件判断:收盘价格跌破15日均线
  41. if self.data_close[0] < self.sma[0]:
  42. self.log("SELL CREATE, %.2f" % self.data_close[0])
  43. # 执行卖出
  44. self.order = self.sell()
  45. def log(self, txt, dt=None, do_print=False):
  46. """
  47. Logging function fot this strategy
  48. """
  49. if self.params.printlog or do_print:
  50. dt = dt or self.datas[0].datetime.date(0)
  51. print('%s, %s' % (dt.isoformat(), txt))
  52. def notify_order(self, order):
  53. """
  54. 记录交易执行情况
  55. """
  56. # 如果 order 为 submitted/accepted,返回空
  57. if order.status in [order.Submitted, order.Accepted]:
  58. return
  59. # 如果order为buy/sell executed,报告价格结果
  60. if order.status in [order.Completed]:
  61. if order.isbuy():
  62. self.log(
  63. f"买入:\n价格:{order.executed.price},\
  64. 成本:{order.executed.value},\
  65. 手续费:{order.executed.comm}"
  66. )
  67. self.buyprice = order.executed.price
  68. self.buycomm = order.executed.comm
  69. else:
  70. self.log(
  71. f"卖出:\n价格:{order.executed.price},\
  72. 成本: {order.executed.value},\
  73. 手续费{order.executed.comm}"
  74. )
  75. self.bar_executed = len(self)
  76. # 如果指令取消/交易失败, 报告结果
  77. elif order.status in [order.Canceled, order.Margin, order.Rejected]:
  78. self.log("交易失败")
  79. self.order = None
  80. def notify_trade(self, trade):
  81. """
  82. 记录交易收益情况
  83. """
  84. if not trade.isclosed:
  85. return
  86. self.log(f"策略收益:\n毛收益 {trade.pnl:.2f}, 净收益 {trade.pnlcomm:.2f}")
  87. def stop(self):
  88. """
  89. 回测结束后输出结果
  90. """
  91. self.log("(MA均线: %2d日) 期末总资金 %.2f" % (self.params.maperiod, self.broker.getvalue()), do_print=True)
  92. def main(code="sh601318", start_cash=1000000, stake=100, commission_fee=0.001):
  93. cerebro = bt.Cerebro() # 创建主控制器
  94. cerebro.optstrategy(MyStrategy, maperiod=range(3, 31)) # 导入策略参数寻优
  95. stock_zh_a_daily_df = ak.stock_zh_a_daily(
  96. symbol=code, adjust="hfq"
  97. ) # 通过 AkShare 获取需要的数据
  98. data = bt.feeds.PandasData(dataname=stock_zh_a_daily_df) # 规范化数据格式
  99. cerebro.adddata(data) # 将数据加载至回测系统
  100. cerebro.broker.setcash(start_cash) # broker设置资金
  101. cerebro.broker.setcommission(commission=commission_fee) # broker手续费
  102. cerebro.addsizer(bt.sizers.FixedSize, stake=stake) # 设置买入数量
  103. print("期初总资金: %.2f" % cerebro.broker.getvalue())
  104. cerebro.run(maxcpus=1) # 用单核 CPU 做优化
  105. print("期末总资金: %.2f" % cerebro.broker.getvalue())

结果

  1. 期初总资金: 1000000.00
  2. 2020-06-12, (MA均线: 3日) 期末总资金 1004105.69
  3. 2020-06-12, (MA均线: 4日) 期末总资金 1002384.49
  4. 2020-06-12, (MA均线: 5日) 期末总资金 1002063.96
  5. 2020-06-12, (MA均线: 6日) 期末总资金 1002113.63
  6. 2020-06-12, (MA均线: 7日) 期末总资金 1001715.32
  7. 2020-06-12, (MA均线: 8日) 期末总资金 999702.60
  8. 2020-06-12, (MA均线: 9日) 期末总资金 1001658.65
  9. 2020-06-12, (MA均线: 10日) 期末总资金 999698.63
  10. 2020-06-12, (MA均线: 11日) 期末总资金 1003370.08
  11. 2020-06-12, (MA均线: 12日) 期末总资金 1002183.37
  12. 2020-06-12, (MA均线: 13日) 期末总资金 1006154.29
  13. 2020-06-12, (MA均线: 14日) 期末总资金 1007900.55
  14. 2020-06-12, (MA均线: 15日) 期末总资金 1008421.63
  15. 2020-06-12, (MA均线: 16日) 期末总资金 1008708.77
  16. 2020-06-12, (MA均线: 17日) 期末总资金 1008734.88
  17. 2020-06-12, (MA均线: 18日) 期末总资金 1010371.15
  18. 2020-06-12, (MA均线: 19日) 期末总资金 1010186.34
  19. 2020-06-12, (MA均线: 20日) 期末总资金 1010201.81
  20. 2020-06-12, (MA均线: 21日) 期末总资金 1010782.44
  21. 2020-06-12, (MA均线: 22日) 期末总资金 1011271.23
  22. 2020-06-12, (MA均线: 23日) 期末总资金 1011711.92
  23. 2020-06-12, (MA均线: 24日) 期末总资金 1012475.96
  24. 2020-06-12, (MA均线: 25日) 期末总资金 1010726.64
  25. 2020-06-12, (MA均线: 26日) 期末总资金 1012502.74
  26. 2020-06-12, (MA均线: 27日) 期末总资金 1011219.53
  27. 2020-06-12, (MA均线: 28日) 期末总资金 1013569.11
  28. 2020-06-12, (MA均线: 29日) 期末总资金 1014176.30
  29. 2020-06-12, (MA均线: 30日) 期末总资金 1014076.32
  30. 期末总资金: 1014076.32