量化系统QTYX使用攻略|“自动交易”篇——“六边形”量化框架!支持股票和ETF,可添加策略(更新v2.9.9)...

a3692b8f02bd6052a8474db594358cc5.png

QTYX系统简介

ba266a72cffe5cc83017da504b48994d.png

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

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

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

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

4a2a691a62bcb6553815cf7f8211ccb2.png

功能概述

9e9a1d4356aead20c5cab32315c310b4.png

QTYX内置了一款“六边形”量化交易框架(集成了“策略&回测&仓位&风控&下单&标注BS”为一体)。

这套框架包含如下模块:

  • 实时扫描交易品种分钟数据

  • 根据择时策略产生交易信号

  • 可视化标注策略BS交易点

  • 根据止盈止损值产生交易信号

  • 通过仓位管理分配下单数量

  • 连接QMT接口自动下单

  • 打通回测框架,实盘前可以回测择时策略,评估策略的效果

  • 支持股票和ETF

  • 可添加自己的择时策略到框架中

为什么要支持ETF?ETF兼具股票和指数基金的特色,既能获得股票一样的超额收益,也具备指数稳定的特点。买ETF相当于购买了一篮子股票,能分散投资并降低投资风险。另外,ETF还能买到海外市场的指数,有些ETF还能够T+0交易,非常灵活!

本篇攻略我们分享下这套框架的使用方法,以及如何在框架中添加自己的策略。

864a884f478557bae7e18322b09e4283.png

如何使用

1c82bb0de30da49fc2ae7ee005a94684.png

 
 
 
 

我们点击“策略导航—>实盘监测—>股票池监控/ETF池T+0”。

选择“ETF池T+0”是启用ETF框架,选择“股票池监控”是启用股票池框架。

cf83a785dbff3b7eb55d7dfe05191b71.png

然后会出现一个操作对话框,如下所示:

接下来,我们介绍下界面上的功能。这里的功能同时适用于ETF和股票框架。
  • 开始日期&结束日期:根据时间范围返回对应的ETF/股票分钟数据。实盘时结束时间保持最新日期。

  • 股票周期:支持1分钟、5分钟、15分钟、30分钟、60分钟级别扫描ETF/股票择时信号

  • 发送邮件使能:ETF/股票出现买卖信号后邮件通知,记得json文件填写邮箱信息。如何填写邮箱信息,下文有具体介绍。

  • 止盈止损使能:ETF/股票触发止盈止损条件时自动卖出,记得json文件填写参数

  • 自动交易使能:ETF/股票出现买卖信号后直接下单,记得json文件填写参数

  • “设置买入滑点”:在当前价格的基础上增加滑点,避免市场波动而出现买不进的情况。设置为0时,现价直接买入。

  • “设置买入股数”:可以选择按总资金比例分配买入和按股数买入,记得json文件填写参数

  • “设置卖出滑点”:在当前价格的基础上增加滑点,避免市场波动而出现卖不出的情况。设置为0时,现价直接卖出。

  • “设置卖出股数”:实盘时卖出该股的股数,目前出现信号全部卖出。

  • “择时策略”:选择当前运行的策略,目前预置了“MACD金叉死叉”、“布林带突破”等4个策略

 
 
点击“开始扫描”后,程序就开始监测ETF/股票池中是否有出现交易信号了。结束时需要先点击“停止扫描”,然后再退出。
可以从对话框中看到,159509、513300监测到卖出信号,但是在账户中未持有,未触发自动卖出。

1b95ec26e4f7d0f0df95e14f3b7a34dc.png

当触发止损信号时,如果159509、513300这些ETF在账户中持有,QTYX自动卖出。

38e1f2d6cf5da3b54ec7230a343bc44a.png

当出现止盈止损交易信号时,系统会链接上QMT客户端(提前登录QMT客户端,并且在configfiles/trade_para.json文件中填写下单参数),自动卖出ETF。

建议提前在QTYX“交易”界面中测试下QMT下单是否成功!

a1f384d13f684c067309825d4bcd5e8b.png

一顿卖出后,QTYX监测到账户中已经清仓了这些ETF!159509、513300这些ETF未在账户中持有,不会监测止盈止损信号。

1aa58f56d1e1190846450fa058e82660.png

0685497a92a31243246101e131f9abff.png

参数配置

1b2c6adb3c75e0cb780e39802562e1ea.png

关于QMT自动下单相关的配置,主要是客户端安装路径和账号。打开configfiles/trade_para.json文件手动更改。配置完成后,可以在“交易”界面上测试下单接口是否配置成功。

f80fed88cc71b140ea6bd8c1d4cc618e.png

 
 
我们把miniQMT的驱动移植到了QTYX/TradeDrv目录下,这样就可以和QMT客户端进行互动。整体的实现原理在miniqmt_if.py文件中,大家可以参看一下。
ETF/股票池,已经搬运至ConfigFiles/trade_para.json文件中,请按格式填写,“percent”的值表示买入资金占总资金的比例,“amount”的值表示买入的股数。

07b3d44b60517ca5cb623c3a968496cb.png

关于ETF/股票止盈止损参数。止盈止损是交易领域中是不可或缺的风险管理方法,有助于限制损失、锁定利润。我们在ConfigFiles/trade_para.json文件中按格式填写,此处我们填写止盈是4%,止损是3%,大家可以根据自己的风险偏好填写。

 
 

6855903bb215553014a2583c274e664e.png

关于策略,我们在StrategyGath\SignalGath.py文件中预置了多个策略,大家可以在这个文件中使用Python语言添加和修改。后续我们也会不断往这个接口中添加和优化策略,比如指数通行红绿灯策略等等。

策略的关键参数,我们在ConfigFiles/trade_para.json文件中按格式填写,比如“MACD金叉死叉”的周期和“布林带突破”的上下轨倍数等。
 
 

6ec8316508d7af7983e425f1b47a7bc3.png

如何回测

35b79904423c7fc61f212f3d443ee401.png

 
 

我们点击“回测参数”标签页,填入ETF代码(注意格式xxxxxx.SH/SZ),选择策略,然后点击“开始回测”。

接下来填写回测参数,比如回测日期、数据周期、初始资金、滑点、手续费等等。

07a703759d0f55aa54905cd954eedd44.png

填写完成后,点击“确认”就会出现可视化回测结果。

ae3de74cba13e6e4dea424c7fb2f9694.png

点击“交易日志”可以查看具体的交易明细。

2d59ec645d28a950e7943a40a0780cbb.png

 
 

回测的策略与实盘框架同源,是在StrategyGath\SignalGath.py文件中预置的策略。

 
 
 
 
 
 
 
 
 
 

a42d28e986356b75410c2a4946b7523b.png

标记策略BS点

f1255e4c5502cba60fd2db5bd7a5ac90.png

在“量化”主页面中,我们看到左边有“策略导航”树形列表,“衍生指标”中列出了目前添加的择时策略。
衍生指标可以把择时策略的交易信号在K线图上标注出来,这样一来,同一个策略可以分别在实盘交易框架、回测评估框架、信号图形化框架中使用!

988e55b26ead0b6ac80862bd6b87538b.png

比如点击“布林带突破”策略作为演示,然后会跳出对话框,选择股票数据的参数,比如起始日期、周期、复权选项等等。

888da95e1e28d3bee0f9ecd59b228e14.png

点击确认后,会出现图形化界面,界面上会标注出股票数据中全部的买卖信号,比如突破上轨/跌破下轨,出现的日期等,效果图如下所示,

0dbdbac05c19a238a33a149bcd2ace57.png

可以清楚看到,每当股价跌破下轨时分仓买入,突破上轨时分仓卖出,这个套利思路非常稳!

比如点击“均线交叉”策略作为演示,如下所示:

0ad8f502747207cfb81c61a1e3d70eb1.png

关于策略,我们在StrategyGath\SignalGath.py文件中预置了多个策略,大家可以在这个文件中使用Python语言添加和修改。后续我们也会不断往这个接口中添加和优化策略,比如指数通行红绿灯策略等等。

策略的关键参数,我们在ConfigFiles/trade_para.json文件中按格式填写,比如“MACD金叉死叉”的周期和“布林带突破”的上下轨倍数等。

刚才提到同一个策略是可以分别用在实盘交易框架、回测评估框架、信号图形化框架中使用!

比如回测的效果图:

ac618438fe9dc4474d3549f057d76f9f.png

比如实盘交易的效果图:

80e10325fb2a814cf5ad491f7b1134c7.png

c096eb32b4f682bd5864d32a62a8c939.png

远程报告配置

f50b23a4d3b4da73cee220047566d615.png

实盘时发现该股已经符合止盈止损交易条件时,会远程发送信息提醒。(要记得在ConfigFiles/sys_para.json中填写邮箱信息,在微信上开启QQ邮箱提醒功能,效果如同微信提醒)

cf65a1257e950e11b573ae8ed836f6c5.jpeg

如何填写邮箱信息:

发送邮件和核心是SMTP(Simple Mail Transfer Protocol)协议,它是一组用于由源地址到目的地址的邮件传输规则。

Python真的是什么都能做,它对SMTP进行了简单的封装,只需用到两个模块,就可以轻松实现发送纯文本邮件、HTML邮件以及带附件的邮件。

哪两个模块呢?Python内置的email模块负责构建邮件,另一个smtplib模块负责发送邮件。

常规的流程,先把涉及到的模块全部导入进来,如下所示:

fd1b6f223f1161bffe949fcbf1413550.png

首先用MIMEText()构造一个最简单的纯文本邮件,其中第一个参数是邮件正文,第二个参数是内容的类型,比如'plain'表示纯文本邮件,'html'表示HTML邮件。

创建的邮件对象中,要添加From、To和Subject这些属性,否则就不是一封完整的邮件,比如会出现邮件没有主题,发件人的名称为匿名,明明收到了邮件却提示不在收件人中这些情况。

典型的例程如下所示:

fa512cb50f4a9addb2fba193bd1d01da.png

再来说说负责发送邮件的smtplib模块,这个模块主要是用smtplib.SMTP()类去连接SMTP服务器,然后发送邮件。

例程中我们会用到几个常用的方法,比如set_debuglevel(1)打印和SMTP服务器交互的所有信息。login()登录SMTP服务器,sendmail()方法发邮件。

典型例程如下所示:

385f282740e5014b65aebd2f662aaf9e.png

这里的password是个比较容易混淆的地方。不是邮箱登陆的密码,而是授权码。

第三方客户端登录QQ邮箱时是需要授权码的,包括其他邮箱也都一样,比如126、163邮箱等等。授权码可以认为是一个专用密码,适用于登录以下服务:POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服务。

如何设置呢?以QQ邮箱为例,我们在QQ邮件的帮助中心找到了方法。

在个人邮箱页面进入[设置] -> [帐户] 页面找到入口,然后把POP3/IMAP/SMTP这几个服务开启。

892d2ea9a7a52f955554325fc95e374e.png

开启的时候有验证密保环节,需要发送短信,接着就获取到授权码,在第三方客户端的密码栏里面输入这16位授权码进行验证即可。

1be1932be7ff49ba9595b9c13fd307bb.png

87d637406af455ea87c0b2b74938844b.png

这样一来邮件就发送成功了!

 
 
添加自定义策略

我们在StrategyGath\SignalGath.py文件中预置了多个策略。如果有新的策略可以在这个文件中使用Python语言添加和修改。
 
 
 
 
 
 
 
 
 
 

131a8841326cd5563f7b3826e390eca0.png

我们在ConfigFiles/trade_para.json文件中按格式填写策略参数,比如“MACD金叉死叉”的周期和“布林带突破”的上下轨倍数等。

我们以"MACD金叉死叉"为例进行讲解。

完整的策略逻辑代码如下所示:

@ind.route_types(u"MACD金叉死叉")
def macd_corss_detect(stock_dat, **kwargs):
    # 检测当前是否有交叉信号
    fast_period, slow_period, signal_period, run_mode = int(kwargs["快速移动平均线周期"]), int(kwargs["慢速移动平均线周期"]), int(kwargs["信号线周期"]), kwargs["模式"]
    dif, dea, hist = talib.MACD(stock_dat['Close'], fastperiod=fast_period, slowperiod=slow_period, signalperiod=signal_period)
    stock_dat["list_diff"] = np.sign(dif - dea)
    # 金叉为1 死叉为-1 中间为0
    stock_dat["Signal"] = np.sign(stock_dat["list_diff"] - stock_dat["list_diff"].shift(1))
    if run_mode == "实盘":
        curtime = stock_dat.index[-1].strftime("%Y-%m-%d %H:%M:%S")
        if stock_dat.loc[stock_dat.index[-1], "Signal"] < 0:
            cont = f"当前时间 {curtime} 出现死叉!!!建议:卖出!\n"
        elif stock_dat.loc[stock_dat.index[-1], "Signal"] > 0:
            cont = f"当前时间 {curtime} 出现金叉!!!建议:买入!\n"
        else:
            cont = f"无金叉/死叉"
        return cont+"\n"
    else:
        stock_dat['Signal'] = stock_dat.Signal.shift(1)  # 当天出信号则第二天买入
        stock_dat['Signal'].fillna(method='ffill', inplace=True)  # 与前面元素值保持一致
        stock_dat['Signal'].fillna(value=0, inplace=True)  # 序列最前面几个NaN值用0填充
        return stock_dat
 
 

完整的策略参数设置如下所示:

"策略参数": {    "MACD金叉死叉": {
        "快速移动平均线周期": 12,
        "慢速移动平均线周期": 26,
        "信号线周期": 9
    }
 }

策略逻辑中的名称要和配置文件中保持一致。

95daee53e5b7cc00eb972f21c3954984.png

把配置文件中策略的参数导入到策略逻辑中,名称要保持一致。

dfb724dd72430219412c1f6cf5d0308f.png

编写策略买卖信号。stock_dat["Signal"]字段存储交易信号,1是买入,-1是卖出,0是保持。

# 检测当前是否有交叉信号
fast_period, slow_period, signal_period, run_mode = int(kwargs["快速移动平均线周期"]), int(kwargs["慢速移动平均线周期"]), int(kwargs["信号线周期"]), kwargs["模式"]
dif, dea, hist = talib.MACD(stock_dat['Close'], fastperiod=fast_period, slowperiod=slow_period, signalperiod=signal_period)
stock_dat["list_diff"] = np.sign(dif - dea)
# 金叉为1 死叉为-1 中间为0
stock_dat["Signal"] = np.sign(stock_dat["list_diff"] - stock_dat["list_diff"].shift(1))

stock_dat是一个dataframe格式数据,我们打印出来如下所示:

Open  Close  High   Low   涨跌幅       涨跌额  Volume       成交额    振幅   换手率  list_diff  Signal
date
2024-11-27 09:45:00  1.08   1.08  1.10  1.08 -0.37 -4.00e-03    2315  2.51e+05  1.47  0.15        NaN     NaN
2024-11-27 10:00:00  1.08   1.08  1.08  1.08 -0.09 -1.00e-03    7549  8.18e+05  0.18  0.48        NaN     NaN
2024-11-27 10:15:00  1.08   1.08  1.08  1.08 -0.28 -3.00e-03    1594  1.72e+05  0.55  0.10        NaN     NaN
2024-11-27 10:30:00  1.08   1.08  1.08  1.08  0.28  3.00e-03     120  1.30e+04  0.37  0.01        NaN     NaN
2024-11-27 10:45:00  1.08   1.08  1.08  1.08  0.18  2.00e-03     220  2.39e+04  0.18  0.01        NaN     NaN
...                   ...    ...   ...   ...   ...       ...     ...       ...   ...   ...        ...     ...
2025-01-10 11:00:00  1.06   1.06  1.06  1.06 -0.19 -2.00e-03      69  7.33e+03  0.19  0.00       -1.0     0.0
2025-01-10 11:15:00  1.06   1.06  1.06  1.06  0.09  1.00e-03   23100  2.45e+06  0.09  1.47       -1.0     0.0
2025-01-10 11:30:00  1.06   1.07  1.07  1.06  0.38  4.00e-03   14010  1.49e+06  0.38  0.89       -1.0     0.0
2025-01-10 13:15:00  1.07   1.06  1.07  1.06 -0.28 -3.00e-03    8112  8.63e+05  0.28  0.52       -1.0     0.0
2025-01-10 13:30:00  1.06   1.06  1.06  1.06  0.00  0.00e+00       0  0.00e+00  0.00  0.00        1.0     1.0


[506 rows x 12 columns]

如果是实盘模式的话,有交易信号时,cont 中要包含字符串“买入”或者“卖出”关键字。

if run_mode == "实盘":
    curtime = stock_dat.index[-1].strftime("%Y-%m-%d %H:%M:%S")
    if stock_dat.loc[stock_dat.index[-1], "Signal"] < 0:
        cont = f"当前时间 {curtime} 出现死叉!!!建议:卖出!\n"
    elif stock_dat.loc[stock_dat.index[-1], "Signal"] > 0:
        cont = f"当前时间 {curtime} 出现金叉!!!建议:买入!\n"
    else:
        cont = f"无金叉/死叉"
    return cont+"\n"

回测时返回的是dataframe格式的序列。

stock_dat['Signal'] = stock_dat.Signal.shift(1)  # 当天出信号则第二天买入
stock_dat['Signal'].fillna(method='ffill', inplace=True)  # 与前面元素值保持一致
stock_dat['Signal'].fillna(value=0, inplace=True)  # 序列最前面几个NaN值用0填充
return stock_dat
下单接口

本套量化框架中涉及的自动交易接口是QMT。关于如何使用QMT,可以查看以下这篇使用攻略!‍‍‍‍‍‍‍‍‍
 
 
 
 
如何QMT开户可以看这篇介绍:量化交易自动下单方案—对接QMT已出炉

说明

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

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

d4909df01e5a15f290517e95281b8d61.jpeg

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值