年化18%-39.3%的策略集 | backtrader通过xtquant连接qmt实战

原创内容第785篇,专注量化投资、个人成长与财富自由。

大年初五,年很快就过完了。

其实就是本身也只是休假一周,但是我们赋予了它太多意义。

周五咱们发布发aitrader v4.1,带了backtrader+ctp期货的实盘接口:

aitrader_v4.1系统更新|含年化39.1%的组合策略代码|backtrader+openctp实盘(代码+数据)

组合策略运行效果如下:

图片

今天,我们把qmt的整合代码带上,然后对照着学习,backtrader对接实盘,需要三个文件:broker,datafeed和store。

图片

需要pip install xtquant,xtquant其实是与本机的qmt终端连接,需要本机安装并登录qmt终端:

我运行的是投研版本:

图片

import backtrader as bt
from live_trade.backtrader_qmt import QMTStore
from datetime import datetime
from xtquant import xtdata
import math


class BuyCondition(bt.Indicator):
    '''买入条件'''
    lines = ('buy_signal',)

    params = (
        ('up_days', 10),  # 连续上涨的天数
    )

    def __init__(self):
        self.lines.buy_signal = bt.If(self.data.close > self.data.close(-250), 1, 0)

    def next(self):
        # 检查250线斜率是否恰好连续向上self.params.up_days个交易日,再往前一个交易日斜率下降
        if len(self) >= self.params.up_days + 1:
            slope_up = all(self.data.close[-i] > self.data.close[-i - 1] for i in range(1, self.params.up_days + 1))
            slope_down_before = self.data.close[-self.params.up_days - 1] < self.data.close[-self.params.up_days - 2]
            if slope_up and slope_down_before:
                self.lines.buy_signal[0] = 1
            else:
                self.lines.buy_signal[0] = 0


class SellCondition(bt.Indicator):
    '''卖出条件'''
    lines = ('sell_signal',)

    params = (
        ('hold_days', 20),  # 持有天数
    )

    def __init__(self):
        self.hold_days = 0

    def next(self):
        # 持有self.params.hold_days个交易日卖出
        if self.hold_days >= self.params.hold_days:
            self.lines.sell_signal[0] = 1
            self.hold_days = 0
        else:
            self.lines.sell_signal[0] = 0
            self.hold_days += 1


class Sizer(bt.Sizer):
    '''仓位控制'''
    params = (
        ('buy_count', 1),  # 最大持仓股票个数
    )

    def __init__(self):
        pass

    def _getsizing(self, comminfo, cash, data, isbuy):
        if isbuy:
            # 如果是买入,平均分配仓位
            commission_rate = comminfo.p.commission
            size = math.floor(cash * (1 - commission_rate) / data.close[0] / self.params.buy_count / 100) * 100
        else:
            # 如果是卖出,全部卖出
            position = self.broker.getposition(data)
            size = position.size

        return size


class DemoStrategy(bt.Strategy):
    params = (
        ('max_positions', 5),  # 最大持仓股票个数
        ('up_days', 10),  # 连续上涨的天数
        ('hold_days', 20),  # 持有天数
    )

    def log(self, txt, dt=None):
        """ 记录交易日志 """
        dt = dt or self.datas[0].datetime.date(0)
        print(f'{dt.isoformat()}, {txt}')

    def __init__(self):
        # 初始化函数
        self.sizer = Sizer()
        self.buy_condition = {d: BuyCondition(d, up_days=self.params.up_days) for d in self.datas}
        self.sell_condition = {d: SellCondition(d, hold_days=self.params.hold_days) for d in self.datas}

    def next(self):
        # 先收集所有需要买入和卖出的股票
        buy_list = []
        sell_list = []

        for i, d in enumerate(self.datas):
            pos = self.getposition(d).size

            if pos and self.sell_condition[d].lines.sell_signal[0] > 0:
                sell_list.append(d)

            if self.buy_condition[d].lines.buy_signal[0] > 0:
                buy_list.append(d)

        # 动态设置Sizer的buy_count参数
        self.sizer.params.buy_count = len(buy_list)

        # 先执行卖出操作
        for d in sell_list:
            self.sell(data=d)

        # 再执行买入操作
        for d in buy_list:
            self.buy(data=d)


if __name__ == '__main__':

    store = QMTStore()

    code_list = xtdata.get_stock_list_in_sector('沪深300')

    # 添加数据
    datas = store.getdatas(code_list=code_list, timeframe=bt.TimeFrame.Days, fromdate=datetime(2022, 7, 1))

    for d in datas:
        # print(len(d))
        cerebro = bt.Cerebro(maxcpus=16)

        cerebro.adddata(d)

        # 添加策略
        # buy_date = datetime(2022, 8, 1).date()  # 设置固定买入日期
        cerebro.addstrategy(DemoStrategy)

        # cerebro.optstrategy

        # # 设置初始资金
        cerebro.broker.setcash(1000000.0)

        # 设置佣金
        cerebro.broker.setcommission(commission=0.001)

        # 运行回测
        # print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
        cerebro.run()
        if cerebro.broker.getvalue() != 1000000.0:
            print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())

    xtdata.run()

    #绘制结果
    cerebro.plot()

显示连接成功:

图片

明天继续。

代码和数据下载:AI量化实验室——2025量化投资的星辰大海

AI量化实验室 星球,已经运行三年多,1300+会员。

aitrader代码,含几十个策略源代码,因子表达式引擎、遗传算法(Deap)因子挖掘引等,支持vnpy,qlib,backtrader和bt引擎,内置多个年化30%+的策略,每周五迭代一次,代码和数据在星球全部开源。

图片

扩展  •  历史文章   

EarnMore(赚得更多)基于RL的投资组合管理框架:一致的股票表示,可定制股票池管理。(附论文+代码)
deap系统重构,再新增一个新的因子,年化39.1%,卡玛提升至2.76(附python代码)

deap时间序列函数补充,挖掘出年化39.12%的轮动因子,卡玛比率2.52

年化19.3%,回撤仅8%的实盘策略,以及backtrader整合CTPBee做实盘(附python代码和数据)

近四年年化收益19.3%,而最大回撤仅8%,卡玛比率2.34,投资应该是一件简单的事情。(附python代码+数据)

AGI通用智能实验室

紧跟前沿AGI研究进展,论文复现,可运行的代码,落地应用等。

既做科研,也做科普;研究基础大模型,也关心应用场景。

通往前沿通用人工智能(AGI)的路径已经展开。

这是一场史诗级的工业革命级别的技术变革,奇点临近,未来已来!

图片

### Backtrader 交易使用指南 对于希望利用 `Backtrader` 进行交易的用户来说,理解如何连接际市场以及执行订单至关重要。虽然官方文档主要中在回测功能上,但社区贡献了许多资源来帮助交易。 #### 配置经纪商接口 为了使策略能够时运行并与真账户交互,需要配置一个支持交易的数据源和经纪人API。常见的选择包括Interactive Brokers (IB),Alpaca等。这里以 Alpaca 为例展示基本设置方法: ```python import alpaca_backtrader_api as alpaca_bt from datetime import datetime cerebro = bt.Cerebro() ALPACA_API_KEY = &#39;your_alpaca_key&#39; ALPACA_SECRET_KEY = &#39;your_secret_key&#39; store = alpaca_bt.AlpacaStore( key_id=ALPACA_API_KEY, secret_key=ALPACA_SECRET_KEY, paper=True, # 是否启用模拟环境 ) data_feed = store.get_data(ticker=&#39;AAPL&#39;, fromdate=datetime(2021, 8, 1), todate=datetime.now(), frame=&#39;day&#39;) cerebro.adddata(data_feed) ``` 这段代码展示了如何创建与 Alpaca 的连接,并获取苹果公司股票的历史日线数据作为输入[^1]。 #### 定义交易策略类 定义继承自 `bt.Strategy` 的子类用于描述具体的买卖逻辑。下面是一个简单的移动平均交叉策略例: ```python class SmaCross(bt.Strategy): params = dict(fast_period=10, slow_period=30) def __init__(self): sma_fast = bt.indicators.SimpleMovingAverage(self.data.close, period=self.params.fast_period) sma_slow = bt.indicators.SimpleMovingAverage(self.data.close, period=self.params.slow_period) self.crossover = bt.ind.CrossOver(sma_fast, sma_slow) def next(self): if not self.position: if self.crossover > 0: self.buy() elif self.crossover < 0: self.sell() cerebro.addstrategy(SmaCross) ``` 此部分现了基于快速SMA穿越慢速SMA信号买入卖出的操作流程[^2]。 #### 启动Cerebro引擎并监控性能 最后一步就是启动 Cerebro 引擎来进行仿真或操作: ```python if __name__ == &#39;__main__&#39;: cerebro.broker.setcash(10000.0) # 设置初始资金量 print(&#39;Starting Portfolio Value: %.2f&#39; % cerebro.broker.getvalue()) result = cerebro.run() # 执行策略 print(&#39;Ending Portfolio Value: %.2f&#39; % cerebro.broker.getvalue()) cerebro.plot() # 可视结果 ``` 以上脚本会打印出起始和结束的投资组合价值,并绘制图表以便直观查看表现情况。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI量化投资实验室

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值