本章处理2个问题,修改现价单和修改挂单。修改定单的规则参见 Order Characteristics 和 Appendix 3。
函数 OrderModify()
用函数 OrderModify(),提出修改现单或挂单的要求。
bool OrderModify(int ticket, double price, double stoploss, double takeprofit, datetime expiration, color arrow_color=CLR_NONE)
本函数修改现单和挂单的参数。若操作成功,返回TRUE,否则,返回FALSE。
参数:
ticket - 定单的唯一编号
price - 挂单或现单新的报价。
stoploss - 新的止损点位。
takeprofit - 新的止盈点位。
expiration - 挂单交易期限。
arrow_color - 在主图中标示修改了止损/止盈点位的箭头颜色。若无此参数,或其等于CLR_NONE,主图中不显示相关箭头。
注意,只能修改挂单的建仓价和交易期限。
如果用未做修改的参数调用本函数,终端会产生出错信息 1 (ERR_NO_RESULT)。有的交易服务器对设置交易期限有限制,若你设定该值不为0,会产生错误信息 147 (ERR_TRADE_EXPIRATION_DENIED) 。
一、修改现价定单
标准的现价定单包括止损和止盈设置。现单的止损/止盈点位可以修改。唯一的限制是,修改后的点位与市场时价的点差,必须符合相关规定 Order Characteristics 和Requirements and Limitations in Making Trades 。
![]() | 示例。一个简单的“操盘手”,修改止损点位,使得新点位与市场现价的点差,大于原定单(modifystoploss.mq4) |
//------------------------------------------------------------------------------------
// modifystoploss.mq4
// 程序仅用于教学
//------------------------------------------------------------------------------------
extern int Tral_Stop=10; // 跟踪止损的点位
//------------------------------------------------------------------------------- 1 --
int start() // 特别函数 'start'
{
string Symb=Symbol(); // 交易对象
//------------------------------------------------------------------------------- 2 --
for(int i=1; i<=OrdersTotal(); i++) // 查找定单的循环
{
if (OrderSelect(i-1,SELECT_BY_POS)==true) // 有定单
{ // 分析定单
int Tip=OrderType(); // 定单类型
if(OrderSymbol()!=Symb||Tip>1)continue;// 不是要找的定单
double SL=OrderStopLoss(); // 选出的定单的止损点位
//---------------------------------------------------------------------- 3 --
while(true) // 修改过程循环
{
double TS=Tral_Stop; // 初始化
int Min_Dist=MarketInfo(Symb,MODE_STOPLEVEL);// 最小点差
if (TS < Min_Dist) // 若小于允许值
TS=Min_Dist; // 以允许值为准
//------------------------------------------------------------------- 4 --
bool Modify=false; // 不修改
switch(Tip) // 按定单类型分别处理
{
case 0 : // 买单 Buy
if (NormalizeDouble(SL,Digits)< // 若低于交易要求
NormalizeDouble(Bid-TS*Point,Digits))
{
SL=Bid-TS*Point; // 修改
string Text="Buy "; // Buy 的字符串
Modify=true; // 修改
}
break; // 退出 'switch'
case 1 : // 卖单 Sell
if (NormalizeDouble(SL,Digits)> // 若高于交易要求
NormalizeDouble(Ask+TS*Point,Digits)
|| NormalizeDouble(SL,Digits)==0)//或等于0
{
SL=Ask+TS*Point; // 修改
Text="Sell "; // Sell 的字符串
Modify=true; // 修改
}
} // 结束 'switch'
if (Modify==false) // 若未做修改
break; // 退出 'while'
//------------------------------------------------------------------- 5 --
double TP =OrderTakeProfit(); // 选出的定单的止盈点位
double Price =OrderOpenPrice(); // 选出的定单的价格
int Ticket=OrderTicket(); // 选出的定单的编号
Alert ("Modification ",Text,Ticket,". Awaiting response..");
bool Ans=OrderModify(Ticket,Price,SL,TP,0);// 提出修改要求!
//------------------------------------------------------------------- 6 --
if (Ans==true) // 完成修改! :)
{
Alert ("Order ",Text,Ticket," is modified:)");
break; // 退出修改流程
}
//------------------------------------------------------------------- 7 --
int Error=GetLastError(); // 修改失败 :(
switch(Error) // 可克服的错误
{
case 130:Alert("Wrong stops. Retrying.");
RefreshRates(); // 更新数据
continue; // 继续迭代
case 136:Alert("No prices. Waiting for a new tick..");
while(RefreshRates()==false) // 得到新报价
Sleep(1); // 延迟循环
continue; // 继续迭代
case 146:Alert("Trading subsystem is busy. Retrying ");
Sleep(500); // 简单处理
RefreshRates(); // 更新数据
continue; // 继续迭代
// Critical errors
case 2 : Alert("Common error.");
break; // 退出 'switch'
case 5 : Alert("Old version of the client terminal.");
break; // 退出 'switch'
case 64: Alert("Account is blocked.");
break; // 退出 'switch'
case 133:Alert("Trading is prohibited");
break; // 退出 'switch'
default: Alert("Occurred error ",Error);// 其他错误
}
break; // 退出修改操作
} // 结束修改操作
//---------------------------------------------------------------------- 8 --
} // 结束定单分析
} // 结束定单查找
//------------------------------------------------------------------------------- 9 --
return; // 退出 start()
}
//------------------------------------------------------------------------------ 10 --
二、修改挂单
挂单的修改,与现单的修改略有不同。修改挂单,必须遵守规则Order Characteristics 和Requirements and Limitations in Making Trades。
![]() | 示例。以鼠标放置“操盘手”最接近的价位为准,确定要改的定单。 (modifyorderprice.mq4). |
//------------------------------------------------------------------------------------
// modifyorderprice.mq4
// 程序仅用于教学
//------------------------------------------------------------------------------- 1 --
int start() // 特别函数 'start'
{
int Tral=10; // 跟踪点差
string Symb=Symbol(); // 交易对象
double Dist=1000000.0; // 预设
double Win_Price=WindowPriceOnDropped(); // 脚本放置于此
//------------------------------------------------------------------------------- 2 --
for(int i=1; i<=OrdersTotal(); i++) // 反复查找定单
{
if (OrderSelect(i-1,SELECT_BY_POS)==true) // 若有定单
{ // 分析定单:
//---------------------------------------------------------------------- 3 --
if (OrderSymbol()!= Symb) continue; // 交易对象不合要求
if (OrderType()<2) continue; // 现价定单
//---------------------------------------------------------------------- 4 --
if(NormalizeDouble(MathAbs(OrderOpenPrice()-Win_Price),Digits)
< NormalizeDouble(Dist,Digits)) // 找出最相接近的
{
Dist=MathAbs(OrderOpenPrice()-Win_Price);// New value
int Tip =OrderType(); // 选出的定单的类型
int Ticket=OrderTicket(); // 选出的定单的编号
double Price =OrderOpenPrice(); // 选出的定单的价格
double SL =OrderStopLoss(); // 选出的定单的止损点位
double TP =OrderTakeProfit(); // 选出的定单的止盈点位
} // 结束 'if'
} // 结束定单分析
} // 结束查找定单
//------------------------------------------------------------------------------- 5 --
if (Tip==0) // 没有挂单
{
Alert("For ",Symb," no pending orders available");
return; // 退出程序
}
//------------------------------------------------------------------------------- 6 --
while(true) // 平仓过程循环
{
RefreshRates(); // 更新数据
//------------------------------------------------------------------------- 7 --
double TS=Tral; // 初始化
int Min_Dist=MarketInfo(Symb,MODE_STOPLEVEL);// 最小点差
if (TS < Min_Dist) // 若小于允许值
TS=Min_Dist; // 以允许值为准
//------------------------------------------------------------------------- 8 --
string Text=""; // 不做修改
double New_SL=0;
double New_TP=0;
switch(Tip) // 按定单类型,分别处理
{
case 2: // BuyLimit挂单
if (NormalizeDouble(Price,Digits) < // 若超过预设值
NormalizeDouble(Ask-TS*Point,Digits))
{
double New_Price=Ask-TS*Point; // 新价格
if (NormalizeDouble(SL,Digits)>0)
New_SL=New_Price-(Price-SL); // 新止损点位
if (NormalizeDouble(TP,Digits)>0)
New_TP=New_Price+(TP-Price); // 新止盈点位
Text= "BuyLimit "; // 修改
}
break; // 退出 'switch'
case 3: // SellLimit 挂单
if (NormalizeDouble(Price,Digits) > // 若超出预设值
NormalizeDouble(Bid+TS*Point,Digits))
{
New_Price=Bid+TS*Point; // 新价格
if (NormalizeDouble(SL,Digits)>0)
New_SL=New_Price+(SL-Price); // 新止损点位
if (NormalizeDouble(TP,Digits)>0)
New_TP=New_Price-(Price-TP); // 新止盈点位
Text= "SellLimit "; // 修改
}
break; // 退出 'switch'
case 4: // BuyStopt挂单
if (NormalizeDouble(Price,Digits) > // 若超出预设值
NormalizeDouble(Ask+TS*Point,Digits))
{
New_Price=Ask+TS*Point; // 新价格
if (NormalizeDouble(SL,Digits)>0)
New_SL=New_Price-(Price-SL); // 新止损点位
if (NormalizeDouble(TP,Digits)>0)
New_TP=New_Price+(TP-Price); // 新止盈点位
Text= "BuyStopt "; // 修改
}
break; // 退出 'switch'
case 5: // SellStop挂单
if (NormalizeDouble(Price,Digits) < // 若走出预设值
NormalizeDouble(Bid-TS*Point,Digits))
{
New_Price=Bid-TS*Point; // 新价格
if (NormalizeDouble(SL,Digits)>0)
New_SL=New_Price+(SL-Price); // 新止损点位
if (NormalizeDouble(TP,Digits)>0)
New_TP=New_Price-(Price-TP); // 新止盈点位
Text= "SellStop "; // 修改
}
}
if (NormalizeDouble(New_SL,Digits)<0) // 检查止损
New_SL=0;
if (NormalizeDouble(New_TP,Digits)<0) // 检查止盈
New_TP=0;
//------------------------------------------------------------------------- 9 --
if (Text=="") // 若未修改
{
Alert("No conditions for modification.");
break; // 退出 'while'
}
//------------------------------------------------------------------------ 10 --
Alert ("Modification ",Text,Ticket,". Awaiting response..");
bool Ans=OrderModify(Ticket,New_Price,New_SL,New_TP,0);// 修改!
//------------------------------------------------------------------------ 11 --
if (Ans==true) // 完成修改! :)
{
Alert ("Modified order ",Text," ",Ticket," :)");
break; // 退出平仓
}
//------------------------------------------------------------------------ 12 --
int Error=GetLastError(); // 修改失败 :(
switch(Error) // 可克服的错误
{
case 4: Alert("Trade server is busy. Retrying..");
Sleep(3000); // 简单处理
continue; // 继续迭代
case 137:Alert("Broker is busy. Retrying..");
Sleep(3000); // 简单处理
continue; // 继续迭代
case 146:Alert("Trading subsystem is busy. Retrying..");
Sleep(500); // 简单处理
continue; // 继续迭代
}
switch(Error) // 致命错误
{
case 2 : Alert("Common error.");
break; // 退出 'switch'
case 64: Alert("Account is blocked.");
break; // 退出 'switch'
case 133:Alert("Trading is prohibited");
break; // 退出 'switch'
case 139:Alert("Order is blocked and is being processed");
break; // 退出 'switch'
case 145:Alert("Modification prohibited. ",
"Order is too close to the market");
break; // 退出 'switch'
default: Alert("Occurred error ",Error);// 其他错误
}
break; // 退出平仓
} // 结束平仓
//------------------------------------------------------------------------------ 13 --
Alert ("The script has completed its operations -----------------------");
return; // 退出 start()
}
//------------------------------------------------------------------------------ 14 --