//+------------------------------------------------------------------+ //| TriplePlay.mq4 | //| Copyright © 2006 | //| Written by Robert Hill | //| Based on idea posted by Ignace BIENVILLE | //| Uses entry rule from MACD Sample to place triple trades | //+------------------------------------------------------------------+ #property copyright "Copyright © 2006, Robert Hill" #include #include //+---------------------------------------------------+ //|Account functions | //+---------------------------------------------------+ extern bool AccountIsMini = true; // Change to true if trading mini account //+---------------------------------------------------+ //|Money Management | //+---------------------------------------------------+ extern bool MoneyManagement = true; // Change to false to shutdown money management controls. // Lots = 1 will be in effect and only 1 lot will be open regardless of equity. extern string str1 = " TradeSizePersent <= 5"; extern double TradeSizePercent = 5; // Change to whatever percent of equity you wish to risk. extern double Lots = 0.1; // standard lot size. double MaxLots = 100; //+---------------------------------------------------+ //|Profit controls | //+---------------------------------------------------+ extern double StopLoss = 70; // Maximum pips willing to lose per position. extern int FirstLevel = 10; extern int SecondLevel = 20; extern double TakeProfit1 = 30; extern double TakeProfit2 = 20; extern double TakeProfit3 = 10; extern string str2 = " TrailingStopType"; extern string str3 = " 1 - Trail immediately"; extern string str4 = " 2 - Wait til TrailingStop"; extern string str5 = " is reached to trail"; extern bool UseTrailingStop = false; extern int TrailingStopType = 2; extern double TrailingStop = 5; double Margincutoff = 800; // Expert will stop trading if equity level decreases to that level. int Slippage = 10; // Possible fix for not getting filled or closed //+---------------------------------------------------+ //|Indicator Variables | //| Change these to try your own system | //| or add more if you like | //+---------------------------------------------------+ extern double MACDOpenLevel=5; extern double MACDCloseLevel=1; extern double MATrendPeriod=21; extern int SignalCandle = 1; extern bool UseDST = false; extern int StartTime2Normal = 1; // Start trades after time extern int StopTime2Normal = 13; // Stop trading after time bool Debug = false; int StartTime2; // Start trades after time int StopTime2; // Stop trading after time double MacdCurrent, MacdPrevious, SignalCurrent; double SignalPrevious, MaCurrent, MaPrevious; //+---------------------------------------------------+ //|General controls | //+---------------------------------------------------+ string setup; double lotMM; int TradesInThisSymbol; int MagicNumber; bool YesStop; //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { MagicNumber = 4000 + func_Symbol2Val(Symbol())*100 + func_TimeFrame_Const2Val(Period()); setup="TriplePlay" + Symbol() + "_" + func_TimeFrame_Val2String(func_TimeFrame_Const2Val(Period())); //---- return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { return(0); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { //---- /* if (Period() != 60) { Alert("60 Minute Chart Only."); return(0); } */ GetIndicators(); //+------------------------------------------------------------------+ //| Check for Open Position | //+------------------------------------------------------------------+ HandleOpenPositions(); // Check if any open positions were not closed TradesInThisSymbol = CheckOpenPositions(); //+------------------------------------------------------------------+ //| Check if OK to make new trades | //+------------------------------------------------------------------+ if(AccountFreeMargin() < Margincutoff) { return(0);} // Only allow 1 trade per Symbol if(TradesInThisSymbol > 0) { return(0);} // setup times to trade based on Day Light Savings Time if (UseDST) { StartTime2 = StartTime2Normal - 1; if (StartTime2 < 0) StartTime2 = 0; StopTime2 = StopTime2Normal - 1; } else { StartTime2 = StartTime2Normal; StopTime2 = StopTime2Normal; } if (Hour() > StopTime2) return(0); if (Hour() < StartTime2) return(0); lotMM = GetLots(); // if(CheckEntryConditionBUY() && !CheckExitConditionBUY()) if(CheckEntryCondition(OP_BUY) ) { CloseOpenOrders(OP_SELL); OpenBuyOrders(); return(0); } // if(CheckEntryConditionSELL() && !CheckExitConditionSELL()) if(CheckEntryCondition(OP_SELL) ) { CloseOpenOrders(OP_BUY); OpenSellOrders(); } //---- return(0); } void GetIndicators() { MacdCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,SignalCandle); MacdPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_MAIN,SignalCandle + 1); SignalCurrent=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,SignalCandle); SignalPrevious=iMACD(NULL,0,12,26,9,PRICE_CLOSE,MODE_SIGNAL,SignalCandle + 1); MaCurrent=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,SignalCandle); MaPrevious=iMA(NULL,0,MATrendPeriod,0,MODE_EMA,PRICE_CLOSE,SignalCandle + 1); } //+------------------------------------------------------------------+ //| CheckExitCondition | //+------------------------------------------------------------------+ bool CheckExitCondition(int type) { switch (type) { case OP_BUY : if(MacdCurrent>0 && MacdCurrentSignalPrevious && MacdCurrent>(MACDCloseLevel*Point)) { return(true); } break; case OP_SELL : if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious(MACDCloseLevel*Point)) { return(true); } } return (false); } //+------------------------------------------------------------------+ //| CheckEntryCondition | //+------------------------------------------------------------------+ bool CheckEntryCondition(int type) { switch (type) { case OP_BUY : if(MacdCurrent<0 && MacdCurrent>SignalCurrent && MacdPrevious(MACDOpenLevel*Point) && MaCurrent>MaPrevious) { return(true); } break; case OP_SELL : if(MacdCurrent>0 && MacdCurrentSignalPrevious && MacdCurrent>(MACDOpenLevel*Point) && MaCurrent 0 ) myStopLoss = myPrice - StopLoss * Point ; myTakeProfit = myPrice + TakeProfit1 * Point; // Normalize all price / stoploss / takeprofit to the proper # of digits. digits = MarketInfo(Symbol( ), MODE_DIGITS) ; if (digits > 0) { myPrice = NormalizeDouble( myPrice, digits); myStopLoss = NormalizeDouble( myStopLoss, digits); myTakeProfit = NormalizeDouble( myTakeProfit, digits); } ticket=OrderSend( Symbol(), OP_BUY, lotMM, myPrice, Slippage, myStopLoss, myTakeProfit, "FirstBuy", MagicNumber, 0, Green); if (ticket > 0) { if (OrderSelect( ticket,SELECT_BY_TICKET, MODE_TRADES) ) { if (Debug) Print("BUY order opened : ", OrderOpenPrice( )); myPrice = OrderOpenPrice() + FirstLevel*Point; myStopLoss = 0; if ( StopLoss > 0 ) myStopLoss = myPrice - StopLoss * Point ; myTakeProfit = myPrice + TakeProfit2*Point; if (digits > 0) { myPrice = NormalizeDouble( myPrice, digits); myStopLoss = NormalizeDouble( myStopLoss, digits); myTakeProfit = NormalizeDouble( myTakeProfit, digits); } ticket=OrderSend( Symbol(), OP_BUYSTOP, 2*lotMM, myPrice, Slippage, myStopLoss, myTakeProfit, "Second Buy", MagicNumber, 0, Green); myPrice = OrderOpenPrice() + SecondLevel*Point; myStopLoss = 0; if ( StopLoss > 0 ) myStopLoss = myPrice - StopLoss * Point ; myTakeProfit = myPrice + TakeProfit3*Point; if (digits > 0) { myPrice = NormalizeDouble( myPrice, digits); myStopLoss = NormalizeDouble( myStopLoss, digits); myTakeProfit = NormalizeDouble( myTakeProfit, digits); } ticket=OrderSend( Symbol(), OP_BUYSTOP, 3*lotMM, myPrice, Slippage, myStopLoss, myTakeProfit, "Third Buy", MagicNumber, 0 ,Green); } } else { err = GetLastError(); Print("Error opening BUY order : (" + err + ") " + ErrorDescription( err) ); } } //+------------------------------------------------------------------+ //| OpenSellOrder | //| If Stop Loss or TakeProfit are used the values are calculated | //| for each trade | //| - 1 st order , 1 lot TARGET 30 pips //| - 2 nd order , 2 lot placed first order price +10 pips TARGET 20 pips //| - 3 nd order , 3 lot placed first order price +20 pips TARGET 10 pips //+------------------------------------------------------------------+ void OpenSellOrders( ) { int ticket, digits, err; double myPrice, myStopLoss, myTakeProfit; myPrice = MarketInfo(Symbol( ), MODE_BID); myStopLoss = 0; if ( StopLoss > 0 ) myStopLoss = myPrice + StopLoss * Point ; myTakeProfit = myPrice - TakeProfit1 * Point; // Normalize all price / stoploss / takeprofit to the proper # of digits. digits = MarketInfo(Symbol( ), MODE_DIGITS) ; if (digits > 0) { myPrice = NormalizeDouble( myPrice, digits); myStopLoss = NormalizeDouble( myStopLoss, digits); myTakeProfit = NormalizeDouble( myTakeProfit, digits); } ticket=OrderSend( Symbol(), OP_SELL, lotMM, myPrice, Slippage, myStopLoss ,myTakeProfit, "First Sell", MagicNumber, 0, Red); if (ticket > 0) { if (OrderSelect( ticket,SELECT_BY_TICKET, MODE_TRADES) ) { if (Debug) Print("Sell order opened : ", OrderOpenPrice()); myPrice = OrderOpenPrice() - FirstLevel*Point; myStopLoss = 0; if ( StopLoss > 0 ) myStopLoss = myPrice + StopLoss * Point ; myTakeProfit = myPrice - TakeProfit2*Point; if (digits > 0) { myPrice = NormalizeDouble( myPrice, digits); myStopLoss = NormalizeDouble( myStopLoss, digits); myTakeProfit = NormalizeDouble( myTakeProfit, digits); } ticket=OrderSend( Symbol(), OP_SELLSTOP, 2*lotMM, myPrice, Slippage, myStopLoss, myTakeProfit, "Second Sell", MagicNumber, 0, Red); myPrice = OrderOpenPrice() - SecondLevel*Point; myStopLoss = 0; if ( StopLoss > 0 ) myStopLoss = myPrice + StopLoss * Point ; myTakeProfit = myPrice - TakeProfit3*Point; if (digits > 0) { myPrice = NormalizeDouble( myPrice, digits); myStopLoss = NormalizeDouble( myStopLoss, digits); myTakeProfit = NormalizeDouble( myTakeProfit, digits); } ticket=OrderSend( Symbol(), OP_SELLSTOP, 3*lotMM, myPrice, Slippage, myStopLoss, myTakeProfit, "Third Sell", MagicNumber, 0, Red); } } else { err = GetLastError(); Print("Error opening Sell order : (" + err + ") " + ErrorDescription( err) ); } } //+------------------------------------------------------------------+ //| Check Open Position Controls | //+------------------------------------------------------------------+ int CheckOpenPositions() { int cnt, total, NumPositions; NumPositions = 0; total=OrdersTotal(); for(cnt=OrdersTotal()-1;cnt>=0;cnt--) { OrderSelect (cnt, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol() != Symbol()) continue; if ( OrderMagicNumber() != MagicNumber) continue; if(OrderType() == OP_BUY ) NumPositions++; if(OrderType() == OP_SELL ) NumPositions++; } return (NumPositions); } //+------------------------------------------------------------------+ //| Close Open Position Controls | //| Try to close position 3 times | //+------------------------------------------------------------------+ int CloseOrder(int ticket,double numLots,int type) { int CloseCnt, err; double close_price; // try to close 3 Times CloseCnt = 0; while (CloseCnt < 3) { switch (type) { case OP_BUY : close_price = MarketInfo(Symbol(),MODE_BID); break; case OP_SELL : close_price = MarketInfo(Symbol(),MODE_ASK); } if (!OrderClose(ticket,numLots,close_price,Slippage,Violet)) { err=GetLastError(); Print(CloseCnt," Error closing order : (", err , ") " + ErrorDescription(err)); if (err > 0) CloseCnt++; } else { CloseCnt = 3; } } } int ModifyStopLoss(int ticket, double stoploss) { int Cnt, digits, err; string symbol; double myStopLoss; OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES); symbol = OrderSymbol(); digits = MarketInfo(symbol,MODE_DIGITS); if (digits > 0) { myStopLoss = NormalizeDouble(stoploss,digits); } Cnt=0; while (Cnt < 3) { if (OrderModify(ticket,OrderOpenPrice(),myStopLoss,OrderTakeProfit(),0,Aqua)) { Cnt = 3; } else { err=GetLastError(); Print(Cnt," Error modifying order : (", err , ") " + ErrorDescription(err)); if (err>0) Cnt++; } } } //+------------------------------------------------------------------+ //| Handle Open Positions | //| Check if any open positions need to be closed or modified | //+------------------------------------------------------------------+ int HandleOpenPositions() { int cnt; bool YesClose; double pt; for(cnt=OrdersTotal()-1;cnt>=0;cnt--) { OrderSelect (cnt, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol() != Symbol()) continue; if ( OrderMagicNumber() != MagicNumber) continue; if(OrderType() == OP_BUY) { if (CheckExitCondition(OP_BUY)) { CloseOrder(OrderTicket(),OrderLots(),OP_BUY); DeletePendingOrders(); return(0); } if (UseTrailingStop) // Handle mods to trailing stop HandleTrailingStop(OrderType(), OrderTicket(), OrderOpenPrice(), OrderStopLoss()); } if(OrderType() == OP_SELL) { if (CheckExitCondition(OP_SELL)) { CloseOrder(OrderTicket(),OrderLots(),OP_SELL); DeletePendingOrders(); return(0); } if (UseTrailingStop) // Handle mods to trailing stop HandleTrailingStop(OrderType(), OrderTicket(), OrderOpenPrice(), OrderStopLoss()); } } return(0); } //============================================================================= // // HandleTrailingStop() // // Type 1 moves the stoploss without delay. // // Type 2 waits for price to move the amount of the trailStop // before moving stop loss then moves like type 1 // // // PARAMETERS: // // type: OP_BUY or OP_SELL // ticket: the ticket number // open_price: the order's open price // cur_sl: the order's current StopLoss value // // RETURN VALUE: // zero for now // // Calling example // HandleTrailingStop(OP_BUY,OrderTicket(),OrderOpenPrice(),OrderStopLoss()); // //============================================================================= int HandleTrailingStop(int type, int ticket, double open_price, double cur_sl) { double pt, TS = 0, myAsk, myBid; if (type == OP_BUY) { myBid = MarketInfo(Symbol(),MODE_BID); switch (TrailingStopType) { case 1: pt = Point * StopLoss; if (myBid - cur_sl > pt) ModifyStopLoss(ticket, myBid - pt); break; case 2: pt = Point * TrailingStop; if (myBid - open_price > pt && (cur_sl < myBid - pt || cur_sl == 0)) ModifyStopLoss(ticket, myBid - pt); break; } return(0); } else if (type == OP_SELL) { myAsk = MarketInfo(Symbol(),MODE_ASK); switch (TrailingStopType) { case 1: pt = Point * StopLoss; if (cur_sl - myAsk > pt) ModifyStopLoss(ticket, myAsk+pt); break; case 2: pt = Point * TrailingStop; if (open_price - myAsk > pt && (cur_sl > myAsk + pt || cur_sl == 0)) ModifyStopLoss(ticket, myAsk+pt); break; } } return(0); } //+------------------------------------------------------------------+ //| Close Open Orders | //| Check if any open positions need to be closed or modified | //+------------------------------------------------------------------+ int CloseOpenOrders(int cmd) { int cnt; bool YesClose; double pt; for(cnt=OrdersTotal()-1;cnt>=0;cnt--) { OrderSelect (cnt, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol() != Symbol()) continue; if ( OrderMagicNumber() != MagicNumber) continue; if(OrderType() == OP_BUY) { if (cmd == OP_BUY) { CloseOrder(OrderTicket(),OrderLots(),Bid); DeletePendingOrders(); } } if(OrderType() == OP_SELL) { if (cmd == OP_SELL) { CloseOrder(OrderTicket(),OrderLots(),Ask); DeletePendingOrders(); } } } } //+------------------------------------------------------------------+ int DeletePendingOrders() { int i, ticket; //Check Orders for (i=OrdersTotal()-1;i>0;i--){ OrderSelect(i,SELECT_BY_POS,MODE_TRADES); if(OrderSymbol()!=Symbol()) continue; if (OrderMagicNumber() != MagicNumber) continue; if( OrderType()==OP_BUYSTOP) OrderDelete(OrderTicket()); if( OrderType()==OP_SELLSTOP) OrderDelete(OrderTicket()); } } //+------------------------------------------------------------------+ //| Get number of lots for this trade | //+------------------------------------------------------------------+ double GetLots() { double lot; if(MoneyManagement) { lot = LotsOptimized(); } else { lot = Lots; } if(AccountIsMini) { if (lot < 0.1) lot = 0.1; } else { if (lot >= 1.0) lot = MathFloor(lot); else lot = 1.0; } if (lot > MaxLots) lot = MaxLots; return(lot); } //+------------------------------------------------------------------+ //| Calculate optimal lot size | //+------------------------------------------------------------------+ double LotsOptimized() { double lot=Lots; int TradePercent; TradePercent = TradeSizePercent; if (TradeSizePercent > 5) TradePercent = 5; //---- select lot size lot=NormalizeDouble(MathFloor(AccountFreeMargin()*TradePercent/10000)/10,1); // lot at this point is number of standard lots // if (Debug) Print ("Lots in LotsOptimized : ",lot); // Check if mini or standard Account if(AccountIsMini) { lot = MathFloor(lot*10)/10; } return(lot); } //+------------------------------------------------------------------+ //| Time frame interval appropriation function | //+------------------------------------------------------------------+ int func_TimeFrame_Const2Val(int Constant ) { switch(Constant) { case 1: // M1 return(1); case 5: // M5 return(2); case 15: return(3); case 30: return(4); case 60: return(5); case 240: return(6); case 1440: return(7); case 10080: return(8); case 43200: return(9); } } //+------------------------------------------------------------------+ //| Time frame string appropriation function | //+------------------------------------------------------------------+ string func_TimeFrame_Val2String(int Value ) { switch(Value) { case 1: // M1 return("PERIOD_M1"); case 2: // M1 return("PERIOD_M5"); case 3: return("PERIOD_M15"); case 4: return("PERIOD_M30"); case 5: return("PERIOD_H1"); case 6: return("PERIOD_H4"); case 7: return("PERIOD_D1"); case 8: return("PERIOD_W1"); case 9: return("PERIOD_MN1"); default: return("undefined " + Value); } } int func_Symbol2Val(string symbol) { if(symbol=="AUDCAD") { return(1); } else if(symbol=="AUDJPY") { return(2); } else if(symbol=="AUDNZD") { return(3); } else if(symbol=="AUDUSD") { return(4); } else if(symbol=="CHFJPY") { return(5); } else if(symbol=="EURAUD") { return(6); } else if(symbol=="EURCAD") { return(7); } else if(symbol=="EURCHF") { return(8); } else if(symbol=="EURGBP") { return(9); } else if(symbol=="EURJPY") { return(10); } else if(symbol=="EURUSD") { return(11); } else if(symbol=="GBPCHF") { return(12); } else if(symbol=="GBPJPY") { return(13); } else if(symbol=="GBPUSD") { return(14); } else if(symbol=="NZDUSD") { return(15); } else if(symbol=="USDCAD") { return(16); } else if(symbol=="USDCHF") { return(17); } else if(symbol=="USDJPY") { return(18); } else { Comment("unexpected Symbol"); return(0); } }