MQL4课程-移动止损和保平止损

  • 文章介绍MQL4课程中关于移动止损和保平止损的功能实现,这两种功能在趋势交易中非常有用,能帮助锁定利润并避免巨大亏损。

  • 移动止损通过OrderModify()函数实现,利用布林带下轨作为止损点,当布林带下轨价格高于当前止损价时调整止损位置。

  • 保平止损在盈利达到一定点数后将止损调整至成本价,避免行情回调导致亏损,代码中设定盈利超过10点时触发保平止损。

  • 文章详细讲解了如何通过MQL4编写EA程序,包括初始止损设置、移动止损逻辑、保平止损条件判断,并提供了完整的代码示例。

  • 通过MT4回测工具验证了程序的正确性,展示了移动止损和保平止损在实际交易中的应用效果。

  • 课程还提到后续将编写双均线EA,并推荐关注公众号【火象】获取更多内容。

总结

第七节 移动止损和保平止损

在趋势交易中,移动止损和保平止损是一个特别有用的功能,它能帮我们及时地锁住利润,避免价格突然反方向运行造成的巨大亏损,同时能够帮我们克制一下人性的弱点。那如何用MQL4来实现这些功能呢,下面我们来写一下。

1移动止损

移动止损用到的函数还是OrderModify()函数,为了方便我们看到移动止损的效果,这次采用EA来编写,同时介绍一下EA的回测功能。我们新建一个EA,把其他函数都删掉,只留下头函数和OnTick()函数,接下来在OnTick函数里面编写。

我们规定在25EMA上穿60EMA时,我们做多0.1手,初始止损设置在入场对应的K线以及前两根K线的最低价,移动止损设置在布林带的下轨,如果移动止损超过了当前的止损价那么就把止损设置为移动止损。

我们一步一步来,首先我们写出当25EMA上穿60EMA时开仓做多,初始止损设置在入场K线以及前两根K线的最低价。这里我们要介绍一下用于提取均线数值的函数,这个函数是iMA()函数,打开帮助文件查一下,我们可以看到要查找MA的数值需要输入7个参数:

第一个参数是品种名称;

第二个参数是时间框架,比如要提取1h图的MA数值那就输入60;

第三个参数是指标的周期;

第四个参数是偏移量,如果输入1,则MA线往前偏移1根K线,什么意思呢,比如说在没有偏移的情况下前1根K线对应的数值是2,那么偏移为1时,2就变成了当前K线对应的数值了。

第五个参数是MA的计算方法,有EMA、SMA、SMMA、LWMA四种,关于均线以及其他指标的计算在此不细讲,感兴趣的同学可以去看一下考夫曼写的《交易系统与方法》,本课只专注于实际的应用。

第六个参数是计算所使用的价格,可以用收盘价计算均线数值,也可以用开盘价、最高价、最低价等,总共有七种价格,可以查帮助文件,一般来说我们都用收盘价计算。

第七个参数是查询的K线的编号,如果查询当前K线对应的均线数值那就是0。

好,有了查询MA数值用的iMA函数,我们就可以写出一些均线的策略逻辑了,实现以上功能的代码如下:

void OnTick()
  {
int i;
string sym= Symbol();
double lot=0.1;
int ticket;
int huadian=10;
int peri= PERIOD_CURRENT;
int mag=1333;
      	for(i=OrdersTotal()-1;i>=0;i--)
      	{
         	if(OrderSelect(i,SELECT_BY_POS))
         	{
            	if(OrderSymbol()==sym && OrderType()==OP_BUY &&
OrderMagicNumber ()==mag)
            	{
					return;
            	}
         	}
      	}
double sl= iLow(sym,peri,0);
sl= MathMin(sl, iLow(sym,peri,1));
sl= MathMin(sl, iLow(sym,peri,2));
if(iMA (sym,peri,25,0, MODE_EMA, PRICE_CLOSE,1)> iMA (sym,peri,60,0, MODE_EMA, PRICE_CLOSE,1) &&
iMA (sym,peri,25,0, MODE_EMA, PRICE_CLOSE,2)< iMA (sym,peri,60,0, MODE_EMA, PRICE_CLOSE,2))
{
	ticket= OrderSend(sym,OP_BUY,lot, MarketInfo(sym, MODE_ASK),
huadian,sl,0,”Lesson 7”,mag,0,clrRed);
}
  }


整个程序我把它分成了三部分,第一部分是控制一次只能开一个单子,如果当前持有仓位,那么就不做任何事情,第二部分是初始止损的计算,用到了MathMin函数来,这个函数返回的是两个值的最小值。

最后一部分是最关键的策略逻辑部分,如果25EMA上穿了60EMA,那么也就是说前一根K线25EMA>60EMA,再前一根K线25EMA<60EMA,这个时候我们开一个多单。

接下来我们用MT4的回测工具验证以下程序是否正确,我们打开MT4后在上方的“显示”这一栏中可以找到EA交易测试的选项,如下两个截图:



关于EA参数的优化我们现在暂时用不到,把优化的勾去掉,测试品种、周期、时间范围、测试的EA都调整好后我们就可以开始测试了。以上EA的测试结果如下图:



可以看到在画红框的位置25EMA上穿了60EMA,在后一根K线的开盘时我们入场了一个多单,止损设置在当前K线以及前两根K线的最低点处。虽然后面被打掉了止损,但是可以看到我们的程序是有效的。

接下来我们需要深化一下,把移动止损给加上去,我们只需要将第一部分的程序修改一下即可,将布林带下轨的价格和订单的止损比较一下,如果布林带下轨的价格大于订单的止损,那么修改订单的止损到布林带的下轨。现在最关键的是我们要查询布林带的数值。和均线的查询类似,布林带也有内置的函数,它就是iBand()函数。使用这个函数我们需要输入8个参数,参数意义分别为:

第一个参数是品种名称;

第二个参数是时间框架;

第三个参数是指标的周期;

第四个参数是偏离的标准差,如果是2那偏离2倍的标准差。

第五个参数是偏移量,参考MA。

第六个参数是计算所使用的价格,同MA。

第七个参数是需要查询的内容,如果想要查询上轨的数值,那么就是MODE_UPPER或者输入1,如果要查询中轨就输入MODE_MAIN或者输入0,如果要查询下轨那么输入MODE_LOWER或者输入2。

于是我们可以轻易地完成移动止损的操作,代码如下:

void OnTick()
  {
int i;
string sym= Symbol();
double lot=0.1;
int ticket;
int huadian=10;
int peri= PERIOD_CURRENT;
int mag=1333;
int check;
double bandlow=iBands(sym,peri,20,2,0,PRICE_CLOSE,2,1);
      	for(i=OrdersTotal()-1;i>=0;i--)
      	{
         	if(OrderSelect(i,SELECT_BY_POS))
         	{
            	if(OrderSymbol()==sym && OrderType()==OP_BUY &&
OrderMagicNumber ()==mag)
            	{
            		if(bandlow>OrderStopLoss())
            		{
						check= OrderModify(OrderTicket(),OrderOpenPrice(),
bandlow,OrderTakeProfit(),0,clrRed);
					}
					return;
            	}
         	}
   		}
……….


以上的省略号省略后面不变的部分。我们用这款EA再测试以下看移动止损是否有效,测试结果如下:



从第一张图看,当前K线的布林带下轨已经高于了止损位置了,那么按照EA的逻辑,下一K线开盘的时候,止损会被移动到布林带下轨的位置,于是我们等待下一根K线的开盘。

从第二张图可以看到,K线开盘后,止损便移动到了上一根K线的布林带下轨处,因此我们的移动止损发挥了作用。

但是我们往回看,发现有的时候一根K线里面会开两次仓,如下图所示。



由于EA不止在K盘的时候可以进场,其他时间只要没有订单也可以进场,这样的话在波动比较剧烈时会开很多次仓,造成严重亏损。所以我们要控制程序只在开盘的时候运行一次,其他时间不运行。要实现这个功能也是非常简单,我们只要数K线的根数就行了,如果新增了一根K线那说明有K线开盘了,程序如下:

于是我们可以轻易地完成移动止损的操作,代码如下:

int bar=0;
void OnTick()
  {
int i;
string sym= Symbol();
double lot=0.1;
int ticket;
int huadian=10;
int peri= PERIOD_CURRENT;
int mag=1333;
if(bar==Bars)
{
	return;
}
		bar= Bars;
……….



可以看到这回的结果是正确的,这一根K线只在开盘的时候开了一个订单。

2保平止损

当盈利达到一定程度后,我们就要将止损设置到成本位置来确保不会由于行情的回调而造成亏损,这个在趋势行情中是非常有用的。

为了实现这个功能,我们就要规定盈利达到多少我们便调整止损到保平,这里暂时定为当K线的收盘价高于订单的开盘价10个点时做保平止损。

代码如下:


………..
for(i=OrdersTotal()-1;i>=0;i--)
      	{
         	if(OrderSelect(i,SELECT_BY_POS))
         	{
            	if(OrderSymbol()==sym && OrderType()==OP_BUY &&
OrderMagicNumber ()==mag)
            	{
            		if(bandlow>OrderStopLoss())
            		{
						check= OrderModify(OrderTicket(),OrderOpenPrice(),
bandlow,OrderTakeProfit(),0,clrRed);
					}
            		if(iClose(sym,peri,1)> OrderOpenPrice()+
10*(MarketInfo(sym,MODE_POINT)*10) && 
bandlow< OrderOpenPrice())
            		{
						check= OrderModify(OrderTicket(),OrderOpenPrice(),
OrderOpenPrice(),OrderTakeProfit(),0,clrRed);
					}
					return;
            	}
         	}
   		}

……….


之所以要在判断保平条件时加上bandlow< OrderOpenPrice()这一句是为了避免保平止损和移动止损的冲突导致止损一直是保平止损。再回测试一下效果:



可以看出我们的移动止损发挥了作用,当价格收盘在开盘价以上10个点时将止损拉到了保平的位置。

以上我们就实现了移动止损和保平的功能,完整的代码如下:


int bar=0;
void OnTick()
  {
int i;
string sym= Symbol();
double lot=0.1;
int ticket;
int huadian=10;
int peri= PERIOD_CURRENT;
int mag=1333;
int check;
double bandlow=iBands(sym,peri,20,2,0,PRICE_CLOSE,2,1);
if(bar==Bars)
{
	return;
}
		bar= Bars;
for(i=OrdersTotal()-1;i>=0;i--)
      	{
         	if(OrderSelect(i,SELECT_BY_POS))
         	{
            	if(OrderSymbol()==sym && OrderType()==OP_BUY &&
OrderMagicNumber ()==mag)
            	{
            		if(bandlow>OrderStopLoss())
            		{
						check= OrderModify(OrderTicket(),OrderOpenPrice(),
bandlow,OrderTakeProfit(),0,clrRed);
					}
            		if(iClose(sym,peri,1)> OrderOpenPrice()+
10*(MarketInfo(sym,MODE_POINT)*10) && 
bandlow< OrderOpenPrice())
            		{
						check= OrderModify(OrderTicket(),OrderOpenPrice(),
OrderOpenPrice(),OrderTakeProfit(),0,clrRed);
					}
					return;
            	}
         	}
   		}
double sl= iLow(sym,peri,0);
sl= MathMin(sl, iLow(sym,peri,1));
sl= MathMin(sl, iLow(sym,peri,2));
if(iMA (sym,peri,25,0, MODE_EMA, PRICE_CLOSE,1)> iMA (sym,peri,60,0, MODE_EMA, PRICE_CLOSE,1) &&
iMA (sym,peri,25,0, MODE_EMA, PRICE_CLOSE,2)< iMA (sym,peri,60,0, MODE_EMA, PRICE_CLOSE,2))
{
	ticket= OrderSend(sym,OP_BUY,lot, MarketInfo(sym, MODE_ASK),
huadian,sl,0,”Lesson 7”,mag,0,clrRed);
}
  }


以上就是本节课程的内容,这节课我们完成了移动止损和保平止损的功能,在以后的EA编写中这两个功能将会经常用到,同时这两个功能对交易结果的提升是有着很大的帮助的,在后面的课我们就开始我们第一个简单的双均线EA的编写。


更多内容请关注公众号【火象】~

分享至:

作者:火象趣交易

本文为PANews入驻专栏作者的观点,不代表PANews立场,不承担法律责任。

文章及观点也不构成投资意见

图片来源:火象趣交易如有侵权,请联系作者删除。

关注PANews官方账号,一起穿越牛熊
推荐阅读
2021-11-01 06:59
2021-11-01 06:57
2021-11-01 06:53
2021-11-01 06:31
2021-11-01 06:27
2021-11-01 06:26

热门文章

行业要闻
市场热点
精选读物

精选专题

App内阅读