用mt4提供的mql4语言实现 比尔威廉姆斯 混沌证券交易方法

0
回复
8376
查看
[复制链接]

294

主题

20

回帖

1380

积分

专栏作家

积分
1380
来源: 2019-11-23 19:59:31 显示全部楼层 |阅读模式
在证券交易界,比尔威廉姆斯运用混沌科学的理论来交易的方法非常出名。国内的译本《证券交易新空间》详细得描述了他这一思想方法的具体操作细则,非常详细。但书编辑排版的质量实在是不敢恭维,插图的质量和摆放位置已经不能用粗制滥造来形容了,那简直是以折磨读者为乐,小小抱怨一下。

此篇博客是我使用mt4交易软件自带的职能交易系统mql4语言实现混沌交易方法的开发笔记,不保证正确,只为了给自己留一些日记,如果有朋友也关注这一个领域的,欢迎交流。这篇博客只是笔记,不是教程,不负责解释所有事情,只为给日后的自己一个交待,如是而已。 是故,涉及到的一些名词概念不会有解释,中文的翻译以《证券交易新空间》一书中的翻译为准。

首先,一个新的智能交易系统有三个默认的函系统函数,分别是 init() 函数,deinit() 函数,以及 start() 函数。三个函数中的第一init()函数会在智能交易系统程序被加载后执行一次,可以理解为初始化函数,而第二个deinit() 函数则是在程序退出时会被执行一次,类似于解构函数。最后一个函数 start() 函数则是在系统每收到一次新的报价后执行一次,因为系统总是收到新的报价(交易时段内),所以这个函数会被反复执行,相当于主循环函数。

比如目前黄金的报价是1650美元一盎司,我们打开智能交易程序,init()函数会被执行一次,假设是交易时段,start()函数会在下一个报价时被触发执行(一般新的报价每秒都有),而只有当我们结束这个智能交易程序时,deinit()函数才有可能被执行。所以start()函数要考虑到性能问题,一般这样的智能交易系统不能涉及到太大规模的计算,否则几乎每秒都要执行的start()函数一次还没有完成就要执行下一次,执行程序的计算机可能会出现问题。这是必须要考虑的。

值得庆幸的是mql4可以调用Win32 API 和其他外部程序获得沟通和协作,如果要涉及到非常大规模的计算的话,也不是没有可能形成一个分布式的架构。而我目标实现的系统的运算量很小,完全每有必要和外部程序协作,mql4可以胜任。

鳄鱼组线

第一个要解决的问题是鳄鱼组线,如何在mql4环境里获得鳄鱼组线的数据。包括鳄鱼的牙齿、唇和下颚。这个是比尔威廉姆斯混沌交易方法里贯穿始终要用到的。

因为该方法在西方投资界的盛名,mt4本身的技术分析里就有鳄鱼组线,mql4也已经有预定义的函数,不需要自己写了,填写几个实参就可以直接获得结果了。

具体的方法是,先在代码的最上方引入外部变量,并赋值,我这里使用书里面的标准值。13根平均线平移8位作为下颚,8根平均线平移5位做牙齿,5根平均线平移3位做唇。

extern int JawsPeriod   =13;
extern int JawsShift    =8;
extern int TeethPeriod  =8;
extern int TeethShift   =5;
extern int LipsPeriod   =5;
extern int LipsShift    =3;




然后在需要的地方就可以直接调用,获取当前这几根线的y轴值了(横轴x轴是时间,纵轴y轴是价格)
  1. <font color="#4b4b4b"><font style="background-color:rgb(255, 255, 255)"><font face="Verdana, Geneva, Arial, Helvetica, sans-serif"><font style="font-size: 13px">1 double jaw   = iAlligator(NULL, 0, JawsPeriod, JawsShift, TeethPeriod, TeethShift, LipsPeriod, LipsShift, MODE_SMMA, PRICE_MEDIAN, MODE_GATORJAW, 1);
  2. 2 double teeth = iAlligator(NULL, 0, JawsPeriod, JawsShift, TeethPeriod, TeethShift, LipsPeriod, LipsShift, MODE_SMMA, PRICE_MEDIAN, MODE_GATORTEETH, 1);
  3. 3 double lips  = iAlligator(NULL, 0, JawsPeriod, JawsShift, TeethPeriod, TeethShift, LipsPeriod, LipsShift, MODE_SMMA, PRICE_MEDIAN, MODE_GATORLIPS, 1);</font></font></font></font>
复制代码

有了鳄鱼组线后,判断趋势产生的另外一个要素就是分形的形成和突破了。

分形几何信号

mql4并每有直接提供分形相关的函数,但分形的技术定义并不复杂。过去5根bar价格柱线里,中间的那根价格柱线的最高值是所有5根柱线里最高的,则是一个向上分形,如果中间的那根的最低价是所有5根里最低的,那就是一个向下分形。

mql4 提供价格柱线的获取方法,不需要函数,用内置的数组就可以了。

当前价格柱线的最高价格、最低价格、开盘价和收盘价可以用数组获取。

double high = High[0];
double low  = Low[0];
double open = Open[0];
double close= Close[0];  



在mql4里,一旦输入High或者Low这样的数组名,颜色会发生变化,这表示是系统保留的内置数组名。这里是high low open close就是当前的最高价,最低价,开盘和收盘价。

如果要获取上一个价格柱线的最高价或者最低价


double last_highest = High[1];
double last_lowest = Low[1];




向前的话,以此类推。 high[2]是前面第二根线的最高,low[2]是前面第二根线的最低。而非 high[-2] low[-2]
  1. 1 bool IsUpFractal     = true;
  2. 2 bool IsDownFractal   = true;
  3. 3   
  4. 4 for(int i=1;i<=5;i++)
  5. 5 {
  6. 6    if(High[3]<High[i])  IsUpFractal    = false;
  7. 7    if(Low[3]>Low[i])    IsDownFractal  = false;   
  8. 8 }
复制代码


这里的算法比较简单

第1,2行定义两个变量,是否是向上分形或者向下分形的标志,先假设是形成了分形的。然后查看前5根价格柱线,如果有任何柱线最高价比中间第三根最高价高的话,也就是打擂法成功的话,没有分形突破形成,否则就确实是一个有效的向上分形,向下分形一样道理。

这个函数的执行时机是个问题,如果按照一小时线图来交易的话,则只需要在每个小时开始时执行一下就可以了,没有必要浪费资源在每一个新报价时执行。

这里要用到系统的时间函数,获取当前时间的小时数,比如现在是下午5点,则Hour()函数返回17,表示是17点。

假设我们现在把上面分形突破的判断方法写在一个叫CatchFractal()函数里,则我们要保证每个小时执行一次的话,我用的方法如下:
  1. 1 int last_hour=-1;
  2. 2 int start()
  3. 3 {
  4. 4    if(Hour()!=last_hour)
  5. 5    {
  6. 6       CatchFractal();
  7. 7       last_hour=Hour();
  8. 8    }
  9. 9    return(0);
  10. 10 }
复制代码

第一行先定义了一个变量,叫做last_hour函数,这个函数用来记录上一个小时数,初始为-1,这样就不可能和任何一个时间一样。

然后在start()函数里只需要判断当前小时数和上一个是否一致,如果一致,证明还没有过一个小时,则不触发任何计算,如果触发了,一定是这个小时的第一个时间点触发的,则我们判断有没有新的分形出现,更新一下last_hour 变量为现在的小时数。这样就实现了一个小时执行一次CatchFractal()函数,这个函数一定是每个小时刚刚开始时执行的。

初始情况,值为-1,然后执行start()函数,假设是7点30分开始执行的程序,则Hour()=7不等于-1,则执行一次,检查有没有分形的情况发生,last_hour函数变成7。然后7点31分,7点46分这样的时间点获取的Hour()=7,于last_hour变量一直,不会执行任何操作,直到8点00分00秒,Hour()=8,不再等于last_hour=7,则再次触发分形判断,last_hour更新为8,直到9点再开始检测,期间不会浪费任何系统资源。

在4小时图和日图周图都可以以此类推进行改进,4小时图如果不修改的话,也能正常运行,只不过每4次检查中有3次是浪费的。日图的话,Day()函数取代Hour()函数即可。周线图也是可以扩展的。如果做更加短时间的,30分钟、15分钟、5分钟、1分钟图的交易,也是这个思路。

至此,我们得到了一个每小时监测有无分形形成的程序,并没有做任何交易,也没有对分形信息做处理。已有的代码整理如下:
  1. 1 extern int JawsPeriod   =13;
  2. 2 extern int JawsShift    =8;
  3. 3 extern int TeethPeriod  =8;
  4. 4 extern int TeethShift   =5;
  5. 5 extern int LipsPeriod   =5;
  6. 6 extern int LipsShift    =3;
  7. 7
  8. 8 int last_hour=-1;
  9. 9 int start()
  10. 10 {
  11. 11    if(Hour()!=last_hour)
  12. 12    {
  13. 13       CatchFractal();
  14. 14       last_hour=Hour();
  15. 15    }
  16. 16    return(0);
  17. 17 }
  18. 18
  19. 19 int CatchFractal()
  20. 20 {
  21. 21    double jaw = iAlligator(NULL, 0, JawsPeriod, JawsShift, TeethPeriod, TeethShift, LipsPeriod, LipsShift, MODE_SMMA, PRICE_MEDIAN, MODE_GATORJAW, 1);
  22. 22    double teeth = iAlligator(NULL, 0, JawsPeriod, JawsShift, TeethPeriod, TeethShift, LipsPeriod, LipsShift, MODE_SMMA, PRICE_MEDIAN, MODE_GATORTEETH, 1);
  23. 23    double lips = iAlligator(NULL, 0, JawsPeriod, JawsShift, TeethPeriod, TeethShift, LipsPeriod, LipsShift, MODE_SMMA, PRICE_MEDIAN, MODE_GATORLIPS, 1);
  24. 24   
  25. 25    bool IsUpFractal     = true;
  26. 26    bool IsDownFractal   = true;
  27. 27   
  28. 28    for(int i=1;i<=5;i++)
  29. 29    {
  30. 30       if(High[3]<High[i])  IsUpFractal    = false;
  31. 31       if(Low[3]>Low[i])    IsDownFractal  = false;   
  32. 32    }
  33. 33 }
复制代码


1~6 行引入外部函数,是鳄鱼组线的参数。
8~17 行用来确保每个小时开始的时候触发一次CatchFractal()函数
19~33 是获取分形的代码
其中
21~23行是鳄鱼组线值得获取
25~32行则计算出是否有向上或者向下分形

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 免费注册
关注微信