0449b1cf95b7d74039ee1e0628261a3e.png

搭建自己的量化系统

e9dad950c88065d375eb51b5fde0268f.png

股票量化交易系统QTYX是一个即可以用于学习,也可以用于实战炒股分析的系统。

分享QTYX系统目的是提供给大家一个搭建量化系统的模版,最终帮助大家搭建属于自己的系统。因此我们提供源码,可以根据自己的风格二次开发。

关于QTYX的使用攻略可以查看链接:QTYX使用攻略

QTYX一直迭代更新,当前版本V3.0.1。后续升级版本会同步更新文档内容。

自从ChatGPT横空出世以来,国内外陆续推出了一系列的AI文本大模型。有了AI工具的加持,我们在搭建交易系统这件事情上变得事半功倍了。

本期我们分享下利用AI工具学习QTYX源码以及二次开发的几个场景。

AI模型介绍

目前流行的AI文本大模型有很多,包括OpenAI的GPT系列、百度的文心一言、最近火爆的DeepSeek等等。

使用起来其实也很方便,就是在对话框内输入我们的需求后,AI会返回给我们想要的结果。

通常,我们与AI交互时候把它当成是我们的“秘书”一样,把问题的背景、目的、条件描述地尽量详尽即可,一次不行就多来回交互几次,直到结果满意为止。

由于几款AI文本大模型都可以满足我们当前学习和开发QTYX的需求,此处我们就以DeepSeek为例来介绍场景。

网址:DeepSeek | 深度求索

典型应用场景
  • 看不懂的代码让DeepSeek解释一下

我输入了一段QTYX工程的PattenGath.py文件中的主升浪形态选股的代码“main_rise_wave”,要求“帮我解释下每一句代码的用途”。

ac456a789920a5edcaadc5d561cb7aa5.png

DeepSeek返回结果非常准确,还额外提出了代码优化方案,甚至给出了优化后的代码。

d91af23c83b981579354515cbd534635.png

  • DeepSeek帮我写一个“六脉神剑”形态选股策略添加到QTYX中

QTYX工程的PattenGath.py文件中有一个用户自定义形态选股Demo代码“user_define_strategy”。我们让DeepSeek模仿这个格式写一个“六脉神剑六红”选股策略。

@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()

同时,我们告诉DeepSeek“六脉神剑六红”选股策略的逻辑是六个技术指标同时共振来选出潜在的买入信号。

MACD:异同移动平均线,是趋势指标,用于判断股票的短期趋势。

KDJ:随机指标,通过比较股票在一定时期内的最高价、最低价和收盘价之间的关系,来反映股价的强弱和超买超卖现象。

RSI:相对强弱指数,通过比较一定时期内股价的上涨幅度和下跌幅度来分析市场超买或超卖状态。

LWR:威廉指标,也是通过比较股价在一定时期内的最高价、最低价和收盘价来预测市场动向。

BBI:多空指标,通过计算不同时间周期的移动平均线的平均值来反映股价的长期趋势。

MTM:动力指标,通过比较股价的变动速度和变动幅度来判断股票的买卖时机。

当以上六个指标同时满足以下条件时,即称为“六红”:

MACD指标当前值大于前一期值。

KDJ指标的K值大于前一期值。

RSI指标的RSI1值大于前一期值。

LWR指标的LWR1值小于前一期值。

BBI指标当前值大于前一期值。

MTM指标当前值大于前一期值。

DeepSeek很快就给出了代码,而且非常工整精简,比我自己写得好多了!

534c5a74ec9e068f4d6a0bd47e5aa68a.png

@staticmethod
def six_swords_six_red_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: DataFrame: 包含符合策略的股票名称和代码
    """
    try:
        df_search = pd.DataFrame()  # 构建一个空的dataframe用来装数据
        # MACD指标计算
        stock_data['EMA12'] = stock_data['收盘价'].ewm(span=12, adjust=False).mean()
        stock_data['EMA26'] = stock_data['收盘价'].ewm(span=26, adjust=False).mean()
        stock_data['MACD'] = stock_data['EMA12'] - stock_data['EMA26']
        stock_data['MACD_Signal'] = stock_data['MACD'].ewm(span=9, adjust=False).mean()
        # KDJ指标计算
        low_list = stock_data['最低价'].rolling(9, min_periods=1).min()
        high_list = stock_data['最高价'].rolling(9, min_periods=1).max()
        rsv = (stock_data['收盘价'] - low_list) / (high_list - low_list) * 100
        stock_data['K'] = rsv.ewm(com=2, adjust=False).mean()
        stock_data['D'] = stock_data['K'].ewm(com=2, adjust=False).mean()
        stock_data['J'] = 3 * stock_data['K'] - 2 * stock_data['D']
        # RSI指标计算
        delta = stock_data['收盘价'].diff()
        gain = (delta.where(delta > 0, 0)).rolling(window=14).mean()
        loss = (-delta.where(delta < 0, 0)).rolling(window=14).mean()
        rs = gain / loss
        stock_data['RSI'] = 100 - (100 / (1 + rs))
        # LWR指标计算
        stock_data['LWR'] = (high_list - stock_data['收盘价']) / (high_list - low_list) * 100
        # BBI指标计算
        stock_data['BBI'] = (stock_data['收盘价'].rolling(window=3).mean() +
                             stock_data['收盘价'].rolling(window=6).mean() +
                             stock_data['收盘价'].rolling(window=12).mean() +
                             stock_data['收盘价'].rolling(window=24).mean()) / 4
        # MTM指标计算
        stock_data['MTM'] = stock_data['收盘价'].diff(6)
        # 判断六个指标是否同时满足条件
        macd_condition = stock_data['MACD'][-1] > stock_data['MACD'][-2]
        kdj_condition = stock_data['K'][-1] > stock_data['K'][-2]
        rsi_condition = stock_data['RSI'][-1] > stock_data['RSI'][-2]
        lwr_condition = stock_data['LWR'][-1] < stock_data['LWR'][-2]
        bbi_condition = stock_data['BBI'][-1] > stock_data['BBI'][-2]
        mtm_condition = stock_data['MTM'][-1] > stock_data['MTM'][-2]


        if (macd_condition and kdj_condition and rsi_condition and
            lwr_condition and bbi_condition and mtm_condition):
            # 输出满足要求的股票
            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框架结构设计非常好,把这段代码拷贝到PattenGath.py文件中,在process_patten函数中注册下就把策略注册到选股框架中了。

593a508c88e49ab0054f4aaa95a90f79.png

接下来,在界面中注册策略。找到文件“QTYX/MainlyGui/ElementGui/DefTreelist.py”, CollegeTreeListCtrl类的“colleges”变量中添加一个策略名称,比如“六脉神剑全红共振”。如以下代码所示:

222dba557fdcc181b1dcad99579e58f1.png

添加完成后,在界面中会看到对应得选项,如下图所示:

36053862b4085babbf69c27c66f0d804.png

另外,每个策略都有它的算法参数,需要创建一个填写参数的对话框。找到文件“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,
                                    "日志信息": "单针探底回升选股正在执行..."},
                         "六脉神剑全红共振": {"对话框函数": UserDefStrategyDialog,
                                    "日志信息": "六脉神剑全红共振选股正在执行..."},
                         "自定义策略-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”类中修改。

27316e54a88687f1b47ae410709ee90a.png

选股完成!总共不到5分钟就把“六脉神剑全红共振”选股策略移植到QTYX框架中了!

e283ccba9baebb2f49b6f06aa87a0fec.png

  • 二次开发过程中遇到报错DeepSeek协助排查。

DeepSeek在协助排查问题时候非常得心应手!不管控制台上报了什么异常信息,只管拷贝到DeepSeek的对话框中即可!
比如我运行QTYX时候控制台上出现了一堆日志,我都懒得看直接让DeepSeek来分析。

DeepSeek不但告诉我原因,还给出了优化后的代码,非常贴心!

2499a90973ea3dd6b2e97c4e55b52412.png

总结‍‍

ebcb941678d838a351c91a3dbeccae55.png

有了AI工具之后可以提高我们获取信息的效率,但是同样的工具不同人使用最后的结果又会有所不同,因此学会如何

利用工具决定了人和人最后的差距。

以上分享使用AI工具学习和二次开发QTYX的几个技巧,希望对大家有所帮助。

后续我们会继续分享这些技巧和场景,帮助大家成长,搭建量化系统!

说明

想要加入知识星球《玩转股票量化交易》的小伙伴记得先微信call我获取福利!

知识星球介绍点击:知识星球《玩转股票量化交易》精华内容概览

5b8f68d03e3c445ce4c82d0d52430181.jpeg

Logo

欢迎加入DeepSeek 技术社区。在这里,你可以找到志同道合的朋友,共同探索AI技术的奥秘。

更多推荐