文章声明:本内容为个人的业余研究,和任何单位,机构没有关系,文章出现的股票代码,全部只是测试例子,不做投资参考,投资有风险,代码学习使用,不做商业用途

今天把蒙斯全市场可转债趋势增强策略4.0做了一些回测,当然大qmt的版本也是上线了,明天给详细的使用教程

图片

图片

1700多行源代码,真正的实盘细节很复杂

图片

图片

下面是我服务器的仿真交易数据全市场趋势增强模型

图片

可转债趋势增强

图片

仿真交易数据

图片

持股数据

图片

策略原理

全市场可转债趋势增强策略参数原理与逻辑分析

1. 策略核心逻辑概述

该策略是一个多因子趋势增强型可转债策略,核心思路是:

  • 趋势跟踪(均线系统+趋势强度指标)

  • 动量增强(短期收益筛选)

  • 波段交易(六脉神剑信号+小水果波段模型)

  • 动态调仓(持股限制+买卖金额控制)

策略通过量化指标筛选可转债,在趋势确立时买入,在趋势转弱或反转时卖出,以增强收益并控制回撤。


2. 关键参数与原理分析

(1)均线系统参数

3日、5日、10日、15日、20日均线
  • 原理:均线代表不同时间周期的市场平均成本,短周期均线反映短期趋势,长周期均线反映长期趋势。

  • 策略作用

    • 趋势确认:短期均线(3日、5日)上穿长期均线(10日、15日、20日)表明趋势增强。

    • 支撑/阻力:价格站上5日均线(df['站上均线'])表明短期趋势向上,跌破则可能转弱。

站上/跌破5日均线信号
  • 买入条件df['站上均线'] == True

    • 逻辑:价格高于5日均线,短期趋势看涨。

  • 卖出条件df['跌破均线'] == True

    • 逻辑:价格低于5日均线,短期趋势可能转弱。


(2)趋势强度指标(df['趋势强度']

计算方式
  • 通过均线排列顺序计算得分:

    • 3日 ≥ 5日 → +25分

    • 5日 ≥ 10日 → +25分

    • 10日 ≥ 15日 → +25分

    • 15日 ≥ 20日 → +25分

    • 满分100分,代表均线呈完美多头排列

策略作用
  • 买入条件趋势强度 ≥ 75

    • 逻辑:短期均线明显强于长期均线,趋势强劲。

  • 卖出条件趋势强度 ≤ 50

    • 逻辑:均线排列混乱或空头排列,趋势可能结束。


(3)动量指标(短期收益筛选)

5日累计收益(df['N日收益']
  • 计算方式:最近5日涨跌幅之和。

  • 买入条件3% ≤ N日收益 ≤ 20%

    • 下限3%:避免买入弱势转债(动量不足)。

    • 上限20%:避免追高短期暴涨品种(防止回调风险)。

    • 逻辑:

前一日收益(df['前N天收益']
  • 计算方式:前1日涨跌幅。

  • 买入条件0% ≤ 前N天收益 ≤ 7%

    • 下限0%:避免买入当日下跌的转债(短期弱势)。

    • 上限7%:避免追高单日暴涨品种(可能回调)。

    • 逻辑:


(4)六脉神剑日周期信号(df['六脉神剑日周期']

原理
  • 该信号可能基于技术形态或波动率指标(如MACD、RSI、布林带等组合),用于判断短期趋势强度。

  • 买入条件六脉神剑日周期 ≥ 4

    • 逻辑:短期趋势信号较强,适合进场。

  • 卖出条件六脉神剑日周期 ≤ 3

    • 逻辑:短期趋势信号减弱,可能反转。

连续六脉神剑数量(df['连续六脉神剑数量']
  • 用于排序买入优先级,连续信号越多,趋势越稳定。


(5)小水果波段交易模型(df['波段状态']

原理
  • 该模型可能基于价格波动区间超买超卖指标(如KDJ、CCI),判断当前处于"买"或"卖"波段。

  • 买入条件波段状态 == '买'

    • 逻辑:当前处于适合买入的波段低位。

  • 卖出条件波段状态 == '卖'

    • 逻辑:当前处于适合卖出的波段高位。


(6)资金管理与风险控制参数

持股限制(self.hold_limit = 20
  • 逻辑:分散持仓,降低单只转债风险,避免过度集中。

单笔买入金额(self.buy_value = 10000
  • 逻辑:固定金额买入,控制单只转债仓位,避免过度暴露。

单笔卖出金额(self.sell_value = 20000
  • 逻辑:卖出金额大于买入金额,可能用于动态止盈加速调仓


3. 策略优势与适用场景

优势

  1. 趋势跟随:避免逆势交易,只在趋势明确时进场。

  2. 动量过滤:筛选近期表现较好的转债,提高胜率。

  3. 多因子验证:均线、趋势强度、波段信号等多指标综合判断,减少误判。

  4. 严格风控:持股分散+动态调仓,降低单一标的风险。

适用市场环境

  • 趋势市(单边上涨或下跌):均线系统+趋势强度有效。

  • 震荡市(波段行情):小水果波段模型+六脉神剑信号辅助判断。

  • 不适合极端波动市(如暴涨暴跌):短期收益限制可能错过极端行情。

看趋势模型选股出来的数据,股票池可以优化结合选个股模板算法,选择全市场趋势强的可转债交易

图片

图片

图片

图片

图片

图片

回测的数据,默认持股20,提高盈亏比

图片

图片

图片

图片

图片

图片

图片

图片

策略我全部上传了,可以结合自己的选股改源代码,后面我会对接选股模块,先自定义选股因子,在做趋势增强交易,这样会比较安全,剔除有问题的可转债,可以参考可转债5因子的自定义算法框架量化研究---推出年华化30%西蒙斯可转债5因子策略2.0版本https://mp.weixin.qq.com/s?__biz=MzI5NTE5NTExMw==&mid=2247494690&idx=1&sn=7977e7c1f7f702cfdf2a4d4bb74f68ab&scene=21#wechat_redirect

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

全部的回测代码,我自研的回测算法框架,回测几百万的数据没有问题​​​​​​

from xms_quant_backtrader import xms_quant_backtraderfrom tdx_strategy_models.small_fruit_band_trading import small_fruit_band_tradingfrom tdx_strategy_models.six_pulse_excalibur_hist import six_pulse_excalibur_histimport pandas as pdfrom xg_tdx_func.xg_tdx_func import *class xms_quant_backtrader_zz100:    def __init__(self,            trader_tool='qmt',            data_api='qmt',            data_type='D',            stock_list=[],            start_date='20200101',            end_date='20500101',            total_cash=200000,            st_name='西蒙斯全市场可转债趋势增强策略'            ):        '''        西蒙斯量化回测系统3.0        作者:西蒙斯量化        微信:xg_quant        数据源data_api选择qmt,需要先打开miniqmt登录,选择dfcf就不需要,建议使用qmt        '''        self.trader_tool=trader_tool        self.data_api=data_api        self.data_type=data_type        self.stock_list=stock_list        self.start_date=start_date        self.end_date=end_date        self.total_cash=total_cash        self.trader=xms_quant_backtrader(                trader_tool=self.trader_tool,                data_api=self.data_api,                data_type=self.data_type,                stock_list=self.stock_list,                start_date=self.start_date,                end_date=self.end_date,                total_cash=self.total_cash,                st_name=st_name)        self.hold_limit=20        self.buy_value=10000        self.sell_value=20000    def get_all_hist_data(self):        '''        获取全部历史数据        '''        stock_list=self.trader.get_read_tdx_data(r'QBKZZ.blk')['证券代码'].tolist()        self.trader.re_trader_stock(stock_list=stock_list)        self.trader.get_hist_data()        hist=self.trader.data.get_hist_data()        hist=hist.sort_values(by='date')        hist.to_csv(r'全部历史数据.csv')        return hist    def get_all_user_hist_data(self):        '''        加载本地历史数据        '''        stock_list=self.trader.get_read_tdx_data(r'ZZA100.blk')['证券代码'].tolist()        self.trader.re_trader_stock(stock_list=stock_list)        df=pd.read_csv(r'全部历史数据.csv')        self.trader.get_user_hist_data(df)        hist=self.trader.data.get_hist_data()        return hist    def cacal_stock_score(self,x1,x2,x3,x4,x5):        '''        计算分数        '''        score=0        if x1>=x2:            score+=25        if x2>=x3:            score+=25        if x3>=x4:            score+=25        if x4>=x5:            score+=25        return score    def cacal_all_stock_indicator(self):        '''        计算全部的指标        '''        data=pd.DataFrame()        #hist=self.get_all_user_hist_data()        hist=self.get_all_hist_data()        stock_list=self.trader.get_trader_stock()        for stock in stock_list:            df=hist[hist['stock']==stock]            df=df.sort_values(by='date')            if df.shape[0]>0:                df['3日均线']=df['close'].rolling(3).mean()                df['5日均线']=df['close'].rolling(5).mean()                df['10日均线']=df['close'].rolling(10).mean()                df['15日均线']=df['close'].rolling(15).mean()                df['20日均线']=df['close'].rolling(20).mean()                df['站上均线']=df['close']>=df['5日均线']                df['跌破均线']=df['close']<df['5日均线']                                df['涨跌幅']=df['close'].pct_change()*100                df['N日收益']=df['涨跌幅'].rolling(5).sum()                df['前N天收益']=df['涨跌幅'].shift(1)                df['趋势强度'] = df.apply(lambda row: self.cacal_stock_score(row['3日均线'], row['5日均线'], row['10日均线'], row['15日均线'], row['20日均线']), axis=1).tolist()                                models=six_pulse_excalibur_hist(df=df)                result=models.six_pulse_excalibur_hist()                stats=result['signal'].tolist()                df['六脉神剑日周期']=stats                df['六脉神剑日周期数量']= df['六脉神剑日周期'].rolling(5).sum()                df.reset_index(drop=True, inplace=True)                df['连续六脉神剑数量']= BARSLASTCOUNT(df['六脉神剑日周期']>=5)                models=small_fruit_band_trading(df=df)                result=models.small_fruit_band_trading()                stats=result['stats'].tolist()                df['波段状态']=stats                df.reset_index(drop=True, inplace=True)                df['买的波段数量'] = BARSLASTCOUNT(df['波段状态']=='买')                data=pd.concat([data,df],ignore_index=False)        print(data)        data.to_excel(r'全部因子数据.xlsx')        return data    def get_buy_sell_data(self):        '''        获取买卖数据        '''        df=self.cacal_all_stock_indicator()        print('获取买卖数据**********')        buy_condi = (            (df['趋势强度'] >= 75) &             (df['站上均线']==True) &             (df['涨跌幅'] >= 0) &             (df['涨跌幅'] <= 5) &             (df['六脉神剑日周期'] >= 4) &            (df['N日收益']>=3) &            (df['N日收益']<=20) &            (df['前N天收益']>=0) &            (df['前N天收益'] <=7) &            (df['波段状态']=='买')        )        sell_condi = (            (df['趋势强度'] <= 50) |             (df['跌破均线']==True) |             (df['六脉神剑日周期'] <= 3) |            (df['波段状态']=='卖')        )        df['buy']=buy_condi        df['sell']=sell_condi        buy_df=df[df['buy']==True]        sell_df=df[df['sell']==True]        return buy_df,sell_df    def run_backtrader(self):        '''        运行回测        '''        print('运行回测')        st_buy_df,st_sell_df=self.get_buy_sell_data()        trader_date_list=self.trader.get_trader_date_list()        for date in trader_date_list:            if st_buy_df.shape[0]>0:                buy_df=st_buy_df[st_buy_df['date']==date]                #排序因子                buy_df=buy_df.sort_values(by=[                    "买的波段数量",                    "N日收益",                    "连续六脉神剑数量",                    "趋势强度"],                    ascending=False)            else:                buy_df=pd.DataFrame()                        if st_sell_df.shape[0]>0:                sell_df=st_sell_df[st_sell_df['date']==date]            else:                sell_df=pd.DataFrame()                        position=self.trader.position.get_position_data()            if position.shape[0]>0:                position=position[position['股票余额']>=10]                if position.shape[0]>0:                    position=position                    hold_amount=position.shape[0]                    hold_stock_list=position['证券代码'].tolist()                else:                    position=pd.DataFrame()                    hold_amount=0                    hold_stock_list=[]            else:                position=pd.DataFrame()                hold_amount=0                hold_stock_list=[]            if position.shape[0]>0:                if sell_df.shape[0]>0:                    sell_stock_list=sell_df['stock'].tolist()                else:                    sell_stock_list=[]                position['卖出']=position['证券代码'].apply(lambda x: '是' if x in sell_stock_list else '不是')                sell_df=position[position['卖出']=='是']                sell_amount=sell_df.shape[0]            else:                sell_df=pd.DataFrame()                sell_amount=0            av_amount=(self.hold_limit-hold_amount)+sell_amount            if av_amount<0:                print(date,'达到持股限制不买入')                av_amount=0            else:                av_amount=av_amount            print('***************************')            print('{} 持股限制{} 持有数量{} 卖出数量{} 可以买入数量{}'.format(date,self.hold_limit,hold_amount,sell_amount,av_amount))            if buy_df.shape[0]>0:                buy_df['持股']=buy_df['stock'].apply(lambda x: '是' if x in hold_stock_list else '不是')                buy_df=buy_df[buy_df['持股']=='不是']            else:                buy_df=buy_df            buy_df=buy_df[:av_amount]            print('持有的股票*****************')            print(position)            print('卖出股票***********')            print(sell_df)            print('买入股票************')            print(buy_df)            #先卖出在买入            if sell_df.shape[0]>0:                for stock in sell_df['证券代码'].tolist():                    price=self.trader.get_price(date=date,stock=stock)                    trader_type,amount,price=self.trader.order_value(                        date=date,                        stock=stock,                        value=self.sell_value,                        price=price,                        trader_type='sell'                    )                    if trader_type=='sell' and amount>=10:                        self.trader.sell(                            date=date,                            stock=stock,                            amount=amount,                            price=price,                            maker='卖出成功')                    else:                        print(date,stock,'买入失败')            else:                print(date,'卖出没有持股数据')            #买入            if buy_df.shape[0]>0:                for stock in buy_df['stock'].tolist():                    price=self.trader.get_open_price(date=date,stock=stock)                    trader_type,amount,price=self.trader.order_value(                        date=date,                        stock=stock,                        value=self.buy_value,                        price=price,                        trader_type='buy'                    )                    if trader_type=='buy' and amount>=10:                        self.trader.buy(                            date=date,                            stock=stock,                            amount=amount,                            price=price,                            maker='买入成功')                    else:                        print(date,stock,'买入失败')            else:                print(date,'买入没有持股数据')            #结算            self.trader.settlement_data(date=date)    def get_backtrader_result(self):        '''        获取回测结果        '''        self.trader.generate_strategy_report()        self.trader.get_all_trader_data()if __name__=='__main__':    trader=xms_quant_backtrader_zz100()    df=trader.run_backtrader()    trader.get_backtrader_result()

Logo

专业量化交易与投资者大本营

更多推荐