您好,欢迎来到意榕旅游网。
搜索
您的当前位置:首页实用MT4编程教学

实用MT4编程教学

来源:意榕旅游网
第一篇 创建新文件

1、打开 MetaEditor (如何打开自己想办法)呵呵,如果这个都打不开,拜托下面的也不用看了。也许你不适合研究这个。:lol

2、选择文件-->新文件 打开文件创建页面。 3、选择第二项 客户指标 然后点下一步。

注:这个页面可以创建6种文件。我们常用的有 《客户指标》,《脚本》,《智能交易系统》三种。我们先从指标开始。

4、输入名字,作者等等。(支持中文)暂时不添加参数。 注:这个位置可以添加用户变量以后讲解。

5、下一步 我们先建一个主窗口指标 所以这个页面什么都不用操作 注:这个位置可以添加指标“线”。以后提及。 6、点击完成。

ok新的指标文件生成了。但还没有任何有用的代码。初始化代码齐全。 呵呵!下一篇继续。

新建文件的样子和各功能区。

1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.

//+------------------------------------------------------------------+ //| MT4指标编辑.mq4 | //| ldj | //| http://www.metaquotes.net | //+------------------------------------------------------------------+ #property copyright \"ldj\"

#property link \"http://www.metaquotes.net\"

#property indicator_chart_window

//+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() {

//---- indicators //----

1

17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32. 33. 34. 35. 36. 37. 38. 39. 40.

return(0); }

//+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- //---- return(0); }

//+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int start() {

int counted_bars=IndicatorCounted(); //---- //---- return(0); }

//+------------------------------------------------------------------+

复制代码

上面的就是刚刚新建的一个指标文件。

第一部分 指标注释 只是一个说明,有没有都不影响指标运行。

1. 2. 3. 4.

//+------------------------------------------------------------------+ //| MT4指标编辑.mq4 | //| ldj | //| http://www.metaquotes.net |

2

5. //+------------------------------------------------------------------+

复制代码

这部分中前面的 “//” 两个斜线 说明后面的是注释语句,不参与实际运行。 第二部分 预处理语句 这部分规定了指标的窗口性质。如下:

1. 2. 3. 4.

#property copyright \"ldj\"

#property link \"http://www.metaquotes.net\"

#property indicator_chart_window

复制代码

#号表示后面是预处理语句。

property 的意思是定义mt4内部变量的性质。变量名是mt4定义好的只能用固定的变量名。 例如:版权变量 copyright 链接变量 link 以及指标窗口类型变量indicator_chart_window等等。 其中窗口类型变量有indicator_chart_window(主窗口)indicator_separate_window(副窗口)两个这里只能用一个不能两个同时用 这部分内容一般不需要修改。 第三部分 初始化函数(加载函数)

1. 2. 3. 4. 5. 6. 7. 8. 9.

//+------------------------------------------------------------------+ //| Custom indicator initialization function | //+------------------------------------------------------------------+ int init() {

//---- indicators //---- return(0); }

复制代码

这个函数中的代码只在只在指标(EA)加载的时候执行一次。用于对一些变量的初始化。 去初注释函数体为

1. int init()

3

2. 3. 4.

{ return(0); }

复制代码

第三部分 卸载函数

1. 2. 3. 4. 5. 6. 7. 8. 9. 10.

//+------------------------------------------------------------------+ //| Custom indicator deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- //---- return(0); }

复制代码

当去初指标(EA)的时候执行一次。用于去除一些控件。 去除注释函数体为

1. 2. 3. 4.

int deinit() {

return(0); }

复制代码

第四部分 主函数,每当价格变化时就调用执行一次。主要执行代码都在这里。

1. 2. 3. 4. 5.

//+------------------------------------------------------------------+ //| Custom indicator iteration function | //+------------------------------------------------------------------+ int start() {

4

6. 7. 8. 9. 10. 11.

int counted_bars=IndicatorCounted(); //---- //---- return(0); }

复制代码

第五部分 子函数。有些指标和EA含有子函数。我习惯写在后面。 不知道我说得清楚不。

今天我们做一个双线MACD(带柱线)

代码部分!后面的帖子逐条语句分析

1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18.

//+------------------------------------------------------------------+ //| macd vs macd[1] |

//+------------------------------------------------------------------+ #property indicator_buffers 3 #property indicator_separate_window #property indicator_color1 White #property indicator_color2 Red #property indicator_color3 Silver //---- buffers double Buffer1[]; double Buffer2[]; double Buffer3[]; extern int Fast = 10; extern int Slow = 22; extern int Signal = 7;

//+------------------------------------------------------------------+ //| Custom indicator initialization function |

//+------------------------------------------------------------------+

5

19. int init() 20. {

21. //---- indicators 22. //IndicatorBuffers(3);

23. SetIndexStyle(0,DRAW_LINE,0,1); 24. SetIndexStyle(1,DRAW_LINE,0,1); 25. SetIndexStyle(2,DRAW_HISTOGRAM,0,1); 26. SetIndexBuffer(0,Buffer1); 27. SetIndexBuffer(1,Buffer2); 28. SetIndexBuffer(2,Buffer3);

29. IndicatorShortName(\"MACD(\"+Fast+\30. SetIndexLabel(0,\"MACD_MAIN\"); 31. SetIndexLabel(1,\"MACD_SIGNAL\"); 32. SetIndexLabel(2,\"MAIN-SIGNAL\"); 33. IndicatorDigits(Digits+2); 34. //---- 35. return(0); 36. }

37. //+------------------------------------------------------------------+ 38. //| Custor indicator deinitialization function | 39. //+------------------------------------------------------------------+ 40. int deinit() 41. { 42. return(0); 43. }

44. //+------------------------------------------------------------------+ 45. //| Custom indicator iteration function | 46. //+------------------------------------------------------------------+ 47. int start() 48. {

49. int limit,counted_bars=IndicatorCounted(); 50.

//---- check for possible errors

6

51. 52. 53. . 55. 56. 57. 58. 59. 60. 61. 62. 63. . 65.

if(counted_bars<0) return(-1); //---- last counted bar will be recounted if(counted_bars>0) counted_bars--; limit=Bars-counted_bars; //---- main loop for(int i=0; iBuffer1[i]=iMACD(NULL,0,Fast,Slow,Signal,PRICE_CLOSE,MODE_MAIN,i); Buffer2[i]=iMACD(NULL,0,Fast,Slow,Signal,PRICE_CLOSE,MODE_SIGNAL,i); Buffer3[i]=Buffer1[i] - Buffer2[i]; } //---- return(0); }

//+------------------------------------------------------------------+

复制代码

MACD1

下面我们来逐步实现这个指标。 我们要形成双线MACD和一个柱状指标。 因此我们在副图上要形成3个指标线。 主指标 信号指标 柱状指标

1、第一步确认指标显示的窗口

1. 2.

#property indicator_separate_window // #property indicator_chart_window

复制代码

这条代码决定了指标在副图窗口显示。下面那条注释语句表示在主图窗口也就是K线图上显示。 2、预定义3个缓冲区来显示这三个指标线

1. #property indicator_buffers 3

7

2. 3. 4.

#property indicator_color1 White #property indicator_color2 Red #property indicator_color3 Silver

复制代码

#property indicator_buffers 3 语句预定义三个指标缓存区。

#property indicator_color1 White #property indicator_color2 Red #property indicator_color3 Silver 这三条语句为这三个指标预定义了三种颜色。 3、定义这三个指标的数组变量。

1. 2. 3.

double Buffer1[]; double Buffer2[]; double Buffer3[];

复制代码

double定义一个浮点变量。因为是一组数所以要定义一个数组“[]”。 4、在init()函数中初始化这三个指标。

1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.

//IndicatorBuffers(3);

SetIndexStyle(0,DRAW_LINE,0,1); SetIndexStyle(1,DRAW_LINE,0,1); SetIndexStyle(2,DRAW_HISTOGRAM,0,1); SetIndexBuffer(0,Buffer1); SetIndexBuffer(1,Buffer2); SetIndexBuffer(2,Buffer3);

IndicatorShortName(\"MACD(\"+Fast+\ SetIndexLabel(0,\"MACD_MAIN\"); SetIndexLabel(1,\"MACD_SIGNAL\"); SetIndexLabel(2,\"MAIN-SIGNAL\"); IndicatorDigits(Digits+2);

复制代码

8

IndicatorBuffers(3);//定义缓冲区的数量最多八个。因为这个指标只需要三个主缓冲区。所有这个有无都可以。有些需要辅助数组就需要定义这个。以后用到的时候再提起。

SetIndexStyle(0,DRAW_LINE,0,1);//定义指标的显示形式。DRAW_LINE标示画线指标。 看下这个内置函数的定义

SetIndexStyle( int index, int type, int style=EMPTY, int width=EMPTY, color clr=CLR_NONE) index:索引号。0就是第一个指标线1就是第二个指标线。 type: 指标类型 下面是可选参数都是MT4的标准常量。 DRAW_LINE = 0 画线 DRAW_SECTION = 1 画线段 DRAW_HISTOGRAM = 2 画柱状图

DRAW_ARROW = 3 画箭头符号(需要设置符号代码) DRAW_ZIGZAG = 4 画锯齿图 DRAW_NONE = 12 不画图

style:指标线型 0~4的选择。也可以不要,默认为0。 Width:指标线宽 1~5的选择。也可以不要,默认为1。

clr: 指标颜色 一般用#property indicator_color1 White语句定义。前面定义了所以我们这里没有定义。

SetIndexBuffer(0,Buffer1);//为定义的指标变量数组标记索引号。就是使他们一一对应。 0号索引对应Buffer1[]变量。依此类推

IndicatorShortName(\"MACD(\"+Fast+\设置指标显示的名称,内容是用+号连接的字符串。

就是当鼠标放在指标上所看到的指标名称。与文件名不相关。

SetIndexLabel(0,\"MACD_MAIN\");//设置指标的标记。就是当鼠标放在指标线上显示的第三行的名称。 这条语句的意思是0号索引对应的指标变量标记是MACD_MAIN。其他类推。

IndicatorDigits(Digits+2);//定义指标的小数点位数数值是整数。这里Digits是MT4的预定义变量。其值为当前货币兑的小数位。

主函数体

有点儿失眠,又静不下心写程序。所以来把最后一段说明下。

9

1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14.

int start() {

int limit,counted_bars=IndicatorCounted(); if(counted_bars<0) return(-1); if(counted_bars>0) counted_bars--; limit=Bars-counted_bars; for(int i=0; iBuffer1[i]=iMACD(NULL,0,Fast,Slow,Signal,PRICE_CLOSE,MODE_MAIN,i); Buffer2[i]=iMACD(NULL,0,Fast,Slow,Signal,PRICE_CLOSE,MODE_SIGNAL,i); Buffer3[i]=Buffer1[i] - Buffer2[i]; } return(0); }

复制代码

1、int limit,counted_bars=IndicatorCounted();//定义两个整形变量,并给counted_bars变量负值。 这里面IndicatorCounted()函数是mt4内置函数不需要参数,其返回值为已经计算过的指标数组数量。 如果指标错误则这个函数会返回一个负数。

2、if(counted_bars<0) return(-1); //如果条件成立说明指标调用运行错误。则退出程序。 3、if(counted_bars>0) counted_bars--;//从已经计算的指标中去除最后一条。

这条语句用来修正counted_bars使得已经计算的最后一个数值可以在接下来的运算中重新计算一次。 4、limit=Bars-counted_bars;//计算需要计算的指标数据的柱数。

这里需要说明。在mt4中指标数组的索引和K线的索引标记相同,是从后向前递增的从0开使的整数。 也就是说,最后一条K线的索引是0同时K线所对应的指标索引也是0。 那么倒数第2条的索引标记为1。倒数第三条的索引标记为2。 这一点一定要理解清楚。不然写程序的时候就会发生错误。 语句中的Bars是mt4预定义变量,其值是当前图表中K线的条数。

这里详细说下为什么有个counted_bars--;的语句,这个语句的意思是对变量counted_bars进行自减一操作。

因为主函数是每次价格变动就会运行一次。当运行完成后。IndicatorCounted()值应该等于Bars也就是K线的条数

如果没有上面的自减一操作,那么当价格变动有了新的收盘价但并没有生成新的K线。这时候计算limit

10

的值将=0.

那么下面的for循环体将不会再计算最后一条k线相对应的指标数值。

实际上这个是需要计算的(因为有了新的收盘价)。而有了自减一的操作就可以对最有一个,也就是当前K线对应的指标值进行运算。

(不知道能看明白不自己慢慢捉摸捉摸)。这个自减一是必需的。

5、for(int i=0; i6、Buffer1[ i ]=iMACD(NULL,0,Fast,Slow,Signal,PRICE_CLOSE,MODE_MAIN,i); //调用MACD指标函数为Buffer1数组负值。

看下iMACD()这个内置指标函数的定义。

iMACD( string symbol, int timeframe, int fast_ema_period, int slow_ema_period, int signal_period, int applied_price, int mode, int shift) symbol: 货币标识。通用指标用NULL常量。

timeframe: 计算所依据的图表时间周期 。0表示依据当前图表周期。 fast_ema_period: 快线周期 slow_ema_period: 慢线周期 signal_period: 信号线周期 applied_price: 计算所用价格模式

mode: 指标索引模式。MACD指标有两条线,因此这个位置有0,1两个选择。也可以用mt4预定义常量。

shift: 索引号

这里Buffer1取macd主线数据。Buffer2取macd信号线数据。

7、Buffer3[ i ]=Buffer1[ i ] - Buffer2[ i ];//计算MACD两条线之间的距离。

8、这里用到了外部变量。也可以叫用户自定义变量。这种变量在加载图表的时候可以修改。

1. 2. 3.

extern int Fast = 10; extern int Slow = 22; extern int Signal = 7;

复制代码

extern 关键字说明后面定义的变量是外部变量。 这里贴下iMACD()函数的英文说明。

double iMACD( string symbol, int timeframe, int fast_ema_period, int slow_ema_period, int signal_period, int applied_price, int mode, int shift)

11

Calculates the Moving averages convergence/divergence and returns its value. In the systems where OsMA is called MACD Histogram, this indicator is displayed as two lines. In the Client Terminal, the Moving Average Convergence/Divergence is drawn as a histogram. Parameters:

symbol - Symbol the data of which should be used to calculate indicator. NULL means the current symbol.

timeframe - Timeframe. It can be any of Timeframe enumeration values. 0 means the current chart timeframe.

fast_ema_period - Number of periods for fast moving average calculation. slow_ema_period - Number of periods for slow moving average calculation. signal_period - Number of periods for signal moving average calculation.

applied_price - Applied price. It can be any of Applied price enumeration values. mode - Indicator line index. It can be any of the Indicators line identifiers enumeration value.

shift - Index of the value taken from the indicator buffer (shift relative to the current bar the given amount of periods ago). Sample:

if(iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0)>iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0)) return(0);

英文好的自己看吧。我看着很累。

再来一个MACD交叉信号显示!

后面只解释增加的代码部分!

macd.gif (16.14 KB)

12

1、为这两种箭头指标增加和修改相应的预定义部分。

1. 2. 3.

#property indicator_buffers 5 #property indicator_color4 Yellow #property indicator_color5 Blue

复制代码

#property indicator_buffers 5 //指标数量由3增加到5 为这两种箭头设置预定义颜色 #property indicator_color4 Yellow #property indicator_color5 Blue[/code] 2、定义存放这两种箭头的变量数组。

1. 2.

double UP[]; double DO[];

复制代码

UP[]存放向上箭头变量 DO[]存放向下箭头变量。

13

3、为这两个箭头指标在int()函数中设置初始化属性。

1. 2. 3. 4. 5. 6. 7. 8.

SetIndexStyle(3,DRAW_ARROW); SetIndexStyle(4,DRAW_ARROW); SetIndexArrow(3,233); SetIndexArrow(4,234); SetIndexBuffer(3,UP); SetIndexBuffer(4,DO);

SetIndexLabel(3,\"BUY_SIGNAL\"); SetIndexLabel(4,\"SELL-SIGNAL\");

复制代码

SetIndexArrow(3,233);//设置箭头的样式。3是索引,233是向上的箭头 234是向下的箭头。 SetIndexArrow()函数定义形式。 void SetIndexArrow( int index, int code)

Sets an arrow symbol for indicators line of the DRAW_ARROW type. Arrow codes out of range 33 to 255 cannot be used.

Parameters:

index - Line index. Must lie between 0 and 7.

code - Symbol code from Wingdings font or Array constants.

4、在主函数start()为这两个指标负值。

1. 2. 3. 4. 5. 6. 7.

for(i=0; iif (Buffer1[i+0]>Buffer2[i+0] && Buffer1[i+1]Buffer2[i+1]) DO[i]=Buffer2[i];

if (Buffer1[i+0]>Buffer2[i+0] && Buffer1[i+1]==Buffer2[i+1] && Buffer1[i+2]Buffer2[i+2]) DO[i]=Buffer2[i]; }

复制代码

这两个指标的取值由MACD指标的两条曲线的相互关系决定。

就是看相邻两点或三个点之间的大小关系(有相等点的时候就要用3点判断)

14

就是 0,1,2三点两条线数值的大小。

不明白的把上面判断条件的i去掉然后画画相互关系关系就明了了。

虽然MACD看着是两条线,实际是每条K线形成一个点。然后把所有点用光滑线连接起来的。 当条件满足的时候就将 Buffer2的值赋予相应的指标数组(UP或者DO)。这样mt4就在Buffer2的相应位置画一个箭头。

对于不满足的位置 就不会对UP[]和DO[]赋值,这时UP[]和DO[]的值默认为空,mt4就不会做任何操作(什么都不画)。

ok这个指标就这样了。

继续完善这个MACD

如果你挂过上面的指标你就会发现假突破的箭头不会消失。因为没有赋空值语句。 那么我们加上去。需要增加两行代码。 UP[ i ]=EMPTY_VALUE; DO[ i ]=EMPTY_VALUE; for语句循环体变成如下。

1. for(i=0; i3. UP[i]=EMPTY_VALUE; 4. DO[i]=EMPTY_VALUE;

5. if (Buffer1[i]>Buffer2[i] && Buffer1[i+1]7. if (Buffer1[i]Buffer2[i+1]) 8. DO[i]=Buffer2[i];

9. if (Buffer1[i]>Buffer2[i] && Buffer1[i+1]==Buffer2[i+1] && Buffer1[i+2]11. if (Buffer1[i]Buffer2[i+2]) 12. DO[i]=Buffer2[i]; 13.

}

复制代码

EMPTY_VALUE是mt4内置常量,表示空值。没有任何值当然就不会画箭头了。

现在我们希望还能有个报警最好。

对于报警只需要判断最后三个点的位置关系。代码如下。

15

1. if (Buffer1[0]>Buffer2[0] && Buffer1[1]3. if (Buffer1[0]Buffer2[1]) 4. Alert(\"MACD死叉\");

5. if (Buffer1[0]>Buffer2[0] && Buffer1[1]==Buffer2[1] && Buffer1[2]7. if (Buffer1[0]Buffer2[2]) 8.

Alert(\"MACD死叉\");

复制代码

这几行代码添加在上面for循环体的外面。一定不要放在上面的循环体内。

Alert()是内置的报警函数。当执行这条语句的时候会弹出报警窗口,并发出叮的声音报警。 这个函数的参数是字符串变量,或者常量。

MT4自带的MACD交易程序分析。

接下来我们研究下mt4自带的MACD交易系统。 分析下其流程。

我们先来确认下其交易的规则。

入场点规则。 一、买单入场规则

1、MACD快线在零轴下方3个点(也就是0轴下方金叉)。 2、MACD金叉(MACD参数12,26,9)。 3、MA26均线方向向上。 二、卖单入场规则

1、MACD快线在零轴上方3个点(也就是0轴上方金叉)。 2、MACD死叉(MACD参数12,26,9)。 3、MA26均线方向向下。 出场规则。

一、止赢止损出场。 二、买单出场条件

1、MACD在零轴上方死叉

2、并且MACD快线在零轴上方2个点 三、卖单出场条件

16

1、MACD在零轴下方金叉

2、并且MACD快线在零轴下方2个点 并有移动止损功能。

[ 本帖最后由 xfxyldj 于 2007-9-19 03:03 编辑 ]

未命名.JPG (26.17 KB)

逐条解释这个EA代码。

先定义几个用户变量并赋默认值。(加载EA的时候用户可修改的)

1. 2. 3. 4. 5. 6.

extern double TakeProfit = 50; //止赢点数变量 初值50点 extern double Lots = 0.1; //仓位的大小, 初值0.1 extern double TrailingStop = 30;//移动止损点数 初值30

extern double MACDOpenLevel=3; //开仓对MACD数值的过滤 初值3个点 extern double MACDCloseLevel=2; //平仓对MACD数值的过滤 初值2个点 extern double MATrendPeriod=26; //过滤移动平均线的参数 初值26。

复制代码

这部分在代码中作了解释。

17

接下来我们看下对于信号判断前的准备

1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19.

double MacdCurrent, MacdPrevious, SignalCurrent; double SignalPrevious, MaCurrent, MaPrevious; int cnt, ticket, total; if(Bars<100) {

Print(\"bars less than 100\"); return(0); }

if(TakeProfit<10) {

Print(\"TakeProfit less than 10\"); return(0); // check TakeProfit }

MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0); MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1); SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0); SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,1); MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,0); MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,1);

复制代码

if(Bars<100) {

Print(\"bars less than 100\"); return(0); }

这个判断的作用是,如果当前图表的K线条数小于100 则1、Print(\"bars less than 100\");//输出bars less than 100字符串。 Print( ...) 函数用来输出一个字符串,也就是一句话。

2、return();这个语句结束这个主函数,后面的程序代码不再执行。 if(TakeProfit<10) {

Print(\"TakeProfit less than 10\"); return(0); // check TakeProfit }

18

这个判断是如果止赢小于10则 输出TakeProfit less than 10 并推出主函数。 这个程序要求止赢大于10,也就是禁止拔头皮吧。

MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,0); MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,1); SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,0); SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,1); MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,0); MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,1); 这个6条语句取得了MACD两条线及26号均线的当前值,和前一点的数值。 MacdCurrent=MACD快线的当前值。 MacdPrevious=MACD快线的前一点值。 SignalCurrent=MACD慢线的当前值。 SignalPrevious=MACD慢线的前一点值。 MaCurrent=26EMA均线的当前值。 MaPrevious=26EMA均线的前一点值。

iMACD()内置指标函数前面介绍过。这里不再重复。下面详细说下iMA()内置指标函数 看下函数的定义。

double iMA( string symbol, int timeframe, int period, int ma_shift, int ma_method, int applied_price, int shift) Calculates the Moving average indicator and returns its value. Parameters:

symbol - Symbol the data of which should be used to calculate indicator. NULL means the current symbol. timeframe - Timeframe. It can be any of Timeframe enumeration values. 0 means the current chart timeframe. period - Averaging period for calculation.

ma_shift - MA shift. Indicators line offset relate to the chart by timeframe.

ma_method - MA method. It can be any of the Moving Average method enumeration value. applied_price - Applied price. It can be any of Applied price enumeration values.

shift - Index of the value taken from the indicator buffer (shift relative to the current bar the given amount of periods ago).

简单翻译下。(我挂着金山词霸翻译,并不是原味的翻译,英文好的看上面的原文) symbol - 货币标识 (NULL表示使用当前图表的货币标识)

timeframe - 时间周期,0表示使用的是图表的当前周期(小时图,日图等选择). period - 均线周期,这里使用了用户变量MATrendPeriod=26. ma_shift - 均线平移。0表示不平移.

ma_method - 均线模式(这里使用了EMA模式“MODE_EMA”)一共有4种模式。添加均线的时候可以看到。.

applied_price - 应用的价格模式。这里用的是收盘价“PRICE_CLOSE”。. shift - 索引号。0当前这条,1向前数1条,依此类推). 基本的准备就绪了。

下单

现在解决下第一部分。下单操作。

1. total=OrdersTotal();

19

2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. 21. 22. 23. 24. 25. 26. 27. 28. 29. 30. 31. 32.

if(total<1) {

if(AccountFreeMargin()<(1000*Lots)) {

Print(\"We have no money. Free Margin = \ return(0); }

if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious(MACDOpenLevel*Point) && MaCurrent>MaPrevious) {

ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,\"macd sample\ if(ticket>0) {

if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print(\"BUY order opened : \ }

else Print(\"Error opening BUY order : \ return(0); }

if(MacdCurrent>0 && MacdCurrentSignalPrevious && MacdCurrent>(MACDOpenLevel*Point) && MaCurrentticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,0,Bid-TakeProfit*Point,\"macd sample\ if(ticket>0) {

if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print(\"SELL order opened : \ }

else Print(\"Error opening SELL order : \ return(0); } return(0); }

20

复制代码

分步拆解下。

total=OrdersTotal();//取得已成交的订单数。OrdersTotal()函数返回总订单数。

if(total<1)这个判断语句检查下现存的订单数。小于1就是没有订单。然后再判断是否需要下单。

1. 2. 3. 4. 5.

if(AccountFreeMargin()<(1000*Lots)) {

Print(\"We have no money. Free Margin = \ return(0); }

复制代码

这个判断体检查账户资金是否足够。AccountFreeMargin()函数返回账户的可用保证金额度。 如果其值小于 仓位乘以1000的值说明资金不够。

接下来是买卖订单的建立。因为是对称的,只分析买入订单的代码部分。

1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11.

if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious(MACDOpenLevel*Point) && MaCurrent>MaPrevious) {

ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,0,Ask+TakeProfit*Point,\"macd sample\ if(ticket>0) {

if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print(\"BUY order opened : \ }

else Print(\"Error opening BUY order : \ return(0); }

复制代码

首先判断当前价格下是否有买入信号产生。

if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious(MACDOpenLevel*Point) && MaCurrent>MaPrevious)

这个if语句,MACD快线当前值小于0,&& MACD快线当前值大于MACD慢线当前值 && MACD快线前一点值小于MACD慢线前一点值。(这两个语句即判断了一个交叉。) && MACD快线当前值的绝对值大于3个点

21

差。(Point,mt4预定以变量。其值是当前货币的小数位。例如英镑的Point=0.0001,日元的Point=0.01) && MA26均线方向向上。(后一点大于前一点)。

MathAbs()是取绝对值函数。这个位置也可以用MacdCurrent如果所有的条件都成立则执行下单函数。OrderSend().Mt4的所有订单都是调用这个函数实现的。挂Stop、Limit单以及即时订单。全部由这个函数完成。 如果下单成功则返回订单号,如果不成功返回-1。

程序把其返回值赋给ticket,接着判断ticket的值来检查是否成功。 GetLastError()函数返回错误代码。 看下OrderSend()函数定义。参数比较多。

int OrderSend( string symbol, int cmd, double volume, double price, int slippage, double stoploss, double takeprofit, string comment=NULL, int magic=0, datetime expiration=0, color arrow_color=CLR_NONE) 参数意义:

symbol - 货币标识. cmd - 订单类型

(OP_BUY=0,OP_SELL=1,OP_BUYLIMIT=2,OP_SELLLIMIT=3,OP_BUYSTOP=4,OP_SELLSTOP=5 volume - 头寸的大小。(多少手). price - 开仓价格.

slippage - 允许的最大滑点数(有的时候价格波动比较快,这个参数决定开仓价格的波动范围,price正负slippage)

stoploss - 止损价格,0表示不设. takeprofit - 止赢价格,0表示不设.

comment - 为订单加一个注释。字符串类型的,“”双括号表示不加.

magic - 为订单加一个子定义的标识好,正整数。对这个订单的后续的处理需要用到。. expiration - 过期时间,(仅挂单需要)

arrow_color - 在图表上标记此订单的箭头颜色,可不加。

下了订单后检查这个订单

OrderSelect()函数用于选取已存在的订单。函数定义如下。 OrderSelect( int index, int select, int pool=MODE_TRADES) 参数说明

index - 订单的索引号.

select - 选择索引号的类型。两个参数可选SELECT_BY_POS或SELECT_BY_TICKET常用后一个。 pool - 这个参数不知道什么意思,一般不用。可选参数两个MODE_TRADES,MODE_HISTORY 英文说明:Optional order pool index. Used when the selected parameter is SELECT_BY_POS. It can be any of the following values:

22

MODE_TRADES (default)- order selected from trading pool(opened and pending orders), MODE_HISTORY - order selected from history pool (closed and canceled order). 英语差,请见谅!

如果找到了订单则输出订单的标识号吗。 否则输出错误号码。

OK差不多了。啰里啰唆的。希望能看明白。 今天分析下最后一段。 这一段if镶嵌比较多。 用代码拆分的方式来分析。 全代码

for(cnt=0;cntOrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); if(OrderType()<=OP_SELL && // check for opened position OrderSymbol()==Symbol()) // check for symbol {

if(OrderType()==OP_BUY) // long position is opened {

if(MacdCurrent>0 && MacdCurrentSignalPrevious && MacdCurrent>(MACDCloseLevel*Point)) {

OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close position return(0); // exit }

if(TrailingStop>0) {

if(Bid-OrderOpenPrice()> Point*TrailingStop) {

if(OrderStopLoss()OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green);

return(0); } } } } else {

if(MacdCurrent<0 && MacdCurrent>SignalCurrent &&

MacdPrevious(MACDCloseLevel*Point)) {

23

OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // close position return(0); }

if(TrailingStop>0) {

if((OrderOpenPrice()-Ask)>(Point*TrailingStop)) {

if((OrderStopLoss()>(Ask+Point*TrailingStop)) || (OrderStopLoss()==0)) {

OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,OrderTakeProfit(),0,Red); return(0); } } } } } }

这是全部的代码。这部分代码主要是处理移动止损和关仓操作。

代码最外围的是for语句用来遍历全部未了解的订单。并进行相应的判断。 for(cnt=0;cnt}这个代码个人觉得不好。这样搜索有时候会出错。最好的语句个人认为是for(cnt=total;cnt>=0;cnt--) 因为在递增搜索的过程中如果有订单被止损或取消会影响语句的执行。 for语句内的分为两部分。主要是针对买单和卖单的处理。 首先要挑选出符合条件的买卖单然后进行操作。 OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); if(OrderType()<=OP_SELL && // check for opened position OrderSymbol()==Symbol()) // check for symbol { }

这部分代码实现订单的选择。

OrderType()<=OP_SELL 代码限定了被选中的是已经成交的订单OP_SELL=1因此使这个语句成立的只有OP_BUY和OP_SELL两种类型的订单。

OrderType()函数返回订单的类型。判断的订单是被OrderSelect()选中的订单。

OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES);语句选择订单列表中编号为cnt的订单。

OrderSymbol()==Symbol()代码用来判断是否是要操作的货币兑。OrderSymbol()函数返回订单的货币标示。也是对OrderSelect()选中的订单进行操作。

接下来是对不同订单进行操作,也就是分买卖订单进行操作。 if(OrderType()==OP_BUY) // long position is opened { } else { }

24

前面已经对订单类型进行了筛选。因此这里如果(if)不是买单(OP_BUY)就是(else)卖单(OP_SELL)。 接下来分析一个买单的操作。卖单的类似。 对卖单的操作有两个。关仓和移动止损。 关仓(平仓)代码

if(MacdCurrent>0 && MacdCurrentSignalPrevious && MacdCurrent>(MACDCloseLevel*Point)) {

OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close position return(0); // exit }

他的判断代码类似于建仓的判断。这里用到了OrderClose()函数。对于这些内置函数后面帖子将详细说明。各位先看下系统的帮助了解下。 接下来是移动止损的操作部分 if(TrailingStop>0) {

if((OrderOpenPrice()-Ask)>(Point*TrailingStop)) {

if((OrderStopLoss()>(Ask+Point*TrailingStop)) || (OrderStopLoss()==0)) {

OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,OrderTakeProfit(),0,Red); return(0); } } }

这里面镶嵌了3个if的判断语句。

第一个TrailingStop>0移动止损的设置大于0。

第二个OrderOpenPrice()-Ask)>(Point*TrailingStop) 当前买价与开仓价格之差大于移动止损设置置 第三个OrderStopLoss()>(Ask+Point*TrailingStop)) || (OrderStopLoss()==0)止损价格没有被移动或者没有设置移动止损。

当三个条件都成立的时候实行修改移动止损的操作。

OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,OrderTakeProfit(),0,Red); 语句来实现。OrderModify()订单修改函数。 这个程序基本就这样了。

个人认为代码里面有很多不足的地方。

以后的帖子将对一些mt4内置的函数进行一些分析讲解。

OrderSend

今天来介绍下OrderSend()函数。这个函数是用来发送订单的。先看下函数定义。 string symbol, int cmd, double volume, double price, int slippage, double stoploss, int double takeprofit, string comment=NULL, int magic=0, datetime expiration=0, color OrderSend( arrow_color=CLR_NONE)

25

去掉参数说明既是调用方法。 symbol,cmd,volume, price,slippage, stoploss, takeprofit, comment=NULL, OrderSend( magic=0, expiration=0, arrow_color=CLR_NONE)

首先int OrderSend()的定义规定了这个函数的返回值是个整型量。当正确的被调用(所谓的正确被调用,就是定单发送成功被服务器接受也就是语法和参数都没有问题)则返回订单的编号。如果订单发送不成功则返回一个小于0的数。这也就是为什么有些EA会将这个函数返回值赋给一个整型变量。通过判断整型变量的值来来判断是否下单成功。 接下来一个的说明个个实参的用法。

1、symbol这个参数是一个字符串参量用来表明要对那个货币品种实施下单操作。可以用Symbol()函数或NULL常量来表示。当然也可以用具体的字符串例如:\"EUR/USD\"这样的具体标示。

2、cmd这个参数是一个整型变量。用来标记订单的类型。因此它有6个可选参数。可以用下面的内置常量也可以用0~5的整数实现输入。内置常量如下。

常量1:OP_BUY 其值为 0 现价买单 常量2: OP_SELL 其值为 1 现价卖单 常量3 :OP_BUYLIMIT 其值为 2 limit买单 常量4 :OP_SELLLIMIT 其值为 3 limit卖单 常量5 :OP_BUYSTOP 其值为 4 stop 买单 常量6:OP_SELLSTOP 其值为 5 stop卖单

3、volume这个参数是一个双精度浮点数,用来标记订单舱位的大小。这个数值必须大于等于平台的最小开仓量,小于等于平台的最大开仓量。并且是最小开仓量的整数倍。有些平台最小开仓是0.1手而有的是0.01手。一般平台的最大开仓量都是50手。

4、price这个参数是一个双精度浮点数,用来表示订单的开仓价格。这个参数要注意。有些人写的EA不能成交就是这个价格有问题。对于即时单买入这个价格必须用Ask变量的值对于卖出这个价格必须用Bid变量的值搞反了就不能成交了。对于挂单,也要安排好这个价格。一定要算好这个价格与现价之间的关系。例如limit买单这个价格要小于Ask的值

5、slippage这个参数是个整型参数。用来表示滑点的我常用3,如果是0 标示非price价格不成交。这个参数个人认为只是对于现价单有影响,对于挂单似乎没有影响。因为现价单才存在发送订单后几个变化的问题。

6、stoploss这个参数是双精度浮点数。用来设置订单的止损价格,尤其要注意这个一个价格。0表示不设置止损。这个参数要处理好点数和价格的运算。如果输入的止损是个点数就要和开仓价格price进行运算。并用乘以Point内置变量来取点数。(切忌不要用0.0001来运算,因为有些货币的小数位不是4位的。比如日元差盘)。

7、 takeprofit这个参数也是双精度浮点数。用来设置订单的止赢价格。特点同stoploss。

8、comment这个参数是个字符串参数。用来输入订单的描述语句。可以用NULL或者\" \"表示什么都不输入。

26

9、magic这个参数是个整型量。用来标记特定的订单。这个参数一般不为0。因为0的意思是手动订单。我比较喜欢这个参数,因为这个参数可以区分订单。不同的EA可以设置不停的magic值,这样即使挂几个EA也不会互相干扰。而且在在后续处理的时候可以通过这个参数来查找指定的订单。例如同一个信号下两个单,一个长线一个短线。通过不同的magic在后续处理的时候就不会搞错。

10、expiration 这个参数是时间量。用来表示订单的有效期。在这个时间前是有效的。这个参数对于挂单有效。现价单无效。

11、arrow_color这个参数是个颜色变量,用来标记下单箭头的颜色。可以省略或者用NULL常量代替。 ok了。

27

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- yrrf.cn 版权所有 赣ICP备2024042794号-2

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务