本章处理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 --