持仓单一键平仓脚本
作者:互联网
转载原文:http://www.popoding.club/post/31/
在手动或自动化交易中,一键平仓功能都是比较常用的,特别是在涉及风控管理的时候,能够快速止损,有效控制风险。这个脚本功能实现起来并不难,但在程序化实现的过程中,会有一些不同的应用场景。
遍历持仓订单
在执行平仓指令前,需要先遍历所有持仓单,找到具体的订单后,根据持仓订单订单号来进行平仓功能实现,需要用到的函数是PositionsTotal(),得到持仓订单总数,再用for循环就可以实现遍历功能。
for(int i = 0; i < PositionsTotal(); i++)
{
//循环体
}
获取订单属性
在循环体内,需要根据订单序列获取订单号,用到的函数是PositionGetTicket(),这个函数可以得到订单号,同时也定位到当前订单,之后才能获取到相关订单属性信息。
ulong pos_ticket = PositionGetTicket(i); //订单号
ulong pos_magic = PositionGetInteger(POSITION_MAGIC); //订单幻数
string pos_symbol = PositionGetString(POSITION_SYMBOL); //订单品种
double pos_profit = PositionGetDouble(POSITION_PROFIT); //订单盈利
平仓条件
这里可以获取MT5平台中显示的所有订单属性信息,比较常用的有订单号、幻数、品种、盈利额、类型等。这些属性都会涉及到不同的应用场景,比如平仓某一品种的所有订单,平仓所有盈利单,平仓所有买入单等等,都是在取到了对应的属性后通过条件判断来实现。
在多品种多模式复杂交易系统中,需要根据不同模式类别将订单进行分类,以便进行适配性更强、更复杂的仓位管理,这里就需要用到订单幻数,可以在开仓时,通过指定幻数编码规则来进行实现,比如11010001,“11”代表品种EURUSD,“01”代表模式1,“0001”代表当前品种当前模式下的第1单。这里只是举个例子,编码规则可以根据需要来制定,那么有了这个幻数编号,就可以通过截取指定的内容,来进行更复杂要求的平仓实现,比如平仓所有EURUSD模式1的亏损订单。
平仓功能
MT5的平仓功能是通过反向订单请求来实现的,也就是说如果持仓单是买入单,通过发送一个卖出单指令,指定相同的订单号、品种、交易量等请求信息,就可以实现平仓;卖出单平仓则是发送一个买入单指令。
request.position = pos_ticket; //指定平仓订单号
需要提及的是,有的平台经纪商会有请求模式上的区别,若是模式不正确,将导致请求失败,模式有ORDER_FILLING_FOK、ORDER_FILLING_IOC、ORDER_FILLING_RETURN三种类型,区别是针对部分成交量的处理方式不同,通过SymbolInfoInteger()函数,SYMBOL_FILLING_MODE属性值获取,就可以进行不同方式的适配。
int filling=(int)SymbolInfoInteger(Symbol(),SYMBOL_FILLING_MODE);
if(filling == 1)
{
request.type_filling = ORDER_FILLING_FOK; //全部成交模式
}
else
if(filling == 2)
{
request.type_filling = ORDER_FILLING_IOC; //部分成交模式
}
else
if(filling == 3)
{
request.type_filling == ORDER_FILLING_RETURN; //限价单执行模式
}
实现源码
#property copyright "公众号 Luyuanmw 微信 wentxiong"
#property link "http://www.popoding.club/"
#property version "1.00"
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//---
//遍历持仓单
for(int i = 0; i < PositionsTotal(); i++)
{
//循环体
ulong pos_ticket = PositionGetTicket(i); //订单号
ulong pos_magic = PositionGetInteger(POSITION_MAGIC); //订单幻数
string pos_symbol = PositionGetString(POSITION_SYMBOL); //订单品种
double pos_profit = PositionGetDouble(POSITION_PROFIT); //订单盈利
double pos_volume = PositionGetDouble(POSITION_VOLUME); //交易量
ENUM_POSITION_TYPE pos_type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);//订单类型
//平仓
MqlTradeRequest request = {0};
MqlTradeResult result = {0};
double ask = SymbolInfoDouble(Symbol(),SYMBOL_ASK);
double bid = SymbolInfoDouble(Symbol(),SYMBOL_BID);
//请求结构体
request.action = TRADE_ACTION_DEAL;
request.position = pos_ticket;
request.symbol = pos_symbol;
request.volume = pos_volume;
request.deviation = 50;
request.magic = pos_magic;
//指定订单成交模式
int filling=(int)SymbolInfoInteger(Symbol(),SYMBOL_FILLING_MODE);
if(filling == 1)
{
request.type_filling = ORDER_FILLING_FOK; //全部成交模式
}
else
if(filling == 2)
{
request.type_filling = ORDER_FILLING_IOC; //部分成交模式
}
else
if(filling == 3)
{
request.type_filling = ORDER_FILLING_RETURN; //限价单执行模式
}
//指定幻数、品种条件
if(pos_magic == 0 && pos_symbol == Symbol())
{
if(pos_type == POSITION_TYPE_SELL)
{
request.type = ORDER_TYPE_BUY;
request.price = ask;
}
else
if(pos_type == POSITION_TYPE_BUY)
{
request.type = ORDER_TYPE_SELL;
request.price = bid;
}
//发送请求命令
if(!OrderSend(request,result))
{
printf("Ordersend Error : %d",GetLastError());
}
}
}
}
//+------------------------------------------------------------------+
标签:平仓,request,持仓,pos,订单,filling,FILLING,单一 来源: https://blog.csdn.net/wentxiong/article/details/118058255