返回列表 发布新帖

量化研究---推出强大西蒙斯量化交易回测系统2.0

69 0
发表于 前天 13:26 | 显示全部楼层 阅读模式

工欲善其事必先利其器,有一个强大的回测框架检验策略还是很必要,我目前利用qmt,ptrade回测,感觉还是有很大的不足,我就开发了自己的回测系统

58c48a33a045f9de7e1ef66140b99b6f.png

底层的源代码不亚于我开发的实盘交易系统

c802d6619c5ea61cd438dae30eb9cad0.png

同时我把qmt实盘也兼容过来了支持实盘交易

3a5f86db4285cf9efe0cc4d1b2a1433a.png

看一下目前免费的回测框架

Python 的策略回测框架种类繁多,适用于不同场景和需求。以下是目前主流的 Python 回测框架及其特点:

1. Backtrader

  • 特点
    • 高度模块化,支持多资产(股票、期货、外汇等)和多时间周期回测。
    • 内置技术分析指标(如 Talib),支持自定义策略和数据分析。
    • 本地数据兼容性强,可直接加载 CSV、Pandas DataFrame 或数据库数据。
    • 支持实盘交易对接(如 Interactive Brokers)。
  • 适用场景:适合需要深度定制策略的量化交易者710。

2. Zipline

  • 特点
    • 由 Quantopian 开发,事件驱动模型,精确模拟订单执行、滑点与手续费。
    • 适用于美股市场,但可通过插件扩展支持 A 股等市场。
    • 提供 Quantopian 生态集成,支持社区策略共享。
  • 适用场景:适合美股策略回测及社区协作28。

3. RQAlpha(米筐)

  • 特点
    • 支持 A 股、期货、ETF 等市场,提供完整的回测、模拟交易、实盘交易解决方案。
    • 模块化架构,易于扩展,适合结合机器学习进行量化研究。
    • 提供滑点、手续费、换手率等真实交易环境模拟。
  • 适用场景:适合中国市场的量化策略开发2。

4. PyAlgoTrade

  • 特点
    • 轻量级,运行速度快,适合快速验证中小型策略。
    • 支持实时交易接口(如 OANDA、Robinhood)。
    • 内置 TALib 技术指标,但不深度整合 Pandas。
  • 适用场景:适合高频策略回测及实盘交易410。

5. QuantConnect

  • 特点
    • 云端一体化平台,支持 Python 和 C#,提供全球化数据(包括新加坡交易所)。
    • 内置风险管理工具,如波动率监测、最大回撤预警。
    • 订阅制收费,适合资源有限的团队。
  • 适用场景:适合需要全托管服务的量化团队37。

6. vn.py

  • 特点
    • 国内开源框架,侧重实盘交易,支持 A 股、期货、期权等市场。
    • 提供 GUI 环境(VN Station),内置 CTA 策略、价差交易等功能。
    • 社区活跃,中文文档完善。
  • 适用场景:适合中国市场的专业量化交易员86。

7. Hikyuu

  • 特点**:**
    • 基于 C++/Python 的高性能框架,百万级 K 线回测仅需 1~2 秒。
    • 支持 A 股全市场计算,内置多种技术指标优化。
    • 提供 pyecharts 可视化支持。
  • 适用场景**:适合超大规模数据回测及高频策略研究9。**

8. bt (Backtesting Toolkit)

  • 特点
    • 基于 Pandas 和 NumPy,支持树状策略结构(多层策略组合)。
    • 提供多种算法(如等权重再平衡、动量策略)。
    • 适合多资产组合优化。
  • 适用场景:适合资产配置策略回测5。

如何选择?

  • 美股策略:Zipline、QuantConnect
  • A 股/中国市场:RQAlpha、vn.py、Hikyuu
  • 高频/实盘交易:PyAlgoTrade、Backtrader

目前就backtrader简单一点本地的回测框架,但是数据处理也是一个难题,我底层的回测框架支持自动加载数据,支持东方财富,qmt,通达信数据源,自动加载数据

022bf801870ca1a13b2a262b20ac61a0.png

ca6897fed4ece925ab4da60a7212dda8.png

1点击安装第三方库库,安装需要安装的库

c352cfd6d7def235d2cbb3078ff14643.png

4dcae32d5da073940816c3c088fb56b4.png

点击例子回测可以设置回测参数

2446e26e232f5ef9f1b728bc37cd0500.png

参数设置

89d236469b8c6e79273e87ad698520df.png

回测的结果自动加载数据

5634b52c8a923ebce5e06ffa56361b76.png

开始回测交易

139d9e5eac462700fd5ed9d746a1e395.png

生成的个股交易买卖点方便分析

7b4e71038b8a276c590542e9a91a50c2.png

个股交易买卖点

75cf3ca1e12b44bcf627fef199d6e51f.png

655a3bb592c25ca5728eddfa1a4be964.png

ca075591a8b3f4e074b04320feea2dae.png

8f4a8331bc79732fa5b29bf49f795bdc.png

点击策略报告文件夹看策略的报告

23b07c6ecd9bbad98921f71f374802ed.png

策略报告

5c4b7f55cac0c00ba521eace8c0e6b9e.png

和实盘差不多,年化20,最大回撤3.7,实盘有高频模块的加持回撤小一点,大概2%

f2c564e2836b72b82cdfc48d25a29ed7.jpg

实盘挂服务器24小时运行

24be0c32b56545c8f5f610712962ce0c.png

35e00a5d41fe528ce23c5bf9b6cd9126.png

明细的策略报告内容

dcd034858fe26841d5ac58d5ac06f6d2.png

d1ef0def61a7ca48937fee2e51de8103.png

b26a64786cd43a995d0b8a8df6bfe561.png

d10a80d0ca053f2bfdde0eb59c301155.png

c392f1c47e0a1e6919ba2ad47054e86b.png

源代码框架我全部上传了知识星球可以下载直接使用,最后几张五一优惠

a367a006bb6c8aab5d23e0d0d6848fd4.png

不懂的问我就可以,加我备注入群可以加入量化研究群

186f5c21be6307d2a4b6d862958e9542.jpg

回测的源代码

'''
西蒙斯量化回测系统
作者:西蒙斯量化
微信:xg_quant
'''
from backtrader import backtrader
from user_def_data.user_def_data import user_def_data
import pandas as pd
from trader_tool import jsl_data
from trader_tool.dfcf_etf_data import dfcf_etf_data
from tqdm import tqdm
from trader_tool.tdx_trader_function import tdx_trader_function
import pandas as pd
class my_backtrader:
    '''
    分析模型
    '''
    def __init__(self,trader_tool='ths',data_api='dfcf',
                start_date='20240101',end_date='20500101',data_type='D',
                 starting_cash=300000,cash=300000,commission=0.001,index_stock='000300',is_week=False):
        self.trader_tool=trader_tool
        self.data_api=data_api
        self.start_date=start_date
        self.end_date=end_date
        self.data_type=data_type
        self.starting_cash=starting_cash
        self.commission=commission
        self.index_stock=index_stock
        #这里输入代码就可以
        #导入自定义股票池
        stock_df=pd.read_excel(r'自定义交易股票池.xlsx',dtype='object')
        stock_df['证券代码']=stock_df['证券代码'].astype(str)
        print(stock_df['证券代码'].tolist())
        print(stock_df['名称'].tolist())
        print(stock_df)
        stock_list=stock_df['证券代码'].tolist()
        #stock_list=['512890']
        stock_list=stock_list
        self.stock_list=stock_list
        self.amount=1000
        self.hold_limit=2000
        #采用目标数量交易
        self.buy_target_volume=10000
        self.sell_target_volume=0
        self.buy_target_value=10000
        self.sell_target_value=0
        self.tdx_trader_function=tdx_trader_function()
        self.is_week=is_week
        self.week_buy_n=2
        self.week_sell_n=1
        self.daily_buy_n=4
        self.daily_sell_n=3
        #一般是-3%为强制
        self.top_sell=-2
        self.trader=backtrader(start_date=self.start_date,end_date=self.end_date,
                               data_type=self.data_type,starting_cash=self.starting_cash,
                               commission=self.commission,cash=cash,index_stock=self.index_stock)
        self.data=user_def_data(trader_tool=self.trader_tool,
                        start_date=self.start_date,end_date=self.end_date,data_type=self.data_type)
    def add_all_data(self):
        '''
        多线程加载数据
        '''
        self.data.get_thread_add_data(stock_list=self.stock_list)
        self.hist=self.data.hist
        return self.hist
    def add_all_week_data(self):
        '''
        获取全部的周数据
        '''
        self.week_df=pd.DataFrame()
        for i in range(len(self.stock_list)):
            stock=self.stock_list[i]
            df=self.data.data.get_hist_data_em(stock=stock,start_date=self.start_date,end_date=self.end_date,data_type='W')
            df['stock']=stock
            self.week_df=pd.concat([self.week_df,df],ignore_index=True)
        print(self.week_df)
        return self.week_df
    #单线程加载数据,避免数据不成功
    def add_all_data_1(self):
        '''
        单线程加载数据,避免数据不成功
        '''
        for i in tqdm(range(len(self.stock_list))):
            stock=self.stock_list[i]
            stock=str(stock)
            self.data.get_add_data(stock=stock)
        self.hist=self.data.hist
        print(self.hist)
        return self.hist
    def connect_daily_week_data(self):
        '''
        合并日线周线数据
        '''
        self.week_df=self.add_all_week_data()
        self.hist=self.add_all_data_1()
        data=pd.DataFrame()
        for stock in self.stock_list:
            week=self.week_df[self.week_df['stock']==stock]
            week_close=dict(zip(week['date'],week['close']))
            week_open=dict(zip(week['date'],week['open']))
            week_low=dict(zip(week['date'],week['low']))
            week_high=dict(zip(week['date'],week['high']))
            hist=self.hist[self.hist['stock']==stock]
            hist['week_close']=hist['date'].apply(lambda x:week_close.get(x,None))
            hist['week_open']=hist['date'].apply(lambda x:week_open.get(x,None))
            hist['week_low']=hist['date'].apply(lambda x:week_low.get(x,None))
            hist['week_high']=hist['date'].apply(lambda x:week_high.get(x,None))
            hist=hist.fillna(method='ffill')
            data=pd.concat([data,hist])
        return data
    def get_cacal_all_indicators(self):
        '''
        计算全部的指标
        '''
        hist=self.connect_daily_week_data()
        trader_info=pd.DataFrame()
        #拆分数据
        for stock in self.stock_list:
            df=hist[hist['stock']==stock]
            week_df=df[['date','week_close','week_open','week_low','week_high']]
            week_df.columns=['date','close','open','low','high']
            signal_daily,markers=self.tdx_trader_function.six_pulse_excalibur_hist(df)
            signal_week,markers=self.tdx_trader_function.six_pulse_excalibur_hist(week_df)
            df['signal_daily']=signal_daily
            df['signal_week']=signal_week
            trader_info=pd.concat([trader_info,df],ignore_index=True)
        return trader_info
    def run_backtrader(self):
        '''
        运行回测
        '''
        trader_list=self.trader.get_trader_date_list()
        trader_info=self.get_cacal_all_indicators()
        for date in trader_list:
            df=trader_info[trader_info['date']==date]
            stock_list=df['stock'].tolist()
            for stock in stock_list:
                df1=df[df['stock']==stock]
                price=df1['close'].tolist()[-1]
                price=float(price)
                zdf=df1['涨跌幅'].tolist()[-1]
                signal_daily=df1['signal_daily'].tolist()[-1]
                signal_week=df1['signal_week'].tolist()[-1]
                if self.is_week:
                    if signal_week>=self.week_buy_n:
                        if signal_daily>=self.daily_buy_n:
                            result=self.trader.order_target_volume(date=date,stock=stock,amount=self.buy_target_volume,price=price)
                            if result==True:
                                pass
                            else:
                                self.trader.settle(date=date,stock=stock,price=price)
                        else:
                            pass
                    else:
                        print("时间{} 标的{} 不符合周线买入".format(date,stock))
                else:
                    if signal_daily>=self.daily_buy_n:
                        result=self.trader.order_target_volume(date=date,stock=stock,amount=self.buy_target_volume,price=price)
                        if result==True:
                            pass
                        else:
                            self.trader.settle(date=date,stock=stock,price=price)
                    else:
                        pass
                if self.is_week:
                    if signal_week<=self.week_sell_n:
                        result=self.trader.order_target_volume(date=date,stock=stock,amount=self.sell_target_volume,price=price)
                        if result==True:
                            pass
                        else:
                            self.trader.settle(date=date,stock=stock,price=price)
                    else:
                        print("时间{} 标的{} 不符合周线卖出".format(date,stock))
                else:
                    print("时间{} 标的{} 不开启周线卖出".format(date,stock))
                if signal_daily<self.daily_sell_n:
                    result=self.trader.order_target_volume(date=date,stock=stock,amount=self.sell_target_volume,price=price)
                    if result==True:
                        pass
                    else:
                        self.trader.settle(date=date,stock=stock,price=price)
                else:
                    print("时间{} 标的{} 不符合日线卖出".format(date,stock))
                if zdf<=self.top_sell:
                    result=self.trader.order_target_volume(date=date,stock=stock,amount=self.sell_target_volume,price=price)
                    if result==True:
                        pass
                    else:
                        self.trader.settle(date=date,stock=stock,price=price)
                else:
                    print("时间{} 标的{} 不符合止盈止损卖出".format(date,stock))
                
if __name__=='__main__':
    trader=my_backtrader(data_type='D',
                )
    trader.run_backtrader()
    #获取全部的交易报告
    trader.trader.get_poition_all_trader_report_html()
    #获取策略报告
    trader.trader.get_portfolio_trader_report_html()
    #显示个股的交易图
    trader.trader.get_plot_all_trader_data_figure(limit=1000)
    #显示策略数据
    df=trader.trader.get_portfolio_trader_data_figure(limit=100000)
    
    


  

回复

您需要登录后才可以回帖 登录 | 立即注册

客服专线

400-080-8112

用思考的速度交易,用真诚的态度合作,我们是认真的!
  • 关注公众号
  • 添加微信客服
Copyright © 2001-2025 迅投QMT社区 版权所有 All Rights Reserved. 蜀ICP备19002686号-2
关灯 快速发帖
扫一扫添加微信客服
QQ客服返回顶部
快速回复 返回顶部 返回列表