什么样的股票交易策略适合用vwap策略

基于动态交易量预测的VWAP算法交易卖出策略--《运筹与管理》2015年02期
基于动态交易量预测的VWAP算法交易卖出策略
【摘要】:传统的VWAP交易策略通过预测区间交易量分布进行拆单交易,对于交易量区间分布的预测是基于区间成交量占总成交量比例进行的,这一预测方法没有考虑股票价格变动因素。因此,本文首先通过时间序列因素分解方法进行区间交易量分布预测,进而根据股票价格变化对区间交易量分布进行动态调整,并构建了基于动态区间交易量分布的股票卖出策略,最后通过实证检验了本文给出的动态区间交易量分布预测的有效性和交易策略的有效性。数值结果表明,本文所给动态区间交易量分布预测方法比传统VWAP方法预测结果更加接近于实际的交易量分布,且本文所给交易策略与传统VWAP交易策略相比,具有更大的收益。
【作者单位】:
【关键词】:
【基金】:
【分类号】:F830.91;F224【正文快照】:
0引言算法交易(Algorithmic Trading)是指通过计算机程序来生成交易中的交易时间、交易价格以及交易数量的一种量化交易方式。算法交易中有TWAP、TVOL、VWAP等算法交易策略,其中交易量加权平均价格策略(VWAP交易策略)以其简单易操作的特性而被普遍应用。在证券市场上,大约近50
欢迎:、、)
支持CAJ、PDF文件格式,仅支持PDF格式
【参考文献】
中国期刊全文数据库
王长江;;[J];中北大学学报(自然科学版);2006年06期
林辉;张涤新;杨浩;丁一;;[J];管理科学学报;2011年05期
中国博士学位论文全文数据库
镇磊;[D];中国科学技术大学;2010年
【共引文献】
中国期刊全文数据库
凌同华;李品钰;李金跃;张胜;;[J];交通科学与工程;2012年02期
杨英俊;吴金中;周元峰;王轶萍;;[J];公路交通科技(应用技术版);2010年06期
燕汝贞;李平;曾勇;;[J];管理学报;2012年07期
何舒华;何霭琳;;[J];广州大学学报(自然科学版);2011年02期
陈方龙;吉培荣;王鹏;;[J];电源技术应用;2013年09期
郭园园;潘文霞;冯博;;[J];电力系统及其自动化学报;2013年05期
王洪德;曹英浩;;[J];辽宁工程技术大学学报(自然科学版);2014年01期
曾丽;;[J];国土与自然资源研究;2015年01期
刘造保;徐卫亚;张开普;刘康;;[J];河海大学学报(自然科学版);2009年03期
齐雪雯;谢开贵;胡博;;[J];电力系统保护与控制;2012年12期
中国博士学位论文全文数据库
李成刚;[D];电子科技大学;2012年
孙亮;[D];沈阳农业大学;2013年
郝建根;[D];北京交通大学;2014年
中国硕士学位论文全文数据库
杨双喜;[D];甘肃农业大学;2010年
陈露露;[D];北京交通大学;2011年
韩玉凤;[D];电子科技大学;2011年
李传涛;[D];郑州大学;2011年
张志强;[D];华北电力大学;2011年
闫冬;[D];燕山大学;2011年
陈晓钰;[D];西北农林科技大学;2011年
宁洁;[D];北京化工大学;2011年
王在涛;[D];吉林大学;2008年
许晨阳;[D];厦门大学;2009年
【二级参考文献】
中国期刊全文数据库
张玉川;张作泉;;[J];北京交通大学学报;2007年06期
常宁,徐国祥;[J];财经研究;2004年03期
马树才;赵丰义;;[J];当代经济管理;2007年03期
刘海龙,吴冲锋,仲黎明;[J];管理工程学报;2003年02期
黄峰;杨朝军;;[J];管理世界;2007年05期
朱赟,王行愚;[J];华东理工大学学报;2002年05期
郭国雄,陈玲,栾长福,陆子强;[J];华南理工大学学报(自然科学版);2003年03期
仲黎明,刘海龙,吴冲锋;[J];管理科学学报;2002年05期
郭福华;邓飞其;;[J];管理科学学报;2009年02期
邹小芃;黄峰;杨朝军;;[J];管理科学学报;2009年06期
中国硕士学位论文全文数据库
张国勇;[D];天津大学;2004年
【相似文献】
中国期刊全文数据库
马云风;曹国华;;[J];企业经济;2013年02期
;[J];;年期
;[J];;年期
;[J];;年期
;[J];;年期
;[J];;年期
;[J];;年期
;[J];;年期
;[J];;年期
;[J];;年期
中国硕士学位论文全文数据库
魏文婷;[D];天津大学;2009年
&快捷付款方式
&订购知网充值卡
400-819-9993
《中国学术期刊(光盘版)》电子杂志社有限公司
同方知网数字出版技术股份有限公司
地址:北京清华大学 84-48信箱 大众知识服务
出版物经营许可证 新出发京批字第直0595号
订购热线:400-819-82499
服务热线:010--
在线咨询:
传真:010-
京公网安备75号君,已阅读到文档的结尾了呢~~
中国证券市场动态vwap策略研究(经济学),vwap策略,vwap和twap 算法,vwap算法,twap vwap,vwap 算法 twap,twap和vwap,vwap指标,vwap 交易,中信证券首席经济学家
扫扫二维码,随身浏览文档
手机或平板扫扫即可继续访问
中国证券市场动态vwap策略研究(经济学)
举报该文档为侵权文档。
举报该文档含有违规或不良信息。
反馈该文档无法正常浏览。
举报该文档为重复文档。
推荐理由:
将文档分享至:
分享完整地址
文档地址:
粘贴到BBS或博客
flash地址:
支持嵌入FLASH地址的网站使用
html代码:
&embed src='/DocinViewer--144.swf' width='100%' height='600' type=application/x-shockwave-flash ALLOWFULLSCREEN='true' ALLOWSCRIPTACCESS='always'&&/embed&
450px*300px480px*400px650px*490px
支持嵌入HTML代码的网站使用
您的内容已经提交成功
您所提交的内容需要审核后才能发布,请您等待!
3秒自动关闭窗口股票配对的趋势跟踪策略之“银行轮动策略”_参考网
股票配对的趋势跟踪策略之“银行轮动策略”
常锐一、策略思想简介(1)配对交易介绍。配对交易(PairsTrading)的理念最早来源于上世纪20年代华尔街传奇交易员JesseLivermore的姐妹股票对(sisterstocks)交易策略。他首先在同一行业内选取业务相似,股价具备一定均衡关系的上市公司股票,然后做空近期的相对强势股,同时做多相对弱势股,等两者股价又回复均衡时,平掉所有仓位,了结交易。该策略与传统股票交易最大的不同之处在于,它的投资标的是两只股票的价差,是一种相对价值而非绝对价值。同时又由于它在股票多头和空头方同时建仓,对冲掉了绝大部分市场风险,因而它又是一种市场中性(MarketNeutral)策略,策略收益和大盘走势的相关性很低。1985年,MorganStanley公司成立了一支由Dr.Tartaglia领导的量化团队,专门开展配对交易的研究,并于1987年投入实战,当年实现盈利5000万美元。不过该策略在之后两年连续亏损,研究团队被迫解散,小组成员散落到各家对冲基金,策略的思想也随之广为市场知晓。经过多年学术机构的研究和市场机构的实战,配对交易的理论框架和配套交易系统都日臻完善。(2)趋势交易介绍。价格以一定的趋势演进,而这一趋势将一直延续下去,直到发生新的事情而改变了供求平衡,并且这一改变通常由市场行为本身发展而来。(3)股票配对的趋势跟踪策略。通过配对交易思路选出多只相似走势的股票,通过趋势交易思路判断整体是否形成上涨趋势,选择组合中预期高收益的品种进行交易。二、策略模型的构建方法(1)策略总体概述。本策略简单概述为在四大银行股中选取目前走势最差的一只进行买入并期望其在未来上涨到与其他股票走势相同时平仓获取收益。具体原理为:在同质化比较严重,估值又接近的版块,可以在不同股票之间来回切换。选取四只市值相近,股市表现较为接近的银行股,当这四只最小的收益率与最大的收益率之差大于开仓阈值时,收益率最小的股票表现异常,处于被低估状态,将会反弹,我们买入获取差价利润。(2)目标交易标的选择。配对交易就是寻找同一行业中股价具备均衡关系的两家/几家上市公司,做空近期相对强势的股票,同时做多相对弱势的股票,以期两者股价返回均衡值时,平仓赚取两只股票价差变动的收益。进行配对交易最关键的一步就是选择符合配对交易条件的股票。股票对的选择可分为基本面分析和技术面分析。基本面分析。从股价走势分析,四大行作为国内股本最大的股票之一,其走势具有稳定且相似的特征,又因为按照传统配对交易的方式,只選择两只股票进行买卖很容易收到单只股票波动的影响,因此我们选择四大行作为我们的股票标的,期待通过股票配对的趋势跟踪策略获得阿尔法收益。从收益率曲线图中也可以观察到,其走势非常相近。技术面分析。本文运用协整法对四大行的估价走势进行分析,得到他们的相关性。Vidvamurthy(2004)通过利用资产之间的协整关系,尝试对配对交易使用参数化交易规则。Vidvamurthv采用Engle and Granger(1987)的协整两步法,根据计算,得到四大行的协整性非常好,因此可对这四只股票进行配对交易。(3)持仓量的选择。本策略的原理简单地说为选择目前走势相对较差的股票做多,而根据配对交易的原理,我们在做多的同时,应该对目前走势最好的股票做空,但是由于目前我国A股市场的做空机制尚不完善,因此我们仅仅对目前走势最差的做多,又因为只是对一只股票进行多空交易,且我们的策略模式是投组权重,因此我们对做多的股票设置Portfolio=1;平仓时直接对股票设置portfolio=0。此处不选择逐渐加仓的原因是因为会严重影响收益率,而且四大行股票极其稳定,很少出现巨大波动,因此我们可以选择全仓买入。(4)风险控制手段。本策略在具体编写中尝试过很多种止损方法,但最终效果都不尽人意,不仅不能减小最大回撤,而且还会对收益率水平造成巨大影响。具体原因据估计可能有以下两个:①银行股具有强大业绩支撑,因此大多数情况下是会回归其投资价值,即股票配对的原理;②当出现意外情况时,如几次金融危机时,由于往往止损完会继续买入走势较差的另一只股票,但此时大盘已经处于下行趋势,哪怕走势最差的股票还是会继续下跌,使得止损的效果甚微。(5)阈值的选择。在配对交易中,最优阈值的选择是一个非常重要的一步。在本策略中,阈值的选取方法为回归和简单的机器学习。通过计算过去1000天的yz=max(ratio)-min(ratio),并且选择75%分位点,此处的原理是当其处于75%分位点时,其既容易开仓(有25%的比例开仓),也容易实现股价回顾(有75%的可能性走势回归),这样算出来的yz为0.005。同时通过简单的机器学习,我们通过在0.005附近以0.0005为步长进行测试,以过去三年的总收益率为衡量标准,得到0.005就是最佳阈值。(6)策略代码说明。在同质化比较严重,估值又接近的版块,可以在不同股票之间来回切换。选取四只市值相近,股市表现较为接近的银行股,当这四只最小的收益率与最大的收益率之差大于开仓阈值时,收益率最小的股票表现异常,处于被低估状态,将会反弹,我们买入获取差价利润。function [ portfolio, newStateMatrix ] = BankShare2( decisionData, stateMatrix )CPday=decisionData.CP_DAY01.data; %提取日频收盘价。open=0.005; %设置开仓阈值ratio=[0;0;0;0]; %初始化收益率%初次交易时if isempty(stateMatrix)portfolio=[0;0;0;0];
index=0;%非初次,提取上次交易数据elseportfolio=stateMatrix.portfolio;index=stateMatrix.index;End%计算收益率for j=1:4ratio(j)=CPday(j,2)/CPday(j,1);End%设置交易信号,当收益率比率最大值与最小值之差大于开仓阈值,买入收益率最小的标的。if index==0if max(ratio)-min(ratio)&open[~,mi]=min(ratio);portfolio(mi,:)=1;index=1;End%平仓判断:如果目前持仓的股票的收益率比率与最小值大于阈值,对持仓股票进行平仓,并且买入目前收益率比率最小的股票。else[~,mx]=max(portfolio);if ratio(mx)-min(ratio)&openportfolio=[0;0;0;0];[~,mi]=min(ratio);portfolio(mi,:)=1;endend%保存数据newStateMatrix.portfolio=portfolio;newStateMatrix.index=index;end三、策略的实证结果(一)预期收益和风险对银行轮动策略过去三年(~)进行回测,获取回测报告。(1)收益率。从回测报告中的整体收益曲线看,该策略与基准收益走势趋同,但收益更加稳定,在市场平稳向好的情况下能够获得超越大盘的收益,且在2015年年中的“股灾”中,该策略收益不随大盘大幅暴跌,体现其较强的风险抵御能力。最终三年的累计收益为121.84%,年化收益率31.56%,年化超额收益率13.45%,说明该策略收益能力较强,能够取得超越市场平均水平的收益。(2)盈亏比。总交易次数320次,盈利交易次数205,占交易总数的64.06%,具有较大胜率,体现策略的有效性。(3)预期风险。最大回撤为27.11%,时间为16/02,这时间段市场遭遇股灾,股价大跌,说明该策略收益受大盘形势影响,而相较于大盘来说,该策略抗跌能力较强,收益不会大幅剧烈波动。(二)其他回测指标(1)夏普比率(Sharpe Ratio)。夏普比率是衡量基金风险调整后收益的指标之一,反映了承担单位风险所获得的超额回报率(Excess Returns),即总回报率高于同期无风险利率的部分。一般情况下,该比率越高,TREX 表示基金在计算期内月度超额回报率(月度总回报率减去同期的无风险利率)的平均值,该策略夏普比率为1.24%,说明对于每单位风险波动,该策略拥有较好的超额收益回报。(2)索提诺比率(Sortino Ratio)。索提诺比率与夏普比率类似,所不同的是它区分了波动的好坏,因此在计算波动率时它所采用的不是标准差,而是下行标准差。这其中的隐含条件是投资组合的上涨(正回报率)符合投资人的需求,不应计入风险调整。索提诺比率为1.91,说明策略承担单位下行风险能获得1.91%的超额回报率,风险回报较好。(3)信息比率。描述股票或组合相对于某一标的残差收益的收益风险比。通常来讲,股票或组合的信息比率越高,表明股票或组合在承担单位残差风险的情况下获取的残差收益越高,表现越好。信息比率为0.38,说明该策略的残差收益较差。四、总结(一)策略优缺点(1)策略优点。①收益率水平较为稳定,最大回撤相对于股灾的下跌程度来说较小,这对于目前的基金来说是比较大的优势,因为目前基金的最大目标是保本而不是获得极高的收益;②夏普比率大于1,因此本策略的单位风险所得到的超额收益较高,对风险的抵抗程度较高;③对计算机性能要求较低,因为是日频的策略,所以相比于其他高频交易策略,本策略不需要计算机有强大的计算能力;④股票标的较少,因此可辅以基本面分析,当出现巨大的基本面转折时可以手动更改策略或者停止交易,有益于止损;⑤交易次数较小,因此产生的交易费用较小,即使交易费用比率上升对最终的收益率影响也不大。(2)策略缺点。①因为选取的是同一行业的四大行股票,因此容易受到行业周期影响而影响整体收益率水平;②在策略中因为对收益率有影响而没有设止损,可能会带来系统性风险;③本策略没有考虑滑点的影响,如果考虑较大的滑点可能会对最终收益率有很大的影响;④因为交易标的单一,当资金量较大时可能会产生巨大的冲击成本,对收益率有很大影响。(二)缺点解决方案(1)策略叠加。针对第一个缺点,根据诺贝尔经济学奖获得者詹姆斯·托宾的名言“不要把你所有的雞蛋都放在一个篮子里,但也不要放在太多的篮子里”,我们可以通过策略的叠加对不同的策略可能风险和回撤进行中和,以期得到一条平滑的收益率曲线。例如我们可以将本策略与其他的策略如多因子选股策略、EMA策略进行叠加,已得到一个更加平滑的收益率曲线。(2)手动止损。因为本策略的决策是日频的,因此我们可以在大盘走势下行的时候通过手动止损,停止交易来有效地止损,原因是因为在整体下行的时候,用策略止损后还是会出现继续开仓的现象,当然这个也可以用代码编出来防止再次开仓,但因为较为复杂,本文不做讨论。(3)滑点影响小。因为四大行的股票交易量巨大,因此每一分钱上可能都有几百万上千万的订单,所以当资金量较大的时候,滑点的影响是可以忽略不计的。同时,根据实证,当设滑点为1分钱时,因为交易次数较少,因此对最终收益率的影响也不算特别大。(4)运用 Vwap和 Twap方法。 交易量加权平均价格Volume Weighted Average Price(VWAP)以及交易时间加权平均价格Time Weighted Average Price (TWAP)是当今量化交易系统中最常用的一类执行模型。此类算法模型的核心是VWAP算法,而TWAP则是作为VWAP的简化版出现的。VWAP算法不需要市场冲击模型,属于第一代算法交易。
2017年26期
商情的其它文章打开股票量化的黑箱(自己动手写一个印钞机) 附录章 - 简书
打开股票量化的黑箱(自己动手写一个印钞机) 附录章
作者:阿布?未经本人允许禁止转载
其它章节地址:
非均衡胜负收益带来的必然非均衡胜负比例,目标由因子的能力解决一部分,模式识别提升关键的一部分
**这个就是这篇文章核心的思想,原创,这一章开不会涉及,本章只是量化知识漫游,希望以后有机会可以展开具体某项
1. 数据系统
爬取或者购买数据,数据的实时度及精确性影响着你的系统实现, 一般不会只听信一个数据源,会有策略进行数据的准确性的校验量化的起点就是数据,没有数据一切扯淡,数据即是起点也会是最终的终点,数据的各种分析组合构成了量化的基础。对于股票数据,它是由股票代码,股票价格,股票成交量,加上时间组成了一个庞大的四维空间,在这个空间中人们根据时间周期,行业类别,市值大小等等历史经验,客观事实又取舍空间中各个部分,提取压缩自己关心的数据,传统股票交易中,由于时间这个维度的客观存在及周期连续特性,时间这个维度很有可能被
一般交易者当作朋友,具体表现就是跌了不卖出股票,等待一段时间后,涨上去再卖出,但是它一定会涨上去吗,也许你的回答就是那就继续拿着吧,
但如果你要是做过美股期权交易,或者期货你就会发现多一个时间这个维度有多么的可怕,对整个交易系统带来多么大的改变,想想科幻小说三体中最后被二维化的地球吧,还有哪些进入4维碎片中的人类怎么形容4维的世界,在整个股票交易中所有的维度都不应该是朋友,但也不应该是敌人,量化的目标就是在这些复杂的维度中根据一定的方法降低复杂度需找特征,总结规律,指导交易
我再次强调,所有内容都为原创,我语言写作能力很一般,如果有说的不恰当的地方请您提出,我将感激不禁!
一般会按照你的交易系统来组织数据,这里只是简单举例
# 获取5年美股, 诺亚财富的数据
kl_pd = SymbolPd.make_kfold_pd('usNOAH', n_folds=5)
kl_pd.head()
如下表格看到分时数据的volume全是0吗,说明这个数据有问题,在你的系统中会有大量代码处理这种异常的,fill,merge数据文章的核心不是这些东西,简单掠过
# 获取分时数据
kl_pd_minute = SymbolPd.make_kminute_foldpd('usNOAH', n_folds=5, period=1)
kl_pd_minute.tail()
所有数据在你的系统中不应该都是实时获取的,最少回归测试没有必要,一般会有全局缓存设置及各种缓存策略, 比如基本面数据对应一个股票一天只获取一次等等策略
# 基本面信息
SymbolPd.make_pd_info('usNOAH')
Avg_Daily_Volume
EPS_Current_Year
EPS_Next_Year
EPS_Next_Quarter
Dividend_Yield
Earnings_Share
Dividend_Share
Dividend_Pay_Date
52_weekLow
52_weekHigh
PERatio_Real
Price_EPS_Current_Year
Price_EPS_Next_Year
1yr_Target_Price
Name: NOAH, dtype: object
可视化数据
数据是一切的基础,准确是首要要求,数据的封装目的是满足上层的需求,在有需求的前提下进行封装,数据的可视化的目的是能快速的进行分析,不因该浪费过多的时间在可视化层面
import MarketDrawer
MarketDrawer.plot_candle_form_klpd(kl_pd[-252:])
绘图在有交互需求的情况下一般会使用bokeh等高级库完成,不要在可视化上造轮子
MarketDrawer.plot_candle_form_klpd(kl_pd, html_bk=True)
一般的实现需要支持从order中绘制,order是你的交易系统中对一次交易的定义,并可加入更多的标记,直观感受策略因子的问题及效果,保存在本地k线图进行深度学习后文会涉及
filter(lambda x: x.startswith('plot'), dir(MarketDrawer))
['plot_candle_form_klpd',
'plot_candle_from_order',
'plot_candle_from_symbol',
'plot_candle_stick',
'plot_html_symbol',
'plot_minute_candle_from_klpd',
'plot_minute_candle_from_symbol',
'plot_simple_mul_stock',
'plot_symbol']
人为的一些分类方式示例(选读与文章主题无关):相同行业类别的股票
import IndustriesHelper
r_symbol = 'usSFUN'
# 这里获取了搜房相关中概股票组成pandas三维面板数据(这里无法对pandas等知识做基础说明,请阅读相关书籍)
pDate, pdata_it = IndustriesHelper.get_industries_panel_from_target(r_symbol, show=True)
output_20_0.png
按照需要,对数据进行的各种维度转换,规整是量化工作中最普遍的任务
change_m = pdata_it['netChangeRatio'].dropna(axis=1, how='all')
change_m = change_m.resample('M').mean().T
change_m.head(2)
更多关于数据请参考:
2.相关性与指标
皮尔逊相关性
斯皮尔曼秩相关性
皮尔逊sign相关性
时间线性加权相关性
atr, obv, macd, rsi,布林带
相关在股票量化中是非常常用的工具,比如底层的beta中会使用它进行仓位控制,简单说你不能买太多走势那么相似的股票,风险太大(beta等概念下文会有)atr, obv, macd, rsi最基本的一些技术指标
如下绘制noah一年走势最相似的10个股票,以多进程的方式运行(由于量化分析中大多数都是cpu密集型运算,结合使用python这个环境一般会使用多进程方式,rolling=True 时间加权即时间约靠近的权重越大,E_CORE_TYPE_PEARS使用皮尔逊相关性)
from SimilarHelper import find_similar_with_cnt, CoreCorrType, pd_list
net_cg_ret = find_similar_with_cnt('usNOAH', 252, show_cnt=10, how='process', rolling=True,
show=True, corr_type=CoreCorrType.E_CORE_TYPE_PEARS.value)
output_26_2.png
在相关性基础上量化应用举例
import TLineSimilar
TLineSimilar.calc_similar_top('usNOAH', sc=slice(1, 2), show_cnt=3)
dtype: float64
如上按照等权重的方式计算相关性排名, 显示对比中会按照look_max方式对齐数据
sc=slice 采用那几种相关性度量方式
slice(1, 2):sperman + pers sign
slice(0, 1):pers +
sperman最后返回的结果是rank的结果,从2开始,1是symbol自身
简单的说就是综合几种相似度对比的方式,按照等权重方式在进行排序,得到一个综合相似度排名
TLineSimilar.calc_similar('usNOAH', 'usSFUN')
usNOAH similar rank scoreusSFUN :0.692
output_32_1.png
output_32_2.png
计算'usNOAH', 'usSFUN'与在所有股票中的相似度水平,会涉及所有股票进行相似度计算,使用它们两个的rank排名的小数表现形式作为结果,这就是量化的最一般应用以数字的最终表现形式将维度及关系进行转换量化
在此基础上完成一个量化应用
相关与协整技术分析相关不一定协整协整不一定相关技术分析思路:从最相关的top n中寻找m个最协整的股票,现在的策略是从top 100多个相关等权重中阀值0.08计算寻找最协整的10个股票,10个股票标准化后做diff之后axis=1 轴上做sum,类似等权重投票机制成如
distance_votes
-14.724491
-12.712066
-11.945266
-13.801350
-13.520431
-11.381343
-11.319338
......................
之后计算vote diff的above std, below std,mean, 可以根据above std, below std等作为交易信号,形成策略因子的基础组成部份
简单说就是从noah综合相关性最高的top100中寻找协整度最高的10个股票,然后运用投票机制,将它们合为一体,计算方差与期望,下图最后显示的那个有三条横行的图就是最终目的,你可以简单理解成费了半天劲就是为了得到这三条线,当股价触及最上方的线就卖,股价触及最下方的线就卖出,在中间区域就是盘整区域
更多关于TLineSimilar请自行阅读源代码,这里只为阐明量化最一般性工作流程
output_35_0.png
output_35_2.png
有点看不明白在说啥了吗?没关系,可以先向下看只要注意最后这个有三条线分割开的图,这就是最一般的量化分析寻找买入卖出点的结论图, 通过数据的技术分析,统计分析,基本面分析目的很多情况下就是找出这几个点作为信号,在你的交易系统上实现对信号的处理,交易系统可能是回测系统,也有可能是实盘系统,但他们都需要信号
更多相关与指标请参考:
3. 基础交易
在有数据和信号的前提下就可以开始做最简单的交易回测回测交易的基本组成:
alpha在因子层下面,负责整个交易大框架的盈利,负责相对激进部分,一般包括最高止盈,最高止损,最大跌幅止损,最大回撤止损等等
因子作为组件插入alpha系统, 因子可以是简单因子只发现信号,也可以有自己的止盈止损等等规则
beta系统作为风险控制层在alpha底层,更高权限的对交易进行风险控制,一般比较谨慎的做出干预,大盘风险,组合的合理相关性等等
因子是量化中很重要的概念,它的好坏可以说是整个系统能否真正盈利的关键,alpha好比有宏图大志的ceo它的目标要挣钱要挣好多好多钱,但是它可能只在上层社会中寻找睁钱的大方向,不会涉及细节,beta好比保守的cfo它的首要任务是不能让公司垮掉,要控制最大的系统风险,factor就是具体的一个个的销售了,它们的销售业绩直接就是整个公司的盈利或者亏损,自己有对产品的完整控制权,但alpha或者beta时不时的要管它们,对它们指手画脚,但是他们必须听从他两个,一般来说cfo的权限会大于ceo但也有设计成cfo,ceo等权限的,factor的产品包装就是类似上面TLineSimilar的封装,如果感觉有点糊涂,先暂时跳过,现在不需要全部理解如下举例(选读):
# 设置aplha的参数
parameters = {
'stop_win_base_n'
'stop_loss_base_n'
'mv_close_atr': 3.0,
'mv_pre_atr'
# 构建因子
# BuyBkFactorClass是向上突破xd天最高股价作为买入信号的因子
# SellBkFactorClass是向下突破xd天最低股价作为卖出信号的因子
buy_factors = [{'XD': 60, 'class': BuyBkFactorClass, 'draw': True},
{'XD': 42, 'class': BuyBkFactorClass, 'draw': True}]
sell_factors = [{'XD': 60, 'class': SellBkFactorClass, 'draw': True},
{'XD': 120, 'class': SellBkFactorClass, 'draw': True}]
target_symbols = ['usNOAH', 'usGOOG']
cap = CapitalClass(1000000)
# 多个股票加载同样的n个因子运行回测
results, orders_pd, action_pd, all_fit_symbols = AlphaBSellMvEstimator.do_symbols_with_same_factors(target_symbols, buy_factors, sell_factors, parameters, cap,
scoring=Metrics.K_RMULT, show=True)
output_42_3.png
output_42_4.png
output_42_6.png
output_42_2.png
直观感觉上面那些交易图,通过分析生效因子生效原因,调整你的因子及底层模型,但要注意不要过拟合,每个微调都不应该只针对这次交易或者这个股票,归纳总结写出自己的有效因子,alpha是这阶段的目标
# 返回的交易数据
orders_pd.head()
# 返回的action数据
action_pd.head()
# 返回的资金情况数据
cap.capital_pd.tail()
针对alpha的参数做grid search(选读与印钞机关键无关)针对alpha会有很多参数需要,设置一般的做法是会首先针对alpha的参数做grid search,针对特定因子组合寻找最优参数,如下所示,量化中不管是使用凸优化还是模特卡洛分析还是grid search都会涉及到寻找最优参数,最优的定义一定要保证不能过拟合你的整个系统,也就是要做根据具体应用train test split, 并且需要有一套合理的scoring metrics 作为检验的标准
import GridHelper
from GridSearch import GridSearchCV
close_atr = np.arange(2.0, 4.0, 0.5)
pre_atr = np.arange(1.5, 3.0, 0.5)
win = np.arange(2.0, 4.0, 0.5)
loss = np.arange(0.5, 1.5, 0.5)
parameters = {
'stop_win_base_n'
'stop_loss_base_n'
'mv_close_atr': close_atr,
'mv_pre_atr'
: pre_atr,
bk_days = [21, 42]
sell_bk_factor_grid = {
'class': [SellBkFactorClass],
: bk_days,
bk_days2 = [60]
sell_bk_factor_grid2 = {
'class': [SellBkFactorClass],
: bk_days2,
sell_factor_prams = GridHelper.gen_factor_grid(GridHelper.K_GEN_FACTOR_PARM_SELL, *[sell_bk_factor_grid, sell_bk_factor_grid2])
buy_bk_factor_grid = {
'class': [BuyBkFactorClass],
buy_bk_factor_grid2 = {
'class': [BuyBkFactorClass],
buy_factor_prams = GridHelper.gen_factor_grid(GridHelper.K_GEN_FACTOR_PARM_BUY, *[buy_bk_factor_grid, buy_bk_factor_grid2])
sell_factor_prams, buy_factor_prams, parameters
([[{'XD': 21, 'class': SellBkFactor.SellBkFactorClass, 'draw': True},
{'XD': 60, 'class': SellBkFactor.SellBkFactorClass, 'draw': True}],
[{'XD': 42, 'class': SellBkFactor.SellBkFactorClass, 'draw': True},
{'XD': 60, 'class': SellBkFactor.SellBkFactorClass, 'draw': True}],
[{'XD': 21, 'class': SellBkFactor.SellBkFactorClass, 'draw': True}],
[{'XD': 42, 'class': SellBkFactor.SellBkFactorClass, 'draw': True}],
[{'XD': 60, 'class': SellBkFactor.SellBkFactorClass, 'draw': True}],
[[{'XD': 60, 'class': BuyBkFactor.BuyBkFactorClass, 'draw': True},
{'XD': 120, 'class': BuyBkFactor.BuyBkFactorClass, 'draw': True}],
[{'XD': 60, 'class': BuyBkFactor.BuyBkFactorClass, 'draw': True}],
[{'XD': 120, 'class': BuyBkFactor.BuyBkFactorClass, 'draw': True}]],
{'mv_close_atr': array([ 2. ,
'mv_pre_atr': array([ 1.5,
'stop_loss_base_n': array([ 0.5,
'stop_win_base_n': array([ 2. ,
# 熟悉scikit的朋友一定对下面这种写法很熟悉,借鉴了scikit中很多实现的写法和方式
svr = AlphaBSellMvEstimator()
clf = GridSearchCV(svr, parameters, n_jobs=-1,
scoring=[Metrics.K_QUANT, Metrics.K_RSMM, Metrics.K_SHARP, Metrics.K_RMULT],
scoring_weight=[0.3, 0.2, 0.2, 0.3],
sell_factor_prams=sell_factor_prams)
clf.fit_with_buy_factor(cap, test_pd, kl_pd, buy_factor_prams, False)
更多基础交易相关请请参考:
因子的能力度量
因子的能力的提升必须要有度量工具度量,不能仅仅凭一两方面就肯定或者否定什么,比如某个因子加alpha组合胜率达到90%,但你可能发现,这个因子在一年的回测周期中就生效了几次,那这个因子也不算是好因子,我的度量演示如下所示
使用黄金分割因子在一年回测周期中,对300只随机股票生效的度量结果
buy_factors = [{'XD': 42, 'class': BuyGoldenFactorClass, 'draw': True}]
sell_factors = []
parameters = {
'stop_loss_base_n': 4.0,
'stop_loss_base_n': 2.0,
'mv_close_atr': 3.5,
'mv_pre_atr': 2.0,
cap, results, orders_pd, action_pd, all_fit_symbols = FactorUnitTest.random_unit_test(ret_cnt_need=300,
buy_factors=buy_factors, sell_factors=sell_factors, parameters=parameters, show=False)
rsc = metrics_rsc(*(cap, results, orders_pd, action_pd, all_fit_symbols))
MetricsManger.make_metrics_from_rsc(rsc, METRICSTYPE.SYSMBOL_R_SCORES_GOLDEN.value)
总资金变化情况
output_54_1.png
output_54_3.png
股本投入变化情况
output_54_2.png
因子生效频率
output_54_4.png
effect mean day: 1.
触发器分布情况
output_54_8.png
output_54_15.png
单子持有天数
output_54_10.png
keep days mean: 20.
keep days median: buy Date
Sell Price
profit_cg_hunder
dtype: float64
factor win effect = 0.6%
factor loss effect = 0.3%
每笔花费情况
output_54_6.png
cost info:
moments_tuple(mean=, std=58294, skewness=-0.963, kurtosis=2.6633)
top win, top loss,最大回撤
output_54_12.png
更多度量相关请参考:
4. 理论基础
类似物理有基础理论物理,基础物理构成应用物理等实用技术
量化系统中构成因子等信号触发器的基础理论技术分析叫做基础技术
基于vwapvwap n日成交量于n日成交均价除总量,计算出n日均线,以std作为波动信号(类似boll)vwap_mean = (kl_pd.volume * uq_close).sum() / kl_pd.volume.sum()
TLineVwap.calc_vwap(kl_pd)
vwap(below=19.12, vwap=24.615, above=29.11)
output_53_0.png
跳空阀值不是取的固定值: 根据每个月的波动率以时间加权计算跳空阀值, 详情看calc_jump具体实现计算每个缺口的强度,记录当前调空阀值, 方向等信息代码详情请自行查阅源代码TLineGolden.py 关键代码如下所示:
def calc_jump(kl_pd, show=True):
要使用np.abs(klPd['netChangeRatio'])去计算每个月的跳空阀值
kl_pd['abs_netChangeRatio'] = np.abs(kl_pd['netChangeRatio'])
xd_mean = kl_pd.resample('21D').mean()
net_change_ratio_mean = xd_mean['abs_netChangeRatio']
volume_mean = xd_mean['volume']
net_change_ratio_min = kl_pd['abs_netChangeRatio'].mean()
last_match_index只是为了提速
last_match_index = 0
jump_pd = pd.DataFrame()
for kl_index in np.arange(0, kl_pd.shape[0]):
today = kl_pd.iloc[kl_index]
if today.abs_netChangeRatio &= net_change_ratio_min:
只处理满足最小幅度的,也可提速
while net_change_ratio_mean.shape[0] & last_match_index \
and kl_pd.index[kl_index] & net_change_ratio_mean.index[last_match_index]:
last_match_index += 1
if net_change_ratio_mean.shape[0] == last_match_index:
到最后了,倒回去一个,可优化代码
last_match_index -= 1
if volume_mean[last_match_index] & today.volume:
首先量不达标的先排除了
jump_threshold = np.abs(net_change_ratio_mean[last_match_index])
if today.preClose == 0 or jump_threshold == 0:
# jump_threshold跳口的百分比, jump_diff需要调控的距离
jump_diff = today.preClose * jump_threshold / 100
if today.netChangeRatio & 0 and (today.low - today.preClose) & jump_diff:
# if today.netChangeRatio & jump_threshold:
向上跳空 1
today['jump'] = 1
today['jump_threshold'] = jump_threshold
today['jump_diff'] = jump_diff
计算出跳空缺口强度
today['jump_power'] = (today.low - today.preClose) / jump_diff
jump_pd = jump_pd.append(today)
# elif (-today.netChangeRatio) & jump_threshold:
elif today.netChangeRatio & 0 and (today.preClose - today.high) & jump_diff:
向下跳空 -1
today['jump'] = -1
today['jump_threshold'] = jump_threshold
today['jump_diff'] = jump_diff
today['jump_power'] = (today.preClose - today.high) / jump_diff
jump_pd = jump_pd.append(today)
MarketDrawer.plot_candle_form_klpd(kl_pd, view_indexs=jump_pd.index)
return jump_pd
jumps = TLineJump.calc_jump(kl_pd, True)
output_56_0.png
jumps.filter(['jump', 'jump_diff', 'jump_power', 'jump_threshold', 'netChangeRatio'])
(选读) 应用举例,fiter出适合做为信号触发器的跳空点
跳口power & 2.0的组成ump array接口不考虑跳空时间权重
TLineJump.calc_jump_line(kl_pd)
[jump(date=Timestamp(' 00:00:00'), direction=1.0, power=3.0186, price=21.57),
jump(date=Timestamp(' 00:00:00'), direction=-1.0, power=2.0726, price=27.93),
jump(date=Timestamp(' 00:00:00'), direction=-1.0, power=3.579, price=24.999),
jump(date=Timestamp(' 00:00:00'), direction=1.0, power=4.322, price=22.998)]
output_59_0.png
考虑跳空时间权重:使用线性时间权重分配sw给予的权重
TLineJump.calc_jump_line_weight(kl_pd, sw=(0.6, 0.4))
[jump(date=Timestamp(' 00:00:00'), direction=1.0, power=3.9267, price=21.57),
jump(date=Timestamp(' 00:00:00'), direction=-1.0, power=2.1949, price=27.93),
jump(date=Timestamp(' 00:00:00'), direction=1.0, power=1.5513, price=22.002),
jump(date=Timestamp(' 00:00:00'), direction=-1.0, power=3.1362, price=24.999),
jump(date=Timestamp(' 00:00:00'), direction=1.0, power=4.2972, price=22.998)]
output_60_0.png
拟合趋势线寻找支撑阻力, 对股票‘技术分析’很熟悉的朋友?们对上升趋势线,下降趋势线,阻力线, 支撑线这些概念很熟悉,但是从理论出发,很难有两个人画出的线是完全一样的,即是是一个人不同的时候去画也会有精度的误差,使用数据分析自己画出趋势与阻力是对量化分析的最根本诠释,人对数据的敏感度一定不如死的机器,因为人是有感情的,也许你会画出自己想要的趋势线阻力线来骗自己,再坚持一下马上就阻力了就上去了等等,快交给机器吧!别自己画了!
TLineTrend.calc_reg_fit(kl_pd)
reg_fit(now=-1.2408, mean=2.3578e-15, above=4.5717, below=-4.5681, distance_max=14.121, distance_min=-7.7687)
output_64_0.png
output_64_1.png
黄金分割综合两种黄金切割方式,根据应用使用 maximum,minimum进行选择 重点说一下这个,下面的例子都是使用这个策略组成的因子做的扩展 黄金分割一种是视觉上的382,618,一种就是统计上的382,618 也就是mean和median的的区别如下代码所示:
def find_golden_point_ex(x_org, y_org, show=False):
sp382 = stats.scoreatpercentile(y_org, 38.2)
sp618 = stats.scoreatpercentile(y_org, 61.8)
sp50 = stats.scoreatpercentile(y_org, 50.0)
x_org = np.array(x_org)
sp382_list = [[x_org.min(), x_org.max()], [sp382, sp382]]
sp618_list = [[x_org.min(), x_org.max()], [sp618, sp618]]
sp50_list = [[x_org.min(), x_org.max()], [sp50, sp50]]
TLineDrawer.plot_xy_with_other_x_y(x_org, y_org, '-', sp382_list, sp50_list, sp618_list)
return sp382, sp50, sp618
def find_golden_point(x_org, y_org, show=False):
cs_max = y_org.max()
cs_min = y_org.min()
sp382 = (cs_max - cs_min) * 0.382 + cs_min
sp618 = (cs_max - cs_min) * 0.618 + cs_min
sp50 = (cs_max - cs_min) * 0.5 + cs_min
x_org = np.array(x_org)
sp382_list = [[x_org.min(), x_org.max()], [sp382, sp382]]
sp618_list = [[x_org.min(), x_org.max()], [sp618, sp618]]
sp50_list = [[x_org.min(), x_org.max()], [sp50, sp50]]
TLineDrawer.plot_xy_with_other_x_y(x_org, y_org, '-', sp382_list, sp50_list, sp618_list)
return sp382, sp50, sp618
def calc_golden(kl_pd, show=True, only_be=False):
dk = True if kl_pd.columns.tolist().count('close') & 0 else False
uq_close = kl_pd.close if dk else kl_pd.price
if not hasattr(kl_pd, 'name'):
kl_pd.name = 'unknown'
g_382, g_500, g_618 = TLineAnalyse.find_golden_point(kl_pd.index, uq_close)
if show and not only_be:
plt.axes([0.025, 0.025, 0.95, 0.95])
plt.plot(uq_close) if dk else plt.plot(uq_close.values)
plt.axhline(g_618, color='c')
plt.axhline(g_500, color='r')
plt.axhline(g_382, color='g')
_ = plt.setp(plt.gca().get_xticklabels(), rotation=30)
plt.legend([kl_pd.name, 'g618', 'g500', 'g382'])
plt.title('mean golden')
plt.show()
gex_382, gex_500, gex_618 = TLineAnalyse.find_golden_point_ex(kl_pd.index, uq_close)
if show and not only_be:
plt.axes([0.025, 0.025, 0.95, 0.95])
plt.plot(uq_close) if dk else plt.plot(uq_close.values)
plt.axhline(gex_618, color='c')
plt.axhline(gex_500, color='r')
plt.axhline(gex_382, color='g')
_ = plt.setp(plt.gca().get_xticklabels(), rotation=30)
plt.legend([kl_pd.name, 'gex618', 'gex500', 'gex382'])
plt.title('median golden')
plt.show()
above618 = np.maximum(g_618, gex_618)
below618 = np.minimum(g_618, gex_618)
above382 = np.maximum(g_382, gex_382)
below382 = np.minimum(g_382, gex_382)
percents = [0.20, 0.25, 0.30, 0.70, 0.80, 0.90, 0.95]
# precents = np.linspace(0.0, 1.0, 0.05)
pts_dict = TLineAnalyse.find_percent_point(percents, uq_close)
# import pdb
# pdb.set_trace()
below200 = np.minimum(*pts_dict[0.20])
below250 = np.minimum(*pts_dict[0.25])
below300 = np.minimum(*pts_dict[0.30])
above700 = np.maximum(*pts_dict[0.70])
above800 = np.maximum(*pts_dict[0.80])
above900 = np.maximum(*pts_dict[0.90])
above950 = np.maximum(*pts_dict[0.95])
plt.axes([0.025, 0.025, 0.95, 0.95])
plt.plot(uq_close) if dk else plt.plot(uq_close.values)
plt.axhline(above950, lw=3.5, color='c')
plt.axhline(above900, lw=3.0, color='y')
plt.axhline(above800, lw=2.5, color='k')
plt.axhline(above700, lw=2.5, color='m')
plt.axhline(above618, lw=2, color='r')
plt.axhline(below618, lw=1.5, color='r')
plt.fill_between(kl_pd.index, above618, below618,
alpha=0.1, color="r")
*************I AM HERE*************
plt.axhline(above382, lw=1.5, color='g')
plt.axhline(below382, lw=2, color='g')
plt.fill_between(kl_pd.index, above382, below382,
alpha=0.1, color="g")
plt.axhline(below300, lw=2.5, color='k')
plt.axhline(below250, lw=3.0, color='y')
plt.axhline(below200, lw=3.5, color='c')
_ = plt.setp(plt.gca().get_xticklabels(), rotation=30)
plt.legend([kl_pd.name, 'above950', 'above900', 'above800', 'above700', 'above618', 'below618',
'above382', 'below382', 'below300', 'below250', 'below200'], bbox_to_anchor=(1.05, 1), loc=2,
borderaxespad=0.)
plt.title('between golden')
plt.show()
return namedtuple('golden', ['g382', 'gex382', 'g500', 'gex500', 'g618',
'gex618', 'above618', 'below618', 'above382', 'below382',
'above950', 'above900', 'above800', 'above700', 'below300', 'below250', 'below200'])(
g_382, gex_382,
g_500, gex_500, g_618, gex_618, above618, below618, above382, below382,
above950, above900, above800, above700, below300, below250, below200)
TLineGolden.calc_golden(kl_pd)
golden(g382=22.002, gex382=23.999, g500=25.998, gex500=24.999, g618=28.001, gex618=25.999, above618=28.001, below618=25.999, above382=23.999, below382=22.002, above950=36.001, above900=34.996, above800=32.998, above700=30.009, below300=20.999, below250=19.0425, below200=17.998)
它们组成的因子联合使用了这两种,如下图所示,配合其它位置做成弹力止盈止损策略,简单的说就是比如我在below382和above382之间再满足一些条件比如ma5 & ma10作为买入信号, 如果股价下跌到below200我的最高止盈也随着下降一个档,如果股价上升一个档,最低止损也上升一个档位,直至向上或者向下击穿止最后一个盈止损位
代码详情请自行查阅源代码:TLineGolden.py
output_67_0.png
output_67_1.png
output_67_2.png
更多基础理论信号请请参考:
感谢?您能有耐心看到这里
如果有什么问题可以加阿布的微信
微信号:aaaabbbuu
mmexport0.jpg

我要回帖

更多关于 股票投资策略 的文章

 

随机推荐