【量化回测】backtracker整体架构和使用示例

backtrader整体框架

backtrader 是一个量化回测的库,支持多品种、多策略、多周期的回测和交易。更重要的是可以集成 torch 等神经网络分析模块。

Cerebro类是 backtrader 的核心。Strategy类、BrokerSizer类都是由Cerebro类实例化而来。

整体流程

  • backtrade 自带的数据源是yahoofinance(),也可使用自己本地的 csv 文件。
  • DataFeed模块会将原始数据导入到 Cerebro ,之后就可以进行矢量化操作。
  • Strategy模块会根据策略将订单提交到BrokerBroker是一个抽象的交易所,里面定义了订单执行、仓位管理和交易费率等。
  • Strategy模块中包括了三个模块ObserverAnalyzerIndicatorObserver负责观测市场数据。Analyzer负责分析算法产生的数据,可以看做是一个评估模块。Indicator是指标和信号模块,策略主要通过指标和信号来判断是否触发交易。
  • Sizer主要负责仓位的管理。因为Strategy只负责触发交易,但不知道怎么分配仓位。Sizer就可以独立控制仓位管理。

数据流程

实操流程

安装环境

python 复制代码
pip install backtrader matplotlib

回测示例

注意,需要准备CSV格式的个股数据。

python 复制代码
import backtrader as bt
import pandas as pd
import matplotlib.pyplot as plt
import datetime as dt
import numpy as np


class SMAStrategy(bt.Strategy):
    '''
    自定义的策略, 需继承 bt.Strategy
    '''
    def __init__(self):
        self.dataclose = self.data0.close
        self.order = None
        self.buyprice = None
        self.buycomm = None

        self.sma = bt.indicators.SimpleMovingAverage(self.data0, period=15)

    def next(self):
        '''
        一般在这里写实际的策略。
        这里就是收盘价上穿sma买入,反之则卖出。
        '''
        if not self.position:  # 判断是否有持仓
            if self.dataclose[0] > self.sma[0]:  # 判断收盘价是否上穿sma
                self.buy()
        else:
            if self.dataclose[0] < self.sma[0]:
                self.close()  # 平仓

    def notify_order(self, order):
        '''
        获取订单状态,这个函数一般可以通用。
        '''
        if order.status in [order.Submitted, order.Accepted]:
            return
        
        if order.status in [order.Completed]:
            if order.isbuy():
                self.log(
                    'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                    (order.executed.price,
                    order.executed.value,
                    order.executed.comm)
                )
                self.buyprice = order.executed.price
                self.buycomm = order.executed.comm
            else:
                self.log(
                    'SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
                    (order.executed.price,
                    order.executed.value,
                    order.executed.comm)
                )
                self.bar_executed = len(self)
        elif order.status in [order.Canceled, order.Margin, order.Rejected]:
            self.log('Drder Canceled / Margin / Rejected')
        self.order = None
    
    def notify_trade(self, trade):
        '''
        追踪每笔交易的状态,这个函数一般可以通用。
        '''
        if not trade.isclosed:
            return
        self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' %
                 (trade.pnl, trade.pnlcomm))
        
    def log(self, txt, dt=None, doprint=False):
        '''
        保存日志
        '''
        if doprint:
            dt = dt or self.datas[0].datetiem.date(0)
            print('%s, %s' % (dt.isoformat(), txt))



if __name__ == "__main__":
    # 实例化cerebro
    cerebro = bt.Cerebro()

    # 处理数据
    dataframe = pd.read_csv('TSLA.csv')
    dataframe['Datetime'] = pd.to_datetime(dataframe['Date'])
    dataframe.set_index('Datetime', inplace=True)

    # 加载数据源
    data_TSLA = bt.feeds.PandasData(dataname = dataframe,
                                    fromdate = dt.datetime(2025,1,2), 
                                    todate = dt.datetime(2025,1,31))
    cerebro.adddata(data_TSLA)

    # 加载策略
    cerebro.addstrategy(SMAStrategy)

    # 加载Analyzer
    cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name="SharpeRatio")
    cerebro.addanalyzer(bt.analyzers.DrawDown, _name = "DrawDown")

    # 在Broker中设置初始资金和手续费
    cerebro.broker.setcash(10000.0)
    cerebro.broker.setcommission(commission = 0.0006)

    # 设置Sizer
    cerebro.addsizer(bt.sizers.PercentSizer, percents = 90)

    result = cerebro.run()

    print("夏普比率", result[0].analyzers.SharpeRatio.get_analysis()['sharperatio'])
    print("最大回撤", result[0].analyzers.DrawDown.get_analysis["max"]['drawdown'])
    cerebro.plot()

参考:【【Backtrader教程01】Python Backtrader量化回测框架 | 代码实战教学 | 单均线回测收益率570%?】 https://www.bilibili.com/video/BV1QR4y147rS/?share_source=copy_web\&vd_source=9eb6d7fad45f9fa869cd9abb34fa68ca

相关推荐
花酒锄作田1 天前
使用 pkgutil 实现动态插件系统
python
前端付豪1 天前
LangChain链 写一篇完美推文?用SequencialChain链接不同的组件
人工智能·python·langchain
曲幽1 天前
FastAPI实战:打造本地文生图接口,ollama+diffusers让AI绘画更听话
python·fastapi·web·cors·diffusers·lcm·ollama·dreamshaper8·txt2img
老赵全栈实战1 天前
Pydantic配置管理最佳实践(一)
python
阿尔的代码屋2 天前
[大模型实战 07] 基于 LlamaIndex ReAct 框架手搓全自动博客监控 Agent
人工智能·python
AI探索者2 天前
LangGraph StateGraph 实战:状态机聊天机器人构建指南
python
AI探索者2 天前
LangGraph 入门:构建带记忆功能的天气查询 Agent
python
FishCoderh2 天前
Python自动化办公实战:批量重命名文件,告别手动操作
python
躺平大鹅2 天前
Python函数入门详解(定义+调用+参数)
python
曲幽2 天前
我用FastAPI接ollama大模型,差点被asyncio整崩溃(附对话窗口实战)
python·fastapi·web·async·httpx·asyncio·ollama