15天搭建ETF量化交易系统Day12—雏形系统关键代码讲解!


9e5ae5c311ea12a51cea63377c0ab516.png

搭建过程

1b0845025759590b77a2eec306c45840.png

每个交易者都应该形成一套自己的交易系统。

 
 

很多交易者也清楚知道,搭建自己交易系统的重要性。现实中,从0到1往往是最难跨越的一步。

授人鱼不如授人以渔,为了帮助大家跨出搭建量化系统的第一步,我们决定推出这个主题系列。

这个系列中,我们用Python从0开始一步步搭建出一套ETF量化交易系统(选择ETF标的是因为对于普通交易者来说,ETF相对于选强势股难度要小,而且没有退市风险)。大家可以跟随着我们的实现路径来一起学习,从过程中掌握方法。

掌握了方法之后,你可以换成期货系统、比特币系统、美股系统,然后在实战中不断去完善自己的系统了。

搭建一套ETF量化交易系统涉及多个模块和组件的协同工作,包括数据源模块、量化策略模块、可视化模块、数据库模块、回测评估模块、自动交易模块等等。

DAY1链接如下:15天搭建ETF量化交易系统Day1—数据源模块
DAY2链接如下:15天搭建ETF量化交易系统Day2—图形显示模块
DAY3链接如下:15天搭建ETF量化交易系统Day3—上手经典回测框架
DAY4链接如下:15天搭建ETF量化交易系统Day4—玩转海龟交易策略
DAY5链接如下:15天搭建ETF量化交易系统Day5—打造实盘量化机器人
DAY6链接如下:15天搭建ETF量化交易系统Day6—打通同花顺自动交易
DAY7链接如下:15天搭建ETF量化交易系统Day7—全自动化交易系统
DAY8链接如下:15天搭建ETF量化交易系统Day8—强化自动交易模块
DAY9链接如下:15天搭建ETF量化交易系统Day9—玩大A必学网格策略

DAY10链接如下:15天搭建ETF量化交易系统Day10—借用网格思想做仓位管理

DAY11链接如下:15天搭建ETF量化交易系统Day11—miniQMT自动交易真香!

经过这些DAYs的努力,我们已经实现了数据源、择时策略、仓位管理、自动交易等功能,这期我们先把这些模块整合成一个ETF量化系统雏形,然后在实盘中运行,在这个过程中不断去优化它!


4689a651a36af0c9212acdab4a653dd5.png

策略逻辑

a9b053f089b08cfcd22eafcf4c438787.png

 
 
 
 

我们的择时策略结合了趋势指标和震荡指标的优势,趋势指标采用经典的“MACD金叉死叉”,震荡指标采用了“非对称式网格仓位管理”。

“量化机器人”以60分钟级别监测ETF品种,计算MACD指标,代码如下所示:

# 计算MACD指标
fast_period = 12 # 快速移动平均线周期
slow_period = 26 # 慢速移动平均线周期
signal_period = 9 # 信号线周期c
dif, dea, hist = talib.MACD(df_index_data['close'], fastperiod=fast_period, slowperiod=slow_period, signalperiod=signal_period)
list_diff = np.sign(dif - dea)
signal_diff = np.sign(list_diff - list_diff.shift(1))

“量化机器人”监测到有ETF符合买入条件时,查询交易账户是否有足够的资金能买入。当账户余额充足时,先设置网格,然后调整仓位买入。

if signal_diff[-1] == 1:
  send_cont += f"{sym} {code} {signal_diff.index[-1]}, 出现金叉信号\n"
  print(f"{sym} {code} {signal_diff.index[-1]}, 出现金叉信号")
  # 出现金叉时设置网格
  self.position_strategy.setup_grid(sym, latest_close)
# 在网格中的品种仓位管理
if sym in self.position_strategy.inquire_position:
  instruct = self.position_strategy.adjust_position(sym, latest_close)

当买入后出现震荡行情时,“量化机器人”的网格仓位管理策略开始接管,根据设定的网格线对仓位进行加减。

instruct = self.position_strategy.adjust_position(sym, latest_close) 
if 'Buy' in instruct:
  if self.order_if.check_stock_is_av_buy(code, latest_close, instruct['Buy'], 5000) == True:
    self.order_if.make_buy(code, 0, instruct['Buy']) # 现价买入
if 'Sell' in instruct:
  if self.order_if.check_stock_is_av_sell(code, instruct['Sell']) == True:
    self.order_if.make_sell(code, 0, instruct['Sell']) # 现价卖出

当行情走出震荡后,如果向上突破时我们采用高点回撤止盈策略卖出,如果向下跌破网格时我们采用止损策略卖出。

# 止盈止损
instruct = self.order_if.check_stop_loss(sym, latest_close)
if 'Sell' in instruct:
  if self.order_if.check_stock_is_av_sell(code, instruct['Sell']) == True:
    self.order_if.make_sell(code, 0, instruct['Sell'])
buy_price = self.position_strategy.inquire_position[sym]['buy_price']
highest_price = self.position_strategy.inquire_position[sym]['highest_price']
instruct = self.order_if.check_profit_taking(sym, buy_price, latest_close, highest_price)
if 'Sell' in instruct:
  if self.order_if.check_stock_is_av_sell(code, instruct['Sell']) == True:
    self.order_if.make_sell(code, 0, instruct['Sell'])

3b8ad6afb450c8549a514cad17364b97.png

自动交易

984482756e718026096e2769ab5f7bc8.png

 
 
我们内置了两套自动交易接口,一套是miniQMT,一套是easytrade控制同花顺客户端下单,在启动的时候可以通过参数选择交易接口。推荐miniQMT,相对比较稳定。
class RealTimeData():
    def __init__(self, index_symbol={}, order_type = "ths"):
        choose_order = {'ths': ThsTrader(), 'qmt':QmtTrader()}
        self.order_if= choose_order[order_type]
        self.order_if.connect(order_type)

无论是miniQMT还是easytrade,在系统中的接口都是完全兼容的。

def connect(self, client="qmt"):
  '''
  连接
  path qmt userdata_min是路径
  session_id 账户的标志,随便
  account账户,
  account_type账户内类型
  '''
  pass


def get_position(self):
  '''
  查询账户所有的持仓
  '''
  pass
def get_balance(self):
  '''
  返回当前证券账号的资产数据
  '''
  pass
def today_trades(self):
  '''
  当日成交
  '''
  pass
def today_entrusts(self):
  '''
  当日委托
  :param account: 证券账号
  :param cancelable_only: 仅查询可撤委托
  :return: 返回当日所有委托的委托对象组成的list
  '''
  pass
def check_stock_is_av_buy(self, stock='600031', price=17.70, amount=10, hold_limit=100000):
  '''
  检查是否可以买入
  '''
  pass
def check_stock_is_av_sell(self, stock='600031', amount=10):
  '''
  检查是否可以卖出
  '''
  pass
def make_buy(self,  security='600031', amount=100, price=20):
  '''
  单独独立股票买入函数
  '''
  pass
def make_sell(self, security='600031.SH', amount=100,  price=20):
  '''
  单独独立股票卖出函数
  '''
  pass
 
 

be1283a867490e9d232cf46492b3ddca.png

时间调度

96540dc53f1b47c44a371b15c865a402.png

 
 
 
 

“量化机器人”创建了一个TimeTrigger类,可以在其中的trigger_run中添加自己要定时执行的任务。

我们使用Schedule模块定时运行任务,使用前需要安装一下:

pip install schedule

我们在交易时间段以小时为周期调用实时行情接口来获取数据,获取到数据后进行策略分析,选出符合要求的标的。

我们可以使用以下代码来设置定时任务。每个任务都使用schedule.every().day.at("HH:MM").do(job)来设置。

其中HH:MM是你想要执行任务的时间,job是你要执行的函数。

import schedule  
import time  
def job():  
    print("执行任务...")  
    # 这里可以放置你想要在特定时间执行的代码  
  
# 设置定时任务  
schedule.every().day.at("9:30").do(job)  
schedule.every().day.at("10:30").do(job)  
schedule.every().day.at("11:30").do(job)  
schedule.every().day.at("13:00").do(job)  
schedule.every().day.at("14:00").do(job)  
schedule.every().day.at("15:00").do(job)  
while True:  
    schedule.run_pending()  
time.sleep(60)  # 等待60秒钟再检查是否有任务需要执行

这段代码会无限循环地检查是否有定时任务需要执行,直到你手动停止它。如果你想要在某个条件下停止循环,你可以在while循环中添加一个条件判断。

cur_time = self.get_curtime # 实盘代码
if self.after_trade_time(cur_time):
print(u"结束时间{0}--已收盘".format(self.end_time.strftime("%Y-%m-%d_%H:%M:%S")))
schedule.clear()

另外,由于schedule库是基于时间的,所以如果你的程序启动时间错过了某个任务的执行时间,那么那个任务将不会被执行,直到下一个设置的时间点。例如,如果你的程序在9:40启动,那么9:30的任务将不会被执行,直到第二天的9:30。

c6d4032ff025d39b06b4009593d7367f.png

远程发送

b1bd7ef40eb83023aebf41c59a9d0bce.png

当出现买卖信号时,“量化机器人”也会发送消息到我手机上,及时通知我。

auto_send_email(sys_para_dict['mailbox']['to_address'],
                '主人!你实时监测的ETF有最新消息!',
                send_cont,
                sys_para_dict['mailbox']['password'],  
                'smtp.qq.com',  # smtp.163.com
                    from_address=sys_para_dict['mailbox']['from_address']) #

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

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

869a8c9b8fe6a2b6afa002dc6feaeac3.png

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

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

典型的例程如下所示:

2af9c7c0e55fe95e0623268dacdffe66.png

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

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

典型例程如下所示:

6f80346acfbbd471d28d20191dc48324.png

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

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

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

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

d7cab11ad8d261dbf761ce7f2fe13821.png

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

ff85eb9601d8062a5952ca0e8311093d.png

ca403c270cbe937a18830b480e77d41b.png

这样一来邮件就发送成功了,手机邮箱也一样可以收到哦!

8b3df78c2edda1c23c44b4d2b27c18f0.png

服务器部署

2ff8abc2e561b727f857aa2cdb22d78a.png

我们已经准备好了量化机器人的Python脚本,能达到定时执行Python程序的本质还是用到Windows下的任务计划,在日常工作中这个功能经常用于提高工作效率的。

接下来创建一个定时任务来执行这个脚本。

第一步,右键我的电脑,点击管理。在弹出的计算机管理对话框点击任务计划程序—>创建基础任务。

19334802ea87c52ae410a1bc3df1af1d.jpeg

第二步,在弹出的创建基本任务向导输入名称和描述,然后点击下一步。

b43e095d3a439e5ae16ee0d1dcf6857e.jpeg

第三步,在触发器页面设置脚本执行的时间计划,选择每天,点击下一步。

16eced73bb9549a5001db07869202c74.jpeg

第四步,设置每天触发的时间,点击下一步。

d1e7ff88f530b4cccd74c77db9347727.jpeg

第五步,在操作页面,选择启动程序,点击下一步。

3d6db914a58356dbd1c441d73e46bc2a.jpeg

第六步,此处程序或脚本中填写的一般是编译器的名称,一般对Python来说就是Python.exe(找到你的安装路径),添加参数就是你所要执行的Python文件(完整路径),这样填写的本质其实就是在命令行中执行Python一样。

305e6b7a5312612f06cc92d8714e61c6.jpeg

第七步,设置到这里已经算是完成了,接着就是等待它自动执行了。

a2a3053f73c735b644b8c4d0c98d7ec7.jpeg

4a4fca23370fbc4465db7c657dcfd0dc.jpeg

158fccfcc5259332fbb50b0b8218a694.png

总结

5c8d9e019737eeda1a33dba736535c99.png

搭建出了闭环的交易系统后,我们可以先用模拟交易放松在实盘中测试,不断去优化这个系统,一步步把策略优化成赚钱的策略,然后让机器人帮我们自动赚钱。

如何获取QMT安装包和开户可以看这篇介绍:量化交易自动下单方案—对接QMT已出炉

说明

此系列为连载专栏,完整代码会上传知识星球《玩转股票量化交易》!作为会员们的学习资料。

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

非星球会员需要的话,需要单独联系我购买!

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

aa97fa3099869303908d911f325f72da.jpeg

  • 15
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值