综合交易模型----可转债双低策略自动轮动实盘,提供源代码

原理 量化研究---可转债双低策略原理

文章链接 综合交易模型----可转债双低策略自动轮动实盘,提供源代码 (qq.com)

就是按照值来轮动,轮动规则

图片

规则

图片

 "策略轮动设置":"策略轮动设置************************,轮动都按排名来",    "轮动方式说明":"每天/每周/每月/特别时间",    "轮动方式":"每周",    "说明":"每天按自定义函数运行",    "每周轮动是说明":"每周比如0是星期一,4是星期五**********",    "每周轮动时间":4,    "每月轮动是说明":"必须是交易日,需要自己每个月自动输入**********",    "每月轮动时间":["2024-02-29","2024-02-29","2024-02-29","2024-02-29","2024-02-29","2024-02-29","2024-02-29"],    "特定时间说明":"特别的应该交易日",    "特定时间":["2024-02-23","2024-02-24","2024-02-25","2024-02-26","2024-02-27"],    "轮动规则设置":"轮动规则设置88888888**********排名",    "买入排名前N":10,    "持有排名前N":13,    "跌出排名卖出N":15,    "持股周期设置":"持股轮动设置,可以买入小于持股限制数量不可以卖出",

实盘设置,选择交易系统比如qmt

图片

"交易系统设置":"*********************************************",    "交易系统选择":"ths/qmt",    "交易系统":"qmt",    "交易品种":"全部",    "交易品种说明":["stock","fund","bond","全部"],    "同花顺下单路径":"C:/同花顺软件/同花顺/xiadan.exe",    "识别软件安装位置":"C:/Program Files/Tesseract-OCR/tesseract",    "qmt路径":"C:/国金QMT交易端模拟/userdata_mini",    "qmt账户":"55003243",    "qmt账户类型":"STOCK",    "证券公司交易设置":"兼容老牌证券公司可转债1手为单位",    "是否开启特殊证券公司交易设置":"否",

选择策略比如可转债双低策

 "是否开启自定义函数模块":"是",    "自定义运行函数设置":"自定义运行函数说明,运行类型有定时和循环,只需要把自定义模块的函数名称放在下面******",    "目前设置说明":"早上交易人气,下午做概念,2个策略的间隔长,干扰小,手动更新数据是最后一个策略的",    "自定义函数运行类型":["定时"],    "自定义函数模块运行时间":["09:45"],    "自定义函数":["run_convertible_bonds_double_low_strategy"],

设置资金分配模型

图片

  "资金管理模块说明":"程序默认管理方式有数量/资金",    "资金分配设置":"交易数量设置数量和金额,利用可转债最低单位位设置条件,股票在基础数据*10,etf*100,值调整持有限制,持股限制",    "交易模式":"金额",    "固定交易资金":4000,    "持有金额限制":4000,    "固定交易数量":10,    "持有限制":10,    "持股限制":10,    "滑点设置":"滑点设置滑点价格最后一位,比如滑点0.01,股票换掉0.01,etf,可转债滑点0.01/10=0.001价格最后一位,比如现在12.01,买入12.02,卖出12.00",    "滑点":0.01,

运行user def models 更新数据

图片

更新数据

图片

图片

图片

运行trader 进入实盘交易

图片

下单结果

图片

全部上传了知识星球可以直接下载使用

策略参数

{    "可转债溢价率设置":"可转债溢价率设置",    "是否测试":"否",    "集思录账户":"151179",    "集思录密码":"LXG90",    "可转债溢价率上限":60,    "可转债溢价率下限":-10,    "资金分配设置":"交易数量设置数量和金额",    "交易模式":"数量",    "固定交易资金":2500,    "持有金额限制":5000,    "固定交易数量":100,    "持有限制":100,    "持股限制":200,    "可转债选择配置":"可转债选择配置",    "价格上限":200,                         "价格下限":100,    "实时涨跌幅上限":8,    "实时涨跌幅下限":-1,    "双低最小值":100,    "双低最大值":170,    "双低平仓":170,    "是否剔除强制赎回":"是",    "距离强制赎回天数":10,    "策略轮动设置":"策略轮动设置************************,轮动都按排名来",    "轮动方式说明":"每天/每周/每月/特别时间",    "轮动方式":"每周",    "说明":"每天按自定义函数运行",    "每周轮动是说明":"每周比如0是星期一,4是星期五**********",    "每周轮动时间":4,    "每月轮动是说明":"必须是交易日,需要自己每个月自动输入**********",    "每月轮动时间":["2024-02-29","2024-02-29","2024-02-29","2024-02-29","2024-02-29","2024-02-29","2024-02-29"],    "特定时间说明":"特别的应该交易日",    "特定时间":["2024-02-23","2024-02-24","2024-02-25","2024-02-26","2024-02-27"],    "轮动规则设置":"轮动规则设置88888888**********排名",    "买入排名前N":10,    "持有排名前N":13,    "跌出排名卖出N":15,    "持股周期设置":"持股轮动设置,可以买入小于持股限制数量不可以卖出",    "是否开启持股周期":"否",    "持股持股周期天数":4,    "持股周期尾盘是否补仓":"是",    "持股周期尾盘更新数据时间":"14:48",    "持股周期是否允许T":"是",    "持股周期尾盘买入时间":"14:53",    "持股周期尾盘卖出时间":"14:50",    "趋势分析设置":"************************************",    "是否开启趋势轮动":"否",    "趋势分析参数":"均线分析--日线",    "使用均线":[5,10,20,30,60],    "跌破N日均线卖出":5,    "均线最低分数":75,    "持有均线最低分":25,    "收益率分析模块":"收益率分析模块",    "最近N天":5,    "最近N天最大收益率":10,    "最近N天最小收益率":-5,    "最近N天最大回撤":-8,    "买入前N":5}

策略源代码

from trader_tool.stock_data import stock_datafrom trader_tool.bond_cov_data import bond_cov_datafrom trader_tool.shape_analysis import shape_analysisfrom trader_tool.analysis_models import analysis_modelsimport pandas as pdfrom trader_tool.ths_rq import ths_rqfrom tqdm import tqdmimport numpy as npimport jsonfrom  trader_tool import jsl_datafrom qmt_trader.qmt_trader_ths import qmt_trader_thsfrom xgtrader.xgtrader import xgtraderimport numpy as npimport osfrom datetime import datetimeimport timeclass convertible_bonds_double_low_strategy:    def __init__(self,trader_tool='ths',exe='C:/同花顺软件/同花顺/xiadan.exe',tesseract_cmd='C:/Program Files/Tesseract-OCR/tesseract',                qq='1029762153@qq.com',open_set='否',qmt_path='D:/国金QMT交易端模拟/userdata_mini',                qmt_account='55009640',qmt_account_type='STOCK',name='run_bond_cov_rend_strategy'):        '''        可转债双低策略        '''        self.exe=exe        self.tesseract_cmd=tesseract_cmd        self.qq=qq        self.trader_tool=trader_tool        self.open_set=open_set        self.qmt_path=qmt_path        self.qmt_account=qmt_account        self.qmt_account_type=qmt_account_type        if trader_tool=='ths':            self.trader=xgtrader(exe=self.exe,tesseract_cmd=self.tesseract_cmd,open_set=open_set)        else:            self.trader=qmt_trader_ths(path=qmt_path,account=qmt_account,account_type=qmt_account_type)        self.stock_data=stock_data()        self.bond_cov_data=bond_cov_data()        self.ths_rq=ths_rq()        self.path=os.path.dirname(os.path.abspath(__file__))        self.name=name    def save_position(self):        '''        保存持股数据        '''        with open(r'分析配置.json',encoding='utf-8') as f:            com=f.read()        text=json.loads(com)        del_stock_list=text['黑名单']        def select_del_stock_list(x):            if str(x)[:6] in del_stock_list:                return '是'            else:                return '否'        self.trader.connect()        df=self.trader.position()        def select_bond_cov(x):            '''            选择可转债            '''            if x[:3] in ['110','113','123','127','128','111','118'] or x[:2] in ['11','12']:                return '是'            else:                return '不是'        try:            if df==False:                print('获取持股失败')        except:            if df.shape[0]>0:                df['选择']=df['证券代码'].apply(select_bond_cov)                try:                    df['持股天数']=df['持股天数'].replace('--',1)                except:                    df['持股天数']=1                df1=df[df['选择']=='是']                df1=df1[df1['可用余额']>=10]                df1['黑名单']=df1['证券代码'].apply(select_del_stock_list)                df1=df1[df1['黑名单']=='否']                print('剔除黑名单**********')                df1.to_excel(r'持股数据\持股数据.xlsx')                return df1            else:                df=pd.DataFrame()                df['账号类型']=None                df['资金账号']=None                df['证券代码']=None                df['股票余额']=None                df['可用余额']=None                df['成本价']=None                df['市值']=None                df['选择']=None                df['持股天数']=None                df['交易状态']=None                df['明细']=None                df['证券名称']=None                df['冻结数量']=None                df['市价']=None                  df['盈亏']=None                df['盈亏比(%)']=None                df['当日买入']=None                  df['当日卖出']=None                df.to_excel(r'持股数据\持股数据.xlsx')                return df    def save_position(self):        '''        保存持股数据        '''        with open(r'分析配置.json',encoding='utf-8') as f:            com=f.read()        text=json.loads(com)        del_stock_list=text['黑名单']        def select_del_stock_list(x):            if str(x)[:6] in del_stock_list:                return '是'            else:                return '否'        self.trader.connect()        df=self.trader.position()        def select_bond_cov(x):            '''            选择可转债            '''            if x[:3] in ['110','113','123','127','128','111','118'] or x[:2] in ['11','12']:                return '是'            else:                return '不是'        try:            if df==False:                print('获取持股失败')        except:            if df.shape[0]>0:                df['选择']=df['证券代码'].apply(select_bond_cov)                try:                    df['持股天数']=df['持股天数'].replace('--',1)                except:                    df['持股天数']=1                df1=df[df['选择']=='是']                df1=df1[df1['可用余额']>=10]                df1['黑名单']=df1['证券代码'].apply(select_del_stock_list)                df1=df1[df1['黑名单']=='否']                print('剔除黑名单**********')                df1.to_excel(r'持股数据\持股数据.xlsx')                return df1            else:                df=pd.DataFrame()                df['账号类型']=None                df['资金账号']=None                df['证券代码']=None                df['股票余额']=None                df['可用余额']=None                df['成本价']=None                df['市值']=None                df['选择']=None                df['持股天数']=None                df['交易状态']=None                df['明细']=None                df['证券名称']=None                df['冻结数量']=None                df['市价']=None                  df['盈亏']=None                df['盈亏比(%)']=None                df['当日买入']=None                  df['当日卖出']=None                df.to_excel(r'持股数据\持股数据.xlsx')                return df    def select_bond_cov(self,x):        '''        选择证券代码        '''        if x[:3] in ['110','113','123','127','128','111'] or x[:2] in ['11','12']:            return '是'        else:            return '不是'    def save_balance(self):        '''        保持账户数据        '''        with open(r'{}/可转债双低策略设置.json'.format(self.path),encoding='utf-8') as f:            com=f.read()        text=json.loads(com)        self.trader.connect()        df=self.trader.balance()        df.to_excel(r'账户数据\账户数据.xlsx')        return df    def get_all_jsl_data(self):        '''        获取可转债全部数据        '''        print('获取可转债全部数据')        with open(r'{}/可转债双低策略设置.json'.format(self.path),encoding='utf-8') as f:            com=f.read()        text=json.loads(com)        max_yjl=text['可转债溢价率上限']        min_yjl=text['可转债溢价率下限']        user=text['集思录账户']        password=text['集思录密码']        df=jsl_data.get_all_cov_bond_data(jsl_user=user,jsl_password=password)        df.to_excel(r'{}\全部数据\全部数据.xlsx'.format(self.path))        df['代码']=df['证券代码'].tolist()        df1=df[df['转股溢价率']<=max_yjl]        df2=df1[df1['转股溢价率']>=min_yjl]        df2.to_excel(r'{}\目前溢价率可转债\目前溢价率可转债.xlsx'.format(self.path))        return df2    def calculated_double_low(self):        '''        计算双低        双低=价格+100*转股溢价率        '''        with open(r'{}/可转债双低策略设置.json'.format(self.path),encoding='utf-8') as f:            com=f.read()        text=json.loads(com)        min_value=text['双低最小值']        max_value=text['双低最大值']        df=pd.read_excel(r'{}\目前溢价率可转债\目前溢价率可转债.xlsx'.format(self.path),dtype='object')        try:            del df['Unnamed: 0']        except:            pass        df['双低']=df['价格']+df['转股溢价率']        df.to_excel(r'{}\原始双低\原始双低.xlsx'.format(self.path ))        #排序        df=df.sort_values(by='双低',ascending=True)        df['双低']=pd.to_numeric(df['双低'])        df1=df[df['双低']>=min_value]        df2=df1[df1['双低']<=max_value]        df2.to_excel(r'{}\双低\双低.xlsx'.format(self.path))    def mean_line_models(self,df):        '''        均线模型        趋势模型        5,10,20,30,60        '''        df=df        #df=self.bond_cov_data.get_cov_bond_hist_data(stock=stock,start=start_date,end=end_date,limit=1000000000)        df1=pd.DataFrame()        df1['date']=df['date']        df1['5']=df['close'].rolling(window=5).mean()        df1['10']=df['close'].rolling(window=10).mean()        df1['20']=df['close'].rolling(window=20).mean()        df1['30']=df['close'].rolling(window=30).mean()        df1['60']=df['close'].rolling(window=60).mean()        score=0        #加分的情况        mean_5=df1['5'].tolist()[-1]        mean_10=df1['10'].tolist()[-1]        mean_20=df1['20'].tolist()[-1]        mean_30=df1['30'].tolist()[-1]        mean_60=df1['60'].tolist()[-1]        #相邻2个均线进行比较        if mean_5>mean_10:            score+=25        if mean_10>mean_20:            score+=25        if mean_20>mean_30:            score+=25        if mean_30>mean_60:            score+=25        return score    def get_return_ananlysis(self,df='',n=5):        '''        收益率分析        '''        #涨跌幅        df1=df        prices=df1[-n:]['close']        zdf= ((prices.iloc[-1] / prices.iloc[0]) - 1)*100        #最大回撤        max_down_result=((prices / prices.expanding(min_periods=1).max()).min() - 1)*100        #累计收益】        return zdf,max_down_result    def get_cov_bond_shape_analysis(self):        '''        可转债形态分析        '''        print('可转债形态分析')        df=pd.read_excel(r'{}\双低\双低.xlsx'.format(self.path),dtype='object')        with open(r'{}/可转债双低策略设置.json'.format(self.path),encoding='utf-8') as f:            com=f.read()        text=json.loads(com)        n=text['跌破N日均线卖出']        try:            del df['Unnamed: 0']        except:            pass        stock_list=df['证券代码'].tolist()        over_lining=[]        mean_line=[]        for i in tqdm(range(len(stock_list))):            stock=stock_list[i]            try:                hist_df=self.bond_cov_data.get_cov_bond_hist_data(stock=stock)                models=shape_analysis(df=hist_df)                over=models.get_over_lining_sell()                over_lining.append(over)                #均线分析                line=models.get_down_mean_line_sell(n=n)                mean_line.append(line)            except:                over_lining.append(None)                mean_line.append(None)        df['上影线']=over_lining        df['跌破均线']=mean_line        df1=df[df['跌破均线']=='不是']        df1.to_excel(r'{}\选择可转债\选择可转债.xlsx'.format(self.path))        return df1    def get_stock_mean_line_retuen_analysis(self):        '''        可转债均线收益分析        '''        print('可转债均线收益分析')        with open(r'{}/可转债双低策略设置.json'.format(self.path),encoding='utf-8') as f:            com=f.read()        text=json.loads(com)        n=text['最近N天']        max_retuen=text['最近N天最大收益率']        min_return=text['最近N天最小收益率']        max_down=text['最近N天最大回撤']        min_secore=text['均线最低分数']        mean_sorce_list=[]        zdf_list=[]        max_down_list=[]        df=pd.read_excel(r'{}\选择可转债\选择可转债.xlsx'.format(self.path),dtype='object')        try:            df['Unnamed: 0']        except:            pass        stock_list=df['证券代码'].tolist()        for i in tqdm(range(len(stock_list))):            stock=stock_list[i]            try:                df1=self.bond_cov_data.get_cov_bond_hist_data(stock=stock,start='19990101',end='20500101',limit=10000000)                sorce=self.mean_line_models(df=df1)                zdf,down=self.get_return_ananlysis(df=df1,n=n)                mean_sorce_list.append(sorce)                zdf_list.append(zdf)                max_down_list.append(down)            except:                mean_sorce_list.append(None)                zdf_list.append(None)                max_down_list.append(None)        df['均线得分']=mean_sorce_list        df['最近{}天收益'.format(n)]=zdf_list        df['最近天{}最大回撤'.format(n)]=max_down_list        df.to_excel(r'{}\分析原始数据\分析原始数据.xlsx'.format(self.path))        df1=df[df['均线得分']>=min_secore]        df2=df1[df1['最近{}天收益'.format(n)]>=min_return]        df3=df2[df2['最近{}天收益'.format(n)]<=max_retuen]        df4=df3[df3['最近天{}最大回撤'.format(n)]>=max_down]        df4.to_excel(r'{}\交易股票池\交易股票池.xlsx'.format(self.path))        return df4    def get_select_trader_type(self):        '''        选择交易方式        '''        with open(r'{}/可转债双低策略设置.json'.format(self.path),encoding='utf-8') as f:            com=f.read()        text=json.loads(com)        rend=text['是否开启趋势轮动']        if rend=='是':            self.get_cov_bond_shape_analysis()            self.get_stock_mean_line_retuen_analysis()        else:            df=pd.read_excel(r'{}\双低\双低.xlsx'.format(self.path),dtype='object')            try:                df['Unnamed: 0']            except:                pass            df.to_excel(r'{}\交易股票池\交易股票池.xlsx'.format(self.path))    def get_del_qzsh_data(self):        '''        剔除强制赎回        '''        print('剔除强制赎回')        with open('{}/可转债双低策略设置.json'.format(self.path),encoding='utf-8') as f:            com=f.read()        text=json.loads(com)        del_select=text['是否剔除强制赎回']        n=text['距离强制赎回天数']        df=self.bond_cov_data.bank_cov_qz()        del_list=[]        for i in range(1,n+1):            n_text='至少还需{}天'.format(i)            del_list.append(n_text)        del_list.append('临近到期')        del_list.append('已满足强赎条件')        del_list.append('是否剔除强制赎回')        text_n=''        for select_text in del_list:            text_n+='"{}" in x or '.format(select_text)        text_n=text_n[:-3]        if del_select=='是':            df1=df            def select_bond_cov(x):                '''                选择可转债                '''                if eval(text_n):                    return '是'                else:                    return '不是'            df1['选择']=df1['cell.redeem_count'].apply(select_bond_cov)            df2=df1[df1['选择']=='是']            df2.to_excel(r'{}\强制赎回\强制赎回.xlsx'.format(self.path))            trader_stock=pd.read_excel(r'{}\交易股票池\交易股票池.xlsx'.format(self.path),dtype='object')            try:                trader_stock['Unnamed: 0']            except:                pass            def select_trader_stock(x):                '''                选择交易股票池                '''                if x not in df2['cell.bond_id'].tolist():                    return '不是'                else:                    return '是'            trader_stock['强制赎回']=trader_stock['证券代码'].apply(select_trader_stock)            trader_stock=trader_stock[trader_stock['强制赎回']=='不是']            trader_stock.to_excel(r'{}\交易股票池\交易股票池.xlsx'.format(self.path))            return trader_stock        else:            df.to_excel(r'非强制赎回\非强制赎回.xlsx')            return df    def get_del_buy_sell_data(self):        '''        处理交易股票池买入股票        '''        with open(r'{}/可转债双低策略设置.json'.format(self.path),encoding='utf-8') as f:            com=f.read()        text=json.loads(com)        limit=text['持股限制']        df=self.save_position()        df1=df[df['可用余额']>=10]        hold_stock_list=df['证券代码'].tolist()        n=text['跌破N日均线卖出']        trader_df=self.get_del_qzsh_data()        def select_data(stock):            if stock in hold_stock_list:                num=df1[df1['证券代码']==stock]['可用余额'].tolist()[-1]                if float(num)>=float(limit):                    return '持股超过限制'                else:                    return '持股不足'            else:                return '没有持股'        trader_df['持股检查']=trader_df['证券代码'].apply(select_data)        trader_df=trader_df[trader_df['持股检查'] !='持股超过限制']        hold_stock_list=trader_df['证券代码'].tolist()        sell_list=[]        for stock in hold_stock_list:            try:                hist_df=self.bond_cov_data.get_cov_bond_hist_data(stock=stock)                models=shape_analysis(df=hist_df)                mean_line=models.get_down_mean_line_sell(n=n)                if mean_line=='是':                    sell_list.append('是')                else:                    sell_list.append('不是')            except:                print('{}有问题'.format(stock))                sell_list.append('是')        trader_df['跌破均线']=sell_list        trader_df=trader_df[trader_df['跌破均线']=='不是']          for i in range(0,10):            try:                trader_df['Unnamed: {}'.format(i/10)]            except:                pass        trader_df.to_excel(r'{}\交易股票池\交易股票池.xlsx'.format(self.path))        return trader_df    def get_time_rotation(self):        '''        轮动方式        '''        with open('{}/可转债双低策略设置.json'.format(self.path),encoding='utf-8') as f:            com=f.read()        text=json.loads(com)        now_date=''.join(str(datetime.now())[:10].split('-'))        now_time=time.localtime()                                       trader_type=text['轮动方式']                                       trader_wday=text['每周轮动时间']                                       moth_trader_time=text['每月轮动时间']        specific_time=text['特定时间']        year=now_time.tm_year        moth=now_time.tm_mon        wday=now_time.tm_wday        daily=now_time.tm_mday        if trader_type=='每天':            print('轮动方式每天')            return True        elif trader_type=='每周':            if trader_wday==wday:                return True            elif trader_wday<wday:                print('安周轮动 目前星期{} 轮动时间星期{} 目前时间大于轮动时间不轮动'.format(wday+1,trader_wday+1))                return False            else:                print('安周轮动 目前星期{} 轮动时间星期{} 目前时间小于轮动时间不轮动'.format(wday+1,trader_wday+1))                return False        elif trader_type=='每月轮动时间':            stats=''            for date in moth_trader_time:                data=''.join(data.split('-'))                if int(moth_trader_time)==int(date):                    print('安月轮动 目前{} 轮动时间{} 目前时间等于轮动时间轮动'.format(now_date,date))                    stats=True                    break                elif int(moth_trader_time)<int(date):                    print('安月轮动 目前{} 轮动时间{} 目前时间小于轮动时间轮动'.format(now_date,date))                    stats=False                else:                    print('安月轮动 目前{} 轮动时间{} 目前时间大于轮动时间轮动'.format(now_date,date))                    stats=False            return stats        else:            #特别时间            stats=''            for date in specific_time:                data=''.join(data.split('-'))                if int(specific_time)==int(date):                    print('安月轮动 目前{} 轮动时间{} 目前时间等于轮动时间轮动'.format(now_date,date))                    stats=True                    break                elif int(specific_time)<int(date):                    print('安月轮动 目前{} 轮动时间{} 目前时间小于轮动时间轮动'.format(now_date,date))                    stats=False                else:                    print('安月轮动 目前{} 轮动时间{} 目前时间大于轮动时间轮动'.format(now_date,date))                    stats=False            return stats                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         def get_buy_sell_stock(self):        '''        获取买卖数据        '''        with open('{}/可转债双低策略设置.json'.format(self.path),encoding='utf-8') as f:            com=f.read()        text=json.loads(com)        buy_num=text['买入排名前N']        hold_rank_num=text['持有排名前N']        sell_rank_num=text['跌出排名卖出N']        sell_value=text['双低平仓']        hold_limit=text['持有限制']        df=pd.read_excel(r'持股数据\持股数据.xlsx',dtype='object')        df_yjl=pd.read_excel(r'{}\原始双低\原始双低.xlsx'.format(self.path))        sd_dict=dict(zip(df_yjl['证券代码'],df_yjl['双低']))        trend=text['是否开启趋势轮动']        df1=df[df['可用余额']>=10]        hold_stock_list=df['证券代码'].tolist()        def select_stock(x):            '''            选择etf            '''            if x in hold_stock_list:                return '持股'            else:                return "持股不足"        try:            del df['Unnamed: 0']        except:            pass        trader_df=pd.read_excel(r'{}\交易股票池\交易股票池.xlsx'.format(self.path),dtype='object')        try:            del trader_df['Unnamed: 0']        except:            pass        print('交易股票池*******************')        print(trader_df)        trader_df['选择']=trader_df['证券代码'].apply(select_stock)        trader_df=trader_df[trader_df['选择']=='持股不足']        select=text['是否开启持股周期']        hold_daily_limit=text['持股持股周期天数']        try:            del trader_df['Unnamed: 0']        except:            pass        if df1.shape[0]>0:            #卖出列表            sell_list=[]            #持股列表            hold_stock_list=df['证券代码'].tolist()            #排名列表            if select=='是':                hold_daily=df[df['证券代码']==stock]['持股天数'].tolist()[-1]                if hold_daily>=hold_daily_limit:                    sell_list.append(stock)                else:                    print('目前持股 {} 没有大于{}'.format(hold_daily,hold_daily_limit))            else:                print('不启动持股限制')            #跌破均线分析            n=text['跌破N日均线卖出']             if trend=='是':                for stock in hold_stock_list:                        try:                            hist_df=self.etf_fund_data.get_ETF_fund_hist_data(stock=stock)                            models=shape_analysis(df=hist_df)                            mean_line=models.get_down_mean_line_sell(n=n)                            if mean_line=='是':                                sell_list.append(stock)                                print('{}跌破均线'.format(stock))                            else:                                pass                        except:                            pass            else:                print('**************************88不开启持股趋势分析')            #双低平仓            for stock in hold_stock_list:                value=sd_dict.get(stock,0)                if value>=sell_value:                    print('双低平仓 {} 双低{} 大于 平仓值{}'.format(stock,value,sell_value))                       sell_list.append(stock)                else:                    print('双低平仓 {} 双低{} 小于 平仓值{}'.format(stock,value,sell_value))               #跌出排名卖出N            rank_df=pd.read_excel(r'{}\双低\双低.xlsx'.format(self.path),dtype='object')             sell_rank_stock=rank_df['证券代码'].tolist()[:sell_rank_num]               if len(sell_rank_stock)>0:                for stock in hold_stock_list:                    if stock in sell_rank_stock:                        print('{} 在持有排名里面'.format(stock))                    else:                        print('{} 不在持有排名里面'.format(stock))                        sell_list.append(stock)            sell_list=list(set(sell_list))            sell_df=pd.DataFrame()            sell_df['证券代码']=sell_list            sell_df['交易状态']='未卖'            if sell_df.shape[0]>0:                print('卖出etf*****************')                print(sell_df)                sell_df['策略名称']=self.name                sell_df.to_excel(r'卖出股票\卖出股票.xlsx')            else:                print('没有卖出etf')                sell_df['证券代码']=None                sell_df['交易状态']=None                sell_df['策略名称']=self.name                sell_df.to_excel(r'卖出股票\卖出股票.xlsx')            hold_num=df1.shape[0]            if hold_num>0:                av_buy_num=hold_limit-hold_num                av_buy_num=av_buy_num+sell_df.shape[0]                buy_df=trader_df[:av_buy_num]            else:                buy_df=trader_df[:buy_num]            buy_df['交易状态']='未买'            print('买入可转债*****************')            df['证券代码']=df['证券代码']            print(buy_df)            buy_df['策略名称']=self.name            buy_df.to_excel(r'买入股票\买入股票.xlsx')            return buy_df        else:            buy_df=trader_df[:buy_num]            print(trader_df)            buy_df['证券代码']=buy_df['证券代码']            buy_df['交易状态']='未买'            print('买入etf*****************')            print(buy_df)            buy_df['策略名称']=self.name            buy_df.to_excel(r'买入股票\买入股票.xlsx')            return buy_df    def updata_all_data(self):        '''        更新全部数据        '''        with open(r'{}/可转债双低策略设置.json'.format(self.path),encoding='utf-8') as f:            com=f.read()        text=json.loads(com)        select=text['是否测试']        if select=='是':            self.save_position()            self.save_balance()            self.get_all_jsl_data()            self.calculated_double_low()            self.get_select_trader_type()            self.get_del_qzsh_data()            self.get_del_buy_sell_data()            self.get_buy_sell_stock()        else:            if self.get_time_rotation()==True:                self.save_position()                self.save_balance()                self.get_all_jsl_data()                print("今天{} 是轮动时间".format(datetime.now()))                self.calculated_double_low()                self.get_select_trader_type()                self.get_del_qzsh_data()                self.get_del_buy_sell_data()                self.get_buy_sell_stock()            else:                print("今天{} 不是是轮动时间".format(datetime.now()))

在Python中编写一个简单的可转债双低策略的回测代码,通常需要结合pandas库进行数据处理,yfinance库获取股票数据,以及backtrader库进行回测。下面是一个简化的示例: ```python # 导入所需库 import pandas as pd from yahoofinancials import YahooFinancials from backtrader import cerebro, strategy, TimeFrame # 定义策略类 class DoubleLowStrategy(strategy.Strategy): def __init__(self): self.data_rsi = self.datas[0].rsi(14) # 使用RSI指标 self.data_low1 = self.datas[0].low[-60:] # 最近60天最低价 self.data_low2 = self.datas[0].low[-120:] # 最近120天最低价 def next(self): if self.data_low1[-1] < self.data_low2[-1]: # 如果最近60天比120天更低 if self.data_rsi[-1] > 30: # 而且RSI超过30,认为有反弹机会 self.buy() # 买入信号 # 获取可转债数据 yf = YahooFinancials('AAPL.PA') # 替换为你要测试的可转债代码 data = yf.get_historical_price_data(start_date='2020-01-01', end_date='2022-12-31') # 将数据转换成backtrader兼容格式 df = pd.DataFrame(data['prices']) df['datetime'] = pd.to_datetime(df['date'], format='%Y-%m-%d') df.set_index('datetime', inplace=True) data_dict = {'Close': df['close'].values} # 创建回测引擎 cerebro = cerebro() cerebro.addstrategy(DoubleLowStrategy) # 添加数据到引擎 cerebro.adddata(data_dict, name='AAPL', timeframe=TimeFrame.Days) # 开始回测 cerebro.run() # 结果打印 print("总收益:", cerebro.broker.getvalue()) # 相关问题--
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

xg_quant

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

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

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

打赏作者

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

抵扣说明:

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

余额充值