3.4 常用自定义函数
MQL4提供了大量的基本函数和语句,然而我们在编程中发现,很多的对行情的判断与操作都是重复的,比如判断指标快慢线是否交叉,这就需要用到自定义函数来简化主程序。
自定义函数通常放在程序的后面,函数格式与说明如下:

函数名称为:myIndicators,被定义为string类型;
该函数带两个参数,分别为string类型的val l和double类型的va12 ;语句括号“笼}”中以两个参数为基础计算交易信号,最后一句是将计算结果返回给自定义函数。
在程序中调用该自定义函数的例子如下:
If ( myIndicators(”金叉”,Close } 0 } ) ) =" Sell"
将自定义函数参数写进去,就会得到按预定算法返回一个结果。
3.4.1 最大开仓量计算
保证金的合理使用是风险控制的重要手段,因此,计算最大开仓量就显得非常重要。在许多风险控制论述中都会有这么一段类似的文字描述:“开仓量为余额的5% 。”其实这种说法极其不准确,甚至会导致因开仓量控制不严格而带来无谓的亏损。
不同货币对的1标准手的自由保证金是不同的。而且,如果你有持仓订单,由于价格变化导致账户净值也在变化,因此开仓量(手)也会发生变化。
以下代码计算了在当前货币对、当前价格的前提下,使用全部自由保证金(本币元)的最大开仓量(手):

其中,myBuyLots为买入订单的最大开仓量(手),mySellLots为卖出订单的最大开仓量(手)。计算方法是:

所以,正确的5%开仓量应该为:myLots x 5 % 。我们来看看通过程序计算显示的结果:

从显示结果可以看出,最大开仓量计算到了小数点后8位,而实际操盘时的开仓量最小为0. 01手,如果你直接使用这个数据,程序会报错,因此还需要通过内置函数将开仓量截止(不用四舍五人)到小数点后2位:
myLots二NormalizeDouble( myLots,2)
OrderSend(Symbol( ) ,OP_SEI,L,myLots ,Bid,0,0,0) ;//开一张卖出订单
3.4.2 新单开仓
读者也许很奇怪,系统中一条命令就能搞定,怎么还需要做这个函数呢?笔者总结程序编写经验的心得是:使用这个自定义函数能大大提高编程速度和质量。
在有些ECN平台上,利用EA新开仓是不允许设置止损止盈价的。
在此提醒读者:使用本函数时尽量不要带止盈止损价格。
[函数源码]



[调用语句说明]
iCloseOrders”All");
持仓单平仓只需要在函数后面跟一个参数,参数类型为String o
参数规定如下:
Buy——多头订单;
Sell——空头订单;
Profit——赢利订单;
Loss——亏损订单;
All——全部订单。
3.4.4 追踪止损
[函数源码]

[调用语句说明]
iMoveStopLoss(25);
止损点为2S,当汀单赢利超过25点时,函数自动修改持仓订单的止损价位。该函数将对所有的持仓订单进行操作。
温馨提示
对赌平台的常用手法之一是:如果你在持仓订单上设置了止损价,它们就会通过服务器发出瞬间的数据导致你亏损平仓,然后再恢复正常的价格传送。因此,笔者建议尽量不要对持仓订单设置止损价格,而是用程序计算平仓。
3.4.5 定时交易
[函数源码]


[调用语句说明]
iTimeControl( 15,00,17,30) ;//从系统时间15;00 - 17;30开始自动交易,函数返回true
在程序中就可以这么使用:
If(iTimeControl( 15;00,17;30))
{
//规定时间段内自动交易的程序代码
}
3.4.6 在屏幕上显示文字
[函数代码]

[调用语句说明]
iSetLable“信息栏1",“当前价格:" + DoubleToStr ( Close } 0 } , 4 ) , 5 , 20 , 10 , " Ver-dana",Olive );
注意:在要显示的内容中使用了DoubleToStr()命令,控制显示小数点后4位,否则会显示小数点后面8位数字。如图3一11所示。
[显示效果]
这个函数与MQL4内置的print和commen,不同,能自定义显示的位置、大小、颜色,对于美化界面,实时追踪数据很有帮助。

3.4.7 两点之间画线
[函数代码]


[调用语句说明]
iDrawL,ine (I 3 , caose } 13 } , 6 , close } 61);//从第13个蜡烛的收盘价到第6个蜡烛的收盘价间画一个绿色虚线
3.4.8 标注符号
[函数代码]


[调用语句说明]
iDrawSign (" Buy" , close } 6 } ) ;//在第5个蜡烛玫盘价上画一个买入箭头
在当前价格标注“买人”箭头。
[显示效果]

3.4.9 指标线交叉信号
[函数代码]


[调用语句说明]
double myMAS一=iMA( Symbol(),0 ,5 ,0,MODE SMA,PRICE_ CLOSE ,O);
double myMAS_I=iMA( Symbol(),0,5 ,0,MODE_ SMA,PRICE CLOSE,1);
double myMA10少=iMA ( Symbol),0,10,0,MODE_SMA,PRICE GLOSE,O);
double myMA10_1=iMA ( Symbol),0,10,0,MODE_SMA,PRICE_CLOSE,1);
string mySignal=iCrossSignal( myMAS_ 0,myMA10一,myMAS_1,myMA10_1);
上面这段代码能够获取移动平均线快线(5个蜡烛周期)与慢线(10个蜡烛周期)的交叉信号,变量mySignal返回交叉信号。