是在横盘时期,该指标具有良好的入场判断时机。
strategy(overlay = true)
len = input.int(1,min = 3, minval=1, maxval=20)
multi = input.int(1,min = 3, minval=1, maxval=5)
[middle, upper, lower] = ta.bb(close, len, multi)
plot(middle, title = 'middle')
plot(upper, title = 'upper')
plot(lower, title = 'lower')
if close > upper[1]
strategy.entry('long',strategy.long)
if close < lower[1]
strategy.entry('short',strategy.short)
布林宽度衍生于布林带指标,计算的是布林上下轨之间的距离。布林宽度基于标准差计算,布林宽度下降意味着波动率的降低。一般而言,窄幅的布林通道运动一旦出现价格突破上下轨的情况下,常常会伴随着后续走势的转向。
上轨UP(阻力线) - 下轨DOWN(支撑线)
ta.bbw(close, 5, 4)
多空布林线(BBIBOLL)是以多空线为中心线,多空线的标准差为带宽的轨道线。UPR线为压力线,对股价有压制作用,DWN线为支撑线,对股价具有支撑作用,BBIBOLL线为中轴线。
中轨计算:
BBIBOLL=(3日简单移动平均价+6日简单移动平均价+12日简单移动平均价+24日简单移动平均价)/4
肯特纳通道是一个技术指标,包含了中间的移动平均线以及上下轨的通道。它是基于平均真实波幅(ATR)原理而形成的指标,对价格波动反应灵敏,它可以和布林线或百分比通道作为判断市场走向的重要工具。
相对于布林带使用的是标准差,肯特纳通道使用的是ATR进行通道宽度计算。与布林带(BOLL)相比,肯特纳通道更加平滑。
中线:指定周期指数移动平均数 上带:中线+mult*ATR(N) 下带:中线-mult*ATR(N)
TR=math.max(high - low, math.abs(high - close[1]), math.abs(low - close[1])); ATR:MA(TR,N)
参数: N: K线数量(长度). mult: 标准差因子。
(1)入场 中轨向上,并且价格升破上轨,开多单; 中轨向下,并且价格跌破下轨,开空单。
(2)出场 当持有多单时,价格跌破中轨,平多单; 当持有空单时,价格升破中轨,平空单。
[middle, upper, lower] = ta.kc(close, 20, 2)
if close > upper[1]
strategy.entry('long',strategy.long)
if close < middle[1]
strategy.close('long')
if close < lower[1]
strategy.entry('short',strategy.short)
if close > middle[1]
strategy.close('short')
和肯特纳通道理念一致,轨道线以20天移动平均为均线,以+/-3%的波动计算上下轨,确定轨道线的宽度。
CDP指标对广大的投资者来说是一个比较陌生的老指标,实际上CDP技术指标在盘中是一个较好的高抛低吸的短线操作工具。CDP是超级短线指标,假设今日价格的波动幅度不会超过昨天,由此计算出今天的最高价、最低价、次高价、次低价。
CDP 为最高价、最低价、收盘价的均值,称中价;中价与前一天的振幅的和、差分别记为AH(最高值)、AL(最低值);两倍中价与最低价的差称NH(近高值),与最高价的差称NL(近低值)。
CDP=(high[1]+low[1]+close[1]*2)/4 AH=CDP+(high[1]-low[1])//最高 NH=CDP*2-low[1]//近高 AL=CDP-(high[1]-low[1])//最低 NL=CDP*2-high[1] //近低
CDP=(high[1]+low[1]+close[1]*2)/4
AH=CDP+(high[1]-low[1])//最高
NH=CDP*2-low[1] //近高
AL=CDP-(high[1]-low[1])//最低
NL=CDP*2-high[1] //近低
plot(CDP,title='CDP')
plot(AH,title='AH')
plot(NH,title='NH')
plot(AL,title='AL')
plot(NL,title='NL')
与BOLL指标一样,MIKE指标是随价格波动幅度大小而变动的压力支撑指标,它是一种专门研究价格各种压力和支撑的中长期技术分析工具。它设有初级、中级、强力三种不同级别的支撑和压力,用图标方式直接显示压力、支撑的位置。
MIKE指标的计算方法比较复杂,其中涉及到指标计算的起初价——TYP和六个辅助指标,即三个压力价和三个支撑价。对于振幅的计算,它使用的是一定周期内的最高价和最低价。
另外,和其他指标的计算一样,由于选用的计算周期的不同,MIKE指标也包括日MIKE指标、周MIKE指标、月MIKE指标年MIKE指标以及分钟MIKE指标等各种类型。
1、 Weak-s、Medium-s、Strong-s三条线代表初级、中级及强力支撑; 2、 Weak-r、Medium-r、Strong-r三条线代表初级、中级及强力压力; 3、 MIKE Base是一种路径指标,依据Typical Price计算,包含三条带状支撑与压力。
从交易心理学分析,压力支撑的形成很大一部份的因素是因为交易者的心理产生的一种共振或者说是共识所产生的作用,大幅下跌后,在“惜售”心理下很少有人愿意割肉,支撑这时候就产生了!大幅上涨后,在“获利了结”的心理下大部分人想套现时,压力就产生了。而关键点位的突破大概率会带来一波行情的走势,因此可利用技术指标判断关键拐点,提前布局。
大家好,今天我们来学习量化指标系统中的量价指标。量价指标是金融市场技术分析中分析成交量与成交价格关系的指标。量价关系进行分析时要考虑两个要素:成交量和价格。成交量包括放量和缩量两种状态,价格则包括上涨和下跌两种状态,有时还会有平价的状态。成交量的变化与价格涨跌之间有着非常密切的联系。量价分析,就是研究成交量与成交价的相关性,并以此来预测价格运动的未来趋势。
成交量是金融市场供求关系的表现形式,它的大小表明了买卖双方对某一品种即时价格的认同程度,记录了交易者在不同价位上买卖的数量,代表着品种的活跃程度和流通性,并由此透露出市场的人气买卖意愿。人气越旺盛,则交易者进出场越自由,同时也意味着人场资金越充沛,盈利的可能性要大于亏损的可能性。因此,成交量重要的价值,是从市场人气的角度透露了市场的参与意愿和参与深度,为交易者的交易提供了参考依据。
OBV(On Balance Volume),中文名称:累积能量线,俗名:能量潮。其主要理论基础是市场价格的变化必须有成交量的配合,价格的波动与成交量的扩大或萎缩有密切的关连。通常价格上升所需的成交量总是较大;下跌时,则成交量总是较小。价格升降而成交量不相应升降,则市场价格的变动难以为继。
OBV的基本观点为:先见量,后见价,量是价的先行指标。当投资者价的认同愈不一致时,则成交量愈大,正是这种成交量涌动的能量及人气,将价推向新的位置。
当周期收盘价比前一周期收盘价高,其成交量记为正数 当周期收盘价较前一周期收盘价低,其成交量记为负数 累计每周期之正或负成交量,即得OBV值
(1)OBV线下降,价格上升,表示买盘无力,是卖出信号; (2)OBV线上升,价格下降,表示逢低承接强,是买进信号; (3)投资者使用OBV时,注意力应集中在OBV的形态上,其具体数值意义不大。事实上,只是一个能量潮并不能产生有效的买卖信号,因为价格在上涨下跌的初期或中期时,会出现较大幅度的变化,价格趋势一旦成立,大多数交易者的想法会趋于一致,此时该买的都已经买了,该卖的也都卖了,这时候虽然价格是上涨的,但成交量会逐渐萎缩,也就是说成交量萎缩并不代表市场趋势行情即将结束。
obv = ta.obv
WVAD(William’s Variable Accumulation Distribution),中文名称:威廉变异离散量;它是将成交量加权的量价指标,其作用在测量从开盘至收盘期间,买方与卖方各自爆发力的程度。
V = 当周期成交量 A = 当周期收盘价 - 当周期开盘价 B = 当周期最高价 - 当周期最低价 C = A / B * V WVAD = 累计N周期的C值
wvad = ta.wvad
MFI指标也可以叫资金流量指标,英文全名(Money Flow Index)。MFI指标实际是将RSI加以修改后,演变而来。RSI以成交价为计算基础;MFI指标则结合价和量,将其列入综合考虑的范围。可以说,MFI指标是成交量的RSI指标。
1.TYP=(high+low+close)/3 2. upper = math.sum(volume * (ta.change(TYP) <= 0.0 ? 0.0 : TYP), length) 3. lower = math.sum(volume * (ta.change(TYP) >= 0.0 ? 0.0 : TYP), length) 3.mfi = 100-(100/(1+upper/lower)
mfi = ta.mfi(hlc3, 14)
plot(mfi, title = 'mfi', color = color.blue)
if mfi < 20
strategy.entry('long',strategy.long)
if mfi > 80
strategy.entry('short',strategy.short)
英文名为Price/Volume Trend 。即从上市第一天起,对每一交易日先求收盘价与昨收的差,再求差值与昨收的比, 最后求比值与当日成交量的乘积。将每天算得的这个值逐日累加。PVT指标可以与其他技术指标一起使用,如移动平均线、相对强弱指数等,以提高其预测能力。
PVT =(今日收盘价-昨日收盘价)/昨日收盘价×今日成交量
pvt = ta.pvt
plot(pvt, title = 'pvt', color = color.blue)
if pvt > pvt[1] and open < close[1]
strategy.entry('long',strategy.long)
if pvt < pvt[1] and open > close[1]
strategy.entry('short',strategy.short)
EMV(Ease Of Movement Value),中文名称:简易波动指标,运用成交量和人气的旺盛和枯竭,构成一个完整的价格系统循环,指示投资者在人气汇集且成交热络的时候买进品种,并且在成交量逐渐展现无力,而狂热的投资者尚未觉察能量即将用尽时卖出品种。
以计算日EMV为例,计算方法如下: A = (今日最高价 + 今日最低价) / 2 B = (前日最高价 + 前日最低价) / 2 C = 今日最高价 - 今日最低价 EM = (A - B) * C / 今日成交额 EMV = 累计N天的EM值
(1)EMV由下往上穿越0轴时,视为中期买进信号; (2)EMV由上往下穿越0轴时,视为中期卖出信号; (3)EMV属于中长线指标,须长期使用EMV,才能获得最佳利润; (4)当趋向指标DMI中的ADX低于±DI时,本指标失去效用。
len = input.int(5,minval=1,maxval=40)
A = (high+low) / 2
B = (high[1]+low[1]) / 2
C = high - low
EM = (A-B) * C / volume*1000
EMV = ta.sma(EM,len)
plot(EMV, title = 'EMV', color = color.blue)
if ta.crossover(EMV,0)
strategy.entry('long',strategy.long)
if ta.crossunder(EMV,0)
strategy.entry('short',strategy.short)
成交量和成交价是市场提供给我们最基本的资料,量价关系的研究是一切技术分析的基础。价格的涨跌来自于多空双方每时每刻的力量对比,某一时点的量和价就是他们在这一时点上共同市场行为的反映。我们可以从价格涨跌和成交量变化来考察多空双方的态度和意图,从而判明价格后期可能的走势。量价关系是一个重要的指标,可用于波段性操作的买入与卖出之中,属于技术面判断的一种,是判断市场长期趋势关键的指标。因为短期的量价可以被操作,长期的量价关系则反应市场中真实的趋势。因此,通过量价指标,可以将市场真实走向以量化的方式进行呈现,为我们提供判断市场信号的参考依据。
大家好,今天我们将学习量化交易指标的最后一个部分–能量指标。在金融市场上,每一天都是多空力量的较量。在一个交易日或某一段时间内,多空双方的优势会不断地交替出现,因此,双方都有可能在一定时期内占据优势。
如果多方力量在一定时期内占据优势,价格将不断上涨;反之,如果空方力量在一定时期内占据优势,价格将不断下跌;如果多空双方的力量大致平衡,价格会在某一区间内窄幅波动。通过量与价的分析计算,能量指标能够正确、全面地反映每一天或某一段时间内多空双方力量的对比情况。通过使用数值指标的形式对多空双方的力量进行量化比较,能量指标帮助投资者提前进行信号判断,把握最佳的入场和出场时机。
VR(Volitility Volume Ratio),中文名称:成交量变异率。该指标是成交量的强弱指标,运用在过热市场及低速盘局中,对辨别头部及认错部的形成有很重要的作用。
VR = (N周期中上涨日成交量 + 1/2价格不变周期成交量) / (N日中下跌周期成交量 + 1/2价格不变周期成交量) * 100 参数N为24
1.VR指标区域分为四个部分:低价区域(40~70)、安全区域(80~150)、获利区域(160~350)和警戒区域(350以上)。 2. VR下跌至40以下时,市场极易形成底部,应积极买入; 3. VR值一般分布在150左右最多,一旦越过250时市场极易产生一段多头行情; 4. VR超过350以上,应有高档危机意识,随时注意反转之可能; 5. VR运用在寻找底部时较可靠,确认头部时,要配合其它指标使用。 6. 相较而言,由于大盘品种不易被人为操控,因此用VR指标进行判研比较合适。
针对VR指标,我们需要计算价格上涨日,不变日,和下跌日成交量。然而,针对期货品种,价格不变的可能性较小,因此我们定义为针对螺纹钢基数较大的品种,如果价格上涨超过20或者下跌超过20,定义为价格明显变化,否则为平价。当然,针对基数比较小的品种,例如玻璃和甲醛,上涨下跌阈值可以设置小一点。设定固定周期为24,然后我们使用for函数循环,使用if语句今日价格是否大于,小于或者等于昨天,当满足某一条件时,上涨日,下跌日和不变日成交量分别汇总计算。最后利用VR公式计算出来所需的值。
upvolume = 0
downvolome = 0
evenvolume = 0
for i = 1 to 24
if close[i-1] - close[i] >= 20
upvolume += volume[i]
else if close[i-1] - close[i] <= -20
downvolome += volume[i]
else
evenvolume += volume[i]
VR = (upvolume + 0.5*evenvolume)/(downvolome + 0.5*evenvolume)*100
MAVR = ta.sma(VR,5)
plot(VR)
AR人气指标和BR意愿指标都是以分析历史价格为手段的技术指标,AR人气指标重视开盘价,反映市场买卖的人气;BR意愿指标重视收盘价,反映市场买卖意愿的程度;两项指标分别从不同的角度对价格波动进行分析,进而达到追踪价格未来动向的目的。
AR = ((最高价 - 开盘价)的N周期之和) / ((开盘价 - 最低价)的N周期之和) * 200 BR = ((最高价 - 前收盘价)的N周期之和) / ((前收盘价 - 最低价)的N周期之和) * 200
1.一般情况下,AR指标可以单独使用,BR指标则需与AR指标并用,才能发挥效用。该指标虽不适合捕捉到大底部,但是灵活运用该指标,却能够抓住局部底部,特别适合做反弹。 2.BR < AR,且BR < 100,可考虑逢低买进。 3.BR < AR,而BRAR,再转为BR < AR时,也可买进。 4.AR和BR同时急速上升,意味着价格已近顶部,持股者应逢高卖出。 5.BR急速上升,而AR处在盘整或小跌时,应逢高卖出。 6.BR从高峰回跌,跌幅达1至2倍时,若AR无警戒讯号出现,应逢低买进。
AR和BR值每个都具有两个部分,都是N周期之和,所以可以用移动平均值代替(移动平均值就是周期内累加和除以周期),使用sma内置函数计算出来AR和BR两个部分,然后相除就是AR和BR值。关于开仓信号,我们确定的是当br小于ar时,并且br小于100的时候,进行开多仓;空仓信号是当AR和BR急速上升,这里使用的是当AR和BR大于两个周期内的平均值时,进行开空。根据回测结果,针对品种,取得了一个正的预估收益,证明该指标具有一定的参考意义。
ar1 = ta.sma(high-open,26)
ar2 = ta.sma(open-low,26)
br1 = ta.sma(high-close[1],26)
br2 = ta.sma(close[1]-low,26)
ar = ar1/ar2*100
br = br1/br2*100
plot(ar,'ar')
plot(br,'br')
n1 = input.int(3,minval = 2, minva = 25)
if br < ar and br < 100
strategy.entry("buy", strategy.long, qty=1)
if ar > ta.sma(ar,n1) and br > ta.sma(br,n1)
strategy.entry("short", strategy.short, qty=1)
CR综合人气指标,与BR、AR最大的不同在于采用中间价作为计算的基准,CR能够测量价格动量的潜能,又能测量人气热度,同时还能显示压力带和支撑带可以补充BR、AR的不足。
中价 = (最高价 + 最低价) / 2 上升值 = 今最高价 - 昨中价 下跌值 = 昨中价 - 今最低价 CR(N) = N周期上升值之和 / N周期下跌值之和 * 100 参数N一般取26。
设置固定周期数为26,根据公式我们首先计算中价,上升值和下跌值。N周期内的值的和,可以用移动平均值代替,利用移动平均数计算26日内的上升值均值和下跌值均值,两者相除就是CR值。
midprice = (high+low)/2
upprice = high-midprice[1]
downprice = midprice[1]-low
CR = ta.sma(upprice,26)/ta.sma(downprice,26)*100
plot(CR,'CR')
PSY(Psychology Line),中文名称:心理线。它是研究某段时间的投资人趋向于买方或卖方的心理与事实,是考察市场中群体心理变化的依据。
PSY = N周期内上涨的周期数 / N * 100
首先我们设置固定周期为12,在12个周期这一时间段内,统计upcount(N周期内上涨的周期数)。这里我们使用一个for循环和if语句就可以将upcount计算出来。接着我们计算psy值,用upcount除以周期数。关于开平仓信号psy值的判断,这里我们可以使用一个参数调试的形式,确定出最好的psy值上限和下限。经过调参,对于玻璃期货,在2022至2023年间,可以确定最好的psy值上限和下限是80和20。最终取得的预估收益为,证明该指标对于玻璃期货具有良好的参考意义。
int upcount = 0
for i = 1 to 12
if close[i] > close[i-1]
downcount += 1
psy = upcount/12*100
plot(psy,'psy')
i_len1 = input.int(25, "Length 1", minval=5, maxval=25, step=5)
i_len2 = input.int(75, "Length 2", minval=60, maxval=85, step=5)
if psy <= i_len1
strategy.entry("buy", strategy.long, qty=1)
if psy >= i_len2
strategy.entry("short", strategy.short, qty=1)
总体而言,可以发现,能量指标和量价指标具有很多相似的地方,都是使用价和量的变化确定多空双方的力量对比。金融市场存在明显的“羊群效应”–追涨杀跌,然而对于信息不对称的散户,有可能空在低谷,多在山顶。套句西方的分析观点,就是以“反市场心理”的立场为基础,当众人一窝蜂的买,市场上充斥着大大小小的好消息,报纸自媒体纷纷报道经济增长率大幅上扬,刹那间,前途似乎一片光明,此时,你应该断然离开市场。能量指标可以帮助我们识别市场的强弱,从而判断是否应该进场或出场。当能量指标显示市场处于高能量状态时,意味着市场处于强势,可以考虑进场。相反,当能量指标显示市场处于低能量状态时,意味着市场处于弱势,可以考虑出场。因此,能量指标可以作为离场信号的参考指标,帮助我们及时确定出场时机,从而避免过度持仓或错失良机。本节课的内容讲述完毕,我们下节课再见!
大家好,在上述的课程中,我们详细介绍了如何使用Pine语言开发一个交易策略。 然而一个新开发出来的交易策略, 需要全方位检测才能应用于实战,同样一个优秀的策略也是在试错中不断改进得以产生。量化交易回测的目的是还原交易过程,进而验证策略的逻辑和可行性,所以回测的准确性尤为重要。在以往的课程中,我们对于回测的解读只有一个指标,预估收益,然而,预估收益并不是唯一的指标。在实际的交易中,我们需要考虑多个指标来评估一个策略的优劣。今天我们来详细了解一下量化交易的回测系统。
量化交易与主观交易的重要区别之一是量化交易能够通过历史数据回测得出绩效报告,交易者可以从中发现策略的缺点并进行优化改进。然而,要正确评估策略并进行优化改进,必须了解回测参数设置和绩效报告,并正确解读它们。只有这样才能知道策略需要改进的方向。
即使是相同的策略,回测配置参数不一样,也会影响最终的回测结果。在解读回测绩效报告之前,先来看下回测配置,上图是优宽量化软件的回测界面, 这里我们需要注意的几个参数的解释说明如下:
一个盈利率高、胜率高的模型并不一定就是一个好模型。衡量策略好坏的指标需要考虑多方面因素,以下是一些重要的参考指标:
累计收益是指在一段时间内某个投资产品或投资组合的总收益。它是通过将所有的收益加起来计算得出的。
年化收益率表示投资期限为一年的理论收益率,日收益率、 月收益率、 季度收益率都可以换算成年收益率。如果一个策略回测的日收益率是 0.01%, 那么年化收益率是3.65%。其计算公式为: (收益 / 本金) / 投资天数 * 252 ×100%。
波动率是衡量策略风险的指标之一,它是描述策略资金曲线的涨跌幅程度,是对策略稳健性的衡量,也反映了策略风险水平。 其计算方式为:最高价减去最低价的值再除以最低价所得到的比率,年化波动率就是每日波动标准差的年化。
除了波动率外,更能直观反映风险绩效指标就是最大回撤率。 它是统计资金曲线任意周期内最高点到最低点时的回撤幅度的最大值。它是描述策略可能出现的最糟糕情况。最大回撤是一个重要的风险指标,对于量化交易而言,该指标甚至比波动率还重要。
回撤意味着风险,也意味着波动,正确的方式是将收益率和风险都考虑在内,也就是说不但要考虑收益率,更要考虑每承担每一单位风险所产生的超额收益。夏普比率就是一个对收益和风险综合考虑的指标。其公式为:(策略收益率-无风险利率)/策略收益率的标准差。每个策略回测都可以计算夏普比率, 如果值为正数, 则表示策略收益大于策略波动风险; 如果值为负数, 则表示策略波动风险大于策略收益。也就是说在设计策略时要考虑风险,尽量用最小的风险换取最大的回报。
量化交易回测虽然可以快速验证策略在历史数据中是否有效,但很多时候回测并不代表未来能盈利,回测看起来非常好的策略,往往实盘表现不佳。因此需要在策略设计过程中规避回测的陷阱, 才能让策略回测反映真实的结果。
未来函数就是利用了未来的价格,交易策略如果包含未来函数,在实盘运行时回造成信号闪烁的问题。比如有一个策略逻辑时这样的:当收盘价大于开盘价就买入,当收盘价小于开盘价就卖出。这在回测时是没有问题的,因为收盘价是已经完成,固定不变的数据。但是在实盘交易中,收盘价只有在收盘的时候才能固定下来,所以程序会把当前的最新价格当作收盘价,这种利用未来价格的策略,会导致买卖信号频繁出现和消失。如果一个策略的买卖点不是固定的,回测的数据也是没有意义的。如何避免使用未来函数?最简单的办法是使用滞后的价格,可以把这个策略条件修改为:当上根K线收盘价大于开盘价就买入,当上根K线收盘价小于开盘价就卖出。因为无论是在回测中还是在实盘中,上根K线始终是已经完成的,这样就可以保证回测与实盘保持一致。
相反偷价是利用了已经过去的价格,偷价并不会造成信号频繁出现和消失,但是会造成信号无效。比如有一个策略逻辑是:当收盘价大于开盘价就在开盘时买入,当收盘价小于开盘价就在开盘时卖出。显然这个策略条件在实盘时是不能成交的,当收盘价出现时,开盘价早就过去了。但是在回测中,程序是会以开盘价买入卖出的,这相当于在原本的资金曲线上叠加了一条斜率为正的直线会造成一种非常夸张的回测资金曲线。为避免这种情况发生,编写完策略首先要检查策略逻辑,如果策略回测的收益曲线非常平滑,回撤极小,就要警惕了。尤其是策略逻辑存在隐蔽性偷价行为,务必在实盘之前先用仿真交易测试一段时间。
实盘交易中为了保证订单能及时成交,通常需要用对手价或者市价下单,商品期货买一价和卖一价至少相差一个点差,如果是交易不活跃的期货合约就需要更多的点差成本。或者当自己的订单量超过市场现有的订单量时,就会造成自己的订单消耗了市场流动性,触动价格朝向不利于自己的方向移动,使交易成本进一步上升。不仅如此,手续费、极端行情、软硬件系统、服务器响应、网络延迟都会增加实盘的交易成本。尤其是交易频率比较高的策略对受市场冲击成本更大,为了让回测更接近实盘环境,折中的办法是在回测时加上固定2跳左右的滑点。
回测也有运气的成分,有时候的回测结果可能这个策略刚好适应了历史数据,再换几个参数或者回测品种就不一定有这么好的结果了。因此回测良好的策略,需要在实盘上进行模拟,确定效果较好才可真正应用于实盘。
过拟合是统计学中的术语,它是指过于精确地匹配数据特征, 以至于无法在其他数据中良好地拟合,量化交易中的过拟合是一种回测时表现很好, 实盘中表现较差的现象。
由于商品期货历史数据有限,所以过拟合问题就更加严重,尤其是对于中低频策略来说,几乎不可能完全避免过拟合,但可以利用下面几种方法来减少拟合: 1. 减少核心参数 2. 简化处理逻辑 3. 增加数据样本 4. 样本内外测试
大家好,今天我们进入Pine语言期货市场量化交易最后一个板块:实战策略编写。Pine语言的功能确实很强大,里面的内置函数基本涵盖了金融常用的量化指标和函数,但是直接使用成熟的指标还是不能灵活的应对中国的期货市场的不同品种。每个品种都有它不同的品性,应该结合自己的理念,运用更加细腻的逻辑编写不同品种的交易策略。
目前对大家来说,可能灵活的使用Pine语言还具有一定的距离。大家通过对于期货大盘的熏陶,可能摸索了一些不成熟的交易理念与想法,但是想真正的转化成为成熟的策略,依然觉得细腻度和成熟度还具有差距。因此,本部分的结尾课程,我将带领大家细细剖析一些量化策略,了解怎样使用Pine语言将自己的交易理念进行代码化,帮助大家真正使用Pine语言对照中国的期货市场,编写出合适的量化策略。本部分的内容初步计划为两个实战策略的讲解:第一节内容为成熟的指标的变化策略;第二节内容为多个指标结合的策略,帮助大家更好的理解指标的变化以及灵活运用。
本节课介绍的策略为吊灯退出策略。吊灯退出指标在某种程度上可视为ATR指标的延伸。吊灯退出指标是一个基于波动性的指标,使交易者能够等到出现明确趋势反转时再进行交易。对于信息不透明的散户来说,期货趋势中明显的反转需要人为的判断,所以只能被动的开展“追涨杀跌”,稍有不慎,下单将会被套牢,出于不想亏损的心理,扛单占据了大部分的时间,而一旦扛单被解套,一点点小盈利散户就抓紧时间平仓,错过了更大盈利的可能性。通过使用吊灯退出指标,交易者将能够避免过早平仓,实现最大的回报。
吊灯退出指标由全球公认平仓策略专家 Chuck Le Beau 创造。 但此指标和与之相关的交易系统却由 Alexander Elder 通过其在 2002 年出版的《Come Into My Trading Room》一书介绍给交易者和投资者。此指标因其与房间天花板上的吊灯相似而得名。
吊灯退出指标基于以下原理:当资产价格背离主要趋势变动的距离达到平均波动幅度的三倍时就很可能发生趋势反转。该指标是利用指定时间范围内的 ATR(真实波动幅度均值) 值创建的。 除了ATR以外,在计算中还使用了资产在特定时间范围内最高的高点和最低的地点价格。在使用移动窗口周期进行分析时,建议使用 22 天的时间范围输入。 这是因为金融市场每个月有 22 个交易日。 为了确保平滑的效果并过滤短期波动或噪声,建议在计算中使用22天的价格水平。对于其他移动窗口周期,我们可以根据反复参数试验的结果确定使用的时间范围输入。 这个方面并没有硬性的规则。就像前面描述的一样,吊灯退出指标的主要目标是在正确的时间提醒交易者即将发生趋势反转。因此,对于多头头寸和空头头寸,吊灯退出指标的计算方式不同。
在上行趋势中,可使用如下公式计算吊灯退出指标:
在下行趋势中,可使用如下公式计算灯笼止损指标:
倍数值3是指吊灯退出指标的倍数,交易者可以更改此倍数。虽然并没有禁止使用不同的时间范围,但对于上涨的移动周期窗口和下跌的移动周期窗口,大部分交易者还是会使用相同的时间范围。计算出的值(日间、每日、每周或每月)在价格图表上绘制成一条线。 根据上述公式,可以推测出在下行趋势中,吊灯退出线将高于该价格线。相反,在上行趋势中,吊灯退出线将低于价格线。如果考虑了资产隐含的波动幅度,则可以更改吊灯退出指标的倍数。更大的时间范围则会延迟平仓,因而会稀释指标的作用。在交易隐含波动幅度(市场预期的资产价格涨跌幅度)较大的期货基数时,需要更大的倍数。 在金融市场上,交易者在下行趋势中使用较小倍数的情况并不罕见,因为价格下跌的速度一般会更快。
study("吊灯退出", overlay=true)
length = input.int(12, title="ATR周期", minval=11, maxval=33)
mult = input.int(3, title="ATR乘数", minval=1, maxval=5)
showLabels = input.bool(title="显示 Buy/Sell 标签 ?", defval=true)
useClose = input.bool(title="使用收盘价作为极值点 ?", defval=true)
//计算真实波幅倍数
atr = mult * ta.atr(length)
//使用收盘价作为极值点,返回移动窗口周期内的收盘价最大值,不使用的话,返回移动窗口周期内的最高值(high)的最大值,然后减去atr
longStop = (useClose ? ta.highest(close, length) : ta.highest(length)) - atr
//如果再开始的时候,longStop[1]是null,返回longStop
longStopPrev = nz(longStop[1], longStop)
//昨日的收盘价大于longStopPrev,说明没有突破longStopPrev,继续上升的趋势,返回longStop和longStopPrev的最大值(为下一日做准备),如果昨日向下突破longStopPrev,返回最新的longstop,这是一个不断更新longstop的过程
longStop := close[1] > longStopPrev ? math.max(longStop, longStopPrev) : longStop
//使用收盘价作为极值点,返回移动窗口周期内的收盘价最小值,不使用的话,返回移动窗口周期内的最低值(low)的最小值,然后加上atr
shortStop = (useClose ? ta.lowest(close, length) : lowest(length)) + atr
//如果再开始的时候,shortStop[1]是null,返回shortStop
shortStopPrev = nz(shortStop[1], shortStop)
//昨日的收盘价小于shortStopPrev,说明没有突破shortStopPrev,继续下降的趋势,返回shortStop和shortStopPrev的最小值(为下一日做准备),如果昨日向上突破shortStopPrev,返回最新的shortStop,这是一个不断更新shortStop的过程
shortStop := close[1] < shortStopPrev ? math.min(shortStop, shortStopPrev) : shortStop
var int dir = 1
//两个三元表达式,下降过程中,如果close向上突破shortStopPrev,应该空头反转开多,返回1;
//否则如果close没有突破shortStopPrev,应该继续空头持有,返回-1;
//上升过程中,如果close向下突破longStopPrev,应该多头反转开空,返回-1;
//否则close没有突破longStopPrev,应该继续多头持有,返回1
//精髓就在于后续是一个var dir,会保留先前的dir状态,只要不进行突破,就会保留原始的var值
//转空是一个1到-1;转多是一个-1到1
dir := close > shortStopPrev ? 1 : close < longStopPrev ? -1 : dir
var color longColor = color.green
var color shortColor = color.red
//空头反转开多,dir由-1转为1,多头止损开启
//画线
longStopPlot = plot(dir == 1 ? longStop : na, title="Long Stop", style=plot.style_linebr, linewidth=2, color=longColor)
buySignal = dir == 1 and dir[1] == -1
//画圆圈
plotshape(buySignal ? longStop : na, title="Long Stop Start", location=location.absolute, style=shape.circle, size=size.tiny, color=longColor, transp=0)
//画箭头
plotshape(buySignal and showLabels ? longStop : na, title="Buy Label", text="Buy", location=location.absolute, style=shape.labelup, size=size.tiny, color=longColor, textcolor=color.white, transp=0)
//多头反转开空,dir由1转为-1,空头止损开启
//画线
shortStopPlot = plot(dir == 1 ? na : shortStop, title="Short Stop", style=plot.style_linebr, linewidth=2, color=shortColor)
sellSignal = dir == -1 and dir[1] == 1
//画圆圈
plotshape(sellSignal ? shortStop : na, title="Short Stop Start", location=location.absolute, style=shape.circle, size=size.tiny, color=shortColor, transp=0)
//画箭头
plotshape(sellSignal and showLabels ? shortStop : na, title="Sell Label", text="Sell", location=location.absolute, style=shape.labeldown, size=size.tiny, color=shortColor, textcolor=color.white, transp=0)
//画出中间价
midPricePlot = plot(ohlc4, title="ohlc4", style=plot.style_circles, linewidth=0, display=display.none, editable=false)
//多头信号,开多仓;空头信号,开空仓
if buySignal
strategy.entry("Enter Long", strategy.long)
else if sellSignal
strategy.entry("Enter Short", strategy.short)
优点 允许交易者以可以忽略的风险等到最后一个点再交易。 允许使用多个指标创建先进的策略。 经验丰富的交易者可以过滤掉错误的信号,从而放心地交易货币。
缺点 需要有足够的知识和实践经验才能更改吊灯退出的倍数值。
通过细细剖析策略源码,可以感到一个形容词“精巧”。通过简单的代码编写,对于突破信号的设计和转换,完成对多头和空头的对调开仓。策略原理我相信大家都可以理解,重要的是怎样使用精确简洁的语言讲自己的交易理念进行代码化呈现,这是我希望大家和我一起学习的事情。本节课的内容讲述完毕,我们下节课再见!
大家好,欢迎大家来到Pine语言商品期货量化最后一节课程,本课程的内容为量化实战之组合指标策略的讲解。如果说一个指标代表衡量趋势的一个维度,使用多个指标则意味着从多个维度,立体捕捉市场的发展趋势。组合指标策略的核心思想是将不同类型、不同特性的指标进行有效的组合,从而达到更准确的市场预测和交易决策。常见的组合指标策略包括趋势型、震荡型和能量型等,具体选用哪种类型要根据市场情况灵活调整。同时,在实际应用中还需要考虑各指标间的权重,以及如何对参数进行优化和调整,从而让策略始终保持优异的表现。
BB-RSI-ADX是一种技术指标组合,用于确定股票或其他交易资产的入场点。BB代表布林带指标(Bollinger Bands),RSI代表相对强弱指标(Relative Strength Index),ADX代表平均趋向指标(Average Directional Index)。这三个指标结合在一起可以提供更全面的市场分析。
基于Bollinger Bands、RSI和ADX指标的交易策略定义了三个指标的参数和输入条件,根据这些条件确定是否进入多头或者空头。具体来说,该策略使用Bollinger Bands指标来确定价格波动的上下限,使用RSI指标来确定价格是否处于超买或超卖状态,使用ADX指标来确定趋势强度。 具体而言,当BB指标和RSI指标同时发出买入信号,并且ADX指标显示市场正处于强劲的趋势中时,这被认为是一个较好的入场点。通过综合三个指标,我们构建出了一个从多方条件约束开平仓信号的震荡策略,然而不可忽视的是,策略的参数越多,不免会陷入过拟合的风险。并且对于不同类别的品种,参数则需要重新调试,因此这就是使用这类综合指标策略需要注意的地方。
//@version=5
indicator(shorttitle="BB-RSI-ADX", title="BB-RSI-ADX Entry Points", overlay=true, timeframe="", timeframe_gaps=true)
// Bollinger Bands Setup
//定义布林带周期的输入变量,并设置最小值、显示标题和所属分组。
bbLength = input.int(9, minval=1, title="BB 周期", group="BB Settings")
//定义数据源的输入变量,并设置显示标题和所属分组。这里使用收盘价作为数据源。
src = input(close, title="数据源", group="BB Settings")
//定义标准差的倍数,并设置最小值、最大值、显示标题和所属分组。
stDev = input.float(2.0, minval=1, maxval=3, title="标准差", group="BB Settings")
//计算布林带的中轨,使用简单移动平均线。
basis = ta.sma(src, bbLength)
//计算布林带的标准差的倍数,使用收盘价作为标准差输入变量,乘以倍数。
dev = stDev * ta.stdev(src, bbLength)
//计算布林带的另一个标准差,使用收盘价和标准差输入变量。这里对标准差倍数进行了一些调整,以使其不小于1。
devMinOne = (stDev > 1 ? stDev - 1 : 1) * ta.stdev(src, bbLength)
//计算上限,中轨加上标准差的倍数
upper = basis + dev
//计算下限,中轨减去标准差的倍数
lower = basis - dev
//计算次上限,中轨加上标准差乘以减一的倍数
upperMinOne = basis + devMinOne
//计算次下限,中轨减去标准差乘以减一的倍数
lowerMinOne = basis - devMinOne
//画出中轨,上限和下限,并使用颜色填充上限和下限
plot(basis, "Basis", color=#FF6D00)
p1 = plot(upper, "BB Upper", color=#2962FF)
p2 = plot(lower, "BB Lower", color=#2962FF)
fill(p1, p2, title = "BB Background", color=color.rgb(33, 150, 243, 95))
// 利用次上限和次下限,计算布林带宽度的百分比B。
bbr = (src - lowerMinOne)/(upperMinOne - lowerMinOne)
// RSI
//RSI周期数参数
rsiLengthInput = input.int(14, minval=1, title="RSI 周期", group="RSI Settings")
//RSI数据源参数
rsiSourceInput = input.source(close, "数据源", group="RSI Settings")
//计算RSI的上升部分,使用RSI数据源的变化值(差分)和RSI周期输入变量,并使用RMA(指数加权移动平均线)进行平滑。
rsiUp = ta.rma(math.max(ta.change(rsiSourceInput), 0), rsiLengthInput)
//计算RSI的下降部分,使用RSI数据源的变化值和RSI周期输入变量,并使用RMA进行平滑。
rsiDown = ta.rma(-math.min(ta.change(rsiSourceInput), 0), rsiLengthInput)
//计算rsi的值,两个三元表达式
//如果rsiDown == 0,rsi=100
//在rsiDown不等于0的情况下,如果rsiUp == 0,rsi=0
//如果rsidown和rsiup都不等于0,则rsi=100 - (100 / (1 + rsiUp / rsiDown))
rsi = rsiDown == 0 ? 100 : rsiUp == 0 ? 0 : 100 - (100 / (1 + rsiUp / rsiDown))
// ADX
//ADX平滑周期
adxlen = input(14, title="ADX 平滑周期", group="ADX Settings")
//ADX DI 周期
dilen = input(14, title="ADX DI 周期", group="ADX Settings")
//dirmov自定义函数
[_, _, adxStr] = ta.dmi(dilen, adxlen)
// Entry condition inputs
//开多仓的参数阈值
c_enter_long_bbr = input(0, title="最小值 BB %B", group="Enter LONG Conditions", tooltip="The Minimum required BB %B required to enter a LONG position. RECOMMENDED: 0")
c_enter_long_rsi_min = input(30, title="最小 RSI", group="Enter LONG Conditions", tooltip="The Minimum RSI value to enter a LONG position. RECOMMENDED: 30", inline="rsi_long")
c_enter_long_rsi_max = input(50, title="最大 RSI", group="Enter LONG Conditions", tooltip="The Maximum RSI value to enter a LONG position. RECOMMENDED: 50", inline="rsi_long")
//开空仓的参数阈值
c_enter_short_bbr = input(1, title="最大值 BB %B", group="Enter SHORT Conditions", tooltip="The Highest required BB %B required to enter a SHORT position. RECOMMENDED: 1")
c_enter_short_rsi_min = input(50, title="最小 RSI", group="Enter SHORT Conditions", tooltip="The Minimum RSI value to enter a SHORT position. RECOMMENDED: 50", inline="rsi_short")
c_enter_short_rsi_max = input(70, title="最大 RSI", group="Enter SHORT Conditions", tooltip="The Maximum RSI value to enter a SHORT position. RECOMMENDED: 70", inline="rsi_short")
//衡量趋势的强度
c_adx_min_str = input(25, title="ADX 最小力度", group="ADX Settings")
// Enter Long Conditions
enter_long = (low < lower) and (bbr > c_enter_long_bbr) and (rsi > c_enter_long_rsi_min) and (rsi < c_enter_long_rsi_max) and (adxStr > c_adx_min_str) ? 1 : 0
// Enter Short Conditions
enter_short = (high > upper) and (bbr < c_enter_short_bbr) and (rsi > c_enter_short_rsi_min) and (rsi < c_enter_short_rsi_max) and (adxStr > c_adx_min_str) ? -1 : 0
if enter_long
strategy.entry("Enter Long", strategy.long)
else if enter_short
strategy.entry("Enter Short", strategy.short)
优点: 多重指标确认:该策略综合了多个指标,可以减少单一指标造成的误判,提高交易准确性; 应用范围广:适用于不同市场和不同品种的交易; 策略灵活调整:可根据实际市场情况进行参数调整。
缺点: 参数需要多次调整; 过拟合风险。
Pine语言的量化课程到目前为止就全部结束了,很感谢大家这段时间的陪伴。我们后续会推出更多的有关金融量化的课程,也很感谢大家对于优宽平台的关注,我们有缘再见!