股市大涨该买吗?教你用算法量化交易行为!

10 篇文章 0 订阅
8 篇文章 0 订阅

 

这几天的股市涨势极猛,上证上涨1.84%,深证成上涨2.43%,创业板上涨2.21%,两市合计金额再次破万亿。盘面上看,两市个股涨多跌少,行业板块全线飘红。

 

 

这样的大好局势却让大家纠结万分,继续跟怕买了就跌,不跟但看着心里又难受,怎么办呢?

 

其实交易行为都可以用数据来分析和量化的,如今,很多企业和投资金融领域保持竞争力,开始采用Python编程来解决期货量化交易。从数据分析的角度切入,以技巧的形式深入数据背后,让读者从基本的期货交易规则开始,了解相关的技术指标,并能够熟练使用Python编程走上量化交易之路。

 

当我们在市场上交易,对于当前市场的趋势变动没有把握时,就需要历史回测来验证 自己的想法是否可行。历史回测不仅仅只是数学量化模型的计算,同时也包含了量化模型以外的市场行为分析。

 

 

期货交易,简单来说就是一买一卖,赚取价差。算法的目的在于将投资人的交易行为,量化转化为代码。程序化交易中的回测算法与实盘交易算法有不同的编写方式,所以来了解一下回测吧!

 

回测算法就是通过历史数据,模拟真实的开盘环境,进行数据解读、计算、判断,决 定是否建仓、平仓,获取成交信息。 量化回测的必要步骤:

(1)读取历史数据;

(2)转换回测指标;

(3)历史算法设计;

(4)历史回测回传明细格式设计;

(5)绩效计算。

 

建立回测流程

 

1.读取历史数据

本技巧要介绍的“读取历史数据”不仅仅是通过函数去取得数据,还要去运用数据。

 

(1)获取数据函数

算法程序必须先获取交易指标数据或历史报价。我们会通过open函数获取文件内的数据。

 

用Python处理文件,常见的方式是通过open、read来读取数据,也可以直接通过列表推导式(list comprehension)来直接将文件存成list对象,常用的用法如下:

变量名称=[循环变量for循环变量inopen('读取文件')]

 

(2)运用历史数据方式

在读取数据后,如何运用这些数据才是重点,因为交易所历史数据的种类是属于按时间顺序的数据,而交易算法与时间字段也息息相关,所以从某个程度上来说时间格式的掌握是相当重要的。

 

在Python中,我们会读取文件并存成一个list对象。读取数据的方式基本上有两种,原理都是通过循环来进行数据筛选,但是代码编写上会有很大的差异。

 

第一种是通过for循环,逐笔判断list当中的值,通常用于有较多逻辑判断的情况。例如,回测的进出场判断,在本章后面的示例中会应用到。

 

第二种是使用列表推导式,简单来说就是可以直接在list中进行循环筛选。在简易的应用中可以用该方式来解决,例如数据处理、筛选字段、简易的逻辑判断筛选数据。以下是一般性的数据读取、筛选字段和操作介绍。

 

首先获取数据(文件名:Futures_20170815_I020.csv),存成I020变量。

 
 >>> I020 = [ line for line in open('Futures_20170815_I020.csv')]  >>>  >>> I020[0:5]   ['INFO_TIME,MATCH_TIME,PROD,ITEM,PRICE,QTY,AMOUNT,MATCH_BUY_CNT,MATCH_SELL_CNT\n',  '8450010, 8450009,TXFH7,128,10310,732,732,202,349\n',  8450011,8450010,TXFH7,128, 10309,4,736,206,350\n',  '8450011,8450010,TXFH7,128,10309,1,737,207,351\n',  '8450011,8450010,TXFH7,128,10310,1,738,208,352\n'] 

 

接着除去数据表头,舍去每行的换行符(\n)。

 
>>> I020a = [ line.strip("\n") for line in I020[1:] ]   >>> I020a[0:5]  ['8450010,8450009,TXFH7,128,10310,732,732,202,349',  '8450011,8450010,TXFH7,128,  10309,4,736,206,350',  '8450011,8450010,TXFH7,128,10309,1,737,207,351', '8450011, 8450010, TXFH7,128,10310,1,738,208,352',  '8450011,8450010,TXFH7,128,10310,1,739, 209,353']  

 

然后将数据通过逗号分隔。

 
>>> I020b = [ line.split(",") for line in I020a ]   >>> I020b[0:5]   [['8450010', '8450009', 'TXFH7', '128', '10310', '732', '732', '202', '349'],   ['8450011', '8450010', 'TXFH7', '128', '10309', '4', '736', '206', '350'],   ['8450011', '8450010', 'TXFH7', '128', '10309', '1', '737', '207', '351'],   ['8450011', '8450010', 'TXFH7', '128', '10310', '1', '738', '208', '352'],  ['8450011', '8450010', 'TXFH7', '128', '10310', '1', '739', '209', '353']] 

 

最后依照每个使用者的需求,可以直接对数据进行初步筛选。这里进行时间筛选(取9点之后的数据)。

 
>>> I020c = [ line for line in I020b if int(line[0]) > 9000000 ]   >>> I020c[0:5]   [['9000006', '8595997', 'TXFH7', '128', '10311', '2', '12906', '6457', '6827'],   ['9000006', '9000000', 'TXFH7', '128', '10311', '1', '12907', '6458', '6828'],    ['9000018', '9000010', 'TXFH7', '128', '10311', '1', '12908', '6459', '6829'],   ['9000018', '9000012', 'TXFH7', '128', '10311', '4', '12912', '6461', '6830'],   ['9000031', '9000024', 'TXFH7', '129', '10311', '1', '12914', '6463', '6831']] 

 

两种方式各有优缺点,假如要依照时间序列判断目前是否锁定收益出场,可以通过for循环来逐笔判断;若要获取特定时期的价格高低点,则会直接通过Python的list搭配max、min来完成。

 

2.转换回测指标

“转换回测指标”就是将现有的历史数据进一步转换成指标,而每个交易者对于指标的定义都不尽相同,所以必须明确定义指标。

以下提供常见的交易指标,供大家参考。

 

(1)移动平均价

假如在期货交易市场上的交易算法是通过移动平均(MA)为主要的交易指标,那就会定义移动平均的周期以及长度。假设是10分MA,周期就是分钟,长度就是10,而显示出来的信息也就是由10分钟的每分钟收盘价所计算的指标。

 

若10分MA通过前10分钟的收盘价计算,那就只能看到上一分钟的状态,无法掌控最新的市场价格动态。若获取tick数据,也就是逐笔信息,就能够依照最新的价格来进行计算,也就是说,从原本的10分钟收盘价变为9分钟的每笔收盘价加上当前的tick计算,可以即时地反映最新的市场动态。

 

(2)当日价格高低点

回测指标所指的是当日的高低点,并非是直接通过历史数据获取当天的最高价和当天的最低价,而是回测时逐笔地去计算当日最高价和最低价。若回测当前时间为09:50:35,则目前的最高价和最低价就是09:50:35以前的最高价和最低价。

若直接取得当日高低点,可能会造成程序逻辑上的错误,所以在定义指标前必须先厘清观念。

动态计算当日最高点和当日最低点,代码如下:

 
# -*- coding: UTF-8 -*-   # 取I020,依照逗号分隔,并将分隔符号去除  I020 = [ line.strip('\n').split(",") for line in open('Futures_20170815_I020.csv')][1:]   # 定义变量初始值  lastPrice=int(I020[0][4])   outDesk=0  inDesk=0   # 开始计算内外盘  for i in I020[1:]:    price = int(i[4])    qty = int(i[5])    if price > lastPrice:     outDesk+=qty    if price < lastPrice:     inDesk+=qty    print ("Time:",i[0]," Price:",price," OutDesk:",outDesk," InDesk:",inDesK)   lastPrice = price 

 

若要将指标存成新文件,可以将上面示例程序中的print函数改为write函数。通过CMD执行Python指令,输出如下:

 
>python 42-1.py   Time: 8450011 Price: 10309 High: 10310 Low: 10309   Time: 8450011 Price: 10309 High: 10310 Low: 10309   Time: 8450011 Price: 10310 High: 10310 Low: 10309   Time: 8450011 Price: 10310 High: 10310 Low: 10309   Time: 8450011 Price: 10309 High: 10310 Low: 10309   Time: 8450011 Price: 10309 High: 10310 Low: 10309   ...  Time: 8450043 Price: 10312 High: 10312 Low: 10309   Time: 8450043 Price: 10312 High: 10312 Low: 10309   Time: 8450056 Price: 10310 High: 10312 Low: 10309   Time: 8450056 Price: 10313 High: 10313 Low: 10308   Time: 8450056 Price: 10313 High: 10313 Low: 10308   Time: 8450056 Price: 10310 High: 10313 Low: 10308   Time: 8450056 Price: 10313 High: 10313 Low: 10308   Time: 8450056 Price: 10313 High: 10313 Low: 10308 

 

(3)内外盘量

内外盘是大家常用的指标之一,一般的计算方式为下一笔成交价落在上一档价(卖方价格)还是下一档价(买方价格),若价格落在上一档价时,则为“外盘价”;落在下一档价时,则为“内盘价”。

 

内外盘还有另外一种算法,就是当成交价大于上一笔成交价时,则为“外盘量”;反之,则为“内盘量”。

 

计算内外盘量的总和可以用来判断目前的多空方趋势:若外盘量较多,则多方趋势较空方趋势重,价格往上的概率较高;反之,若内盘量较多,则空方趋势较多方趋势重,价格往下的概率较高。

 

动态计算当天的内外盘量,预测当天的多空趋势,代码如下:

 
# -*- coding: UTF-8 -*-   # 取I020,依照逗号分隔,并将分隔符号去除  I020 = [ line.strip('\n').split(",") for line in open('Futures_20170815_I020.csv')][1:]   # 定义变量初始值  lastPrice=int(I020[0][4])   outDesk=0  inDesk=0   # 开始计算内外盘  for i in I020[1:]:    price = int(i[4])    qty = int(i[5])    if price > lastPrice:     outDesk+=qty    if price < lastPrice:     inDesk+=qty    print ("Time:",i[0]," Price:",price," OutDesk:",outDesk," InDesk:",inDesK)   lastPrice = price 

 

若要将指标存成新文件,可以将上面示例程序中的print函数改为write函数。

 

本示例是通过单纯的成交价比对计算的,若要通过上下五档价来做内外盘判断计算,则需要搭配I080数据计算。

通过CMD执行Python指令,输出如下:

 
# -*- coding: UTF-8 -*-   # 取I020,依照逗号分隔,并将分隔符号去除  I020 = [ line.strip('\n').split(",") for line in open('Futures_20170815_I020. csv')][1:]  # 起始时间至结束时间  I020a= [ line for line in I020 if int(line[0])>9000000 and int(line[0])<11000000]  # 初始仓位  index=0  for i in I020a:    if index==0:     if 进场条件:       OrderTime=i[0]  #下单时间记录      OrderPrice=i[4] #下单价格记录   elif index!=0:    if 出场条件:     OrderTime=i[0]  #下单时间记录     OrderPrice=i[4] #下单价格记录 

 

(4)委托手数差值

委托手数差值是通过委托信息来计算的,会将委托的买方手数以及委托的卖方手数相减。若值为负数,则代表目前委托买方手数较少,代表目前市场委托趋势较偏向空方;反之,若值为正数,则代表卖方手数较少,代表目前市场委托趋势较偏向多方。

 

(5)委托比重

委托比重指标是从委托信息计算而来的,会将委托的买卖方分别用手数除以笔数来计 算买卖方的平均单笔手数,进而通过比重的方式计算该指标。假设委托的买方为 100 手、50 笔,卖方为 80 手、20 笔,则委托的买方平均手数为 2 手,卖方平均手数为 4 手,进而 计算出多方委托比重为 33.33%,空方委托比重为 66.67%。

 

这个指标与委托手数差值指标最大的不同在于委托比重不会受到手数绝对的影响,就 算买方的手数相当多,但笔数也相对多,还是有可能被空方趋势胜过。

 

(6)成交买卖单笔数

成交买卖单笔数是由成交信息获取的,通常交易者会根据成交买卖笔数来做趋势的判断,因为对于累积成交量,买卖方是相等的,所以当成交买笔数小于成交卖笔数时,代表 成交买方平均手数大于卖方平均手数,这时就可以判断买方趋势大于卖方趋势。

 

3.历史算法设计

由于回测算法获取的是历史数据,因此在编写回测算法时可以依照需求去撷取需要的 部分信息。假设交易算法只操作当日开盘的第二个小时,那么通过子集合的函数去获取那 一段期间的数据即可,不必再从文件的开始读取到结尾。

 

回测算法也是交易算法,所以依照流程会有趋势判断、进场、出场和止损等相关步骤。 下面会通过简单的程序流程来帮助大家了解如何操作。

 
# -*- coding: UTF-8 -*-   # 取I020,依照逗号分隔,并将分隔符号去除  I020 = [ line.strip('\n').split(",") for line in open('Futures_20170815_I020. csv')][1:]  # 起始时间至结束时间  I020a= [ line for line in I020 if int(line[0])>9000000 and int(line[0])<11000000]  # 初始仓位  index=0  for i in I020a:    if index==0:     if 进场条件:       OrderTime=i[0]  #下单时间记录      OrderPrice=i[4] #下单价格记录   elif index!=0:    if 出场条件:     OrderTime=i[0]  #下单时间记录     OrderPrice=i[4] #下单价格记录 

 

该策略仅展示用途,并没有实际用意,要编写回测算法,可以通过上述概念来进行, 但实际上还是有许多细节需要注意。

 

4.历史回测回传明细格式设计

回测交易格式的设计,是希望完整地保存回测交易记录,并且真实地表达交易事件的 细节,最后让这些记录能够被适度地分析,让回测的效益最佳化。 以下是交易事件回传格式:

 
交易序列号、交易商品、开仓日期、开仓时间、开仓价格、买卖、 数量、平仓日期、平仓时间、平仓价格、注记、税金、 手续费、策略编号、交易者编号  SerialNumber,Good,ODate,OTime,OPrice,BorS,Number,CDate,CTime,CPrice,Comment,Tax,Fee, PID,ID 

 

读者看到这里,或许会好奇,为什么没有盈亏字段呢?首先,通过原有的数据字段就 可以计算出盈亏,为了避免表格字段过于冗长,所以不另外设置字段。另外,若要观察回 测的效益,盈亏也并非绝对标准。怎么说呢?就好比一个回测程序虽然说一个月的总盈亏 是−1000,但它并不代表就是一个不好的策略,或许买方的头寸净利是 3000,卖方的头寸 净利是−4000,只要将这个策略设置为只做买方,就会是一个赚钱的策略。除了盈亏,也有 很多角度可以分析策略的好坏,例如:交易时间、持仓时间等。除盈亏以外的分析对于交 易而言也是相当重要的,后面会有介绍。

 

每个字段都具有存在的价值,而第一个字段交易序列号代表唯一值,所以每笔数据并 不会发生重复的现象。上述交易回传格式不一定符合每种交易类型的需求,可以依照自己 的需求做更改。 以下是开盘买、收盘卖的策略,做一个基础的交易回传明细:

 
# -*- coding: UTF-8 -*-    # 取I020,依照逗号分隔,并将分隔符号去除  I020 = [ line.strip('\n').split(",") for line in open('Futures_20170815_I020. csv')][1:]   OrderTime=I020[0][0] #下单时间记录  OrderPrice=int(I020[0][4])  #下单价格记录  CoverTime=I020[-1][0]       #平仓时间记录  CoverPrice=int(I020[-1][4]) #平仓时间记录  print ("Buy OrderTime:",OrderTime," OrderPrice:",OrderPrice,)   print (" CoverTime:",CoverTime," CoverPrice:",CoverPrice," Profit:",CoverPrice- OrderPrice) 

 

执行回测后,输出如下:

 
>python 42-4.py   Buy OrderTime: 8450010 OrderPrice: 10310 CoverTime: 13450006 CoverPrice: 10309 Profit: -1 

 

5.绩效计算

读取交易记录后,就可以依照交易回传的数据去加以计算分析。绩效不仅可以从盈亏 去观察,也可以从买卖、交易次数、交易时间点来进行分析。本节提供的绩效分析示例虽 不多,但主要是让读者熟悉系统分析命令的用法。

 

某些策略会符合某些时期的趋势条件,但不代表那些策略会符合长期市场的走势,毕竟交 易市场是瞬息万变的,若要调试出一个长期稳定获利的策略,必须要经过长期回测的测试。

 

绩效计算不一定是从获利盈余的数字上来看,以下提供其他参考绩效的方向让读者参考:

(1)交易次数胜率;

(2)买卖个别成交结果。

 

股市有风险,投资需谨慎,并不是学了这个技巧后,你就能成为股神巴菲特,在相应的资讯,信息,海量数据之下,用python程序量化交易可以降低风险,稳定获益。想了解更多关于程序量化交易的技巧,这本《Python期货量化交易实战》一定别错过哦!

 

本书内容由最基本的期货交易规则开始,逐步切入程序编写,通过计算技术指标,能进行历史回测,最后透过下单函数进行程序交易。通过对案例的逐步演练,可降低学习的门坎,带领读者进入程序交易的殿堂。

全书通过121个技巧,以10章内容的形式呈现给读者精简的操作方法和思路,帮助读者快速入门,并能够在实际的案例式学习中,更好地掌握核心思想。

 

-END-

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值