搭建自己的量化系统
股票量化交易系统QTYX是一个即可以用于学习,也可以用于实战炒股分析的系统。
分享QTYX系统目的是提供给大家一个搭建量化系统的模版,最终帮助大家搭建属于自己的系统。因此我们提供源码,可以根据自己的风格二次开发。
关于QTYX的使用攻略可以查看链接:QTYX使用攻略
QTYX一直迭代更新,当前版本V2.7.2。后续升级版本会同步更新文档内容。
DIY系列说明
本篇属于使用攻略的DIY系列,即教大家如何在QTYX源码基础上二次开发自己的策略和用法。
QTYX系统内置了一些形态选股策略,比如双底形态突破、主升浪拉升等。我们不但可以对这些策略进行优化修改,也可以单独在这个系统中植入自己的策略。
形态选股设计框架
整体的设计框架如下图所示。
操作上,要在主界面上更新股票数据和选择选股策略。操作方法可参照使用攻略中对应专题。
执行选股时采用多任务方案,每个任务中注册了相应的策略,股票数据会分发给这些任务,每个任务独立选股,最后合并为一份选股结果。
选股结果出来后,还可以叠加一些特殊数据进行多方位条件选股,比如财务数据、基金持仓数据、基本面数据等等。
如何添加代码
接下来介绍下如何添加策略代码。
首先找到文件“QTYX/StrategyGath/PattenGath.py”,根据统一格式添加一个自己的策略函数,比如名称“user_define_strategy”,然后在函数中用Python添加自己的策略逻辑,如下代码所示:(编写策略代码时,请注意传入参数的格式和内容,以及返回数据的格式,以兼容这个系统框架)
@staticmethod
def user_define_strategy(name, code, stock_data, patlog_obj, **kwargs):
"""
# 输入参数
:param name: 股票名称, 平安银行
:param code: 股票代码, 000001.SZ
:param stock_data: 股票数据, DataFrame格式
:param patlog_obj: 打印日志接口
:param kwargs: dict: 配置参数, 可以直接在函数中修改
:return:
"""
try:
df_search = pd.DataFrame() # 构建一个空的dataframe用来装数据
MA1 = stock_data["收盘价"].rolling(window=5).mean() # 计算M日的移动平均线
MA2 = stock_data["收盘价"].rolling(window=10).mean() # 计算M日的移动平均线
MA3 = stock_data["收盘价"].rolling(window=20).mean() # 计算M日的移动平均线
MA4 = stock_data["收盘价"].rolling(window=30).mean() # 计算M日的移动平均线
CLOSE = stock_data["收盘价"]
MA1.fillna(0, inplace=True)
MA2.fillna(0, inplace=True)
MA3.fillna(0, inplace=True)
MA4.fillna(0, inplace=True)
# 循环判断是否连续N日都符合均线多头排列的特征
for id in range(0, 4):
T = (CLOSE[-1 - id] > MA1[-1 - id] > MA2[-1 - id] > MA3[-1 - id] > MA4[-1 - id])
if T != True: break # 只要有一天不满足则退出
if id >= 3:
# 输出满足要求的股票
patlog_obj.re_print("符合特征: 股票 {},代码 {}".format(name, code))
df_search = pd.DataFrame([[name, code]], index=[0], columns=["股票名称", "股票代码"])
return df_search
except Exception as e:
print(e)
return pd.DataFrame()
编写完策略后,需要把策略注册到选股框架中。先是在界面中注册。找到文件“QTYX/MainlyGui/ElementGui/DefDialogs/ParaDialog.py”, SelectModeDialog类的“self.patten_type_cmbo”变量中添加一个策略名称,比如“自定义策略-DIY学习”。如以下代码所示:
class SelectModeDialog(wx.Dialog): # 形态选股参数/更新行情数据参数/RPS选股参数
def __init__(self, parent, title=u"形态选股参数配置", size=(750, 200)):
pass
def patten_dialog(self, sizer_object):
# 中间代码已省略
# 形态选股参数——形态类型选取
self.patten_type_box = wx.StaticBox(self, -1, u'选股模型')
self.patten_type_sizer = wx.StaticBoxSizer(self.patten_type_box, wx.HORIZONTAL)
self.patten_type_cmbo = wx.ComboBox(self, -1, choices=["主升浪(均线多头&突破前高)", "双底形态突破", "箱体形态突破", "单针探底回升",
"自定义策略-DIY学习", "线性回归-预留"],
style=wx.CB_READONLY | wx.CB_DROPDOWN) # 选股项
添加完成后,在界面中会看到对应得选项,如下图所示:
然后在选股框架中注册。找到文件“QTYX/MainlyGui/UserFrame.py”,在“patten_analy_execute”函数的“register_info”变量中添加刚才创建的策略名称,记得要界面中的名称和函数名称一一对应。如以下代码所示:
def patten_analy_execute(self, stock_code):
register_info = {"双底形态突破": Base_Patten_Group.double_bottom_search,
"箱体形态突破": Base_Patten_Group.bottom_average_break,
"单针探底回升": Base_Patten_Group.needle_bottom_raise,
"主升浪(均线多头&突破前高)": Base_Patten_Group.main_rise_wave,
"自定义策略-DIY学习": Base_Patten_Group.user_define_strategy,
}
# 中间代码已省略
return df_return # 有效则添加至分析结果文件中
另外,每个策略都有它的算法参数,需要创建一个填写参数的对话框。找到文件“QTYX/MainlyGui/ElementGui/DefDialogs/SpecDialog.py”,添加一个对话框类,比如名称“UserDefStrategyDialog”。如果是自己使用,并且参数已经确定了,可以直接在策略代码中固定参数值,界面只需要留一个空壳即可,这样更简单点。如下代码所示:
class UserDefStrategyDialog(wx.Dialog): # 用户自定义参数界面
def __init__(self, parent, title=u"自定义提示信息", size=(500, 360)):
wx.Dialog.__init__(self, parent, -1, title, size=size, style=wx.DEFAULT_FRAME_STYLE)
# 中间代码已省略
# 创建FlexGridSizer布局网格
# rows 定义GridSizer行数
# cols 定义GridSizer列数
# vgap 定义垂直方向上行间距
# hgap 定义水平方向上列间距
self.FlexGridSizer = wx.FlexGridSizer(rows=1, cols=2, vgap=0, hgap=0)
self.ok_btn = wx.Button(self, wx.ID_OK, u"确认")
self.ok_btn.SetDefault()
self.cancel_btn = wx.Button(self, wx.ID_CANCEL, u"取消")
self.FlexGridSizer.Add(self.ok_btn, proportion=1, border=1, flag=wx.ALL | wx.EXPAND)
self.FlexGridSizer.Add(self.cancel_btn, proportion=1, border=1, flag=wx.ALL | wx.EXPAND)
self.FlexGridSizer.SetFlexibleDirection(wx.BOTH)
self.SetSizerAndFit(self.FlexGridSizer)
self.Centre()
def feedback_paras(self):
self.user_para = dict()
return self.user_para
接下来在文件“QTYX/MainlyGui/UserFrame.py”中,把对话框函数“UserDefStrategyDialog”导入进去。如下代码所示:
from MainlyGui.ElementGui.DefDialogs.SpecDialog import UserDefStrategyDialog
接下来在文件“QTYX/MainlyGui/UserFrame.py”中,找到事件函数“_ev_patten_select_func”,把对话框函数“UserDefStrategyDialog”注册进去,记得要界面中的名称和函数名称一一对应。
def _ev_patten_select_func(self, event):
pass
register_info = {"主升浪(均线多头&突破前高)":{"对话框函数": MainRiseWaveDialog,
"日志信息":"主升浪形态选股正在执行..."},
"双底形态突破": {"对话框函数": DouBottomDialog,
"日志信息":"双底形态选股正在执行..."},
"箱体形态突破":{"对话框函数": BreakBottomDialog,
"日志信息":"底部形态选股正在执行..."},
"单针探底回升": {"对话框函数": NeedleBottomDialog,
"日志信息": "单针探底回升选股正在执行..."},
"自定义策略-DIY学习":{"对话框函数": UserDefStrategyDialog,
"日志信息": "单针探底回升选股正在执行..."}
}
pass
最后生成选股结果时,如果想要叠加特色数据,就在文件“QTYX/MainlyGui/UserFrame.py”中,找到函数“patten_analy_result”,把特色数据叠加到形态选股文件中即可。
def patten_analy_result(self):
pass
if self.patten_paras[u"北向资金持股"] == True:
pass
if self.patten_paras[u"每日基本面指标"] == True:
pass
if self.patten_paras[u"叠加利润报表"] == True:
pass
Base_File_Oper.save_csv_file(df_search, f"全市场选股结果/{self.patten_paras['选股模型']}分析结果_{select_date.strftime('%Y-%m-%d')}_高速版.csv")
self.patlog.re_print("\n形态分析完成!明细查看路径ConfigFiles/全市场选股结果/")
想要叠加的特色数据类别是在选股配置界面上勾选的,也是在“QTYX/MainlyGui/ElementGui/DefDialogs/ParaDialog.py”的“SelectModeDialog”类中修改。
总结
以上就是在QTYX系统中添加自己的选股策略的方法,例程代码会体现在2.7.2版本中,以供大家参考和学习。在调试过程中难免不会一帆风顺,大家记得多使用print打印日志,排查问题,祝愿各位早日搭建出属于自己的量化系统!
说明
想要加入知识星球《玩转股票量化交易》的小伙伴记得先微信call我获取福利!
知识星球介绍点击:知识星球《玩转股票量化交易》精华内容概览