//+------------------------------------------------------------------+ //| Strategy: LordFX13.mq4 | //| //+------------------------------------------------------------------+ #property copyright "LordFX13" #property link "" #property version "1.00" #property description "" #include #include extern double Risk_per_trade = 1; extern double SL_Points = 30; extern double TP_Points = 30; extern double TrailStart_Points = 20; extern double TrailStep_Points = 10; extern double Breakeven_Points = 0; extern double ATR_Mini = 0.8; extern double Points_AboveBelow_PendingOrder = 30; extern int PendingOrderExpirationSeconds = 50; int LotDigits; extern int TOD_From_Hour = 15; extern int TOD_From_Min = 00; extern int TOD_To_Hour = 20; extern int TOD_To_Min = 00; double MM_Percent = 0.01; extern int MagicNumber = 333; extern double MaxSpread = 35; extern int MaxSlippage = 3; bool TradeMonday = true; bool TradeTuesday = true; bool TradeWednesday = true; bool TradeThursday = true; bool TradeFriday = true; bool TradeSaturday = false; bool TradeSunday = false; bool Push_Notifications = FALSE; int MaxOpenTrades = 1; int MaxLongTrades = 1000; int MaxShortTrades = 1000; int MaxPendingOrders = 2; int MaxLongPendingOrders = 1; int MaxShortPendingOrders = 1; bool Hedging = true; int OrderRetry = 5; int OrderWait = 5; double myPoint; bool inTimeInterval(datetime t, int From_Hour, int From_Min, int To_Hour, int To_Min) { string TOD = TimeToString(t, TIME_MINUTES); string TOD_From = StringFormat("%02d", From_Hour)+":"+StringFormat("%02d", From_Min); string TOD_To = StringFormat("%02d", To_Hour)+":"+StringFormat("%02d", To_Min); return((StringCompare(TOD, TOD_From) >= 0 && StringCompare(TOD, TOD_To) <= 0) || (StringCompare(TOD_From, TOD_To) > 0 && ((StringCompare(TOD, TOD_From) >= 0 && StringCompare(TOD, "23:59") <= 0) || (StringCompare(TOD, "00:00") >= 0 && StringCompare(TOD, TOD_To) <= 0)))); } void DeleteByDuration(int sec) { if(!IsTradeAllowed()) return; bool success = false; int err = 0; int total = OrdersTotal(); ulong orderList[][2]; int orderCount = 0; int i; for(i = 0; i < total; i++) { while(IsTradeContextBusy()) Sleep(100); if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue; if(OrderMagicNumber() != MagicNumber || OrderSymbol() != Symbol() || OrderType() <= 1 || OrderOpenTime() + sec > TimeCurrent()) continue; orderCount++; ArrayResize(orderList, orderCount); orderList[orderCount - 1][0] = OrderOpenTime(); orderList[orderCount - 1][1] = OrderTicket(); } if(orderCount > 0) ArraySort(orderList, WHOLE_ARRAY, 0, MODE_ASCEND); for(i = 0; i < orderCount; i++) { if(!OrderSelect(orderList[i][1], SELECT_BY_TICKET, MODE_TRADES)) continue; while(IsTradeContextBusy()) Sleep(100); RefreshRates(); success = OrderDelete(OrderTicket()); if(!success) { err = GetLastError(); myAlert("error", "OrderDelete failed; error #"+IntegerToString(err)+" "+ErrorDescription(err)); } } if(success) myAlert("order", "Orders deleted by duration: "+Symbol()+" Magic #"+IntegerToString(MagicNumber)); } double MM_Size(double SL) { double MaxLot = MarketInfo(Symbol(), MODE_MAXLOT); double MinLot = MarketInfo(Symbol(), MODE_MINLOT); double tickvalue = MarketInfo(Symbol(), MODE_TICKVALUE); double ticksize = MarketInfo(Symbol(), MODE_TICKSIZE); double lots = MM_Percent * 1.0 / 100 * AccountBalance() / (SL / ticksize * tickvalue); if(lots > MaxLot) lots = MaxLot; if(lots < MinLot) lots = MinLot; return(lots); } double MM_Size_BO() { double MaxLot = MarketInfo(Symbol(), MODE_MAXLOT); double MinLot = MarketInfo(Symbol(), MODE_MINLOT); double tickvalue = MarketInfo(Symbol(), MODE_TICKVALUE); double ticksize = MarketInfo(Symbol(), MODE_TICKSIZE); return(MM_Percent * 1.0 / 100 * AccountBalance()); } bool TradeDayOfWeek() { int day = DayOfWeek(); return((TradeMonday && day == 1) || (TradeTuesday && day == 2) || (TradeWednesday && day == 3) || (TradeThursday && day == 4) || (TradeFriday && day == 5) || (TradeSaturday && day == 6) || (TradeSunday && day == 0)); } void myAlert(string type, string message) { if(type == "print") Print(message); else if(type == "error") { Print(type+" | LordFX13 @ "+Symbol()+","+IntegerToString(Period())+" | "+message); if(Push_Notifications) SendNotification(type+" | LordFX13 @ "+Symbol()+","+IntegerToString(Period())+" | "+message); } else if(type == "order") { Print(type+" | LordFX13 @ "+Symbol()+","+IntegerToString(Period())+" | "+message); if(Push_Notifications) SendNotification(type+" | LordFX13 @ "+Symbol()+","+IntegerToString(Period())+" | "+message); } else if(type == "modify") { Print(type+" | LordFX13 @ "+Symbol()+","+IntegerToString(Period())+" | "+message); if(Push_Notifications) SendNotification(type+" | LordFX13 @ "+Symbol()+","+IntegerToString(Period())+" | "+message); } } int TradesCount(int type) { int result = 0; int total = OrdersTotal(); for(int i = 0; i < total; i++) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) continue; if(OrderMagicNumber() != MagicNumber || OrderSymbol() != Symbol() || OrderType() != type) continue; result++; } return(result); } int myOrderSend(int type, double price, double volume, string ordername) { if(!IsTradeAllowed()) return(-1); int ticket = -1; int retries = 0; int err = 0; int long_trades = TradesCount(OP_BUY); int short_trades = TradesCount(OP_SELL); int long_pending = TradesCount(OP_BUYLIMIT) + TradesCount(OP_BUYSTOP); int short_pending = TradesCount(OP_SELLLIMIT) + TradesCount(OP_SELLSTOP); string ordername_ = ordername; if(ordername != "") ordername_ = "("+ordername+")"; if(!Hedging && ((type % 2 == 0 && short_trades + short_pending > 0) || (type % 2 == 1 && long_trades + long_pending > 0))) { myAlert("print", "Order"+ordername_+" not sent, hedging not allowed"); return(-1); } if((type % 2 == 0 && long_trades >= MaxLongTrades) || (type % 2 == 1 && short_trades >= MaxShortTrades) || (long_trades + short_trades >= MaxOpenTrades) || (type > 1 && type % 2 == 0 && long_pending >= MaxLongPendingOrders) || (type > 1 && type % 2 == 1 && short_pending >= MaxShortPendingOrders) || (type > 1 && long_pending + short_pending >= MaxPendingOrders) ) { myAlert("print", "Order"+ordername_+" not sent, maximum reached"); return(-1); } while(IsTradeContextBusy()) Sleep(100); RefreshRates(); if(type == OP_BUY) price = Ask; else if(type == OP_SELL) price = Bid; else if(price < 0) { myAlert("order", "Order"+ordername_+" not sent, invalid price for pending order"); return(-1); } int clr = (type % 2 == 1) ? clrRed : clrBlue; if(MaxSpread > 0 && Ask - Bid > MaxSpread * myPoint) { myAlert("order", "Order"+ordername_+" not sent, maximum spread "+DoubleToStr(MaxSpread * myPoint, Digits())+" exceeded"); return(-1); } while(ticket < 0 && retries < OrderRetry+1) { ticket = OrderSend(Symbol(), type, NormalizeDouble(volume, LotDigits), NormalizeDouble(price, Digits()), MaxSlippage, 0, 0, ordername, MagicNumber, 0, clr); if(ticket < 0) { err = GetLastError(); myAlert("print", "OrderSend"+ordername_+" error #"+IntegerToString(err)+" "+ErrorDescription(err)); Sleep(OrderWait*1000); } retries++; } if(ticket < 0) { myAlert("error", "OrderSend"+ordername_+" failed "+IntegerToString(OrderRetry+1)+" times; error #"+IntegerToString(err)+" "+ErrorDescription(err)); return(-1); } string typestr[6] = {"Buy", "Sell", "Buy Limit", "Sell Limit", "Buy Stop", "Sell Stop"}; myAlert("order", "Order sent"+ordername_+": "+typestr[type]+" "+Symbol()+" Magic #"+IntegerToString(MagicNumber)); return(ticket); } void myOrderDelete(int type, string ordername) { if(!IsTradeAllowed()) return; bool success = false; int err = 0; string ordername_ = ordername; if(ordername != "") ordername_ = "("+ordername+")"; int total = OrdersTotal(); ulong orderList[][2]; int orderCount = 0; int i; for(i = 0; i < total; i++) { while(IsTradeContextBusy()) Sleep(100); if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue; if(OrderMagicNumber() != MagicNumber || OrderSymbol() != Symbol() || OrderType() != type) continue; orderCount++; ArrayResize(orderList, orderCount); orderList[orderCount - 1][0] = OrderOpenTime(); orderList[orderCount - 1][1] = OrderTicket(); } if(orderCount > 0) ArraySort(orderList, WHOLE_ARRAY, 0, MODE_ASCEND); for(i = 0; i < orderCount; i++) { if(!OrderSelect(orderList[i][1], SELECT_BY_TICKET, MODE_TRADES)) continue; while(IsTradeContextBusy()) Sleep(100); RefreshRates(); success = OrderDelete(OrderTicket()); if(!success) { err = GetLastError(); myAlert("error", "OrderDelete"+ordername_+" failed; error #"+IntegerToString(err)+" "+ErrorDescription(err)); } } string typestr[6] = {"Buy", "Sell", "Buy Limit", "Sell Limit", "Buy Stop", "Sell Stop"}; if(success) myAlert("order", "Orders deleted"+ordername_+": "+typestr[type]+" "+Symbol()+" Magic #"+IntegerToString(MagicNumber)); } int myOrderModify(int ticket, double SL, double TP) { if(!IsTradeAllowed()) return(-1); bool success = false; int retries = 0; int err = 0; SL = NormalizeDouble(SL, Digits()); TP = NormalizeDouble(TP, Digits()); if(SL < 0) SL = 0; if(TP < 0) TP = 0; while(IsTradeContextBusy()) Sleep(100); if(!OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES)) { err = GetLastError(); myAlert("error", "OrderSelect failed; error #"+IntegerToString(err)+" "+ErrorDescription(err)); return(-1); } while(IsTradeContextBusy()) Sleep(100); RefreshRates(); if(CompareDoubles(SL, 0)) SL = OrderStopLoss(); if(CompareDoubles(TP, 0)) TP = OrderTakeProfit(); if(CompareDoubles(SL, OrderStopLoss()) && CompareDoubles(TP, OrderTakeProfit())) return(0); while(!success && retries < OrderRetry+1) { success = OrderModify(ticket, NormalizeDouble(OrderOpenPrice(), Digits()), NormalizeDouble(SL, Digits()), NormalizeDouble(TP, Digits()), OrderExpiration(), CLR_NONE); if(!success) { err = GetLastError(); myAlert("print", "OrderModify error #"+IntegerToString(err)+" "+ErrorDescription(err)); Sleep(OrderWait*1000); } retries++; } if(!success) { myAlert("error", "OrderModify failed "+IntegerToString(OrderRetry+1)+" times; error #"+IntegerToString(err)+" "+ErrorDescription(err)); return(-1); } string alertstr = "Order modified: ticket="+IntegerToString(ticket); if(!CompareDoubles(SL, 0)) alertstr = alertstr+" SL="+DoubleToString(SL); if(!CompareDoubles(TP, 0)) alertstr = alertstr+" TP="+DoubleToString(TP); myAlert("modify", alertstr); return(0); } int myOrderModifyRel(int ticket, double SL, double TP) { if(!IsTradeAllowed()) return(-1); bool success = false; int retries = 0; int err = 0; SL = NormalizeDouble(SL, Digits()); TP = NormalizeDouble(TP, Digits()); if(SL < 0) SL = 0; if(TP < 0) TP = 0; while(IsTradeContextBusy()) Sleep(100); if(!OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES)) { err = GetLastError(); myAlert("error", "OrderSelect failed; error #"+IntegerToString(err)+" "+ErrorDescription(err)); return(-1); } while(IsTradeContextBusy()) Sleep(100); RefreshRates(); if(OrderType() % 2 == 0) { if(NormalizeDouble(SL, Digits()) != 0) SL = OrderOpenPrice() - SL; if(NormalizeDouble(TP, Digits()) != 0) TP = OrderOpenPrice() + TP; } else { if(NormalizeDouble(SL, Digits()) != 0) SL = OrderOpenPrice() + SL; if(NormalizeDouble(TP, Digits()) != 0) TP = OrderOpenPrice() - TP; } if(CompareDoubles(SL, 0)) SL = OrderStopLoss(); if(CompareDoubles(TP, 0)) TP = OrderTakeProfit(); if(CompareDoubles(SL, OrderStopLoss()) && CompareDoubles(TP, OrderTakeProfit())) return(0); while(!success && retries < OrderRetry+1) { success = OrderModify(ticket, NormalizeDouble(OrderOpenPrice(), Digits()), NormalizeDouble(SL, Digits()), NormalizeDouble(TP, Digits()), OrderExpiration(), CLR_NONE); if(!success) { err = GetLastError(); myAlert("print", "OrderModify error #"+IntegerToString(err)+" "+ErrorDescription(err)); Sleep(OrderWait*1000); } retries++; } if(!success) { myAlert("error", "OrderModify failed "+IntegerToString(OrderRetry+1)+" times; error #"+IntegerToString(err)+" "+ErrorDescription(err)); return(-1); } string alertstr = "Order modified: ticket="+IntegerToString(ticket); if(!CompareDoubles(SL, 0)) alertstr = alertstr+" SL="+DoubleToString(SL); if(!CompareDoubles(TP, 0)) alertstr = alertstr+" TP="+DoubleToString(TP); myAlert("modify", alertstr); return(0); } void TrailingStopTrail(int type, double TS, double step, bool aboveBE, double aboveBEval) { int total = OrdersTotal(); TS = NormalizeDouble(TS, Digits()); step = NormalizeDouble(step, Digits()); for(int i = total-1; i >= 0; i--) { while(IsTradeContextBusy()) Sleep(100); if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue; if(OrderMagicNumber() != MagicNumber || OrderSymbol() != Symbol() || OrderType() != type) continue; RefreshRates(); if(type == OP_BUY && (!aboveBE || Bid > OrderOpenPrice() + TS + aboveBEval) && (NormalizeDouble(OrderStopLoss(), Digits()) <= 0 || Bid > OrderStopLoss() + TS + step)) myOrderModify(OrderTicket(), Bid - TS, 0); else if(type == OP_SELL && (!aboveBE || Ask < OrderOpenPrice() - TS - aboveBEval) && (NormalizeDouble(OrderStopLoss(), Digits()) <= 0 || Ask < OrderStopLoss() - TS - step)) myOrderModify(OrderTicket(), Ask + TS, 0); } } bool NewBar() { static datetime LastTime = 0; bool ret = Time[0] > LastTime && LastTime > 0; LastTime = Time[0]; return(ret); } //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { myPoint = Point(); if(Digits() == 5 || Digits() == 3) { myPoint *= 10; MaxSlippage *= 10; } double LotStep = MarketInfo(Symbol(), MODE_LOTSTEP); if(NormalizeDouble(LotStep, 3) == round(LotStep)) LotDigits = 0; else if(NormalizeDouble(10*LotStep, 3) == round(10*LotStep)) LotDigits = 1; else if(NormalizeDouble(100*LotStep, 3) == round(100*LotStep)) LotDigits = 2; else LotDigits = 3; MM_Percent = Risk_per_trade; ObjectCreate("LordFX13",OBJ_LABEL,0,0,0.0,0,0.0,0,0.0); ObjectSet("LordFX13",OBJPROP_CORNER,1.0); ObjectSet("LordFX13",OBJPROP_YDISTANCE,30.0); ObjectSet("LordFX13",OBJPROP_XDISTANCE,10.0); ObjectSetText("LordFX13","LordFX13",9,"Arial",Gold); ChartSetInteger(0,CHART_SHOW_GRID,false); ChartSetInteger(0, CHART_SHIFT, 1); ChartSetDouble(0, CHART_SHIFT_SIZE, 35); ChartSetInteger(0,CHART_SHOW_ONE_CLICK,0,false); return(0); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { int ticket = -1; double price; double TradeSize; double SL; double TP; bool isNewBar = NewBar(); DeleteByDuration(PendingOrderExpirationSeconds * 1); TrailingStopTrail(OP_BUY, TrailStart_Points * myPoint, TrailStep_Points * myPoint, true, Breakeven_Points * myPoint); TrailingStopTrail(OP_SELL, TrailStart_Points * myPoint, TrailStep_Points * myPoint, true, Breakeven_Points * myPoint); if(TradesCount(OP_SELL) == 1 ) { if(IsTradeAllowed()) myOrderDelete(OP_BUYSTOP, ""); else myAlert("order", ""); } if(TradesCount(OP_BUY) == 1 ) { if(IsTradeAllowed()) myOrderDelete(OP_SELLSTOP, ""); else myAlert("order", ""); } RefreshRates(); if(isNewBar && iATR(NULL, PERIOD_M1, 7, 0) > ATR_Mini && TradesCount(OP_BUYLIMIT) + TradesCount(OP_BUYSTOP) == 0 ) { price = Bid + Points_AboveBelow_PendingOrder * myPoint; SL = Bid - SL_Points * myPoint; TradeSize = MM_Size(price - SL); TP = TP_Points * myPoint; if(!inTimeInterval(TimeCurrent(), TOD_From_Hour, TOD_From_Min, TOD_To_Hour, TOD_To_Min)) return; if(!TradeDayOfWeek()) return; if(IsTradeAllowed()) { ticket = myOrderSend(OP_BUYSTOP, price, TradeSize, "[LordFX13]"); if(ticket <= 0) return; } else myAlert("order", "[LordFX13]"); myOrderModify(ticket, SL, 0); myOrderModifyRel(ticket, 0, TP); } RefreshRates(); if(isNewBar && iATR(NULL, PERIOD_M1, 7, 0) > ATR_Mini && TradesCount(OP_SELLLIMIT) + TradesCount(OP_SELLSTOP) == 0 ) { price = Bid - Points_AboveBelow_PendingOrder * myPoint; SL = Bid + SL_Points * myPoint; TradeSize = MM_Size(SL - price); TP = TP_Points * myPoint; if(!inTimeInterval(TimeCurrent(), TOD_From_Hour, TOD_From_Min, TOD_To_Hour, TOD_To_Min)) return; if(!TradeDayOfWeek()) return; if(IsTradeAllowed()) { ticket = myOrderSend(OP_SELLSTOP, price, TradeSize, "[LordFX13]"); if(ticket <= 0) return; } else myAlert("order", "[LordFX13]"); myOrderModify(ticket, SL, 0); myOrderModifyRel(ticket, 0, TP); } } //+------------------------------------------------------------------+