缠学-线段指标的创新(MQL4)

更新时间:2024-05-28 01:32:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

这日闲来无事,逛网游络。忽到一处,有《缠论》一书映入眼帘,被其“市场哲学的数学原理”的醒目副标触动视欲,于是信手翻来,倒也随处可见“深入浅出”,直至日薄西山方知爱不释手。

如此好书岂能让它停于理论!

看官,您可曾听说过:10多年前的亿安科技案,名动一时。亿安科技是中国首只股价突破百元的股票,也是首只跌幅达到百元的股票。它编织了许多暴富的神话,但也带来了更多的噩梦。和您讲这个故事,是要告诉您:《缠论》就是亿安科技操盘手李彪的杰作。

我的座右铭是:到最风险的领域去做最稳健的事业。

因此,我想把《缠论》理论付诸实施,把缠学理论转化为普通老百姓都可以引用的技术指标和自动交易软件。

如果您有足够的耐心,您将看到我把《缠论》一直转换到自动交易程序出来为止。如果说做市商的行当是金融寡头们的摇

钱树,那么稳健的EA将是普通老百姓的聚宝盆,这就是我的理想!

撰稿人:陆锡林2011年9月17日于浙江金华。

本系列文档,作者试图将《缠论》的理论应用到外汇市场上去。课程所涉及到的外汇交易平台是MT4平台,所涉编程语言是MetaQuotes Language 4 (MQL4),敬请读者对号入座,已发表的文档列表如下: 第一课 分型

请参阅:http://www.docin.com/p-259940757.html 第二课 笔

请参阅:http://www.docin.com/p-302124711.html 笔勘误

请参阅:http://www.docin.com/p-328321787.html 第三课 线段

请参阅:http://www.docin.com/p-331242781.html

本课指标:

本课程将向读者提供以下技术指标源代码文档: ⑴电指标:ElectricityIndex.mq4。

第四课 线段的创新

上节课,我们以“破坏识别法”为基本原理开发了缠论线段指标:BoundTheoryLine.mq4,其走势图如图1所示。

图1

图中A点时间为:2011.11.25 14:00对应价格为1.31833,最后时间为:2012.01.26 16:00。如果果真能实现A买B卖C买D卖E买,最终在2012.01.26 16:00全部平仓,那么虽然历时2个月仅交易了5单,但也有2153点的盈利:

A单获利=1.35383-1.32122=326.1Points B单获利=1.35383-1.28578=680.5Points C单获利=1.30733-1.28578=215.5Points D单获利=1.30733-1.26628=410.5Points E单获利=1.31833-1.26628=520.5Points

若以每次下单1Lot计,就是21530美元的收获,月收入达到了6.5万RMB,是个不错的买卖。

但事实上,我们并没有如此幸运!

且不说我们在第二课曾经告诉大家“笔尖是假的”这一事实就使得上述收入大打折扣,仅图1整个走势中有过的许多“曾经”也足以干扰我们无法实现如此完美的交易。这些“曾经”我们将在第五课中进行详细讲解(第五课是《再论未来函数效应(包括首款缠论EA)》),为了让读者更加深入地了解未来函数效应及其应用,本课先来讲述有关线段指标的创新,以便在下一课讲述未来函数效应对EA的影响时,能对新旧线段指标作一个全面的比较。

一、为什么要创新

由于图1太过“完美”,使得线段指标不仅不利于应用于“走势中枢”,而且也不利于作为个体指标应用于其他领域,我们有必要增加线段。

图2

图2是图1从C点之后的放大图。我们计划把新的线段指标走势图布局为a→b→c→d→e→f→g→h,以实现在提高交易量的同时降低系统风险。

二、新线段指标

⑴新线段的确认规则:

①当笔走势形成电符号时,或者说走出一个Z字形并满足有重叠原理,就构成一条新线段,此为第一类新线段,如图中的ab、de、ef等线段。

②当笔走势超过前期高点或低点并达到一定的宽度时,我们称为触及高压线,也构成一条新线段,此为第二类新线段,如图中的bc、fg、gh等线段。

③当笔走势虽然没有超过前期高点或低点,但汇价宽度触及了超高压线,也构成一条新线段,此为第三类新线段。

④未成线段的笔,如果在它的右侧出现了第一类新线段,那么未成形的笔就成了第四类新线段(也称视同线段),如图中的cd线段。

其中第二类新线段和第三类新线段的不同之处,如图3所示。

图3

第二类新线段和第三类新线段都是指图中的bc线段,它们的不同之处在于:

第二类新线段发生在较短的ab线段之后,因此c点必须低于a点才称得上触及高压线;

第三类新线段发生在较长的ab线段之后,c点跌破a点是不容易的,因此c点没有跌破a点就应该被确认,前提是必须触及超高压线。

高压线我们以HighVoltage来度量,它的单位是点数,比如100Points;超高压线我们以HighVoltage增加δ增量来度量,比如δ=20%时,那么超高压就是120Points。

⑵新线段的指标命名:

下节课我们要开发第一款缠论EA,届时我们还会提到低压电的概念,既然我们引用电作为该指标的形象描述,那么我们就把新线段指标命名为电线段指标,简称电指标。磁盘文件为:ElectricityIndex.mq4。

⑶电指标线段形成的分折

电指标对线段的确认比缠论线段指标大大简化了,它的确认全景图如图4所示。

图4

假设a点是前一向下线段的终点,线段确认过程如下: 第一步,当出现了一条向上的笔后,我们就测该笔的电压: ①若该笔触及超高压,那么它就是线段,如图中①。

②若该笔虽未触及超高压,但已达到高电压,那么进入第二步判断,如图中②。

③若该笔连一般的高压都未达到,那么它不能成线段,如图中③。 注:图中的③是指当前的ab笔不能构成新线段,但并不一定会发展成如图中③的形态,也有可能成为如图E或者F的形态。

第二步,对②形态作进一步判断:

如果是先短后长,ab构成突破状态,则ab笔自成线段,如图中的A。 如果是先长后短,ab笔不能自成线段,如图中的B。此时需等待向下的笔c的出现,c出现后又分二种情形:一种是c点跌破a点,那么进入第三步;一种是c点没有跌破a点,那么跳转至第四步。

第三步,继向上的b笔后又出现了c笔,而且c点低于a点,线段分二种情形来确定:

⒈(b-c)>=HighVoltage,即构成了一条第二类的新线段,此时c笔自成线段,而b笔成为视同线段,如图中的C。

⒉(b-c)请注意,我们之所以把c笔是否触及高压电分成C和D二种情形,是为了讲清楚线段确认的基本原理。在实务中是无需如此刻意的,尤其是在EA交易中分为二种情形是没有意义的,因为b笔是不是线段对于当前的交易已成为历史,当前的交易我们只需关心c点是不是一个线段的端点,显然,C和D告诉我们同一个结果:c是一个向下线段的端点。

第四步,继向上的b笔后又出现了c笔,但c点没有跌破a点,那么: 或形成向上Z字走势,如图中E;或形成向下Z字走势,如图中F。其中向上的Z字形要求d突破b,即d>b;而向下的Z字形并不要求e一定要突破a,但必须突破c,即e

亲爱的读者,我之所以用这么大的篇幅来讲解电指标的基本运算,是因为我们已经离EA很近了,希望您能做到知其然,知其所以然。

⑷电指标的核心运算 ⒈形态坐标变量

图5

在图5中: A图: ①假设

▲Start与a已成一条向下的线段 ▲ab笔不满足成线条件 ▲abcd形成了第一类新线段

②需求

在d点出现之前,指标只画了Start与a一条向下的线段,当d点出现后需要在ad之间画一条向上的线段

③记忆

形态坐标变量管理以下信息: △d点坐标:RightShift, RightPrice。 △a点坐标:LeftShift, LeftPrice。 △Start点坐标:BeforeShift, BeforePrice。 B图: ①假设

▲Start与a已成一条向下的线段 ▲ab笔不满足成线条件 ▲bcde形成了第一类新线段 ②需求

在e点出现之前,指标只画了Start与a一条向下的线段,当e点出现后需要在be之间画一条向下的线段,在ab间画一条向上的(视同)线段

③记忆

形态坐标变量管理以下信息: △e点坐标:RightShift, RightPrice。 △b点坐标:MiddShift, MiddPrice。 △a点坐标:LeftShift, LeftPrice。 △Start点坐标:BeforeShift, BeforePrice。 ⒉形态坐标记忆的逻辑关系

以上形态坐标记忆逻辑是依据自左向右运算的。 ⒊简化约定

如前第三步所述,在B图需求中画ab(视同)线段是没有意义的,因此我们把它简化为Start与e一条向下的线段,有兴趣的读者可以自行添加。

电指标的核心运算由函数GetElectricity()承担,函数GetElectricity()解读如下:

⒈参数表

int nY_Shift 左侧起始坐标,该值与LeftShift保持一致。 ⒉状态代码 ①笔即线,代码1。

●笔触及超高压,如图6所示。

图6

运算代码: //●笔触及超高压,代码1 if( (nY_High-nY_Low)>=(1+Delta)*HighVoltage ) { if( LineTowards>0 ) { RightPrice = nY_High; } else { RightPrice = nY_Low; } return(1); } 其中此前已对右侧坐标赋值:RightShift = Stroke[nY_Pos][3];,而LineTowards存储的是笔方向(即新线段方向)=±1。

●笔触及高压线并创新高或新低,如图7所示。

图7

图7与图6的不同之处在于它必须是创新高或新低,所以它肯定是非首柱的,即BeforePrice>0;图6就没有这个限制,它可以发生在BeforePrice=0的位置。

运算代码:

//●非首柱笔触及高压线 if( nY_Shift<(TotalStroke-2) && (nY_High-nY_Low)>=HighVoltage ) { //且创新高或新低,绝对值为1 if( (LastTowards<0 && nY_High>BeforePrice) || (LastTowards>0 nY_Low0 ) { RightPrice = nY_High; } else { RightPrice = nY_Low; } return(1); } } && 其中此前已对右侧坐标赋值:RightShift = Stroke[nY_Pos][3];,而LineTowards存储的是笔方向(即新线段方向)=±1。

②笔成电(Z字形),代码2或3。

笔成电分为正向电(如图8所示)和反向电(如图9所示)二种。

图8

图9

●延续原线方向的电称为正向电,包括图8中的 A和B二种情形,状态代码为2;与原线方向相反的电称为反向电,包括图9中的 A和B二种情形,状态代码为3。

●Z字形包括一重和多重振荡。

●运算代码分为三步走: 第一步,确定Up线和Dn线 //●笔成Z字形 if( LineTowards>0 ) { nY_Up = nY_High; nY_Dn = LeftPrice; } else { nY_Up = LeftPrice; nY_Dn = nY_Low; } 第二步,搜寻突破的K线 //-- nY_Pos--; nY_NewPos = nY_Pos; nY_Type = 0; nY_Number = 0; while( nY_NewPos>=0 ) { if( Stroke[nY_NewPos][1]>nY_Up ) { nY_Type = 1; break; } if( Stroke[nY_NewPos][2]0 ) { RightPrice = Stroke[nY_NewPos][1]; //正向电还是反向电 if( LastTowards>0 ) { nY_Number = 2; } else { nY_Number = 3; } } else { RightPrice = Stroke[nY_NewPos][2]; //正向电还是反向电 if( LastTowards>0 ) { nY_Number = 3; } else { nY_Number = 2; } } ⑸电指标走势图

图10

三、深入认识电指标

从中图10我们可以看出,电指标的效果介于笔指标和线指标之间,但其优点远不止于此。

⑴电指标是可以调节的 我们在电指标中引入参数:

extern double HighVoltage = 0.01; extern double Delta = 0.2;

其中HighVoltage我们直接用价差表示,HighVoltage=0.01对应EURUSD就是100Points,直接用价差表示就无需再判断交易平台的价格是5位小数的还是4位小数的了。

设定HighVoltage参数不仅能满足用户对参数偏好的应用,而且还能大大优化对电指标的应用。

虽然,所有技术指标参数都带有个人的主观性,但电指标可以通过目测就能取个较好的参数,这是其他技术指标所无法比拟的。

●比如MACD取值12,26,9;KDJ取值5,3,3,它们都无法用眼睛去感受它们的优劣,而HighVoltage却能明明白白地告诉用户,你采用的波浪参数浪高是多少。

●再比如BOLL的20,2;SAR的0.02,0.2,更有甚者CCI嵌在指标内部的0.015都没有HighVoltage来得看得见摸得着。

正如我平时告诉朋友千万不要用ATR指标值来动态管理价格波动那样,ATR小不等于该货币对波幅小,ATR大不等于该货币对波幅大,那些都是暂时的现象,远没有目测的来得好。

⑵电指标有消化“走势中枢”的功能

前已述及,笔成Z字形走势时,判断是否形成电要分三步走,第一步就是确定Up线和Dn线,其实Up线和Dn线就构成了一个小小的“走势中枢”。

无论是形成正向电被确认还是形成正向电被确认,汇价都必须突破这个小小的“走势中枢”,从而避免了在振荡区的重复下单。

⑶状态代码是实现几何指标编程的好途径

在电指标的编程过程中,我们引入了状态代码概念,状态代码是实现几何指标编程的好途径,当系统具有多种状态时,您可以这样处理:

j = GetElectricity(i); switch(j) { case 1:

W_2DotDrawZigZag( RightShift, LeftShift, RightPrice, LeftPrice, LineBeffer ); BeforeShift = LeftShift; BeforePrice = LeftPrice; break; case 2:

W_2DotDrawZigZag( RightShift, BeforeShift, RightPrice, BeforePrice, LineBeffer ); break; case 3:

W_2DotDrawZigZag( RightShift, LeftShift, RightPrice, LeftPrice, LineBeffer ); BeforeShift = LeftShift; BeforePrice = LeftPrice; break; case 4: …… break; case 5: …… break; …… }

虽然我们把状态代码解释为几何指标编程的好方法,但是读者可以通过这个案例实现多重指标复合作用下的指标值定位问题,从而派生出许许多多的好指标来。

今天的课就到这里。 再见!

四、本课指标代码档案

⑴电指标:ElectricityIndex.mq4。 #property copyright \#property link \ E-mail: TradingLovers@163.com\//---- #property indicator_chart_window #property indicator_buffers 1 #property indicator_color1 Snow //---- extern double HighVoltage = 0.01; //对EURUSD为100Points extern double Delta = 0.2; //---- int TotalStroke, LeftShift, RightShift, BeforeShift, LineTowards, LastTowards,LastArraySeat; double LeftPrice, RightPrice, BeforePrice; double Stroke[][4]; double LineBeffer[]; //+------------------------------------------------------------------+ int init() { //---- IndicatorBuffers(1); SetIndexStyle(0,DRAW_SECTION,0,3); SetIndexBuffer(0,LineBeffer); SetIndexEmptyValue(0,0.0); //---- return(0); } //+------------------------------------------------------------------+ int deinit() { return(0); } //+------------------------------------------------------------------+ int start() { double ThisUp, ThisDn; int i, j, limit, counted_bars = IndicatorCounted(); if(counted_bars>0) counted_bars--; limit = Bars-counted_bars; //---- //建立笔K线数据库 ArrayResize(Stroke,0); TotalStroke = 0; for(i=0; i0.0 ) { Stroke[TotalStroke-1][0] = 1; Stroke[TotalStroke-1][1] = ThisUp; if( TotalStroke>1 ) { Stroke[TotalStroke-2][1] = ThisUp; } } else { Stroke[TotalStroke-1][0] = -1; Stroke[TotalStroke-1][2] = ThisDn; if( TotalStroke>1 ) { Stroke[TotalStroke-2][2] = ThisDn; } } } //-- Stroke[TotalStroke-1][1] = MathMax(Stroke[TotalStroke-1][1],Stroke[TotalStroke-1][2]); Stroke[TotalStroke-1][2] = MathMax(Stroke[TotalStroke-1][1],Stroke[TotalStroke-1][2]); //---- LastTowards = Stroke[TotalStroke-1][0]; LeftPrice = Stroke[TotalStroke-1][1]; LeftShift = Stroke[TotalStroke-1][3]; //搜寻线段端点 i = TotalStroke-2; while( i>=0 ) { j = GetElectricity(i); if( j==0 ) { break; } //-- if( j==2 ) { W_2DotDrawZigZag( RightShift, BeforeShift, RightPrice, BeforePrice, LineBeffer ); } else { W_2DotDrawZigZag( RightShift, LeftShift, RightPrice, LeftPrice, LineBeffer ); BeforeShift = LeftShift;

BeforePrice = LeftPrice; } LastTowards = LineTowards; LeftPrice = RightPrice; LeftShift = RightShift; i = LastArraySeat; } //---- return(0); } //+------------------------------------------------------------------+ int GetElectricity( int nY_Shift ) { //---- int nY_Number,nY_Pos,nY_NewPos,nY_Type; double nY_High,nY_Low,nY_Up,nY_Dn; //---- nY_Pos = nY_Shift-1; LastArraySeat = nY_Pos; LineTowards = Stroke[nY_Pos][0]; nY_High = Stroke[nY_Pos][1]; nY_Low = Stroke[nY_Pos][2]; RightShift = Stroke[nY_Pos][3]; //●笔触及超高压,代码1 if( (nY_High-nY_Low)>=(1+Delta)*HighVoltage ) { if( LineTowards>0 ) { RightPrice = nY_High; } else { RightPrice = nY_Low; } return(1); } //●非首柱笔触及高压线 if( nY_Shift<(TotalStroke-2) && (nY_High-nY_Low)>=HighVoltage ) { //且创新高或新低,绝对值为1 if( (LastTowards<0 && nY_High>BeforePrice) || (LastTowards>0 && nY_Low0 ) { RightPrice = nY_High; } else { RightPrice = nY_Low; } return(1); } } //●笔成Z字形 if( LineTowards>0 ) { nY_Up = nY_High; nY_Dn = LeftPrice; } else { nY_Up = LeftPrice; nY_Dn = nY_Low; } //-- nY_Pos--; nY_NewPos = nY_Pos; nY_Type = 0; nY_Number = 0; while( nY_NewPos>=0 ) { if( Stroke[nY_NewPos][1]>nY_Up ) { nY_Type = 1; break; } if( Stroke[nY_NewPos][2]0 ) { RightPrice = Stroke[nY_NewPos][1]; //正向电还是反向电 if( LastTowards>0 ) { nY_Number = 2; } else { nY_Number = 3; } } else { RightPrice = Stroke[nY_NewPos][2]; //正向电还是反向电 if( LastTowards>0 ) { nY_Number = 3; } else { nY_Number = 2; } } //---- return(nY_Number); } //+------------------------------------------------------------------+ void W_2DotDrawZigZag( int nY_x1, int nY_x2, double nY_y1, double nY_y2, double& nY_ZigArray[] ) { //---- nY_ZigArray[nY_x1] = nY_y1; nY_ZigArray[nY_x2] = nY_y2; //---- for( int Y_Shift=nY_x2-1; Y_Shift>nY_x1; Y_Shift--) { nY_ZigArray[Y_Shift] = 0.0; } //---- return; } //+------------------------------------------------------------------+

本文来源:https://www.bwwdw.com/article/s377.html

Top