//+------------------------------------------------------------------+ //| MTP.mq4 | //| Copyright © 2006, Taylor Stockwell | //| Version: 1.8 | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006, Taylor Stockwell" #property link "stockwet@yahoo.com" /* Updates: 11/2/2006:: Fixed bug that caused the sl var to be set to 1 when a pending order was > than the First_Stop_Target value. 1/23/2007:: Fixed pip calculation. The old way of calculating pips could be off by 1 pip, resulting in missed TP or move stops. The new calculation is more accurate. 5/31/2007:: Lousan: Added a Third Stop Loss. Renamed EA to MTP to differentiate it from Stockwell's version. 6/01/2007:: Lousan: Added a pip by pip trailing stop loss to kick in after the last fixed Stop Loss is in place. 7/27/2007:: Lousan: Ver 1.2 Added Version # and Revision date and Pre-Set Name to display. 8/09/2007:: Lousan: Ver 1.3 Trailing stop was not being moved when fixed stops were zero. 8/14/2007:: Lousan: Cosmetic change to Legend 8/17/2007:: Lousan: Ver 1.31 Added email and sound alerts 8/24/2007:: Lousan: Ver 1.4 Revised to make the Trailing Stop an imaginary stop, ie. don't send a Move Stop request to the server, but keep track of the stop within MTP, like it does with Max Loss. 8/27/2007:: Lousan: Ver 1.5 If fixed Stop 2 or 3 was zero, then previous current stop would be set to zero. Fixed that. 9/03/2007:: Lousan: Ver 1.51 Revised to set Max_Loss to 999 if input value is zero. Also added display for open and close (last) spreads and for Max Pips (high water mark). 9/21/2007:: Lousan: Ver. 1.6 Added option to choose of closing lots. Method 1 closes one position at each TP point. Method 2 increases number of lots to close at each TP point by adding the original Lots to Close to the current number. 9/26/2007:: Lousan: Ver. 1.7 Increased the number of TP targets from 1 to 3. Removed the Move_Stops and Use_Max_Loss input parameters. 3/19/2008:: SwingMan: Ver. 1.8 In the Comment() row with: ""\nOrder Open: ",dOrderOpenPrice," the use of OrderOpenPrice() was false. 10/23/2010:: Markdshark: Ver1.81 Added a couple of tradeState flags and a state transition check based on OrdersTotal(). Now deinit is called when the EA detects transition from tradeOn to tradeOff */ //=============== VARS external extern string PreSet_Name = "Default"; extern int First_TP = 100; extern int Second_TP = 200; extern int Third_TP = 300; extern int TP_Increment =100; extern double Close_Lots = 0.1; extern int Close_Method = 1; extern int First_Stop_Target = 50; extern int First_Stop = 25; extern int Second_Stop_Target = 100; extern int Second_Stop = 50; extern int Third_Stop_Target = 200; extern int Third_Stop = 100; extern int Trail_Stop_By = 100; extern int Max_Loss = 300; extern bool Alert_Sound = true; extern bool Alert_Email = false; extern int Magic_Number=0; //=============== VARS internal int nextTP; int sl; int range = 5; int multiplier; int Trail_Stop; int Trail_Trigger; int Open_Spread=0; int Close_Spread=0; int Max_Pips=-99; int temp; double Lots2Close; string trailon; string version="MTP 1.8 Mar. 19, 2008 "; double dOrderOpenPrice; bool tradeFlag=false; bool prevTradeFlag=false; // OrderType == 1 is OP_SELL //=============== FUNCTION init int init() { if(First_Stop==0 && First_Stop_Target !=0) First_Stop=1; if(Max_Loss < 0) Max_Loss=(-1*Max_Loss); if(Max_Loss==0) Max_Loss=999; if(Trail_Stop_By < 0) Trail_Stop_By = -1*Trail_Stop_By; sl = -1*Max_Loss; if(First_TP!=0) nextTP = First_TP; else nextTP = TP_Increment; Trail_Stop = sl; trailon = "Off "; getMaxLoss(); // ???? Why is getMaxLoss function necessary? ~Lousan if(Third_Stop!=0) Trail_Trigger=Third_Stop+Trail_Stop_By; else if(Second_Stop!=0) Trail_Trigger=Second_Stop+Trail_Stop_By; else if(First_Stop!=0) Trail_Trigger=First_Stop+Trail_Stop_By; else Trail_Trigger=sl+Trail_Stop_By; Lots2Close = Close_Lots; Comment(version, "\nPreSet . . . ", PreSet_Name, "\nClose Method: ", Close_Method, "\nClose Lots: ", Close_Lots, "\nTP: ", First_TP, " ", Second_TP, " ", Third_TP, " +", TP_Increment, "\nSL1: ", First_Stop_Target, " ", First_Stop, "\nSL2: ", Second_Stop_Target, " ", Second_Stop, "\nSL3: ", Third_Stop_Target, " ", Third_Stop, "\nTSL: ", Trail_Stop_By, "\nMax Loss: ", Max_Loss); } //== end function //=============== FUNCTION deinit int deinit() { //---- sl = -1*Max_Loss; nextTP = First_TP; Trail_Stop = sl; Comment(""); //---- return(0); } //== end function //========== FUNCTION Start int start() { //---- getOpenOrders(); getSpread(); //Comment(sl); //---- return(0); } //== end function //========== FUNCTION getPipValue double getPipValue(double ord,int dir) { double val; RefreshRates(); if(dir == 1) val=(NormalizeDouble(ord,Digits) - NormalizeDouble(Ask,Digits)); else val=(NormalizeDouble(Bid,Digits) - NormalizeDouble(ord,Digits)); val = val/Point; return(val); } //== end function int getSpread() { int spread=MarketInfo(Symbol(),MODE_SPREAD); if(Open_Spread==0) Open_Spread=spread; Close_Spread=spread; return(spread); } int getMaxLoss() { int calcMaxLoss; calcMaxLoss = Max_Loss; return(calcMaxLoss); } //========== FUNCTION getOpenOrders void getOpenOrders() { int nsl, nsd; string mngMagic; int totalorders = OrdersTotal(); if (totalorders > 0 ) tradeFlag=true; else tradeFlag=false; if (tradeFlag != prevTradeFlag){ if(prevTradeFlag==true) deinit(); prevTradeFlag=tradeFlag; } for(int j=0; j nextTP) takeProfit(val,OrderTicket()); } if(Magic_Number == 0) mngMagic = "All "+Symbol()+" trades."; else mngMagic = "Trades with magic number = "+Magic_Number; if(sl==-1*Max_Loss) { nsl = First_Stop_Target; nsd = First_Stop; } else if(sl==First_Stop) { nsl = Second_Stop_Target; nsd = Second_Stop; } else if(sl==Second_Stop) { nsl = Third_Stop_Target; nsd = Third_Stop; } else if(Trail_Stop_By != 0 && val >= Trail_Trigger) { nsl = val + 1; nsd = val + 1 - Trail_Stop_By; trailon = " On"; } //RefreshRates(); Comment(version, "\nPreSet . . . ", PreSet_Name, "\nClose Method: ", Close_Method, "\nClose Lots: ", Close_Lots, "\nTP: ", First_TP, " ", Second_TP, " ", Third_TP, " +", TP_Increment, "\nSL1: ", First_Stop_Target, " ", First_Stop, "\nSL2: ", Second_Stop_Target, " ", Second_Stop, "\nSL3: ", Third_Stop_Target, " ", Third_Stop, "\nTSL: ", Trail_Stop_By, "\nMax Loss: ", Max_Loss, "\n----------------------------", "\nOrder Open: ",dOrderOpenPrice, "\nOpen Spread: ",Open_Spread, "\nClose Spread: ",Close_Spread, "\nMax Pips: ",Max_Pips, "\nPip Count: ", val, "\nNext TP: ", nextTP, " ", Lots2Close, " Lots", "\nCurr SL: ", sl, "\nTSL Trigger: ", Trail_Trigger, " ", trailon, "\nManaging: ", mngMagic); } } //========== FUNCTION takeProfit void takeProfit(int pips, int ticket) { if(OrderSelect(ticket, SELECT_BY_TICKET)==true) { if(pips >= nextTP) { if(Alert_Sound) PlaySound("mtp2.wav"); if(OrderType()==1) // 1 = OP_Sell { if(OrderClose(ticket, Lots2Close, Ask, 3, Lime)) temp=0; else Print("Error closing order : ",GetLastError()); } else { if(OrderClose(ticket, Lots2Close, Bid, 3, Lime)) temp=0; else Print("Error closing order : ",GetLastError()); } if(Close_Method==2) Lots2Close = Lots2Close + Close_Lots; if(nextTP == Third_TP) nextTP = nextTP + TP_Increment; else if (nextTP == Second_TP) nextTP = Third_TP; else if (nextTP == First_TP) nextTP = Second_TP; else nextTP = nextTP + TP_Increment; } } } //== end function //========== FUNCTION moveStops void checkStops(int pips,int ticket) { if(sl==-1*Max_Loss && First_Stop != 0 && pips >= First_Stop_Target) { moveStops(ticket, First_Stop); } else if(sl==First_Stop && First_Stop != 0 && pips >= Second_Stop_Target && Second_Stop !=0) { moveStops(ticket,Second_Stop); } else if(sl==Second_Stop && Second_Stop != 0 && pips >= Third_Stop_Target && Third_Stop !=0) { moveStops(ticket,Third_Stop); } else if(Trail_Stop_By != 0 && pips >= Trail_Trigger && pips - Trail_Stop_By > sl) { Trail_Stop = pips - Trail_Stop_By; sl = Trail_Stop; trailon = " ON"; } if(pips <= sl) stopTrade(pips,OrderTicket()); if(pips > Max_Pips) Max_Pips = pips; } //== end function //========== FUNCTION moveStops void moveStops(int ticket,int stopDiff) { if(OrderSelect(ticket, SELECT_BY_TICKET)==true) { Print("moveStops called ",ticket, " ",stopDiff); if(OrderType()==1) // 1 = OP_Sell { OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice()-stopDiff*Point, OrderTakeProfit(),0,Plum); sl=stopDiff; } else { OrderModify(ticket,OrderOpenPrice(),OrderOpenPrice()+stopDiff*Point, OrderTakeProfit(),0,Plum); sl=stopDiff; } } } //== end function //========== FUNCTION killTrades void stopTrade(int pips, int ticket) { if(OrderSelect(ticket, SELECT_BY_TICKET)==true) { if(OrderType()==1) OrderClose(ticket,OrderLots(),Ask,3,DarkViolet); else OrderClose(ticket,OrderLots(),Bid,3,DarkViolet); if(Alert_Email) SendMail("MTP: Trade Stopped "+pips," "); if(Alert_Sound) if(pips > 0) PlaySound("mtp3.wav"); else PlaySound("mtp1.wav"); } } //== end function