Backtrader案例:简单双均线

一、双均线策略介绍

  • 买入:MA5 上穿 MA20
  • 卖出:MA5 下穿 MA20
  • 回测对象:上证指数
  • 起始时间:2020.1.1
  • 截止时间:2022.11.25
  • 佣金:双边各 0.03%
  • 滑点:双边各 0.01%

二、数据获取代码

import akshare as ak

# 从 akshare 获取上证指数每日数据,并加工成 backtrader 要求的格式
sh_index = ak.stock_zh_index_daily(symbol="sh000001")
sh_index['openinterest'] = 0
sh_index.index = pd.to_datetime(sh_index.date)
sh_index = sh_index[['open', 'high', 'low', 'close', 'volume', 'openinterest']] 

在这里插入图片描述

三、策略完整代码

import pandas as pd
import backtrader as bt
import akshare as ak

#双均线策略
class DoubleMA_Strategy(bt.Strategy):
    params = (
        ("sma5",5),
        ("sma20",20)
    )
    
    # 打印日志
    def log(self, txt, dt=None):
        dt = dt or self.data.datetime.date(0)
        print("%s, %s, "%(dt, txt))
        
    def __init__(self):
        # 用于保存订单
        self.order = None
        
        # 计算MA5
        self.sma5 = bt.ind.MovingAverageSimple(self.data.close,period=self.params.sma5)
        
        # 计算MA20
        self.sma20 = bt.ind.MovingAverageSimple(self.data.close,period=self.params.sma20)
    
    def notify_order(self,order):
        # 等待订单提交,订单被cerebro接受
        if order.status in [order.Submitted, order.Accepted]:
            return
        
        # 等待订单完成
        if order.status in [order.Completed]:
            if order.isbuy():
                self.log(
                    '买入,价格: %.2f, 成本: %.2f, 佣金 %.2f' %
                    (order.executed.price,
                     order.executed.value,
                     order.executed.comm)
                )
            else:
                self.log(
                    '卖出,价格: %.2f, 成本: %.2f, 佣金 %.2f' %
                    (order.executed.price,
                     order.executed.value,
                     order.executed.comm)
                )
                
        # 如果订单保证金不足,将不会执行,而是执行以下拒绝程序        
        elif order.status in [order.Cancled, order.Margin, order.Rejected]:
                self.log("Order Canceled(取消)/Margin()/Rejected(拒绝)")
            
        self.order = None
        
    def notify_trade(self, trade):
        if not trade.isclosed:
            return
        
        self.log('盈利: %.2f, 手续费: %.2f\n' %
                 (trade.pnl, trade.pnlcomm))  # pnl:盈利  pnlcomm:手续费
        
    def next(self):
        # 当今天的10日均线大于30日均线并且昨天的10日均线小于30日均线,则进入市场(买)
        if self.sma5[0] > self.sma20[0] and self.sma5[-1] < self.sma20[-1]:
            # 判断订单是否完成,完成则为None,否则为订单信息
            if self.order:
                return
            
            #若上一个订单处理完成,可继续执行买入操作
            self.order = self.buy()
            
        # 当今天的10日均线小于30日均线并且昨天的10日均线大于30日均线,则退出市场(卖)
        elif self.sma5[0] < self.sma20[0] and self.sma5[-1] > self.sma20[-1]:
            # 卖出
            self.order = self.sell()
        
                
if __name__ == "__main__":
    # 从 akshare 获取上证指数每日数据
    sh_index = ak.stock_zh_index_daily(symbol="sh000001")
    sh_index['openinterest'] = 0
    sh_index.index = pd.to_datetime(sh_index.date)
    sh_index = sh_index[['open', 'high', 'low', 'close', 'volume', 'openinterest']]
    
    # 导入数据到 Backtrader
    data = bt.feeds.PandasData(
        dataname=sh_index, 
        fromdate=pd.to_datetime("2020-01-01"), # 回测开始日期
        todate=pd.to_datetime("2022-11-25")    # 回测结束日期
    )
    
    cerebro = bt.Cerebro()                 # 实例化大脑
    cerebro.addstrategy(DoubleMA_Strategy) # 添加策略
    cerebro.adddata(data, name="SH")       # 添加数据
    
    cerebro.broker.setcash(1000000.0)      # 初始资金
    cerebro.broker.setcommission(commission=0.0003) # 佣金,双边各 0.0003
    cerebro.broker.set_slippage_perc(perc=0.0001)   # 滑点:双边各 0.0001
    
    print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) # 打印初始现金
    cerebro.run()  # 执行策略
    print('Ending Portfolio Value: %.2f' % cerebro.broker.getvalue())  # 打印策略运行结束后的现金
    
    cerebro.plot(style='candlestick',volume=False) # 可视化

在这里插入图片描述

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值