diff --git a/MQL4/Experts/Trailing Stop on Profit.mq4 b/MQL4/Experts/Trailing Stop on Profit.mq4 new file mode 100644 index 0000000..3924e8d --- /dev/null +++ b/MQL4/Experts/Trailing Stop on Profit.mq4 @@ -0,0 +1,275 @@ +#property link "https://www.earnforex.com/metatrader-expert-advisors/Trailing-Stop-on-Profit/" +#property version "1.00" +#property strict +#property copyright "EarnForex.com - 2022" +#property description "This Expert Advisor will start trailing the stop-loss after a given profit is reached." +#property description " " +#property description "WARNING: No warranty. This EA is offered \"as is\". Use at your own risk.\r\n" +#property icon "\\Files\\EF-Icon-64x64px.ico" + +#include +#include + +enum ENUM_CONSIDER +{ + All = -1, // All orders + Buy = OP_BUY, // Buy only + Sell = OP_SELL, // Sell only +}; + +input string Comment_1 = "===================="; // Expert Advisor Settings +input int TrailingStop = 50; // Trailing Stop, points +input int Profit = 100; // Profit in points when TS should kick in. +input string Comment_2 = "===================="; // Orders Filtering Options +input ENUM_CONSIDER OnlyType = All; // Apply to +input bool UseMagic = false; // Filter by magic number +input int MagicNumber = 0; // Magic number (if above is true) +input bool UseComment = false; // Filter by comment +input string CommentFilter = ""; // Comment (if above is true) +input bool EnableTrailingParam = false; // Enable trailing stop +input string Comment_3 = "===================="; // Notification Options +input bool EnableNotify = false; // Enable motifications feature +input bool SendAlert = true; // Send alert notification +input bool SendApp = true; // Send notification to mobile +input bool SendEmail = true; // Send notification via email +input string Comment_3a = "===================="; // Graphical Window +input bool ShowPanel = true; // Show graphical panel +input string IndicatorName = "TSOP"; // Indicator name (to name the objects) +input int Xoff = 20; // Horizontal spacing for the control panel +input int Yoff = 20; // Vertical spacing for the control panel + +int OrderOpRetry = 5; // Number of order modification attempts. +bool EnableTrailing = EnableTrailingParam; + +void OnInit() +{ + EnableTrailing = EnableTrailingParam; + if (ShowPanel) DrawPanel(); +} + +void OnDeinit(const int reason) +{ + CleanPanel(); +} + +void OnTick() +{ + if (EnableTrailing) TrailingStop(); + if (ShowPanel) DrawPanel(); +} + +void OnChartEvent(const int id, + const long &lparam, + const double &dparam, + const string &sparam) +{ + if (id == CHARTEVENT_OBJECT_CLICK) + { + if (sparam == PanelEnableDisable) // Click on the enable/disable button. + { + ChangeTrailingEnabled(); + } + } + if (id == CHARTEVENT_KEYDOWN) + { + if (lparam == 27) // Escape key. + { + if (MessageBox("Are you sure you want to close the EA?", "Terminate?", MB_YESNO) == IDYES) + { + ExpertRemove(); + } + } + } +} + +void TrailingStop() +{ + for (int i = OrdersTotal() - 1; i >= 0; i--) + { + if (OrderSelect(i, SELECT_BY_POS, MODE_TRADES) == false) + { + int Error = GetLastError(); + string ErrorText = ErrorDescription(Error); + Print("ERROR - Unable to select the order - ", Error); + Print("ERROR - ", ErrorText); + break; + } + if (OrderSymbol() != Symbol()) continue; + if ((UseMagic) && (OrderMagicNumber() != MagicNumber)) continue; + if ((UseComment) && (StringFind(OrderComment(), CommentFilter) < 0)) continue; + if ((OnlyType != All) && (OrderType() != OnlyType)) continue; + + // Normalize trailing stop value to the point value. + double TSTP = TrailingStop * _Point; + double P = Profit * _Point; + + if (OrderType() == OP_BUY) + { + if (NormalizeDouble(Bid - OrderOpenPrice(), _Digits) > NormalizeDouble(P, _Digits)) + { + if ((TSTP != 0) && (OrderStopLoss() < NormalizeDouble(Bid - TSTP, _Digits))) + { + ModifyOrder(OrderTicket(), OrderOpenPrice(), NormalizeDouble(Bid - TSTP, _Digits), OrderTakeProfit()); + } + } + } + else if (OrderType() == OP_SELL) + { + if ((TSTP != 0) && (NormalizeDouble(OrderOpenPrice() - Ask, _Digits) > TSTP)) + { + if ((OrderStopLoss() > NormalizeDouble(Ask + TSTP, _Digits)) || (OrderStopLoss() == 0)) + { + ModifyOrder(OrderTicket(), OrderOpenPrice(), NormalizeDouble(Ask + TSTP, _Digits), OrderTakeProfit()); + } + } + } + } +} + +void ModifyOrder(int Ticket, double OpenPrice, double SLPrice, double TPPrice) +{ + for (int i = 1; i <= OrderOpRetry; i++) // Several attempts to modify the order. + { + bool result = OrderModify(Ticket, OpenPrice, SLPrice, TPPrice, 0); + if (result) + { + Print("TRADE - UPDATE SUCCESS - Order ", Ticket, " new stop-loss ", SLPrice); + NotifyStopLossUpdate(Ticket, SLPrice); + break; + } + else + { + int Error = GetLastError(); + string ErrorText = ErrorDescription(Error); + Print("ERROR - UPDATE FAILED - error modifying order ", Ticket, " return error: ", Error, " Open=", OpenPrice, + " Old SL=", OrderStopLoss(), + " New SL=", SLPrice, " Bid=", MarketInfo(OrderSymbol(), MODE_BID), " Ask=", MarketInfo(OrderSymbol(), MODE_ASK)); + Print("ERROR - ", ErrorText); + } + } +} + +void NotifyStopLossUpdate(int Ticket, double SLPrice) +{ + if (!EnableNotify) return; + if ((!SendAlert) && (!SendApp) && (!SendEmail)) return; + string EmailSubject = IndicatorName + " " + Symbol() + " Notification"; + string EmailBody = AccountCompany() + " - " + AccountName() + " - " + IntegerToString(AccountNumber()) + "\r\n\r\n" + IndicatorName + " Notification for " + Symbol() + "\r\n\r\n"; + EmailBody += "Stop-loss for order " + IntegerToString(Ticket) + " moved to " + DoubleToString(SLPrice, _Digits); + string AlertText = IndicatorName + " - " + Symbol() + " Notification: "; + AlertText += "Stop-loss for order " + IntegerToString(Ticket) + " moved to " + DoubleToString(SLPrice, _Digits); + string AppText = AccountCompany() + " - " + AccountName() + " - " + IntegerToString(AccountNumber()) + " - " + IndicatorName + " - " + Symbol() + " - "; + AppText += "Stop-loss for order " + IntegerToString(Ticket) + " moved to " + DoubleToString(SLPrice, _Digits); + if (SendAlert) Alert(AlertText); + if (SendEmail) + { + if (!SendMail(EmailSubject, EmailBody)) Print("Error sending email " + IntegerToString(GetLastError())); + } + if (SendApp) + { + if (!SendNotification(AppText)) Print("Error sending notification " + IntegerToString(GetLastError())); + } + Print(IndicatorName + " - last notification sent on " + TimeToString(TimeCurrent())); +} + +string PanelBase = IndicatorName + "-P-BAS"; +string PanelLabel = IndicatorName + "-P-LAB"; +string PanelEnableDisable = IndicatorName + "-P-ENADIS"; + +int PanelMovX = 50; +int PanelMovY = 20; +int PanelLabX = 150; +int PanelLabY = PanelMovY; +int PanelRecX = PanelLabX + 4; + +void DrawPanel() +{ + string PanelText = "TSL on Profit"; + string PanelToolTip = "Trailing Stop on Profit by EarnForex"; + int Rows = 1; + ObjectCreate(ChartID(), PanelBase, OBJ_RECTANGLE_LABEL, 0, 0, 0); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_XDISTANCE, Xoff); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_YDISTANCE, Yoff); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_XSIZE, PanelRecX); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_YSIZE, (PanelMovY + 2) * 1 + 2); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_BGCOLOR, clrWhite); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_BORDER_TYPE, BORDER_FLAT); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_STATE, false); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_HIDDEN, true); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_FONTSIZE, 8); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_SELECTABLE, false); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_COLOR, clrBlack); + + DrawEdit(PanelLabel, + Xoff + 2, + Yoff + 2, + PanelLabX, + PanelLabY, + true, + 10, + PanelToolTip, + ALIGN_CENTER, + "Consolas", + PanelText, + false, + clrNavy, + clrKhaki, + clrBlack); + + string EnableDisabledText = ""; + color EnableDisabledColor = clrNavy; + color EnableDisabledBack = clrKhaki; + if (EnableTrailing) + { + EnableDisabledText = "TRAILING ENABLED"; + EnableDisabledColor = clrWhite; + EnableDisabledBack = clrDarkGreen; + } + else + { + EnableDisabledText = "TRAILING DISABLED"; + EnableDisabledColor = clrWhite; + EnableDisabledBack = clrDarkRed; + } + + DrawEdit(PanelEnableDisable, + Xoff + 2, + Yoff + (PanelMovY + 1)*Rows + 2, + PanelLabX, + PanelLabY, + true, + 8, + "Click to enable or disable the trailing stop feature", + ALIGN_CENTER, + "Consolas", + EnableDisabledText, + false, + EnableDisabledColor, + EnableDisabledBack, + clrBlack); + + Rows++; + + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_XSIZE, PanelRecX); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_YSIZE, (PanelMovY + 1)*Rows + 3); +} + +void CleanPanel() +{ + ObjectsDeleteAll(ChartID(), IndicatorName); +} + +void ChangeTrailingEnabled() +{ + if (EnableTrailing == false) + { + if (IsTradeAllowed()) EnableTrailing = true; + else + { + MessageBox("You need to first enable Autotrading in your MetaTrader options", "WARNING", MB_OK); + } + } + else EnableTrailing = false; + DrawPanel(); +} +//+------------------------------------------------------------------+ \ No newline at end of file diff --git a/MQL4/Files/EF-Icon-64x64px.ico b/MQL4/Files/EF-Icon-64x64px.ico new file mode 100644 index 0000000..0723753 Binary files /dev/null and b/MQL4/Files/EF-Icon-64x64px.ico differ diff --git a/MQL4/Include/MQLTA Utils.mqh b/MQL4/Include/MQLTA Utils.mqh new file mode 100644 index 0000000..6268f76 --- /dev/null +++ b/MQL4/Include/MQLTA Utils.mqh @@ -0,0 +1,368 @@ +#property link "https://www.earnforex.com/" +#property version "1.00" +#property strict +#property copyright "EarnForex.com - 2020" +#property description "" +#property description "" +#property description "" +#property description "" +#property description "Find More on EarnForex.com" + +#define OP_BUY 0 //Buy +#define OP_SELL 1 //Sell +#define OP_BUYLIMIT 2 //Pending order of BUY LIMIT type +#define OP_SELLLIMIT 3 //Pending order of SELL LIMIT type +#define OP_BUYSTOP 4 //Pending order of BUY STOP type +#define OP_SELLSTOP 5 //Pending order of SELL STOP type +//--- +#define MODE_OPEN 0 +#define MODE_CLOSE 3 +#define MODE_VOLUME 4 +#define MODE_REAL_VOLUME 5 +#define MODE_TRADES 0 +#define MODE_HISTORY 1 +#define SELECT_BY_POS 0 +#define SELECT_BY_TICKET 1 +//--- +#define DOUBLE_VALUE 0 +#define FLOAT_VALUE 1 +#define LONG_VALUE INT_VALUE +//--- +#define CHART_BAR 0 +#define CHART_CANDLE 1 +//--- +#define MODE_ASCEND 0 +#define MODE_DESCEND 1 +//--- +#define MODE_LOW 1 +#define MODE_HIGH 2 +#define MODE_TIME 5 +#define MODE_BID 9 +#define MODE_ASK 10 +#define MODE_POINT 11 +#define MODE_DIGITS 12 +#define MODE_SPREAD 13 +#define MODE_STOPLEVEL 14 +#define MODE_LOTSIZE 15 +#define MODE_TICKVALUE 16 +#define MODE_TICKSIZE 17 +#define MODE_SWAPLONG 18 +#define MODE_SWAPSHORT 19 +#define MODE_STARTING 20 +#define MODE_EXPIRATION 21 +#define MODE_TRADEALLOWED 22 +#define MODE_MINLOT 23 +#define MODE_LOTSTEP 24 +#define MODE_MAXLOT 25 +#define MODE_SWAPTYPE 26 +#define MODE_PROFITCALCMODE 27 +#define MODE_MARGINCALCMODE 28 +#define MODE_MARGININIT 29 +#define MODE_MARGINMAINTENANCE 30 +#define MODE_MARGINHEDGED 31 +#define MODE_MARGINREQUIRED 32 + +enum ENUM_HOUR{ + h00=00, //00:00 + h01=01, //01:00 + h02=02, //02:00 + h03=03, //03:00 + h04=04, //04:00 + h05=05, //05:00 + h06=06, //06:00 + h07=07, //07:00 + h08=08, //08:00 + h09=09, //09:00 + h10=10, //10:00 + h11=11, //11:00 + h12=12, //12:00 + h13=13, //13:00 + h14=14, //14:00 + h15=15, //15:00 + h16=16, //16:00 + h17=17, //17:00 + h18=18, //18:00 + h19=19, //19:00 + h20=20, //20:00 + h21=21, //21:00 + h22=22, //22:00 + h23=23, //23:00 +}; + +ENUM_TIMEFRAMES TimeFrames[]={ + PERIOD_M1, + PERIOD_M2, + PERIOD_M3, + PERIOD_M4, + PERIOD_M5, + PERIOD_M6, + PERIOD_M10, + PERIOD_M12, + PERIOD_M15, + PERIOD_M20, + PERIOD_M30, + PERIOD_H1, + PERIOD_H2, + PERIOD_H3, + PERIOD_H4, + PERIOD_H6, + PERIOD_H8, + PERIOD_H12, + PERIOD_D1, + PERIOD_W1, + PERIOD_MN1 + }; + + +//Return the index of the requested time frame in the array TimeFrames +int TimeFrameIndex(ENUM_TIMEFRAMES TimeFrame){ + int j=0; + if(TimeFrame==PERIOD_CURRENT) TimeFrame=Period(); + for(int i=0;i=Start && Hour()<=End) return true; + if(Start>End && ((Hour()>=Start && Hour()<=23) || (Hour()<=End && Hour()>=0))) return true; + return false; +} + + +//Check if the software is over the date of use, throw a message and return true if it is +bool UpdateCheckOver(string Name, datetime ExpiryDate, bool ShowAlert){ + if(TimeCurrent()>ExpiryDate){ + string EditText="Version Expired, This Product Must Be Updated"; + string AlertText="Version Expired, Please Download The New Version From MQL4TradingAutomation.com"; + DrawExpiry(Name,EditText); + if(ShowAlert){ + Alert(AlertText); + Print(AlertText); + } + return true; + } + else return false; +} + +//Check if the software is over the warning date and throw a message if it is +void UpdateCheckWarning(string Name, datetime WarnDate, datetime ExpDate, bool ShowAlert){ + if(TimeCurrent()>WarnDate){ + MqlDateTime WarningDate,ExpiryDate; + TimeToStruct(WarnDate,WarningDate); + TimeToStruct(ExpDate,ExpiryDate); + string WarningDateStr=(string)ExpiryDate.day+"/"+(string)ExpiryDate.mon+"/"+(string)ExpiryDate.year; + string EditText="This Product Version Will Stop Working On The "+WarningDateStr+""; + string AlertText="This Product Version Will Stop Working On The "+WarningDateStr+", Please Download The New Version From MQL4TradingAutomation.com"; + DrawExpiry(Name,EditText); + if(ShowAlert){ + Alert(AlertText); + Print(AlertText); + } + } +} + +//Draw a box to advise of the warning/expiry of the product +void DrawExpiry(string Name, string Text){ + string TextBoxName=Name+"ExpirationTextBox"; + if(ObjectFind(0,TextBoxName)<0){ + DrawEdit(TextBoxName,20,20,300,20,true,8,"",ALIGN_CENTER,"Arial",Text,true,clrNavy,clrKhaki,clrBlack); + } +} + +//Draw an edit box with the specified parameters +void DrawEdit( string Name, + int XStart, + int YStart, + int Width, + int Height, + bool ReadOnly, + int EditFontSize, + string Tooltip, + int Align, + string EditFont, + string Text, + bool Selectable, + color TextColor=clrBlack, + color BGColor=clrWhiteSmoke, + color BDColor=clrBlack + ){ + + ObjectCreate(0,Name,OBJ_EDIT,0,0,0); + ObjectSetInteger(0,Name,OBJPROP_XDISTANCE,XStart); + ObjectSetInteger(0,Name,OBJPROP_YDISTANCE,YStart); + ObjectSetInteger(0,Name,OBJPROP_XSIZE,Width); + ObjectSetInteger(0,Name,OBJPROP_YSIZE,Height); + ObjectSetInteger(0,Name,OBJPROP_BORDER_TYPE,BORDER_FLAT); + ObjectSetInteger(0,Name,OBJPROP_STATE,false); + ObjectSetInteger(0,Name,OBJPROP_HIDDEN,true); + ObjectSetInteger(0,Name,OBJPROP_READONLY,ReadOnly); + ObjectSetInteger(0,Name,OBJPROP_FONTSIZE,EditFontSize); + ObjectSetString(0,Name,OBJPROP_TOOLTIP,Tooltip); + ObjectSetInteger(0,Name,OBJPROP_ALIGN,Align); + ObjectSetString(0,Name,OBJPROP_FONT,EditFont); + ObjectSetString(0,Name,OBJPROP_TEXT,Text); + ObjectSetInteger(0,Name,OBJPROP_SELECTABLE,Selectable); + ObjectSetInteger(0,Name,OBJPROP_COLOR,TextColor); + ObjectSetInteger(0,Name,OBJPROP_BGCOLOR,BGColor); + ObjectSetInteger(0,Name,OBJPROP_BORDER_COLOR,BDColor); +} + + +string AccountCompany(){ + return AccountInfoString(ACCOUNT_COMPANY); +} + + +string AccountName(){ + return AccountInfoString(ACCOUNT_NAME); +} + + +long AccountNumber(){ + return AccountInfoInteger(ACCOUNT_LOGIN); +} + +string AccountCurrency(){ + return AccountInfoString(ACCOUNT_CURRENCY); +} + +double AccountBalance(){ + return AccountInfoDouble(ACCOUNT_BALANCE); +} + +double AccountEquity(){ + return AccountInfoDouble(ACCOUNT_EQUITY); +} + +double AccountFreeMargin(){ + return AccountInfoDouble(ACCOUNT_MARGIN_FREE); +} + +void SetIndex(int Index, int Type, int Style, int Width, int Color, string Label){ + PlotIndexSetInteger(Index,PLOT_DRAW_TYPE,Type); + PlotIndexSetInteger(Index,PLOT_LINE_STYLE,Style); + PlotIndexSetInteger(Index,PLOT_LINE_WIDTH,Width); + PlotIndexSetInteger(Index,PLOT_LINE_COLOR,Color); + PlotIndexSetString(Index,PLOT_LABEL,Label); +} + +int WindowFind(string Name){ + return ChartWindowFind(0,Name); +} + +string TimeFrameDescription(int TimeFrame){ + string perioddesc=""; + switch (TimeFrame){ + case PERIOD_M1: + perioddesc="M1"; + break; + case PERIOD_M2: + perioddesc="M2"; + break; + case PERIOD_M3: + perioddesc="M3"; + break; + case PERIOD_M4: + perioddesc="M4"; + break; + case PERIOD_M5: + perioddesc="M5"; + break; + case PERIOD_M6: + perioddesc="M6"; + break; + case PERIOD_M10: + perioddesc="M10"; + break; + case PERIOD_M12: + perioddesc="M12"; + break; + case PERIOD_M15: + perioddesc="M15"; + break; + case PERIOD_M20: + perioddesc="M20"; + break; + case PERIOD_M30: + perioddesc="M30"; + break; + case PERIOD_H1: + perioddesc="H1"; + break; + case PERIOD_H2: + perioddesc="H2"; + break; + case PERIOD_H3: + perioddesc="H3"; + break; + case PERIOD_H4: + perioddesc="H4"; + break; + case PERIOD_H6: + perioddesc="H6"; + break; + case PERIOD_H8: + perioddesc="H8"; + break; + case PERIOD_H12: + perioddesc="H12"; + break; + case PERIOD_D1: + perioddesc="D1"; + break; + case PERIOD_W1: + perioddesc="W1"; + break; + case PERIOD_MN1: + perioddesc="MN1"; + break; + } + return perioddesc; +} + + +string OrderSymbol(){ + return OrderGetString(ORDER_SYMBOL); +} + +long OrderMagicNumber(){ + return OrderGetInteger(ORDER_MAGIC); +} + +double OrderStopLoss(){ + return OrderGetDouble(ORDER_SL); +} + +double OrderTakeProfit(){ + return OrderGetDouble(ORDER_TP); +} + +ENUM_ORDER_TYPE OrderType(){ + return (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE); +} + +long OrderTicket(){ + return OrderGetInteger(ORDER_TICKET); +} + +long OrderOpenTime(){ + return OrderGetInteger(ORDER_TIME_DONE); +} + +double OrderOpenPrice(){ + return OrderGetDouble(ORDER_PRICE_OPEN); +} + +double OrderLots(){ + return OrderGetDouble(ORDER_VOLUME_CURRENT); +} + +int Hour(){ + MqlDateTime mTime; + TimeCurrent(mTime); + return(mTime.hour); +} \ No newline at end of file diff --git a/MQL5/Experts/Trailing Stop on Profit.mq5 b/MQL5/Experts/Trailing Stop on Profit.mq5 new file mode 100644 index 0000000..69e1ded --- /dev/null +++ b/MQL5/Experts/Trailing Stop on Profit.mq5 @@ -0,0 +1,294 @@ +#property link "https://www.earnforex.com/metatrader-expert-advisors/Trailing-Stop-on-Profit/" +#property version "1.00" +#property strict +#property copyright "EarnForex.com - 2022" +#property description "This Expert Advisor will start trailing the stop-loss after a given profit is reached." +#property description " " +#property description "WARNING: No warranty. This EA is offered \"as is\". Use at your own risk.\r\n" +#property icon "\\Files\\EF-Icon-64x64px.ico" + +#include +#include +#include + +enum ENUM_CONSIDER +{ + All = -1, // All orders + Buy = POSITION_TYPE_BUY, // Buy only + Sell = POSITION_TYPE_SELL, // Sell only +}; + +input group "Expert advisor settings" +input int TrailingStop = 50; // Trailing Stop, points +input int Profit = 100; // Profit in points when TS should kick in. +input group "Orders filtering options" +input ENUM_CONSIDER OnlyType = All; // Apply to +input bool UseMagic = false; // Filter by magic number +input int MagicNumber = 0; // Magic number (if above is true) +input bool UseComment = false; // Filter by comment +input string CommentFilter = ""; // Comment (if above is true) +input bool EnableTrailingParam = false; // Enable trailing stop +input group "Notification options" +input bool EnableNotify = false; // Enable motifications feature +input bool SendAlert = true; // Send alert notification +input bool SendApp = true; // Send notification to mobile +input bool SendEmail = true; // Send notification via email +input group "Graphical window" +input bool ShowPanel = true; // Show graphical panel +input string IndicatorName = "TSOP"; // Indicator name (to name the objects) +input int Xoff = 20; // Horizontal spacing for the control panel +input int Yoff = 20; // Vertical spacing for the control panel + +int OrderOpRetry = 5; // Number of position modification attempts. +bool EnableTrailing = EnableTrailingParam; +CTrade *Trade; + +void OnInit() +{ + EnableTrailing = EnableTrailingParam; + if (ShowPanel) DrawPanel(); + Trade = new CTrade; +} + +void OnDeinit(const int reason) +{ + CleanPanel(); + delete Trade; +} + +void OnTick() +{ + if (EnableTrailing) TrailingStop(); + if (ShowPanel) DrawPanel(); +} + +void OnChartEvent(const int id, + const long &lparam, + const double &dparam, + const string &sparam) +{ + if (id == CHARTEVENT_OBJECT_CLICK) + { + if (sparam == PanelEnableDisable) // Click on the enable/disable button. + { + ChangeTrailingEnabled(); + } + } + if (id == CHARTEVENT_KEYDOWN) + { + if (lparam == 27) // Escape key. + { + if (MessageBox("Are you sure you want to close the EA?", "Terminate?", MB_YESNO) == IDYES) + { + ExpertRemove(); + } + } + } +} + +void TrailingStop() +{ + for (int i = PositionsTotal() - 1; i >= 0; i--) + { + + ulong ticket = PositionGetTicket(i); + + if (ticket <= 0) + { + int Error = GetLastError(); + string ErrorText = ErrorDescription(Error); + Print("ERROR - Unable to select the position - ", Error); + Print("ERROR - ", ErrorText); + break; + } + + // Trading disabled. + if (SymbolInfoInteger(PositionGetString(POSITION_SYMBOL), SYMBOL_TRADE_MODE) == SYMBOL_TRADE_MODE_DISABLED) continue; + + // Filters. + if (PositionGetString(POSITION_SYMBOL) != Symbol()) continue; + if ((UseMagic) && (PositionGetInteger(POSITION_MAGIC) != MagicNumber)) continue; + if ((UseComment) && (StringFind(PositionGetString(POSITION_COMMENT), CommentFilter) < 0)) continue; + if ((OnlyType != All) && (PositionGetInteger(POSITION_TYPE) != OnlyType)) continue; + + // Normalize trailing stop value to the point value. + double TSTP = TrailingStop * _Point; + double P = Profit * _Point; + + double Bid = SymbolInfoDouble(Symbol(), SYMBOL_BID); + double Ask = SymbolInfoDouble(Symbol(), SYMBOL_ASK); + double OpenPrice = PositionGetDouble(POSITION_PRICE_OPEN); + double StopLoss = PositionGetDouble(POSITION_SL); + double TakeProfit = PositionGetDouble(POSITION_TP); + + if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) + { + if (NormalizeDouble(Bid - OpenPrice, _Digits) > NormalizeDouble(P, _Digits)) + { + if ((TSTP != 0) && (StopLoss < NormalizeDouble(Bid - TSTP, _Digits))) + { + ModifyPosition(ticket, OpenPrice, NormalizeDouble(Bid - TSTP, _Digits), TakeProfit); + } + } + } + else if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL) + { + if ((TSTP != 0) && (NormalizeDouble(OpenPrice - Ask, _Digits) > TSTP)) + { + if ((StopLoss > NormalizeDouble(Ask + TSTP, _Digits)) || (StopLoss == 0)) + { + ModifyPosition(ticket, OpenPrice, NormalizeDouble(Ask + TSTP, _Digits), TakeProfit); + } + } + } + } +} + +void ModifyPosition(ulong Ticket, double OpenPrice, double SLPrice, double TPPrice) +{ + for (int i = 1; i <= OrderOpRetry; i++) // Several attempts to modify the position. + { + bool result = Trade.PositionModify(Ticket, SLPrice, TPPrice); + if (result) + { + Print("TRADE - UPDATE SUCCESS - Order ", Ticket, " new stop-loss ", SLPrice); + NotifyStopLossUpdate(Ticket, SLPrice); + break; + } + else + { + int Error = GetLastError(); + string ErrorText = ErrorDescription(Error); + Print("ERROR - UPDATE FAILED - error modifying order ", Ticket, " return error: ", Error, " Open=", OpenPrice, + " Old SL=", PositionGetDouble(POSITION_SL), + " New SL=", SLPrice, " Bid=", SymbolInfoDouble(Symbol(), SYMBOL_BID), " Ask=", SymbolInfoDouble(Symbol(), SYMBOL_ASK)); + Print("ERROR - ", ErrorText); + } + } +} + +void NotifyStopLossUpdate(ulong Ticket, double SLPrice) +{ + if (!EnableNotify) return; + if ((!SendAlert) && (!SendApp) && (!SendEmail)) return; + string EmailSubject = IndicatorName + " " + Symbol() + " Notification"; + string EmailBody = AccountInfoString(ACCOUNT_COMPANY) + " - " + AccountInfoString(ACCOUNT_NAME) + " - " + IntegerToString(AccountInfoInteger(ACCOUNT_LOGIN)) + "\r\n\r\n" + IndicatorName + " Notification for " + Symbol() + "\r\n\r\n"; + EmailBody += "Stop-loss for order " + IntegerToString(Ticket) + " moved to " + DoubleToString(SLPrice, _Digits); + string AlertText = IndicatorName + " - Notification: "; + AlertText += "Stop-loss for order " + IntegerToString(Ticket) + " moved to " + DoubleToString(SLPrice, _Digits); + string AppText = AccountInfoString(ACCOUNT_COMPANY) + " - " + AccountInfoString(ACCOUNT_NAME) + " - " + IntegerToString(AccountInfoInteger(ACCOUNT_LOGIN)) + " - " + IndicatorName + " - " + Symbol() + " - "; + AppText += "Stop-loss for order " + IntegerToString(Ticket) + " moved to " + DoubleToString(SLPrice, _Digits); + if (SendAlert) Alert(AlertText); + if (SendEmail) + { + if (!SendMail(EmailSubject, EmailBody)) Print("Error sending email " + IntegerToString(GetLastError())); + } + if (SendApp) + { + if (!SendNotification(AppText)) Print("Error sending notification " + IntegerToString(GetLastError())); + } + Print(IndicatorName + " - last notification sent on " + TimeToString(TimeCurrent())); +} + +string PanelBase = IndicatorName + "-P-BAS"; +string PanelLabel = IndicatorName + "-P-LAB"; +string PanelEnableDisable = IndicatorName + "-P-ENADIS"; + +int PanelMovX = 50; +int PanelMovY = 20; +int PanelLabX = 150; +int PanelLabY = PanelMovY; +int PanelRecX = PanelLabX + 4; + +void DrawPanel() +{ + string PanelText = "TSL on Profit"; + string PanelToolTip = "Trailing Stop on Profit by EarnForex"; + int Rows = 1; + ObjectCreate(ChartID(), PanelBase, OBJ_RECTANGLE_LABEL, 0, 0, 0); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_XDISTANCE, Xoff); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_YDISTANCE, Yoff); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_XSIZE, PanelRecX); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_YSIZE, (PanelMovY + 2) * 1 + 2); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_BGCOLOR, clrWhite); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_BORDER_TYPE, BORDER_FLAT); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_STATE, false); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_HIDDEN, true); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_FONTSIZE, 8); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_SELECTABLE, false); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_COLOR, clrBlack); + + DrawEdit(PanelLabel, + Xoff + 2, + Yoff + 2, + PanelLabX, + PanelLabY, + true, + 10, + PanelToolTip, + ALIGN_CENTER, + "Consolas", + PanelText, + false, + clrNavy, + clrKhaki, + clrBlack); + + string EnableDisabledText = ""; + color EnableDisabledColor = clrNavy; + color EnableDisabledBack = clrKhaki; + if (EnableTrailing) + { + EnableDisabledText = "TRAILING ENABLED"; + EnableDisabledColor = clrWhite; + EnableDisabledBack = clrDarkGreen; + } + else + { + EnableDisabledText = "TRAILING DISABLED"; + EnableDisabledColor = clrWhite; + EnableDisabledBack = clrDarkRed; + } + + DrawEdit(PanelEnableDisable, + Xoff + 2, + Yoff + (PanelMovY + 1)*Rows + 2, + PanelLabX, + PanelLabY, + true, + 8, + "Click to enable or disable the trailing stop feature", + ALIGN_CENTER, + "Consolas", + EnableDisabledText, + false, + EnableDisabledColor, + EnableDisabledBack, + clrBlack); + + Rows++; + + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_XSIZE, PanelRecX); + ObjectSetInteger(ChartID(), PanelBase, OBJPROP_YSIZE, (PanelMovY + 1)*Rows + 3); + ChartRedraw(); +} + +void CleanPanel() +{ + ObjectsDeleteAll(ChartID(), IndicatorName); +} + +void ChangeTrailingEnabled() +{ + if (EnableTrailing == false) + { + if (MQLInfoInteger(MQL_TRADE_ALLOWED)) EnableTrailing = true; + else + { + MessageBox("You need to first enable Autotrading in your MetaTrader options", "WARNING", MB_OK); + } + } + else EnableTrailing = false; + DrawPanel(); +} +//+------------------------------------------------------------------+ \ No newline at end of file diff --git a/MQL5/Files/EF-Icon-64x64px.ico b/MQL5/Files/EF-Icon-64x64px.ico new file mode 100644 index 0000000..0723753 Binary files /dev/null and b/MQL5/Files/EF-Icon-64x64px.ico differ diff --git a/MQL5/Include/MQLTA Utils.mqh b/MQL5/Include/MQLTA Utils.mqh new file mode 100644 index 0000000..6268f76 --- /dev/null +++ b/MQL5/Include/MQLTA Utils.mqh @@ -0,0 +1,368 @@ +#property link "https://www.earnforex.com/" +#property version "1.00" +#property strict +#property copyright "EarnForex.com - 2020" +#property description "" +#property description "" +#property description "" +#property description "" +#property description "Find More on EarnForex.com" + +#define OP_BUY 0 //Buy +#define OP_SELL 1 //Sell +#define OP_BUYLIMIT 2 //Pending order of BUY LIMIT type +#define OP_SELLLIMIT 3 //Pending order of SELL LIMIT type +#define OP_BUYSTOP 4 //Pending order of BUY STOP type +#define OP_SELLSTOP 5 //Pending order of SELL STOP type +//--- +#define MODE_OPEN 0 +#define MODE_CLOSE 3 +#define MODE_VOLUME 4 +#define MODE_REAL_VOLUME 5 +#define MODE_TRADES 0 +#define MODE_HISTORY 1 +#define SELECT_BY_POS 0 +#define SELECT_BY_TICKET 1 +//--- +#define DOUBLE_VALUE 0 +#define FLOAT_VALUE 1 +#define LONG_VALUE INT_VALUE +//--- +#define CHART_BAR 0 +#define CHART_CANDLE 1 +//--- +#define MODE_ASCEND 0 +#define MODE_DESCEND 1 +//--- +#define MODE_LOW 1 +#define MODE_HIGH 2 +#define MODE_TIME 5 +#define MODE_BID 9 +#define MODE_ASK 10 +#define MODE_POINT 11 +#define MODE_DIGITS 12 +#define MODE_SPREAD 13 +#define MODE_STOPLEVEL 14 +#define MODE_LOTSIZE 15 +#define MODE_TICKVALUE 16 +#define MODE_TICKSIZE 17 +#define MODE_SWAPLONG 18 +#define MODE_SWAPSHORT 19 +#define MODE_STARTING 20 +#define MODE_EXPIRATION 21 +#define MODE_TRADEALLOWED 22 +#define MODE_MINLOT 23 +#define MODE_LOTSTEP 24 +#define MODE_MAXLOT 25 +#define MODE_SWAPTYPE 26 +#define MODE_PROFITCALCMODE 27 +#define MODE_MARGINCALCMODE 28 +#define MODE_MARGININIT 29 +#define MODE_MARGINMAINTENANCE 30 +#define MODE_MARGINHEDGED 31 +#define MODE_MARGINREQUIRED 32 + +enum ENUM_HOUR{ + h00=00, //00:00 + h01=01, //01:00 + h02=02, //02:00 + h03=03, //03:00 + h04=04, //04:00 + h05=05, //05:00 + h06=06, //06:00 + h07=07, //07:00 + h08=08, //08:00 + h09=09, //09:00 + h10=10, //10:00 + h11=11, //11:00 + h12=12, //12:00 + h13=13, //13:00 + h14=14, //14:00 + h15=15, //15:00 + h16=16, //16:00 + h17=17, //17:00 + h18=18, //18:00 + h19=19, //19:00 + h20=20, //20:00 + h21=21, //21:00 + h22=22, //22:00 + h23=23, //23:00 +}; + +ENUM_TIMEFRAMES TimeFrames[]={ + PERIOD_M1, + PERIOD_M2, + PERIOD_M3, + PERIOD_M4, + PERIOD_M5, + PERIOD_M6, + PERIOD_M10, + PERIOD_M12, + PERIOD_M15, + PERIOD_M20, + PERIOD_M30, + PERIOD_H1, + PERIOD_H2, + PERIOD_H3, + PERIOD_H4, + PERIOD_H6, + PERIOD_H8, + PERIOD_H12, + PERIOD_D1, + PERIOD_W1, + PERIOD_MN1 + }; + + +//Return the index of the requested time frame in the array TimeFrames +int TimeFrameIndex(ENUM_TIMEFRAMES TimeFrame){ + int j=0; + if(TimeFrame==PERIOD_CURRENT) TimeFrame=Period(); + for(int i=0;i=Start && Hour()<=End) return true; + if(Start>End && ((Hour()>=Start && Hour()<=23) || (Hour()<=End && Hour()>=0))) return true; + return false; +} + + +//Check if the software is over the date of use, throw a message and return true if it is +bool UpdateCheckOver(string Name, datetime ExpiryDate, bool ShowAlert){ + if(TimeCurrent()>ExpiryDate){ + string EditText="Version Expired, This Product Must Be Updated"; + string AlertText="Version Expired, Please Download The New Version From MQL4TradingAutomation.com"; + DrawExpiry(Name,EditText); + if(ShowAlert){ + Alert(AlertText); + Print(AlertText); + } + return true; + } + else return false; +} + +//Check if the software is over the warning date and throw a message if it is +void UpdateCheckWarning(string Name, datetime WarnDate, datetime ExpDate, bool ShowAlert){ + if(TimeCurrent()>WarnDate){ + MqlDateTime WarningDate,ExpiryDate; + TimeToStruct(WarnDate,WarningDate); + TimeToStruct(ExpDate,ExpiryDate); + string WarningDateStr=(string)ExpiryDate.day+"/"+(string)ExpiryDate.mon+"/"+(string)ExpiryDate.year; + string EditText="This Product Version Will Stop Working On The "+WarningDateStr+""; + string AlertText="This Product Version Will Stop Working On The "+WarningDateStr+", Please Download The New Version From MQL4TradingAutomation.com"; + DrawExpiry(Name,EditText); + if(ShowAlert){ + Alert(AlertText); + Print(AlertText); + } + } +} + +//Draw a box to advise of the warning/expiry of the product +void DrawExpiry(string Name, string Text){ + string TextBoxName=Name+"ExpirationTextBox"; + if(ObjectFind(0,TextBoxName)<0){ + DrawEdit(TextBoxName,20,20,300,20,true,8,"",ALIGN_CENTER,"Arial",Text,true,clrNavy,clrKhaki,clrBlack); + } +} + +//Draw an edit box with the specified parameters +void DrawEdit( string Name, + int XStart, + int YStart, + int Width, + int Height, + bool ReadOnly, + int EditFontSize, + string Tooltip, + int Align, + string EditFont, + string Text, + bool Selectable, + color TextColor=clrBlack, + color BGColor=clrWhiteSmoke, + color BDColor=clrBlack + ){ + + ObjectCreate(0,Name,OBJ_EDIT,0,0,0); + ObjectSetInteger(0,Name,OBJPROP_XDISTANCE,XStart); + ObjectSetInteger(0,Name,OBJPROP_YDISTANCE,YStart); + ObjectSetInteger(0,Name,OBJPROP_XSIZE,Width); + ObjectSetInteger(0,Name,OBJPROP_YSIZE,Height); + ObjectSetInteger(0,Name,OBJPROP_BORDER_TYPE,BORDER_FLAT); + ObjectSetInteger(0,Name,OBJPROP_STATE,false); + ObjectSetInteger(0,Name,OBJPROP_HIDDEN,true); + ObjectSetInteger(0,Name,OBJPROP_READONLY,ReadOnly); + ObjectSetInteger(0,Name,OBJPROP_FONTSIZE,EditFontSize); + ObjectSetString(0,Name,OBJPROP_TOOLTIP,Tooltip); + ObjectSetInteger(0,Name,OBJPROP_ALIGN,Align); + ObjectSetString(0,Name,OBJPROP_FONT,EditFont); + ObjectSetString(0,Name,OBJPROP_TEXT,Text); + ObjectSetInteger(0,Name,OBJPROP_SELECTABLE,Selectable); + ObjectSetInteger(0,Name,OBJPROP_COLOR,TextColor); + ObjectSetInteger(0,Name,OBJPROP_BGCOLOR,BGColor); + ObjectSetInteger(0,Name,OBJPROP_BORDER_COLOR,BDColor); +} + + +string AccountCompany(){ + return AccountInfoString(ACCOUNT_COMPANY); +} + + +string AccountName(){ + return AccountInfoString(ACCOUNT_NAME); +} + + +long AccountNumber(){ + return AccountInfoInteger(ACCOUNT_LOGIN); +} + +string AccountCurrency(){ + return AccountInfoString(ACCOUNT_CURRENCY); +} + +double AccountBalance(){ + return AccountInfoDouble(ACCOUNT_BALANCE); +} + +double AccountEquity(){ + return AccountInfoDouble(ACCOUNT_EQUITY); +} + +double AccountFreeMargin(){ + return AccountInfoDouble(ACCOUNT_MARGIN_FREE); +} + +void SetIndex(int Index, int Type, int Style, int Width, int Color, string Label){ + PlotIndexSetInteger(Index,PLOT_DRAW_TYPE,Type); + PlotIndexSetInteger(Index,PLOT_LINE_STYLE,Style); + PlotIndexSetInteger(Index,PLOT_LINE_WIDTH,Width); + PlotIndexSetInteger(Index,PLOT_LINE_COLOR,Color); + PlotIndexSetString(Index,PLOT_LABEL,Label); +} + +int WindowFind(string Name){ + return ChartWindowFind(0,Name); +} + +string TimeFrameDescription(int TimeFrame){ + string perioddesc=""; + switch (TimeFrame){ + case PERIOD_M1: + perioddesc="M1"; + break; + case PERIOD_M2: + perioddesc="M2"; + break; + case PERIOD_M3: + perioddesc="M3"; + break; + case PERIOD_M4: + perioddesc="M4"; + break; + case PERIOD_M5: + perioddesc="M5"; + break; + case PERIOD_M6: + perioddesc="M6"; + break; + case PERIOD_M10: + perioddesc="M10"; + break; + case PERIOD_M12: + perioddesc="M12"; + break; + case PERIOD_M15: + perioddesc="M15"; + break; + case PERIOD_M20: + perioddesc="M20"; + break; + case PERIOD_M30: + perioddesc="M30"; + break; + case PERIOD_H1: + perioddesc="H1"; + break; + case PERIOD_H2: + perioddesc="H2"; + break; + case PERIOD_H3: + perioddesc="H3"; + break; + case PERIOD_H4: + perioddesc="H4"; + break; + case PERIOD_H6: + perioddesc="H6"; + break; + case PERIOD_H8: + perioddesc="H8"; + break; + case PERIOD_H12: + perioddesc="H12"; + break; + case PERIOD_D1: + perioddesc="D1"; + break; + case PERIOD_W1: + perioddesc="W1"; + break; + case PERIOD_MN1: + perioddesc="MN1"; + break; + } + return perioddesc; +} + + +string OrderSymbol(){ + return OrderGetString(ORDER_SYMBOL); +} + +long OrderMagicNumber(){ + return OrderGetInteger(ORDER_MAGIC); +} + +double OrderStopLoss(){ + return OrderGetDouble(ORDER_SL); +} + +double OrderTakeProfit(){ + return OrderGetDouble(ORDER_TP); +} + +ENUM_ORDER_TYPE OrderType(){ + return (ENUM_ORDER_TYPE)OrderGetInteger(ORDER_TYPE); +} + +long OrderTicket(){ + return OrderGetInteger(ORDER_TICKET); +} + +long OrderOpenTime(){ + return OrderGetInteger(ORDER_TIME_DONE); +} + +double OrderOpenPrice(){ + return OrderGetDouble(ORDER_PRICE_OPEN); +} + +double OrderLots(){ + return OrderGetDouble(ORDER_VOLUME_CURRENT); +} + +int Hour(){ + MqlDateTime mTime; + TimeCurrent(mTime); + return(mTime.hour); +} \ No newline at end of file diff --git a/MQL5/Include/errordescription.mqh b/MQL5/Include/errordescription.mqh new file mode 100644 index 0000000..db72831 --- /dev/null +++ b/MQL5/Include/errordescription.mqh @@ -0,0 +1,224 @@ +//+------------------------------------------------------------------+ +//| ErrorDescription.mqh | +//| Copyright 2010, MetaQuotes Software Corp. | +//| http://www.mql5.com | +//+------------------------------------------------------------------+ +#property copyright "2010, MetaQuotes Software Corp." +#property link "http://www.mql5.com" +#property version "1.00" +//+------------------------------------------------------------------+ +//| returns trade server return code description | +//+------------------------------------------------------------------+ +string TradeServerReturnCodeDescription(int return_code) + { +//--- + switch(return_code) + { + case TRADE_RETCODE_REQUOTE: return("Requote"); + case TRADE_RETCODE_REJECT: return("Request rejected"); + case TRADE_RETCODE_CANCEL: return("Request canceled by trader"); + case TRADE_RETCODE_PLACED: return("Order placed"); + case TRADE_RETCODE_DONE: return("Request completed"); + case TRADE_RETCODE_DONE_PARTIAL: return("Only part of the request was completed"); + case TRADE_RETCODE_ERROR: return("Request processing error"); + case TRADE_RETCODE_TIMEOUT: return("Request canceled by timeout"); + case TRADE_RETCODE_INVALID: return("Invalid request"); + case TRADE_RETCODE_INVALID_VOLUME: return("Invalid volume in the request"); + case TRADE_RETCODE_INVALID_PRICE: return("Invalid price in the request"); + case TRADE_RETCODE_INVALID_STOPS: return("Invalid stops in the request"); + case TRADE_RETCODE_TRADE_DISABLED: return("Trade is disabled"); + case TRADE_RETCODE_MARKET_CLOSED: return("Market is closed"); + case TRADE_RETCODE_NO_MONEY: return("There is not enough money to complete the request"); + case TRADE_RETCODE_PRICE_CHANGED: return("Prices changed"); + case TRADE_RETCODE_PRICE_OFF: return("There are no quotes to process the request"); + case TRADE_RETCODE_INVALID_EXPIRATION: return("Invalid order expiration date in the request"); + case TRADE_RETCODE_ORDER_CHANGED: return("Order state changed"); + case TRADE_RETCODE_TOO_MANY_REQUESTS: return("Too frequent requests"); + case TRADE_RETCODE_NO_CHANGES: return("No changes in request"); + case TRADE_RETCODE_SERVER_DISABLES_AT: return("Autotrading disabled by server"); + case TRADE_RETCODE_CLIENT_DISABLES_AT: return("Autotrading disabled by client terminal"); + case TRADE_RETCODE_LOCKED: return("Request locked for processing"); + case TRADE_RETCODE_FROZEN: return("Order or position frozen"); + case TRADE_RETCODE_INVALID_FILL: return("Invalid order filling type"); + case TRADE_RETCODE_CONNECTION: return("No connection with the trade server"); + case TRADE_RETCODE_ONLY_REAL: return("Operation is allowed only for live accounts"); + case TRADE_RETCODE_LIMIT_ORDERS: return("The number of pending orders has reached the limit"); + case TRADE_RETCODE_LIMIT_VOLUME: return("The volume of orders and positions for the symbol has reached the limit"); + } +//--- + return("Invalid return code of the trade server"); + } +//+------------------------------------------------------------------+ +//| returns runtime error code description | +//+------------------------------------------------------------------+ +string ErrorDescription(int err_code) + { +//--- + switch(err_code) + { + //--- Constant Description + case ERR_SUCCESS: return("The operation completed successfully"); + case ERR_INTERNAL_ERROR: return("Unexpected internal error"); + case ERR_WRONG_INTERNAL_PARAMETER: return("Wrong parameter in the inner call of the client terminal function"); + case ERR_INVALID_PARAMETER: return("Wrong parameter when calling the system function"); + case ERR_NOT_ENOUGH_MEMORY: return("Not enough memory to perform the system function"); + case ERR_STRUCT_WITHOBJECTS_ORCLASS: return("The structure contains objects of strings and/or dynamic arrays and/or structure of such objects and/or classes"); + case ERR_INVALID_ARRAY: return("Array of a wrong type, wrong size, or a damaged object of a dynamic array"); + case ERR_ARRAY_RESIZE_ERROR: return("Not enough memory for the relocation of an array, or an attempt to change the size of a static array"); + case ERR_STRING_RESIZE_ERROR: return("Not enough memory for the relocation of string"); + case ERR_NOTINITIALIZED_STRING: return("Not initialized string"); + case ERR_INVALID_DATETIME: return("Invalid date and/or time"); + case ERR_ARRAY_BAD_SIZE: return("Requested array size exceeds 2 GB"); + case ERR_INVALID_POINTER: return("Wrong pointer"); + case ERR_INVALID_POINTER_TYPE: return("Wrong type of pointer"); + case ERR_FUNCTION_NOT_ALLOWED: return("System function is not allowed to call"); + //--- Charts + case ERR_CHART_WRONG_ID: return("Wrong chart ID"); + case ERR_CHART_NO_REPLY: return("Chart does not respond"); + case ERR_CHART_NOT_FOUND: return("Chart not found"); + case ERR_CHART_NO_EXPERT: return("No Expert Advisor in the chart that could handle the event"); + case ERR_CHART_CANNOT_OPEN: return("Chart opening error"); + case ERR_CHART_CANNOT_CHANGE: return("Failed to change chart symbol and period"); + case ERR_CHART_CANNOT_CREATE_TIMER: return("Failed to create timer"); + case ERR_CHART_WRONG_PROPERTY: return("Wrong chart property ID"); + case ERR_CHART_SCREENSHOT_FAILED: return("Error creating screenshots"); + case ERR_CHART_NAVIGATE_FAILED: return("Error navigating through chart"); + case ERR_CHART_TEMPLATE_FAILED: return("Error applying template"); + case ERR_CHART_WINDOW_NOT_FOUND: return("Subwindow containing the indicator was not found"); + case ERR_CHART_INDICATOR_CANNOT_ADD: return("Error adding an indicator to chart"); + case ERR_CHART_INDICATOR_CANNOT_DEL: return("Error deleting an indicator from the chart"); + case ERR_CHART_INDICATOR_NOT_FOUND: return("Indicator not found on the specified chart"); + //--- Graphical Objects + case ERR_OBJECT_ERROR: return("Error working with a graphical object"); + case ERR_OBJECT_NOT_FOUND: return("Graphical object was not found"); + case ERR_OBJECT_WRONG_PROPERTY: return("Wrong ID of a graphical object property"); + case ERR_OBJECT_GETDATE_FAILED: return("Unable to get date corresponding to the value"); + case ERR_OBJECT_GETVALUE_FAILED: return("Unable to get value corresponding to the date"); + //--- MarketInfo + case ERR_MARKET_UNKNOWN_SYMBOL: return("Unknown symbol"); + case ERR_MARKET_NOT_SELECTED: return("Symbol is not selected in MarketWatch"); + case ERR_MARKET_WRONG_PROPERTY: return("Wrong identifier of a symbol property"); + case ERR_MARKET_LASTTIME_UNKNOWN: return("Time of the last tick is not known (no ticks)"); + case ERR_MARKET_SELECT_ERROR: return("Error adding or deleting a symbol in MarketWatch"); + //--- History Access + case ERR_HISTORY_NOT_FOUND: return("Requested history not found"); + case ERR_HISTORY_WRONG_PROPERTY: return("Wrong ID of the history property"); + //--- Global_Variables + case ERR_GLOBALVARIABLE_NOT_FOUND: return("Global variable of the client terminal is not found"); + case ERR_GLOBALVARIABLE_EXISTS: return("Global variable of the client terminal with the same name already exists"); + case ERR_MAIL_SEND_FAILED: return("Email sending failed"); + case ERR_PLAY_SOUND_FAILED: return("Sound playing failed"); + case ERR_MQL5_WRONG_PROPERTY: return("Wrong identifier of the program property"); + case ERR_TERMINAL_WRONG_PROPERTY: return("Wrong identifier of the terminal property"); + case ERR_FTP_SEND_FAILED: return("File sending via ftp failed"); + case ERR_NOTIFICATION_SEND_FAILED: return("Error in sending notification"); + //--- Custom Indicator Buffers + case ERR_BUFFERS_NO_MEMORY: return("Not enough memory for the distribution of indicator buffers"); + case ERR_BUFFERS_WRONG_INDEX: return("Wrong indicator buffer index"); + //--- Custom Indicator Properties + case ERR_CUSTOM_WRONG_PROPERTY: return("Wrong ID of the custom indicator property"); + //--- Account + case ERR_ACCOUNT_WRONG_PROPERTY: return("Wrong account property ID"); + case ERR_TRADE_WRONG_PROPERTY: return("Wrong trade property ID"); + case ERR_TRADE_DISABLED: return("Trading by Expert Advisors prohibited"); + case ERR_TRADE_POSITION_NOT_FOUND: return("Position not found"); + case ERR_TRADE_ORDER_NOT_FOUND: return("Order not found"); + case ERR_TRADE_DEAL_NOT_FOUND: return("Deal not found"); + case ERR_TRADE_SEND_FAILED: return("Trade request sending failed"); + //--- Indicators + case ERR_INDICATOR_UNKNOWN_SYMBOL: return("Unknown symbol"); + case ERR_INDICATOR_CANNOT_CREATE: return("Indicator cannot be created"); + case ERR_INDICATOR_NO_MEMORY: return("Not enough memory to add the indicator"); + case ERR_INDICATOR_CANNOT_APPLY: return("The indicator cannot be applied to another indicator"); + case ERR_INDICATOR_CANNOT_ADD: return("Error applying an indicator to chart"); + case ERR_INDICATOR_DATA_NOT_FOUND: return("Requested data not found"); + case ERR_INDICATOR_WRONG_HANDLE: return("Wrong indicator handle"); + case ERR_INDICATOR_WRONG_PARAMETERS: return("Wrong number of parameters when creating an indicator"); + case ERR_INDICATOR_PARAMETERS_MISSING: return("No parameters when creating an indicator"); + case ERR_INDICATOR_CUSTOM_NAME: return("The first parameter in the array must be the name of the custom indicator"); + case ERR_INDICATOR_PARAMETER_TYPE: return("Invalid parameter type in the array when creating an indicator"); + case ERR_INDICATOR_WRONG_INDEX: return("Wrong index of the requested indicator buffer"); + //--- Depth of Market + case ERR_BOOKS_CANNOT_ADD: return("Depth Of Market can not be added"); + case ERR_BOOKS_CANNOT_DELETE: return("Depth Of Market can not be removed"); + case ERR_BOOKS_CANNOT_GET: return("The data from Depth Of Market can not be obtained"); + case ERR_BOOKS_CANNOT_SUBSCRIBE: return("Error in subscribing to receive new data from Depth Of Market"); + //--- File Operations + case ERR_TOO_MANY_FILES: return("More than 64 files cannot be opened at the same time"); + case ERR_WRONG_FILENAME: return("Invalid file name"); + case ERR_TOO_LONG_FILENAME: return("Too long file name"); + case ERR_CANNOT_OPEN_FILE: return("File opening error"); + case ERR_FILE_CACHEBUFFER_ERROR: return("Not enough memory for cache to read"); + case ERR_CANNOT_DELETE_FILE: return("File deleting error"); + case ERR_INVALID_FILEHANDLE: return("A file with this handle was closed, or was not opening at all"); + case ERR_WRONG_FILEHANDLE: return("Wrong file handle"); + case ERR_FILE_NOTTOWRITE: return("The file must be opened for writing"); + case ERR_FILE_NOTTOREAD: return("The file must be opened for reading"); + case ERR_FILE_NOTBIN: return("The file must be opened as a binary one"); + case ERR_FILE_NOTTXT: return("The file must be opened as a text"); + case ERR_FILE_NOTTXTORCSV: return("The file must be opened as a text or CSV"); + case ERR_FILE_NOTCSV: return("The file must be opened as CSV"); + case ERR_FILE_READERROR: return("File reading error"); + case ERR_FILE_BINSTRINGSIZE: return("String size must be specified, because the file is opened as binary"); + case ERR_INCOMPATIBLE_FILE: return("A text file must be for string arrays, for other arrays - binary"); + case ERR_FILE_IS_DIRECTORY: return("This is not a file, this is a directory"); + case ERR_FILE_NOT_EXIST: return("File does not exist"); + case ERR_FILE_CANNOT_REWRITE: return("File can not be rewritten"); + case ERR_WRONG_DIRECTORYNAME: return("Wrong directory name"); + case ERR_DIRECTORY_NOT_EXIST: return("Directory does not exist"); + case ERR_FILE_ISNOT_DIRECTORY: return("This is a file, not a directory"); + case ERR_CANNOT_DELETE_DIRECTORY: return("The directory cannot be removed"); + case ERR_CANNOT_CLEAN_DIRECTORY: return("Failed to clear the directory (probably one or more files are blocked and removal operation failed)"); + case ERR_FILE_WRITEERROR: return("Failed to write a resource to a file"); + //--- String Casting + case ERR_NO_STRING_DATE: return("No date in the string"); + case ERR_WRONG_STRING_DATE: return("Wrong date in the string"); + case ERR_WRONG_STRING_TIME: return("Wrong time in the string"); + case ERR_STRING_TIME_ERROR: return("Error converting string to date"); + case ERR_STRING_OUT_OF_MEMORY: return("Not enough memory for the string"); + case ERR_STRING_SMALL_LEN: return("The string length is less than expected"); + case ERR_STRING_TOO_BIGNUMBER: return("Too large number, more than ULONG_MAX"); + case ERR_WRONG_FORMATSTRING: return("Invalid format string"); + case ERR_TOO_MANY_FORMATTERS: return("Amount of format specifiers more than the parameters"); + case ERR_TOO_MANY_PARAMETERS: return("Amount of parameters more than the format specifiers"); + case ERR_WRONG_STRING_PARAMETER: return("Damaged parameter of string type"); + case ERR_STRINGPOS_OUTOFRANGE: return("Position outside the string"); + case ERR_STRING_ZEROADDED: return("0 added to the string end, a useless operation"); + case ERR_STRING_UNKNOWNTYPE: return("Unknown data type when converting to a string"); + case ERR_WRONG_STRING_OBJECT: return("Damaged string object"); + //--- Operations with Arrays + case ERR_INCOMPATIBLE_ARRAYS: return("Copying incompatible arrays. String array can be copied only to a string array, and a numeric array - in numeric array only"); + case ERR_SMALL_ASSERIES_ARRAY: return("The receiving array is declared as AS_SERIES, and it is of insufficient size"); + case ERR_SMALL_ARRAY: return("Too small array, the starting position is outside the array"); + case ERR_ZEROSIZE_ARRAY: return("An array of zero length"); + case ERR_NUMBER_ARRAYS_ONLY: return("Must be a numeric array"); + case ERR_ONEDIM_ARRAYS_ONLY: return("Must be a one-dimensional array"); + case ERR_SERIES_ARRAY: return("Timeseries cannot be used"); + case ERR_DOUBLE_ARRAY_ONLY: return("Must be an array of type double"); + case ERR_FLOAT_ARRAY_ONLY: return("Must be an array of type float"); + case ERR_LONG_ARRAY_ONLY: return("Must be an array of type long"); + case ERR_INT_ARRAY_ONLY: return("Must be an array of type int"); + case ERR_SHORT_ARRAY_ONLY: return("Must be an array of type short"); + case ERR_CHAR_ARRAY_ONLY: return("Must be an array of type char"); + //--- Operations with OpenCL + case ERR_OPENCL_NOT_SUPPORTED: return("OpenCL functions are not supported on this computer"); + case ERR_OPENCL_INTERNAL: return("Internal error occurred when running OpenCL"); + case ERR_OPENCL_INVALID_HANDLE: return("Invalid OpenCL handle"); + case ERR_OPENCL_CONTEXT_CREATE: return("Error creating the OpenCL context"); + case ERR_OPENCL_QUEUE_CREATE: return("Failed to create a run queue in OpenCL"); + case ERR_OPENCL_PROGRAM_CREATE: return("Error occurred when compiling an OpenCL program"); + case ERR_OPENCL_TOO_LONG_KERNEL_NAME: return("Too long kernel name (OpenCL kernel)"); + case ERR_OPENCL_KERNEL_CREATE: return("Error creating an OpenCL kernel"); + case ERR_OPENCL_SET_KERNEL_PARAMETER: return("Error occurred when setting parameters for the OpenCL kernel"); + case ERR_OPENCL_EXECUTE: return("OpenCL program runtime error"); + case ERR_OPENCL_WRONG_BUFFER_SIZE: return("Invalid size of the OpenCL buffer"); + case ERR_OPENCL_WRONG_BUFFER_OFFSET: return("Invalid offset in the OpenCL buffer"); + case ERR_OPENCL_BUFFER_CREATE: return("Failed to create and OpenCL buffer"); + //--- User-Defined Errors + default: if(err_code>=ERR_USER_ERROR_FIRST && err_code