第六节 交易函数平仓及修改止损止盈
俗话说进场是徒弟,出场是师傅,一款程序想要盈利,那就得学会如何出场,要出场那我们还是有必要学一学离场的函数。首先和大家说一下,离场一般就分为两类,一种是主动离场,一种是被动离场。所谓主动离场,便是当价格达到某一个条件后主动平仓,被动离场便是打掉止损止盈或者被强行平仓。
如果做趋势交易,我的建议是不要设置止盈,让市场来决定我们可以盈利多少,主动平仓和移动止损最好都做,这个时候主动平仓也称之为柔性止损,而止损称为刚性止损。
下面我们为这两类止损打一个基础。
1平仓
平仓我们可以用OrderClose()函数来做,其实也没有多么复杂,最关键的还是要从一大堆单子中筛选出我们想要平掉的那个单子。那么我们先从OrderClose()函数说起,打开帮助文件可以看到这个函数有5个参数:
第一个参数需要平仓的订单的号码,每个订单都有一个识别码,后面会讲到;
第二个参数是订单的手数;
第三个参数是订单的平仓价格;
第四个参数是平仓的滑点控制;
第五个参数是平仓显示的箭头的颜色。
以上参数和之前的开单有点类似,所以不细讲。
下面我们要在GBPUSD、USDJPY以及EURUSD这三个品种各开一个单子,然后从这些单子里面筛选出EURUSD的单子并把它平掉。
在MQL4中,有一个函数能够返回单子的总数量,这个函数是OrdersTotal()函数,还有一个函数可以用于选择订单,这个函数就是OrderSelect()函数。参考一下帮助文件我们发现OrderSelect()函数有三个参数:
第一个参数是订单的标志,这个根据第二参数不同而有变化;
第二个参数是选择订单的模式,SELECT_BY_POS是根据订单的位置编号来选择订单,MT4把订单从上往下依次从零开始编号,如下图,这个模式就是依据这个编号来选择订单,采用这种模式时,第一个参数应该输入订单的位置编号。第二种模式是SELECT_BY_TICKET,这个模式是根据订单号码来选择订单,就如下图的215325180号订单,这个号码就是第一个参数应该输入的数字。
第三个参数是订单的性质,MODE_TRADES是现有的订单,MODE_HISTORY是历史订单,有时我们会根据历史订单来安排仓位,比如说上一单盈利了下一单就不做,这时我们就要参考上一个订单了,这也是MODE_HISTORY的作用。默认的情况下第三个参数是MODE_TRADE,所以如果不涉及历史订单,这个参数我们可以不用填。
另外还有几个函数如OrderTicket(),返回的是订单的订单号,OrderLots()返回的是订单的手数,OrderType()返回的是订单的类型(OP_BUY、OP_SELL、OP_BUYSTOP等等),OrderTakeProfit()返回的是订单的止盈价位,OrderStopLoss()返回的是订单的止损价位,OrderMagicNumber()返回的是订单的魔术号,还有一些Order系列的函数就不说了,大家可以通过帮助文件查看,以上的函数都是需要先选中了一个订单才能使用的,也就是说必须先用OrderSelect()函数,以上几个函数才有用。
有了这几个函数,我们就能通过循环来选择需要平掉的订单了,代码如下:
void OnStart()
{
int i;
string sym= "EURUSD";
int huadian=10;
int check;
for(i=OrdersTotal()-1;i>=0;i--)
{
if(OrderSelect(i,SELECT_BY_POS))
{
if(OrderSymbol()==sym && OrderType()==OP_SELL)
{
check=OrderClose(OrderTicket(),OrderLots(),MarketInfo(sym,
MODE_ASK),huadian);
}
else if(OrderSymbol()==sym && OrderType()==OP_BUY)
{
check=OrderClose(OrderTicket(),OrderLots(),MarketInfo(sym,
MODE_BID),huadian);
}
}
}
}
以上代码将订单的数量赋给了i,之所以要减1是因为MT4的订单是根据位置从上到下来编号的,而第一个订单的编号是0,那么最后一个订单的编号就是订单总数减1了,注意,挂单也算在订单总数里面,所以我们在循环时一定要注意把挂单区别开,否则会把挂单给删掉。然后我们选择位置为i的订单,如果选中了,那么就继续判断,没有选中那就跳过。选中的情况下,如果这个订单的品种是”EURUSD”而且是卖单,那么我们就以买入价平仓,如果这个订单品种是”EURUSD”而且是买单,那么我们就以卖出价平仓。
我们运行一下这个脚本,结果如下:
可以看出我们把两个欧美的订单平掉了。
理解了这一段代码其实可以注意到,我们平仓时是从最后一个订单向前寻找的,那是因为如果需要平掉两个以上的单子,从前向后寻找订单有可能会出问题。现在我们来编写一个从前向后找订单平仓的脚本,代码如下:
void OnStart()
{
int i;
string sym= "EURUSD";
int huadian=10;
int check;
for(i=0;i=<OrdersTotal()-1;i++)
{
if(OrderSelect(i,SELECT_BY_POS))
{
if(OrderSymbol()==sym && OrderType()==OP_SELL)
{
check=OrderClose(OrderTicket(),OrderLots(),MarketInfo(sym,
MODE_ASK),huadian);
}
else if(OrderSymbol()==sym && OrderType()==OP_BUY)
{
check=OrderClose(OrderTicket(),OrderLots(),MarketInfo(sym,
MODE_BID),huadian);
}
}
}
}
我们再试一下程序的效果。如下图所示,现在有三个订单,两个欧美的单子和一个镑美的单子,按MT4的编号那么两张欧美的单子编号分别是0和1,镑美编号是2,现在从上往下循环平掉欧美的订单。当i=0时,程序选中了一个单子,确实是欧美的单子,平掉了,结果很好,然后再往下走,i变成了1,接下来我们要选中的是编号为1的单子看看是不是欧美的单子。就在这个时候我们发现,由于之前我们选中的0号单子被平掉了,原来的1号单子变成了现在的0号单子,而原来的2号单子变成了现在的1号单子,于是我们选择的1号单子就成了镑美的单子,于是一个循环下来,我们发现我们只平掉了一个欧美的单子,另外一个单子没有平掉。
那如果我非想用从上到下寻找订单的方法可不可以?当然可以,你只要在循环的最后加一句i—就行了,原来由于平仓造成的位置错位就被纠正回来了,代码如下:
void OnStart()
{
int i;
string sym= "EURUSD";
int huadian=10;
int check;
for(i=0;i=<OrdersTotal()-1;i++)
{
if(OrderSelect(i,SELECT_BY_POS))
{
if(OrderSymbol()==sym && OrderType()==OP_SELL)
{
check=OrderClose(OrderTicket(),OrderLots(),MarketInfo(sym,
MODE_ASK),huadian);
}
else if(OrderSymbol()==sym && OrderType()==OP_BUY)
{
check=OrderClose(OrderTicket(),OrderLots(),MarketInfo(sym,
MODE_BID),huadian);
}
}
i--;
}
}
以上说了这么多是为了让大家少走弯路,笔者在刚开始学的时候用的就是从上往下寻找订单平仓的方法,过了很久才意识到这个方法是有问题的。
当然有人会问,如果是不同的EA下的单子,怎么筛选出特定EA的单子并平仓?之前已经说过了,EA的单子是可以根据魔术号来识别的,只要在判定条件里加入OrderMagicNumber()的判断就可以实现区分不同EA的订单了。
2修改订单
有了以上选择订单的基础,我们就可以开始后面的修改订单的操作了。修改订单还是比较简单的,只不过把上面的OrderClose()函数换成OrderModify()函数。函数不用记,看字面意思就知道了,Modify是修改的意思,OrderModify就是修改订单的意思了。
同样打开帮助文件查找OrderModify函数,可以看到这个函数需要输入6个参数,下面一一讲解:
第一个参数是订单的号码,就是之前的Ticket;
第二个参数是修改后单子的价位,修改挂单的时候用得上;
第三个参数是修改后单子的止损位置;
第四个参数是修改后单子的止盈位置;
第五个参数是修改后单子的持续时间,一般不用,设置为0即可;
第六个参数是修改后显示的箭头颜色。
下面我们在EURUSD上开一个多单,然后把它的止损修改到市价以下10个点,再把止盈修改到市价以上10个点,代码如下:
void OnStart()
{
int i;
string sym= "EURUSD";
double sl=MarketInfo(sym,MODE_BID)-10*
( MarketInfo(sym,MODE_POINT)*10);
double tp=MarketInfo(sym,MODE_BID)+10*
( MarketInfo(sym,MODE_POINT)*10);
int check;
for(i=OrdersTotal()-1;i>=0;i--)
{
if(OrderSelect(i,SELECT_BY_POS))
{
if(OrderSymbol()==sym && OrderType()==OP_BUY)
{
check= OrderModify (OrderTicket(),OrderOpenPrice(),
sl,tp, 0, clrAliceBlue);
}
}
}
}
以上代码中将止损的价格赋给了sl,将止盈的价格赋给了tp,然后挑选订单,选出欧美的的买单,然后将止损止盈的价格写入单子中。
这是修改已经开仓的订单,如果我们要修改挂单,只需要把OrderModify函数的第二个参数改成需要的挂单价格即可,在这里不作介绍,权且当做大家的课后作业。
下节课我们会介绍一下移动止损和保平止损,之后我们会开始编写一个简单的双均线策略并对其测试,希望之前的基本功大家好好掌握。
更多内容请关注公众号【火象】~
————————————————
版权声明:本文为CSDN博主「ALPHA交易达人」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/m0_62038975/article/details/121081321
|