
已打开头寸的两步修改
简介
“T.DeMark 的技术分析方法”一文中,包含了推荐的修正长度系数,具体为 0.382 和 0.618。在打开头寸时使用这些系数,可以避免邻近趋势时不必要的关闭和重新打开头寸。该功能效果很好,尤其在出现偏离的情况下。
在重新设置获利值的情况下,这种方法帮助检测“有利”趋势的出现。例如,图 1 和图 2 所示。
功能算法
对订单的第一个改动由指定 TrailingStop 值执行,随后的改动设置的 StopLoss 比可能的修正水平低 1 到 2 个点(在这种情况,修正系数=0,382 "Coeff_")。在每个步长上按照,例如,TrailingStop 值的一半(你也可以选择其他值!)增加 TakeProfit 值。TakeProfit 的值也可以更改。为此,在程序开始时应该设置 extern double March = 0; 的零值。
对于喜欢在交易时直接执行特定程序的地址分析支持操作的交易者,最好将 MagicNumber 变量转移到 Expert Advisor 自身打开头寸的代码中。关于具体的地址支持,可以在 MQL4.com 网站上发布的 S. Kovalyov 的书籍 中阅读更多详情。
我们来仔细检查 EA 中预期函数的建议代码和其中的注释:
//+------------------------------------------------------------------+ //| Two-stage variant of TrailingStop Modify_2step v5.mq4 | //| Orders modification: re-placing StopLoss and TakeProfit | //+------------------------------------------------------------------+ #property copyright "Copyright © 2008, GenKov" #property link Genkov@bk.ru //+------------------------------------------------------------------+ /* Magic=N
Magic=N - 此运算符应在建仓时于程序自身(Expert Advisor)中的条件依从控制运算符之后插入,以及在函数中插入。或许鉴于市场的不可预测性,我无法创建一个通用修饰符,所以应该为每种类型的头寸打开条件(按 Magic=N)编写跟踪函数(S/L 和 T/P 的走势)以及头寸关闭条件。
extern double March = 1; // step of increasing TakeProfit // step 0 doesn't increase T/P.
S/L 必须小于 TrailingStop 1 个点,以在第一次触发时使 S/L 处于安全水平。利用这种方式,我们可以确保免于可能的损失(资本管理)。
extern double StopLoss = 15; extern double TrailingStop = 16; extern double TakeProfit = 60; // fitting with the tester //+------------------------------------------------------------------+ //void TrailingStop() int start() { //----------------------------------------------------------------+ int point = MarketInfo(Symbol(),MODE_POINT); // Point size int StopLev= MarketInfo(Symbol(),MODE_STOPLEVEL); double half_Trail = MathRound(TrailingStop/2);//half TrailingStop double Step = March*half_Trail; //value of TakeProfit increase if (TrailingStop<0) return; { for (int i=0; i<OrdersTotal(); i++) { if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break; if (OrderSymbol()!=Symbol() || OrderMagicNumber()!=Magic) continue; if (OrderType()==OP_BUY) {
买入头寸改动的第一步
if(OrderStopLoss()<OrderOpenPrice())//if S/L is less than the order open price { // and if the difference between the current price and the position opening price is greater than T/S if(Bid-OrderOpenPrice()>TrailingStop*Point) // && { // and if OrderStopLoss() is less than the difference between the current price and T/S if(OrderStopLoss()<Bid-TrailingStop*Point) { // calculate new T/P value double Now_T_P=(OrderTakeProfit()+Step*Point); { OrderModify(OrderTicket(),OrderOpenPrice(), OrderStopLoss()+TrailingStop*Point, OrderTakeProfit()+Step*Point,0,Aqua); // increasing T/P value return; } } } }
但是,可能发生以下情形:TakeProfit 偏移高于之前计划的获利水平 2-3 个点,停止并开始慢慢下降。
为避免损失获利,我们输入情形控制的运算符,以在计划的获利水平关闭订单。如果价格持续增长,则 StopLoss 和 TakeProfit 的偏移将继续。
if(Bid-OrderOpenPrice()>=TakeProfit*Point && (Pr_Op_1-Pr_Op_0)>2*Point) { // Print(" Bid= ",Bid," >= ",OrderTakeProfit()," Magic= ",Magic); OrderClose(OrderTicket(),Lots,Bid,2,Red); }
// Second stage of BUY position modification
if(OrderStopLoss()>=OrderOpenPrice()) // StopLoss is on a lossless level { // calculate correction coefficient double Coeff_up = NormalizeDouble((Bid-OrderOpenPrice())*0.382,Digits); // and if the differnece between the current and the open price of the position is greater than corr. coefficient if(Bid-OrderOpenPrice()>Coeff_up) { // calculate the value of new StopLoss with the margin of 2 points double New_S_Loss = Bid-Coeff_up-2*Point; // and if the value of new StopLoss is higer than the current one if(New_S_Loss-OrderStopLoss()>3*Point) { // move S/L and T/P OrderModify(OrderTicket(),OrderOpenPrice(), New_S_Loss,OrderTakeProfit()+Step*Point,0,Yellow); } // Print(" Bid-OrderOpenPrice()= ",Bid-OrderOpenPrice()); // Print(" 2 Coeff_up= ",Coeff_up," Order_S_Los= ",New_S_Loss," Bid= ",Bid); return; } } }
做空头寸的方法跟上面一样,所以注释变少了。
// ---------------------------- 1 stage of modification -----SELL-------------& else if(OrderType()==OP_SELL) { if(OrderStopLoss()>OrderOpenPrice())//if S/L is greater than order open price { if(OrderOpenPrice()-Ask>TrailingStop*Point && OrderStopLoss()>Ask+TrailingStop*Point) { OrderModify(OrderTicket(),OrderOpenPrice(), Ask+TrailingStop*Point,OrderTakeProfit()-Step*Point,0,SkyBlue); return; } } if(OrderOpenPrice()-Ask>=TakeProfit*Point && (Pr_Op_0-Pr_Op_1)>2*Point) { OrderClose(OrderTicket(),Lots,Bid,2,Red); } // ---------------------------- 2 stage of modification -----SELL-------------& if(OrderStopLoss()<=OrderOpenPrice()) // StopLoss is on a lossless level { // calculate correction coefficient double Coeff_down = NormalizeDouble((OrderOpenPrice()-Ask)*0.382,Digits); // and if the difference between the price of position opening and the current price is greater than corr. coefficient if(OrderOpenPrice()-Ask>Coeff_down) { // calculate the value of new StopLoss with the margin of 2 points New_S_Loss = Ask+Coeff_down+2*Point; // and if the value of new StopLoss is less than the current value if(New_S_Loss-OrderStopLoss()>3*Point) { // move S/L and T/P OrderModify(OrderTicket(),OrderOpenPrice(), New_S_Loss,OrderTakeProfit()-Step*Point,0,Khaki); return; } } } } } // -----------------------------------------------------------------------------------
为将该 EA 变为函数,有必要对位于程序开头的特殊 int start() 函数添加注释,并用位于程序开头的 TrailingStop() 函数的未注释描述替换。对函数调用取消注释:
//TrailingStop();
在程序的最后。
如果添加下面的程序块,可以将其用作测试程序中的 EA 来检验函数的有效性。
// -------------------------------------------------------------------------------- double Macd_m15_0= iMACD(NULL,PERIOD_M15,12,26,9,PRICE_CLOSE,MODE_MAIN,0); double Macd_m15_1= iMACD(NULL,PERIOD_M15,12,26,9,PRICE_CLOSE,MODE_MAIN,1); if(OrdersTotal()<2) { if(Macd_m15_0<Macd_m15_1) { OrderSend(Symbol(),OP_SELL,0.1,Bid,3,Ask+StopLoss*Point,Bid-TakeProfit*Point,"",Magic,0,Red); } if(Macd_m15_0>Macd_m15_1) { OrderSend(Symbol(),OP_BUY,0.1,Ask,3,Bid-StopLoss*Point,Ask+TakeProfit*Point,"",Magic,0,Blue); } return(0); } // -------------------------------------------------------------------------------- // TrailingStop(); } return(0); } // --- end --- &
现在从上述的代码文本中移除详细的注释,形成可执行的函数:我们将得到可执行文件,建议将其保存在 Terminal_folder\experts\include 目录下,扩展名为 .mqh 或者在 terminal_folder\libraries 目录下,扩展名为 mq4。
//+------------------------------------------------------------------+ //| Modify_2_Step v5.mq4 | //| Copyright © 2008, GenKov | //| Genkov@bk.ru | //+------------------------------------------------------------------+ #property copyright "Copyright © 2008, GenKov" #property link "Genkov@bk.ru" extern double March = 1; // the step of TakeProfit increase // "0" step doesn't increase T/P. // S/L must be less than TrailingStop by 1 point to bring the S/L // on a safe level in the time of the very first triggering extern double StopLoss = 15; extern double TrailingStop = 16; extern double Lots = 0.1; extern double TakeProfit = 60; // fitting with the tester void TrailingStop() { int Magic=3090; // number of condition that opens position int point = MarketInfo(Symbol(),MODE_POINT); // Point size int StopLev= MarketInfo(Symbol(),MODE_STOPLEVEL); double half_Trail = MathRound(TrailingStop/2);//half TrailingStop double Step = March*half_Trail; //TakeProfit-а increase size if (TrailingStop<0) return; { for (int i=0; i<OrdersTotal(); i++) {//1 +cycle by orders search if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==false) break; if (OrderSymbol()!=Symbol() || OrderMagicNumber()!=Magic) continue; if (OrderType()==OP_BUY) { // --------------------------- 1 stage of modification -----BUY-------------& if(OrderStopLoss()<OrderOpenPrice())//if the S/L is less than the order open price { // and if the difference between the current and the open price is greater than T/S if(Bid-OrderOpenPrice()>TrailingStop*Point) // && { // and if OrderStopLoss() is less than the difference between current price andT/S if(OrderStopLoss()<Bid-TrailingStop*Point) { // calculate new T/P value double Now_T_P=(OrderTakeProfit()+Step*Point); { OrderModify(OrderTicket(),OrderOpenPrice(), OrderStopLoss()+TrailingStop*Point, OrderTakeProfit()+Step*Point,0,Aqua); // increase T/P value return; } } } } if(Bid-OrderOpenPrice()>=TakeProfit*Point) { OrderClose(OrderTicket(),Lots,Bid,2,Red); } //------------------------- 2 stage of modification -----BUY---------------& if(OrderStopLoss()>=OrderOpenPrice()) // StopLoss is on the lossless level { // calculate correction coefficient double Coeff_up = NormalizeDouble((Bid-OrderOpenPrice())*0.382,Digits); // and if the difference between the current and the position price is greater than correction coefficient if(Bid-OrderOpenPrice()>Coeff_up) { // clculate new StopLoss value with the margin of 6 points double New_S_Loss = Bid-Coeff_up-6*Point-StopLev*Point; // if the value of new StopLoss is greater than the current value if((New_S_Loss-OrderStopLoss())<2*Point) { // move S/L and T/P OrderModify(OrderTicket(),OrderOpenPrice(), OrderStopLoss(),OrderTakeProfit()+Step*Point/2,0,Yellow); } else { OrderModify(OrderTicket(),OrderOpenPrice(), New_S_Loss+1*Point,OrderTakeProfit()+Step*Point,0,Yellow); } return; } } } // ---------------------------- 1 stage of modification -----SELL-------------& else if(OrderType()==OP_SELL) { if(OrderStopLoss()>OrderOpenPrice())//if S/L is greater than the order open price { if(OrderOpenPrice()-Ask>TrailingStop*Point && OrderStopLoss()>Ask+TrailingStop*Point) { OrderModify(OrderTicket(),OrderOpenPrice(), Ask+TrailingStop*Point,OrderTakeProfit()-Step*Point,0,SkyBlue); return; } } if(OrderOpenPrice()-Ask>=TakeProfit*Point) { OrderClose(OrderTicket(),Lots,Bid,2,Red); } // ---------------------------- 2 stage of modification -----SELL-------------& if(OrderStopLoss()<=OrderOpenPrice()) // StopLoss is on the lossless level if(OrderOpenPrice()-Ask>=OrderTakeProfit()) OrderClose(OrderTicket(),Lots,Ask,2,Red); { // calculate correction coefficient double Coeff_down = NormalizeDouble((OrderOpenPrice()-Ask)*0.382,Digits); // and if the difference between the position open price and the current price is greater than corr. coefficient if(OrderOpenPrice()-Ask>Coeff_down) { // calculate the value of new StopLoss with the margin of 6 points New_S_Loss = Ask+Coeff_down+6*Point; // and if the value of new StopLoss is less than the current value if((OrderStopLoss()-New_S_Loss-StopLev*Point)>=10*Point) { // move S/L and T/P OrderModify(OrderTicket(),OrderOpenPrice(), New_S_Loss-5*Point,OrderTakeProfit()-Step*Point,0,Khaki); return; } } } } } return(0); } } // ---end----- void TrailingStop()--------------------------------& // this block is only for error controlling in the function code // int start() // { // if(25>26) TrailingStop(); // } // --------------------------------
总结
应该说,跟 Sergey Kravchuk 在 “一种跟踪止损和退出市场的模式”(A Pattern Trailing Stop and Exit the Market) 一文中描述的“典型跟踪止损”相比,这个版本更容易理解,而且它在我的 EA 中(实际是在模拟账户上)效果良好,我认为,它适合激进和稳健跟踪。
随附的版本:
v4 - 按止损关闭;v5 - 按获利的预测关闭;v6 - 考虑了预测和幻数的地址支持。
本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/1529


