现在可转债交易系统使用的人多,服务器比较小,今天对服务器进行了升级,提供快速的数据支持,同时我也给了服务器的源代码,支持自定义服务器数据支持,不通过我服务器,可以挂在服务器上面24小时快速交易,文章https://mp.weixin.qq.com/s/vmDorXu6ZbgazhJCS-JPSg
服务器24小时运行

配合高频量化模块

同时我也提供了大qmt版本

知识星球有全部直接下载就可以

高速服务器网页http://101.34.65.108:8023/

默认因子数据

合成因子


策略表现


我实盘的表现不错,可转债网页http://120.78.132.143:8888/

比如可转债5因子策略

点击选股数据

持股数据

交易报告


实盘设置点击可转债高速服务器策略

输入账户

支持自定义框架

源代码很多1000行可以研究


点击运行测试数据

选股数据

和网页一样的


挂模型实盘交易

源代码我全部上传了知识星球可以下载使用研究实盘框架,我也给了miniqmt版本
不懂的问我就可以,加我备注人群可以加入量化群
部分源代码,完整的1000多行太长了
#encoding:gbk'''小果可转债5因子轮动策略2,换了一个高速服务器小果可转债5因子轮动策略高速服务器作者:小果微信:15117320079时间:20250226输入自己的账户就可以"账户":"111111",建议使用综合交易模型,miniqmt,配合实时脉冲,网格,止盈止损交易先小资金测试熟悉,支持融资融券支持自定义服务器数据下单的价格编码数值 描述-1 无效(只对于algo_passorder起作用)0 卖5价1 卖4价2 卖3价3 卖2价4 卖1价5 最新价6 买1价7 买2价(组合不支持)8 买3价(组合不支持)9 买4价(组合不支持)10 买5价(组合不支持)'''import pandas as pdimport talibimport time from datetime import datetimeimport mathimport jsonimport requeststext={
"账户":"", "账户支持融资融券":"账户支持融资融券,账户类型STOCK/CREDIT", "账户类型":"STOCK",
"买入价格编码":5, "卖出价格编码":5,
"是否测试":"否", "测试时间":'20250303',
"黑名单":['600031.SH'],
"是否隔离策略":"是", "交易模式说明":"金额/数量", "交易模式":"金额", "固定交易金额":2000, "固定交易数量":100, "特殊交易标的设置":"特殊交易标的设置", "特殊交易标的":[], "特殊交易标的固定交易金额":15000, "特殊交易标的固定交易数量":100, "小果可转债自定义因子轮动策略": "小果可转债服务器提供实时因子数据支持", "服务器数据源设置": "服务器数据源设置********", "服务器": "http://101.34.65.108", "端口": "8023", "服务器编码":"5071dc6e12cd478aa2ab511bbb96abce1f6c0a05a17df9112582acfb29cc3216", "授权码": "123456", "时间设置":"时间设置********", "交易时间段":8, "交易开始时间":9, "交易结束时间":24, "是否参加集合竞价":"否", "开始交易分钟":0, "可转债自定义因子计算": "可转债自定义因子计算************,基于默认因子表计算,df是因子表名称", "是否开启默认因子计算": "是", "默认因子计算": { "三要素评分": "df['溢价率']*100+df['剩余年限']-df['到期税前收益']*100" }, "强制赎回设置": "************************", "是否剔除强制赎回": "是", "满足强制赎回天数": 10, "排除上市天数": 3, "是否排除ST": "是", "排除市场": [], "行业说明": "查询行业表**********,混合排除不区分一二三级行业", "排除行业": [], "排除企业类型": [], "排除地域": [], "排除外部评级": [], "排除三方评级": [], "添加排除因子": "排除因子设置************************", "因子计算符号说明": "大于,小于,大于排名%,小于排名%,空值,排除是相反的,大于是小于", "排除因子": [ "双低", "双低", "剩余规模(亿)", "剩余规模(亿)", "剩余年限", "溢价率", "溢价率", "价格", "价格", "正股年化波动率", "涨幅", "换手率" ], "因子计算符号": [ "大于", "小于", "大于", "小于", "小于", "大于", "小于", "大于", "小于", "小于", "小于", "小于" ], "因子值": [ 170, 100, 8, 1, 1, 70, -1, 150, 100, 60, 0, 5 ], "打分因子设置": "*************************************************", "打分因子说明": "正相关:因子值越大得分越高;负相关:因子值越大得分越低,", "打分因子": [ "5日斜率", "正股年化波动率" ], "因子相关性": [ "正相关", "正相关" ], "因子权重": [ 1 ], "持有限制": 10, "持股限制": 10, "轮动规则设置": "轮动规则设置88888888**********排名", "买入排名前N": 10, "持有排名前N": 10, "跌出排名卖出N": 10, "买入前N": 10,}class A(): passa=A()
def init(c): #账户 c.account=text['账户'] #账户类型 c.account_type=text['账户类型'] #交易股票池 hold_limit=text['持有限制'] if c.account_type=='stock' or c.account_type=='STOCK': c.buy_code=23 c.sell_code=24 else: #融资融券 c.buy_code=33 c.sell_code=34 c.buy_price_code=text['买入价格编码'] c.sell_price_code=text['卖出价格编码'] c.del_trader_list=text['黑名单'] #可以考虑一天轮动2次 c.run_time("run_tarder_func","1nDay","2024-07-25 10:30:00") c.run_time("run_tarder_func","1nDay","2024-07-25 14:25:00") #30分钟一次 #c.run_time("run_tarder_func","1800nSecond","2024-07-25 13:20:00") c.run_time("trader_info","3nSecond","2024-07-25 13:20:00") print(get_account(c,c.account,c.account_type)) print(get_position(c,c.account,c.account_type)) print(run_tarder_func(c))def handlebar(c): #run_tarder_func(c) passdef trader_info(c): if check_is_trader_date_1(): print('{} 等待程序调仓'.format(datetime.now())) else: print('{} 不是交易时间等待程序调仓'.format(datetime.now()))
def get_price(c,stock): ''' 获取最新价格 ''' tick=c.get_full_tick(stock_code=[stock]) tick=tick[stock] price=tick['lastPrice'] return pricedef get_trader_data(c): ''' 小果可转债5因子轮动策略 ''' url=text['服务器'] port=text['端口'] url_code=text['服务器编码'] password=text['授权码'] test=text['是否测试'] test_date=text['测试时间'] if test=='是': print('开启测试模式实盘记得关闭********************') date=test_date else: date=''.join(str(datetime.now())[:10].split('-')) #date='20250229' print('小果服务器提供数据支持***************************') print('服务器{} 端口{} 授权码{}'.format(url,port,password)) models=small_fruit_custom_factor_selection_system(url=url, port=port, url_code=url_code, password=password, text=text, date=date, limit=30) stats,df=models.get_select_result() if stats==True: print('可转债数据获取成功,开始轮动分析') print('选股结果*********************') print(df) df['更新时间']=datetime.now() hold_limit=text['持股限制'] buy_rank=text['持有排名前N'] hold_stock=get_position(c,c.account,c.account_type) if hold_stock.shape[0]>0: hold_stock=hold_stock[hold_stock['持仓量']>=10] if hold_stock.shape[0]>0: hold_stock['证券代码']=hold_stock['证券代码'].astype(str) hold_stock_list=hold_stock['证券代码'].tolist() hold_amount=hold_stock.shape[0] else: hold_stock_list=[] hold_amount=0 else: hold_stock_list=[] hold_amount=0 df=df if df.shape[0]>0: df['可转债代码']=df['可转债代码'].astype(str) df['可转债代码']=df['可转债代码'].apply(lambda x:adjust_stock(x)) all_stock_list=df['可转债代码'].tolist() buy_stock_list=df['可转债代码'].tolist()[:buy_rank] else: all_stock_list=[] buy_stock_list=[] #轮动卖出 sell_stock_list=[] for stock in hold_stock_list: if stock not in buy_stock_list: print('卖出 {} 不在买入前{} 排名{}'.format(stock,buy_rank,buy_stock_list)) sell_stock_list.append(str(stock)) else: print('持有 {} 在买入前{} 排名{}'.format(stock,buy_rank,buy_stock_list.index(stock))) #轮动买入 buy_stock_list_1=[] for stock in buy_stock_list: if stock in hold_stock_list: print('已经持有 {} 在买入前{} 排名{}'.format(stock,buy_rank,buy_stock_list.index(stock))) else: print('买入 {} 在买入前{} 排名{}'.format(stock,buy_rank,buy_stock_list.index(stock))) buy_stock_list_1.append(stock) sell_df=pd.DataFrame() sell_df['证券代码']=sell_stock_list sell_df['交易状态']='卖' sell_amount=sell_df.shape[0] av_buy=(hold_limit-hold_amount)+sell_amount if av_buy>=hold_limit: av_buy=hold_limit else: av_buy=av_buy buy_df=pd.DataFrame() buy_df['证券代码']=buy_stock_list_1[:av_buy] buy_df['交易状态']='买'
if sell_df.shape[0]>0: sell_df['名称']=sell_df['证券代码'] else: sell_df['名称']=None if buy_df.shape[0]>0: buy_df['证券代码']=buy_df['证券代码'].astype(str) buy_df['名称']=buy_df['证券代码'] else: buy_df['名称']=None buy_df['交易时间']=datetime.now() print('买入股票****************') print(buy_df) print('卖出股票*****************') print(sell_df) if hold_stock.shape[0]>0: hold_stock=hold_stock[hold_stock['持仓量']>=10] if hold_stock.shape[0]>0: hold_stock['证券代码']=hold_stock['证券代码'].astype(str) hold_stock['卖出']=hold_stock['证券代码'].apply(lambda x: '是' if x in sell_stock_list else '不是') sell_df=hold_stock[hold_stock['卖出']=='是'] else: sell_df=pd.DataFrame() else: sell_df=pd.DataFrame() return buy_df,sell_df else: print('可转债数据获取失败,等待服务器更新') buy_df=pd.DataFrame() sell_df=pd.DataFrame() return buy_df,sell_dfdef run_tarder_func(c): ''' 运行交易函数 ''' trader_models=text['交易模式'] fix_value=text['固定交易金额'] fix_amount=text['固定交易金额'] sep_fix_value=text['特殊交易标的固定交易金额'] sep_fix_amount=text['特殊交易标的固定交易数量'] sep_stock_list=text['特殊交易标的'] if check_is_trader_date_1(): #先卖在买入 buy_df,sell_df=get_trader_data(c) if sell_df.shape[0]>0: for stock,hold_amount,av_amount in zip(sell_df['证券代码'],sell_df['持仓量'],sell_df['可用数量']): if stock not in c.del_trader_list: print('{} 标的不在黑名单卖出'.format(stock)) try: if av_amount>=10: print('{} 持有数量{} 可以数量{}大于0 卖出数量{}'.format(stock,hold_amount,av_amount,av_amount)) passorder(c.sell_code, 1101,c.account, stock, c.sell_price_code, 0, av_amount, '',1,'',c) else: print('{} 持有数量{} 可以数量{}等于0 卖出数量{} 不交易'.format(stock,hold_amount,av_amount,av_amount)) except: print('{}卖出有问题'.format(stock)) else: print('{} 标的在黑名单不卖出'.format(stock)) else: print('没有卖出的数据') #买入 if buy_df.shape[0]>0: for stock in buy_df['证券代码'].tolist(): if stock not in c.del_trader_list: print('{} 标的不在黑名单买入'.format(stock)) try: if stock in sep_stock_list: print('{}在特殊标的里面*********'.format(stock)) fix_value=sep_fix_value volume=sep_fix_amount else: fix_value=text['固定交易金额'] volume=fix_amount print(stock,fix_value) if trader_models=='金额': print('{}金额交易模式*******'.format(stock)) tader_type,amount,price=order_stock_value(c,c.account,c.account_type,stock,fix_value,'buy') print(tader_type,amount,price) if tader_type=='buy' and amount>=10 : passorder(c.buy_code, 1101, c.account, str(stock), c.buy_price_code, 0, amount, '',1,'',c) #passorder(23, 1101, c.account, str('513100.SH'), 5, 0, 100, '',1,'',c) print('{} 最新价格 买入{} 元'.format(stock,fix_value)) else: print('{}金额交易模式买入不了*******'.format(stock)) else: print('{}数量交易模式*******'.format(stock)) passorder(23, 1101, c.account, str(stock), 5, 0, volume, '',1,'',c) print('{} 最新价格 买入{} 数量'.format(stock,volume)) except Exception as e: print(e,'{}买入有问题'.format(stock)) else: print('{} 标的在黑名单不买入'.format(stock))
else: print('没有买入数据') else: print('{} 目前不少交易时间'.format(datetime.now()))class xg_bond_factor_data: ''' 小果可转债因子数据库 http://124.220.32.224:8023/ ''' def __init__(self,url='http://124.220.32.224', port='8023', url_code='5071dc6e12cd478aa2ab511bbb96abce1f6c0a05a17df9112582acfb29cc3216', password='123456'): ''' 小果可转债因子数据库 url服务器网页 port端口 password授权码 ''' self.url=url self.port=port self.url_code=url_code self.password=password def xg_bond_factor_data(self,date_type='实时数据',date='2024-09-09'): ''' 小果可转债因子数据库 date_type=实时数据/全部默认因子/合成因子 ''' url='{}:{}/_dash-update-component'.format(self.url,self.port) headers={'Content-Type':'application/json'} data={ "output":"xg_bond_data_maker_table.data@{}".format(self.url_code), "outputs":{"id":"xg_bond_data_maker_table","property":"data@{}".format(self.url_code)}, "inputs":[{"id":"password","property":"value","value":self.password}, {"id":"xg_bond_data_data_type","property":"value","value":date_type}, {"id":"xg_bond_data_end_date","property":"date","value":date}, {"id":"xg_bond_data_run","property":"value","value":"运行"}, {"id":"xg_bond_data_down_data","property":"value","value":"不下载数据"}], "changedPropIds":["xg_bond_data_run.value"], "parsedChangedPropsIds":["xg_bond_data_run.value"]} res=requests.post(url=url,data=json.dumps(data),headers=headers) text=res.json() df=pd.DataFrame(text['response']['xg_bond_data_maker_table']['data']) return dfclass small_fruit_custom_factor_selection_system: def __init__(self,url='http://124.220.32.224', port='8023', url_code='5071dc6e12cd478aa2ab511bbb96abce1f6c0a05a17df9112582acfb29cc3216', password='xg123456', text={}, date='20250114', limit=30): print('小果可转债自定义因子选择系统 ') print('作者:小果') print('作者微信:15117320079,开实盘qmt可以联系我,开户也可以') print('作者微信公众号:数据分析与运用') print('公众号链接:https://mp.weixin.qq.com/s/rxGJpZYxdUIHitjvI-US1A') print("作者知识星球:金融量化交易研究院 https://t.zsxq.com/19VzjjXNi") self.url=url self.port=port self.url_code=url_code self.password=password self.text=text self.xg_data=xg_bond_factor_data(url=self.url,port=self.port,url_code=self.url_code,password=self.password) self.date=date self.limit=limit self.stats=False 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 get_all_factor_data(self): ''' 获取可转债全部数据 ''' print("获取可转债全部数据************") text=self.text now_date=self.date df=self.xg_data.xg_bond_factor_data(date_type='合成因子',date=now_date) stats=df['数据状态'].tolist()[-1] try: if stats==True or stats=='True' or stats=='true': df=df print('可转债获取成功***********') self.stats=True else: print(df) df=pd.DataFrame() self.stats=False except Exception as e: df=pd.DataFrame() self.stats=False
return df
def get_cacal_factor_base_table(self): ''' 计算默认因子 ''' print('计算默认因子***********************') text=self.text is_open=text['是否开启默认因子计算'] df=self.get_all_factor_data() if df.shape[0]>0: factor=text['默认因子计算'] if is_open=='是': print('开启计算默认因子***********************') factor_name=list(factor.keys()) if len(factor_name)>0: for name in factor_name: try: print(name,'因子计算完成') func=factor[name] df[name]=eval(func) except Exception as e: print(e,name,'因子计算有问题') else: print('没有默认因子需要计算') else: print('不开启计算默认因子***********************') else: df=pd.DataFrame() return df def get_del_qzsh_data(self): ''' 剔除强制赎回 ''' print('剔除强制赎回') text=self.text del_select=text['是否剔除强制赎回'] n=text['满足强制赎回天数'] df=self.get_cacal_factor_base_table() if df.shape[0]>0: select_list=['公告要强赎','已公告'] df['强赎']=df['强赎天计数'].apply(lambda x : '是' if '公告要强赎' in x or '已公告' in x else '不是') df1=df[df['强赎']=='是'] df2=df[df['强赎']=='不是'] df2['强赎天计数']=df2['强赎天计数'].apply(lambda x: '0/15 | 30' if str(x)[:4]=='暂不强赎' or '不强赎' in x else x) df2['强赎天数']=df2['强赎天计数'].apply(lambda x: int(str(x).split('/')[0])) df2=df2[df2['强赎天数']<=n] else: df2=pd.DataFrame() return df2 def days_excluded_from_market(self): ''' 排除上市天数 ''' print('排除上市天数') text=self.text df=self.get_del_qzsh_data() if df.shape[0]>0: n=text['排除上市天数'] try: df['上市天数']=df['上市天数'].apply(lambda x: float(str(x).split('days')[0])) df=df[df['上市天数']>=n] except: df=df else: df=pd.DataFrame()
return df def st_exclusion(self): ''' 排除st ''' print('排除st') text=self.text is_del=text['是否排除ST'] df=self.days_excluded_from_market() if df.shape[0]>0: if is_del=='是': def_list=['ST','st','*ST','*st'] df['ST']=df['正股名称'].apply(lambda x: '是' if 'st' in x or 'ST' in x or '*st' in x or '*ST' in x else '不是' ) df=df[df['ST']=='不是'] else: df=df else: df=pd.DataFrame() return df def exclusion_of_market(self): ''' 排除市场 ''' print("排除市场") text=self.text exclusion_market_list = [] del_stock_list=text['排除市场'] for exclusion_market in del_stock_list: if exclusion_market == '沪市主板': exclusion_market_list.append(['110','113']) elif exclusion_market == '深市主板': exclusion_market_list.append(['127','128']) elif exclusion_market == '创业板': exclusion_market_list.append('123') elif exclusion_market == '科创板': exclusion_market_list.append('118') else: pass df=self.st_exclusion() if df.shape[0]>0: df['market'] = df['转债代码'].apply(lambda x: '排除' if str(x)[:3] in exclusion_market_list else '不排除') df = df[df['market'] == '不排除'] else: df=pd.DataFrame() return df