diff --git a/MQL4/Experts/Position Sizer/Defines.mqh b/MQL4/Experts/Position Sizer/Defines.mqh index 8dcd479..8776911 100644 --- a/MQL4/Experts/Position Sizer/Defines.mqh +++ b/MQL4/Experts/Position Sizer/Defines.mqh @@ -23,6 +23,8 @@ color DARKMODE_EDIT_BG_COLOR = 0xAAAAAA; color DARKMODE_BUTTON_BG_COLOR = 0xA19999; color DARKMODE_TEXT_COLOR = 0x000000;; +color CONTROLS_BUTTON_COLOR_TP_UNLOCKED, CONTROLS_BUTTON_COLOR_TP_LOCKED; + enum ENTRY_TYPE { Instant, @@ -132,6 +134,8 @@ struct Settings int MaxEntrySLDistance; int MinEntrySLDistance; // For SL/TP distance modes: + bool SLDistanceInPoints; + bool TPDistanceInPoints; int StopLoss; int TakeProfit; // Only for SL distance mode: @@ -151,6 +155,7 @@ struct Settings double MaxPositionSizePerSymbol; double MaxRiskTotal; double MaxRiskPerSymbol; + int ExpiryMinutes; // For ATR: int ATRPeriod; double ATRMultiplierSL; diff --git a/MQL4/Experts/Position Sizer/Position Sizer Trading.mqh b/MQL4/Experts/Position Sizer/Position Sizer Trading.mqh index 8408812..b9e8f3b 100644 --- a/MQL4/Experts/Position Sizer/Position Sizer Trading.mqh +++ b/MQL4/Experts/Position Sizer/Position Sizer Trading.mqh @@ -240,6 +240,12 @@ void Trade() } } + datetime expiry = 0; + if ((sets.EntryType == Pending) && (sets.ExpiryMinutes > 0)) + { + expiry = TimeCurrent() + sets.ExpiryMinutes * 60; + } + if (sets.AskForConfirmation) { // Evoke confirmation modal window. @@ -281,9 +287,13 @@ void Trade() if (PositionMargin != 0) message += "Margin: " + FormatDouble(DoubleToString(PositionMargin, 2)) + " " + account_currency + "\n"; message += "Entry: " + DoubleToString(sets.EntryLevel, _Digits) + "\n"; if (!sets.DoNotApplyStopLoss) message += "Stop-loss: " + DoubleToString(sets.StopLossLevel, _Digits) + "\n"; - if ((sets.TakeProfitLevel > 0) && (!sets.DoNotApplyTakeProfit)) message += "Take-profit: " + DoubleToString(sets.TakeProfitLevel, _Digits); - if (sets.TakeProfitsNumber > 1) message += " (multiple)"; - message += "\n"; + if ((sets.TakeProfitLevel > 0) && (!sets.DoNotApplyTakeProfit)) + { + message += "Take-profit: " + DoubleToString(sets.TakeProfitLevel, _Digits); + if (sets.TakeProfitsNumber > 1) message += " (multiple)"; + message += "\n"; + } + if (expiry > 0) message += "Expiry: " + TimeToString(expiry, TIME_DATE|TIME_MINUTES|TIME_SECONDS); int ret = MessageBox(message, caption, MB_OKCANCEL | MB_ICONWARNING); if (ret == IDCANCEL) @@ -363,7 +373,7 @@ void Trade() sub_position_size = position_size; position_size = 0; // End the cycle; } - int ticket = OrderSend(Symbol(), ot, sub_position_size, sets.EntryLevel, sets.MaxSlippage, order_sl, order_tp, Commentary, sets.MagicNumber); + int ticket = OrderSend(Symbol(), ot, sub_position_size, sets.EntryLevel, sets.MaxSlippage, order_sl, order_tp, Commentary, sets.MagicNumber, expiry); if (ticket == -1) { int error = GetLastError(); diff --git a/MQL4/Experts/Position Sizer/Position Sizer.mq4 b/MQL4/Experts/Position Sizer/Position Sizer.mq4 index a6db31f..3c56749 100644 --- a/MQL4/Experts/Position Sizer/Position Sizer.mq4 +++ b/MQL4/Experts/Position Sizer/Position Sizer.mq4 @@ -6,8 +6,8 @@ #property copyright "EarnForex.com" #property link "https://www.earnforex.com/metatrader-expert-advisors/Position-Sizer/" #property icon "EF-Icon-64x64px.ico" -#property version "3.06" -string Version = "3.06"; +#property version "3.063" +string Version = "3.063"; #property strict #property description "Calculates risk-based position size for your account." @@ -23,6 +23,7 @@ input string ____Compactness = ""; input bool ShowLineLabels = true; // ShowLineLabels: Show point distance for TP/SL near lines? input bool ShowAdditionalSLLabel = false; // ShowAdditionalSLLabel: Show SL $/% label? input bool ShowAdditionalTPLabel = false; // ShowAdditionalTPLabel: Show TP $/% + R/R label? +input bool ShowAdditionalEntryLabel = false; // ShowAdditionalEntryLabel: Show Position Size label? input bool DrawTextAsBackground = false; // DrawTextAsBackground: Draw label objects as background? input bool HideAccSize = false; // HideAccSize: Hide account size? input bool ShowPointValue = false; // ShowPointValue: Show point value? @@ -34,16 +35,16 @@ input bool ShowFusesOnTrading = true; // Show trading "fuses" on Trading tab? input bool ShowCheckboxesOnTrading = true; // Show checkboxes on Trading tab? input group "Fonts" input string ____Fonts = ""; -input color sl_label_font_color = clrLime; // SL Label Color -input color tp_label_font_color = clrYellow; // TP Label Font Color +input color sl_label_font_color = clrGreen; // SL Label Color +input color tp_label_font_color = clrGoldenrod; // TP Label Font Color input color entry_label_font_color = clrBlue; // Entry Label Font Color input uint font_size = 13; // Labels Font Size input string font_face = "Courier"; // Labels Font Face input group "Lines" input string ____Lines = ""; input color entry_line_color = clrBlue; // Entry Line Color -input color stoploss_line_color = clrLime; // Stop-Loss Line Color -input color takeprofit_line_color = clrYellow; // Take-Profit Line Color +input color stoploss_line_color = clrGreen; // Stop-Loss Line Color +input color takeprofit_line_color = clrGoldenrod; // Take-Profit Line Color input color be_line_color = clrNONE; // BE Line Color input ENUM_LINE_STYLE entry_line_style = STYLE_SOLID; // Entry Line Style input ENUM_LINE_STYLE stoploss_line_style = STYLE_SOLID; // Stop-Loss Line Style @@ -100,10 +101,13 @@ input ENUM_BASE_CORNER DefaultPanelPositionCorner = CORNER_LEFT_UPPER; // PanelP input bool DefaultTPLockedOnSL = false; // TPLockedOnSL: Lock TP to (multiplied) SL distance. input int DefaultTrailingStop = 0; // TrailingStop: For the Trading tab. input int DefaultBreakEven = 0; // BreakEven: For the Trading tab. +input int DefaultExpiryMinutes = 0; // ExpiryMinutes: Pending order expiration in minutes. Min = 10. input int DefaultMaxNumberOfTradesTotal = 0; // MaxNumberOfTradesTotal: For the Trading tab. 0 - no limit. input int DefaultMaxNumberOfTradesPerSymbol = 0; // MaxNumberOfTradesPerSymbol: For the Trading tab. 0 - no limit. input double DefaultMaxRiskTotal = 0; // MaxRiskTotal: For the Trading tab. 0 - no limit. input double DefaultMaxRiskPerSymbol = 0; // MaxRiskPerSymbol: For the Trading tab. 0 - no limit. +input bool DefaultSLDistanceInPoints = false; // SLDistanceInPoints: SL distance in points instead of a level. +input bool DefaultTPDistanceInPoints = false; // TPDistanceInPoints: TP distance in points instead of a level. input group "Keyboard shortcuts" input string ____Keyboard_Shortcuts = "Case-insensitive hotkey. Supports Ctrl, Shift."; input string TradeHotKey = "T"; // TradeHotKey: Execute a trade. @@ -113,6 +117,9 @@ input string SwitchHideShowLinesHotKey = "H"; // SwitchHideShowLinesHotKey: Swit input string SetStopLossHotKey = "S"; // SetStopLossHotKey: Set SL to where mouse pointer is. input string SetTakeProfitHotKey = "P"; // SetTakeProfitHotKey: Set TP to where mouse pointer is. input string SetEntryHotKey = "E"; // SetEntryHotKey: Set Entry to where mouse pointer is. +input string MinimizeMaximizeHotkey = "`"; // MinimizeMaximizeHotkey: Minimize/maximize the panel. +input string SwitchSLPointsLevelHotKey = "Shift+S"; // SwitchSLPointsLevelHotKey: Switch SL between points and level. +input string SwitchTPPointsLevelHotKey = "Shift+P"; // SwitchTPPointsLevelHotKey: Switch TP between points and level. input group "Miscellaneous" input string ____Miscellaneous = ""; input double TP_Multiplier = 1; // TP Multiplier for SL value, appears in Take-profit button. @@ -120,8 +127,6 @@ input bool UseCommissionToSetTPDistance = false; // UseCommissionToSetTPDistance input SHOW_SPREAD ShowSpread = No; // ShowSpread: Show current spread in points or as an SL ratio. input double AdditionalFunds = 0; // AdditionalFunds: Added to account balance for risk calculation. input double CustomBalance = 0; // CustomBalance: Overrides AdditionalFunds value. -input bool SLDistanceInPoints = false; // SLDistanceInPoints: SL distance in points instead of a level. -input bool TPDistanceInPoints = false; // TPDistanceInPoints: TP distance in points instead of a level. input CANDLE_NUMBER ATRCandle = Current_Candle; // ATRCandle: Candle to get ATR value from. input bool CalculateUnadjustedPositionSize = false; // CalculateUnadjustedPositionSize: Ignore broker's restrictions. input bool SurpassBrokerMaxPositionSize = false; // Surpass Broker Max Position Size with multiple trades. @@ -144,9 +149,9 @@ bool Dont_Move_the_Panel_to_Default_Corner_X_Y; uint LastRecalculationTime = 0; bool StopLossLineIsBeingMoved = false; bool TakeProfitLineIsBeingMoved[]; // Separate for each TP. -uchar MainKey_TradeHotKey = 0, MainKey_SwitchOrderTypeHotKey = 0, MainKey_SwitchEntryDirectionHotKey = 0, MainKey_SwitchHideShowLinesHotKey = 0, MainKey_SetStopLossHotKey = 0, MainKey_SetTakeProfitHotKey = 0, MainKey_SetEntryHotKey = 0; -bool CtrlRequired_TradeHotKey = false, CtrlRequired_SwitchOrderTypeHotKey = false, CtrlRequired_SwitchEntryDirectionHotKey = false, CtrlRequired_SwitchHideShowLinesHotKey = false, CtrlRequired_SetStopLossHotKey = false, CtrlRequired_SetTakeProfitHotKey = false, CtrlRequired_SetEntryHotKey = false;; -bool ShiftRequired_TradeHotKey = false, ShiftRequired_SwitchOrderTypeHotKey = false, ShiftRequired_SwitchEntryDirectionHotKey = false, ShiftRequired_SwitchHideShowLinesHotKey = false, ShiftRequired_SetStopLossHotKey = false, ShiftRequired_SetTakeProfitHotKey = false, ShiftRequired_SetEntryHotKey = false; +uchar MainKey_TradeHotKey = 0, MainKey_SwitchOrderTypeHotKey = 0, MainKey_SwitchEntryDirectionHotKey = 0, MainKey_SwitchHideShowLinesHotKey = 0, MainKey_SetStopLossHotKey = 0, MainKey_SetTakeProfitHotKey = 0, MainKey_SetEntryHotKey = 0, MainKey_MinimizeMaximizeHotkey = 0, MainKey_SwitchSLPointsLevelHotKey = 0, MainKey_SwitchTPPointsLevelHotKey = 0; +bool CtrlRequired_TradeHotKey = false, CtrlRequired_SwitchOrderTypeHotKey = false, CtrlRequired_SwitchEntryDirectionHotKey = false, CtrlRequired_SwitchHideShowLinesHotKey = false, CtrlRequired_SetStopLossHotKey = false, CtrlRequired_SetTakeProfitHotKey = false, CtrlRequired_SetEntryHotKey = false, CtrlRequired_MinimizeMaximizeHotkey = false, CtrlRequired_SwitchSLPointsLevelHotKey = false, CtrlRequired_SwitchTPPointsLevelHotKey = false; +bool ShiftRequired_TradeHotKey = false, ShiftRequired_SwitchOrderTypeHotKey = false, ShiftRequired_SwitchEntryDirectionHotKey = false, ShiftRequired_SwitchHideShowLinesHotKey = false, ShiftRequired_SetStopLossHotKey = false, ShiftRequired_SetTakeProfitHotKey = false, ShiftRequired_SetEntryHotKey = false, ShiftRequired_MinimizeMaximizeHotkey = false, ShiftRequired_SwitchSLPointsLevelHotKey = false, ShiftRequired_SwitchTPPointsLevelHotKey = false; bool NeedToCheckToggleScaleOffOn; int PrevChartWidth = -1; int DeinitializationReason = -1; @@ -162,6 +167,8 @@ int OnInit() CONTROLS_EDIT_COLOR_DISABLE = 0x999999; CONTROLS_BUTTON_COLOR_ENABLE = DARKMODE_BUTTON_BG_COLOR; CONTROLS_BUTTON_COLOR_DISABLE = 0x919999; + CONTROLS_BUTTON_COLOR_TP_UNLOCKED = DARKMODE_BUTTON_BG_COLOR; + CONTROLS_BUTTON_COLOR_TP_LOCKED = 0x909090; } else { @@ -169,6 +176,8 @@ int OnInit() CONTROLS_EDIT_COLOR_DISABLE = C'221,221,211'; CONTROLS_BUTTON_COLOR_ENABLE = C'200,200,200'; CONTROLS_BUTTON_COLOR_DISABLE = C'224,224,224'; + CONTROLS_BUTTON_COLOR_TP_UNLOCKED = CONTROLS_BUTTON_COLOR_BG; + CONTROLS_BUTTON_COLOR_TP_LOCKED = CONTROLS_BUTTON_COLOR_ENABLE; } TickSize = -1; @@ -295,6 +304,8 @@ int OnInit() sets.TPLockedOnSL = DefaultTPLockedOnSL; sets.TrailingStopPoints = DefaultTrailingStop; sets.BreakEvenPoints = DefaultBreakEven; + sets.ExpiryMinutes = DefaultExpiryMinutes; + if ((sets.ExpiryMinutes != 0) && (sets.ExpiryMinutes < 10)) sets.ExpiryMinutes = 0; sets.MaxNumberOfTradesTotal = DefaultMaxNumberOfTradesTotal; sets.MaxNumberOfTradesPerSymbol = DefaultMaxNumberOfTradesPerSymbol; if ((sets.MaxNumberOfTradesTotal < sets.MaxNumberOfTradesPerSymbol) && (sets.MaxNumberOfTradesTotal != 0)) sets.MaxNumberOfTradesTotal = sets.MaxNumberOfTradesPerSymbol; @@ -303,9 +314,20 @@ int OnInit() if ((sets.MaxRiskTotal < sets.MaxRiskPerSymbol) && (sets.MaxRiskTotal != 0)) sets.MaxRiskTotal = sets.MaxRiskPerSymbol; sets.ShareVolumeMode = Decreasing; sets.TemplateChanged = false; + sets.SLDistanceInPoints = DefaultSLDistanceInPoints; + sets.TPDistanceInPoints = DefaultTPDistanceInPoints; if (DeinitializationReason == REASON_CHARTCHANGE) is_InitControlsValues_required = true; } - if (sets.TakeProfitsNumber < 1) sets.TakeProfitsNumber = 1; // At least one TP. + if (sets.TakeProfitsNumber < 1) // Read an old settings file with absent or bogus TakeProfitNumber parameter + { + sets.TakeProfitsNumber = 1; // At least one TP. + ArrayResize(sets.TP, sets.TakeProfitsNumber); + ArrayResize(sets.TPShare, sets.TakeProfitsNumber); + ArrayResize(TakeProfitLineIsBeingMoved, sets.TakeProfitsNumber); + ArrayInitialize(sets.TP, 0); + ArrayInitialize(sets.TPShare, 100 / sets.TakeProfitsNumber); + ArrayResize(sets.WasSelectedAdditionalTakeProfitLine, sets.TakeProfitsNumber - 1); // -1 because the flag for the main TP is saved elsewhere. + } if (DeinitializationReason != REASON_CHARTCHANGE) { if (!ExtDialog.Create(0, "Position Sizer (ver. " + Version + ")", 0, DefaultPanelPositionX, DefaultPanelPositionY)) return INIT_FAILED; @@ -326,6 +348,9 @@ int OnInit() if (SetStopLossHotKey != "") DissectHotKeyCombination(SetStopLossHotKey, ShiftRequired_SetStopLossHotKey, CtrlRequired_SetStopLossHotKey, MainKey_SetStopLossHotKey); if (SetTakeProfitHotKey != "") DissectHotKeyCombination(SetTakeProfitHotKey, ShiftRequired_SetTakeProfitHotKey, CtrlRequired_SetTakeProfitHotKey, MainKey_SetTakeProfitHotKey); if (SetEntryHotKey != "") DissectHotKeyCombination(SetEntryHotKey, ShiftRequired_SetEntryHotKey, CtrlRequired_SetEntryHotKey, MainKey_SetEntryHotKey); + if (SwitchSLPointsLevelHotKey != "") DissectHotKeyCombination(SwitchSLPointsLevelHotKey, ShiftRequired_SwitchSLPointsLevelHotKey, CtrlRequired_SwitchSLPointsLevelHotKey, MainKey_SwitchSLPointsLevelHotKey); + if (SwitchTPPointsLevelHotKey != "") DissectHotKeyCombination(SwitchTPPointsLevelHotKey, ShiftRequired_SwitchTPPointsLevelHotKey, CtrlRequired_SwitchTPPointsLevelHotKey, MainKey_SwitchTPPointsLevelHotKey); + if (MinimizeMaximizeHotkey != "") DissectHotKeyCombination(MinimizeMaximizeHotkey, ShiftRequired_MinimizeMaximizeHotkey, CtrlRequired_MinimizeMaximizeHotkey, MainKey_MinimizeMaximizeHotkey); } else if (OldSymbol != _Symbol) { @@ -428,7 +453,6 @@ int OnInit() { string obj_name = ObjectName(ChartID(), i); if (StringSubstr(obj_name, 0, StringLen(ExtDialog.Name())) != ExtDialog.Name()) continue; // Skip non-panel objects. - //if (ObjectType(obj_name) != OBJ_RECTANGLE_LABEL) continue; if (obj_name == ExtDialog.Name() + "Back") { @@ -450,6 +474,10 @@ int OnInit() ObjectSetInteger(ChartID(), obj_name, OBJPROP_BGCOLOR, DARKMODE_EDIT_BG_COLOR); ObjectSetInteger(ChartID(), obj_name, OBJPROP_BORDER_COLOR, DARKMODE_CONTROL_BRODER_COLOR); } + else if (obj_name == ExtDialog.Name() + "m_BtnTakeProfit") // TakeProfit button has its own colors. + { + ObjectSetInteger(ChartID(), obj_name, OBJPROP_BORDER_COLOR, DARKMODE_CONTROL_BRODER_COLOR); + } else if (StringSubstr(obj_name, 0, StringLen(ExtDialog.Name() + "m_Btn")) == ExtDialog.Name() + "m_Btn") { ObjectSetInteger(ChartID(), obj_name, OBJPROP_BGCOLOR, DARKMODE_BUTTON_BG_COLOR); @@ -539,7 +567,7 @@ void OnChartEvent(const int id, Mouse_Last_Y = (int)dparam; if (((uint)sparam & 1) == 1) // While left mouse button is down. { - if ((SLDistanceInPoints) || ((ShowATROptions) && (sets.ATRMultiplierSL > 0))) + if ((sets.SLDistanceInPoints) || ((ShowATROptions) && (sets.ATRMultiplierSL > 0))) { double current_line_price = NormalizeDouble(ObjectGetDouble(ChartID(), ObjectPrefix + "StopLossLine", OBJPROP_PRICE, 0), _Digits); if (MathAbs(current_line_price - tStopLossLevel) > _Point / 2.0) // != for doubles. @@ -548,7 +576,7 @@ void OnChartEvent(const int id, } else StopLossLineIsBeingMoved = false; } - if ((TPDistanceInPoints) || ((ShowATROptions) && (sets.ATRMultiplierTP > 0))) + if ((sets.TPDistanceInPoints) || ((ShowATROptions) && (sets.ATRMultiplierTP > 0))) { ArrayInitialize(TakeProfitLineIsBeingMoved, false); double current_line_price = NormalizeDouble(ObjectGetDouble(ChartID(), ObjectPrefix + "TakeProfitLine", OBJPROP_PRICE, 0), _Digits); @@ -650,109 +678,146 @@ void OnChartEvent(const int id, if (id == CHARTEVENT_KEYDOWN) { // Trade direction: - if ((MainKey_SwitchEntryDirectionHotKey != 0) && (lparam == MainKey_SwitchEntryDirectionHotKey)) + if ((MainKey_SwitchEntryDirectionHotKey != 0) && (lparam == MainKey_SwitchEntryDirectionHotKey) + && ((((!ShiftRequired_SwitchEntryDirectionHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_SwitchEntryDirectionHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_SwitchEntryDirectionHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_SwitchEntryDirectionHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0)))) // Control + ) { - if (((!ShiftRequired_SwitchEntryDirectionHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0)) // Shift - && ((!CtrlRequired_SwitchEntryDirectionHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))) // Control - { - SwitchEntryDirection(); - } + SwitchEntryDirection(); } // Order type: - else if ((MainKey_SwitchOrderTypeHotKey != 0) && (lparam == MainKey_SwitchOrderTypeHotKey)) + else if ((MainKey_SwitchOrderTypeHotKey != 0) && (lparam == MainKey_SwitchOrderTypeHotKey) + && ((((!ShiftRequired_SwitchOrderTypeHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_SwitchOrderTypeHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_SwitchOrderTypeHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_SwitchOrderTypeHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))))) // Control { - if (((!ShiftRequired_SwitchOrderTypeHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0)) // Shift - && ((!CtrlRequired_SwitchOrderTypeHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))) // Control - { - ExtDialog.OnClickBtnOrderType(); - } + ExtDialog.OnClickBtnOrderType(); } // Hide/Show lines: - else if ((MainKey_SwitchHideShowLinesHotKey != 0) && (lparam == MainKey_SwitchHideShowLinesHotKey)) + else if ((MainKey_SwitchHideShowLinesHotKey != 0) && (lparam == MainKey_SwitchHideShowLinesHotKey) + && ((((!ShiftRequired_SwitchHideShowLinesHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_SwitchHideShowLinesHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_SwitchHideShowLinesHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_SwitchHideShowLinesHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))))) // Control { - if (((!ShiftRequired_SwitchHideShowLinesHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0)) // Shift - && ((!CtrlRequired_SwitchHideShowLinesHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))) // Control - { - ExtDialog.OnClickBtnLines(); - } - } + ExtDialog.OnClickBtnLines(); + } // Trade: - else if ((MainKey_TradeHotKey != 0) && (lparam == MainKey_TradeHotKey)) + else if ((MainKey_TradeHotKey != 0) && (lparam == MainKey_TradeHotKey) + && ((((!ShiftRequired_TradeHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_TradeHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_TradeHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_TradeHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))))) // Control + { + Trade(); + } + // Set stop-loss: + else if ((MainKey_SetStopLossHotKey != 0) && (lparam == MainKey_SetStopLossHotKey) + && ((((!ShiftRequired_SetStopLossHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_SetStopLossHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_SetStopLossHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_SetStopLossHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))))) // Control { - if (((!ShiftRequired_TradeHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0)) // Shift - && ((!CtrlRequired_TradeHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))) // Control + // Capture point price location. + int subwindow; + double price; + datetime time; // Dummy. + ChartXYToTimePrice(ChartID(), Mouse_Last_X, Mouse_Last_Y, subwindow, time, price); + // If valid, move the SL line there. + if ((subwindow == 0) && (price > 0)) { - Trade(); + if (TickSize > 0) price = NormalizeDouble(MathRound(price / TickSize) * TickSize, _Digits); + ObjectSetDouble(ChartID(), ObjectPrefix + "StopLossLine", OBJPROP_PRICE, price); + if ((sets.SLDistanceInPoints) || (ShowATROptions)) ExtDialog.UpdateFixedSL(); + ExtDialog.RefreshValues(); } } - // Set stop-loss: - else if ((MainKey_SetStopLossHotKey != 0) && (lparam == MainKey_SetStopLossHotKey)) + // Set take-profit: + else if ((MainKey_SetTakeProfitHotKey != 0) && (lparam == MainKey_SetTakeProfitHotKey) + && ((((!ShiftRequired_SetTakeProfitHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_SetTakeProfitHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_SetTakeProfitHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_SetTakeProfitHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))))) // Control { - if (((!ShiftRequired_SetStopLossHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0)) // Shift - && ((!CtrlRequired_SetStopLossHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))) // Control + // Capture point price location. + int subwindow; + double price; + datetime time; // Dummy. + ChartXYToTimePrice(ChartID(), Mouse_Last_X, Mouse_Last_Y, subwindow, time, price); + // If valid, move the TP line there. + if ((subwindow == 0) && (price > 0)) { - // Capture point price location. - int subwindow; - double price; - datetime time; // Dummy. - ChartXYToTimePrice(ChartID(), Mouse_Last_X, Mouse_Last_Y, subwindow, time, price); - // If valid, move the SL line there. - if ((subwindow == 0) && (price > 0)) + // If "TP locked on SL" mode was on, turn it off. + if (sets.TPLockedOnSL) { - if (TickSize > 0) price = NormalizeDouble(MathRound(price / TickSize) * TickSize, _Digits); - ObjectSetDouble(ChartID(), ObjectPrefix + "StopLossLine", OBJPROP_PRICE, price); - if ((SLDistanceInPoints) || (ShowATROptions)) ExtDialog.UpdateFixedSL(); - ExtDialog.RefreshValues(); + ExtDialog.SetTPButtonBackGroundColor(CONTROLS_BUTTON_COLOR_TP_UNLOCKED); + sets.TPLockedOnSL = false; } + if (TickSize > 0) price = NormalizeDouble(MathRound(price / TickSize) * TickSize, _Digits); + ObjectSetDouble(ChartID(), ObjectPrefix + "TakeProfitLine", OBJPROP_PRICE, price); + if ((sets.TPDistanceInPoints) || (ShowATROptions)) ExtDialog.UpdateFixedTP(); + ExtDialog.ShowTPRelatedEdits(); + ExtDialog.RefreshValues(); + ExtDialog.HideShowMaximize(); + ExtDialog.MoveAndResize(); } } - // Set take-profit: - else if ((MainKey_SetTakeProfitHotKey != 0) && (lparam == MainKey_SetTakeProfitHotKey)) + // Set entry: + else if ((MainKey_SetEntryHotKey != 0) && (lparam == MainKey_SetEntryHotKey) + && ((((!ShiftRequired_SetEntryHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_SetEntryHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_SetEntryHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_SetEntryHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))))) // Control { - if (((!ShiftRequired_SetTakeProfitHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0)) // Shift - && ((!CtrlRequired_SetTakeProfitHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))) // Control + // Capture point price location. + int subwindow; + double price; + datetime time; // Dummy. + ChartXYToTimePrice(ChartID(), Mouse_Last_X, Mouse_Last_Y, subwindow, time, price); + // If valid, move the Entry line there and switch from Instant to Pending if necessary. + if ((subwindow == 0) && (price > 0)) { - // Capture point price location. - int subwindow; - double price; - datetime time; // Dummy. - ChartXYToTimePrice(ChartID(), Mouse_Last_X, Mouse_Last_Y, subwindow, time, price); - // If valid, move the TP line there. - if ((subwindow == 0) && (price > 0)) + if (TickSize > 0) price = NormalizeDouble(MathRound(price / TickSize) * TickSize, _Digits); + ObjectSetDouble(ChartID(), ObjectPrefix + "EntryLine", OBJPROP_PRICE, price); + if (sets.EntryType == Instant) { - if (TickSize > 0) price = NormalizeDouble(MathRound(price / TickSize) * TickSize, _Digits); - ObjectSetDouble(ChartID(), ObjectPrefix + "TakeProfitLine", OBJPROP_PRICE, price); - if ((TPDistanceInPoints) || (ShowATROptions)) ExtDialog.UpdateFixedTP(); - ExtDialog.ShowTPRelatedEdits(); - ExtDialog.RefreshValues(); - ExtDialog.HideShowMaximize(); - ExtDialog.MoveAndResize(); + ExtDialog.OnClickBtnOrderType(); // Includes RefreshValues(). } + else ExtDialog.RefreshValues(); } } - // Set entry: - else if ((MainKey_SetEntryHotKey != 0) && (lparam == MainKey_SetEntryHotKey)) + // Minimize/maximize: + else if ((MainKey_MinimizeMaximizeHotkey != 0) && (lparam == MainKey_MinimizeMaximizeHotkey) + && ((((!ShiftRequired_MinimizeMaximizeHotkey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_MinimizeMaximizeHotkey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_MinimizeMaximizeHotkey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_MinimizeMaximizeHotkey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))))) // Control { - if (((!ShiftRequired_SetEntryHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0)) // Shift - && ((!CtrlRequired_SetEntryHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))) // Control + ExtDialog.EmulateMinMaxClick(); + } + // Switch SL between points and level: + else if ((MainKey_SwitchSLPointsLevelHotKey != 0) && (lparam == MainKey_SwitchSLPointsLevelHotKey) + && ((((!ShiftRequired_SwitchSLPointsLevelHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_SwitchSLPointsLevelHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_SwitchSLPointsLevelHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_SwitchSLPointsLevelHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))))) // Control + { + if (sets.SLDistanceInPoints) sets.SLDistanceInPoints = false; // If was in points, set to level. + else { - // Capture point price location. - int subwindow; - double price; - datetime time; // Dummy. - ChartXYToTimePrice(ChartID(), Mouse_Last_X, Mouse_Last_Y, subwindow, time, price); - // If valid, move the Entry line there and switch from Instant to Pending if necessary. - if ((subwindow == 0) && (price > 0)) + sets.SLDistanceInPoints = true; // If was in level, set to points. + sets.StopLoss = (int)MathRound(MathAbs(sets.StopLossLevel - sets.EntryLevel) / _Point); + } + ExtDialog.RefreshValues(); + } + // Switch TP between points and level: + else if ((MainKey_SwitchTPPointsLevelHotKey != 0) && (lparam == MainKey_SwitchTPPointsLevelHotKey) + && ((((!ShiftRequired_SwitchTPPointsLevelHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_SwitchTPPointsLevelHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_SwitchTPPointsLevelHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_SwitchTPPointsLevelHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))))) // Control + { + if (sets.TPDistanceInPoints) sets.TPDistanceInPoints = false; // If was in points, set to level. + else + { + sets.TPDistanceInPoints = true; // If was in level, set to points. + sets.TakeProfit = (int)MathRound(MathAbs(sets.TakeProfitLevel - sets.EntryLevel) / _Point); + // Additional take-profits. + if (sets.TakeProfitsNumber > 1) { - if (TickSize > 0) price = NormalizeDouble(MathRound(price / TickSize) * TickSize, _Digits); - ObjectSetDouble(ChartID(), ObjectPrefix + "EntryLine", OBJPROP_PRICE, price); - if (sets.EntryType == Instant) + for (int i = 1; i < sets.TakeProfitsNumber; i++) { - ExtDialog.OnClickBtnOrderType(); // Includes RefreshValues(). + if (sets.TP[i] != 0) // With zero points TP, keep the TP lines at zero level - as with the main TP level. + { + ExtDialog.AdditionalTPEdits[i - 1].Text(DoubleToString(MathRound((sets.TP[i] - sets.EntryLevel) / _Point), 0)); + } } - else ExtDialog.RefreshValues(); } } + ExtDialog.RefreshValues(); } } @@ -764,7 +829,7 @@ void OnChartEvent(const int id, ((id == CHARTEVENT_OBJECT_DRAG) && ((sparam == ObjectPrefix + "EntryLine") || (sparam == ObjectPrefix + "StopLossLine") || (StringFind(sparam, ObjectPrefix + "TakeProfitLine") != -1)))) { // Moving lines when fixed SL/TP distance is enabled. Should set a new fixed SL/TP distance. - if ((id == CHARTEVENT_OBJECT_DRAG) && ((SLDistanceInPoints) || (TPDistanceInPoints) || (ShowATROptions))) + if ((id == CHARTEVENT_OBJECT_DRAG) && ((sets.SLDistanceInPoints) || (sets.TPDistanceInPoints) || (ShowATROptions))) { if (sparam == ObjectPrefix + "StopLossLine") ExtDialog.UpdateFixedSL(); else if (sparam == ObjectPrefix + "TakeProfitLine") ExtDialog.UpdateFixedTP(); diff --git a/MQL4/Experts/Position Sizer/Position Sizer.mqh b/MQL4/Experts/Position Sizer/Position Sizer.mqh index 32d2659..44201db 100644 --- a/MQL4/Experts/Position Sizer/Position Sizer.mqh +++ b/MQL4/Experts/Position Sizer/Position Sizer.mqh @@ -17,8 +17,8 @@ class CPositionSizeCalculator : public CAppDialog private: CButton m_BtnTabMain, m_BtnTabRisk, m_BtnTabMargin, m_BtnTabSwaps, m_BtnTabTrading, m_BtnOrderType, m_BtnAccount, m_BtnLines, m_BtnStopLoss, m_BtnTakeProfit, m_BtnEntry, m_BtnATRTimeframe, m_BtnCommissionType, m_BtnMaxPS, m_BtnTrade, m_BtnTPsInward, m_BtnTPsOutward, m_BtnTradingTPShare, m_BtnQuickRisk1, m_BtnQuickRisk2, m_BtnEntryIncrease, m_BtnEntryDecrease, m_BtnStopLossIncrease, m_BtnStopLossDecrease, m_BtnTakeProfitIncrease, m_BtnTakeProfitDecrease, m_BtnTakeProfitsNumberAdd, m_BtnTakeProfitsNumberRemove; CCheckBox m_ChkSpreadAdjustmentSL, m_ChkSpreadAdjustmentTP, m_ChkCountPendings, m_ChkIgnoreOrdersWithoutSL, m_ChkIgnoreOrdersWithoutTP, m_ChkIgnoreOtherSymbols, m_ChkDisableTradingWhenLinesAreHidden, m_ChkSubtractPositions, m_ChkSubtractPendingOrders, m_ChkDoNotApplyStopLoss, m_ChkDoNotApplyTakeProfit, m_ChkAskForConfirmation, m_ChkCommentAutoSuffix; - CEdit m_EdtEntryLevel, m_EdtSL, m_EdtTP, m_EdtAccount, m_EdtCommissionSize, m_EdtRiskPIn, m_EdtRiskPRes, m_EdtRiskMIn, m_EdtRiskMRes, m_EdtReward1, m_EdtReward2, m_EdtRR1, m_EdtRR2, m_EdtPosSize, m_EdtPointValue, m_EdtATRPeriod, m_EdtATRMultiplierSL, m_EdtATRMultiplierTP, m_EdtCurRiskM, m_EdtCurRiskP, m_EdtPotRiskM, m_EdtPotRiskP, m_EdtCurProfitM, m_EdtCurProfitP, m_EdtPotProfitM, m_EdtPotProfitP, m_EdtCurL, m_EdtPotL, m_EdtPosMargin, m_EdtUsedMargin, m_EdtFreeMargin, m_EdtCustomLeverage, m_EdtMaxPositionSizeByMargin, m_EdtSwapsType, m_EdtSwapsTripleDay, m_EdtSwapsNominalLong, m_EdtSwapsNominalShort, m_EdtSwapsDailyLongLot, m_EdtSwapsDailyShortLot, m_EdtSwapsDailyLongPS, m_EdtSwapsDailyShortPS, m_EdtSwapsYearlyLongLot, m_EdtSwapsYearlyShortLot, m_EdtSwapsYearlyLongPS, m_EdtSwapsYearlyShortPS, m_EdtMagicNumber, m_EdtCommentary, m_EdtMaxSlippage, m_EdtMaxSpread, m_EdtMaxEntrySLDistance, m_EdtMinEntrySLDistance, m_EdtMaxPositionSize, m_EdtTrailingStopPoints, m_EdtBreakEvenPoints, m_EdtMaxNumberOfTradesTotal, m_EdtMaxNumberOfTradesPerSymbol, m_EdtMaxPositionSizeTotal, m_EdtMaxPositionSizePerSymbol, m_EdtMaxRiskTotal, m_EdtMaxRiskPerSymbol; - CLabel m_LblEntryLevel, m_LblEntryWarning, m_LblSL, m_LblSLWarning, m_LblTPWarning, m_LblOrderType, m_LblCommissionSize, m_LblAdditionalFundsAsterisk, m_LblInput, m_LblResult, m_LblRisk, m_LblRiskM, m_LblReward, m_LblRR, m_LblPosSize, m_LblPointValue, m_LblATRPeriod, m_LblATRMultiplierSL, m_LblATRMultiplierTP, m_LblATRValue, m_LblATRTimeframe, m_LblCurrentRiskMoney, m_LblCurrentRiskPerc, m_LblCurrentProfitMoney, m_LblCurrentProfitPerc, m_LblPotentialRiskMoney, m_LblPotentialRiskPerc, m_LblPotentialProfitMoney, m_LblPotentialProfitPerc, m_LblCurrentLots, m_LblPotentialLots, m_LblCurrentPortfolio, m_LblPotentialPortfolio, m_LblPosMargin, m_LblUsedMargin, m_LblFreeMargin, m_LblCustomLeverage, m_LblAccLeverage, m_LblSymbolLeverage, m_LblMaxPositionSizeByMargin, m_LblSwapsType, m_LblSwapsTripleDay, m_LblSwapsLong, m_LblSwapsShort, m_LblSwapsNominal, m_LblSwapsDaily, m_LblSwapsYearly, m_LblSwapsPerLotDaily, m_LblSwapsPerPSDaily, m_LblSwapsPerLotYearly, m_LblSwapsPerPSYearly, m_LblMagicNumber, m_LblCommentary, m_LblTradingPoints, m_LblMaxSlippage, m_LblMaxSpread, m_LblMaxEntrySLDistance, m_LblMinEntrySLDistance, m_LblTradingLots, m_LblURL, m_LblTradingTP, m_LblTrailingStop, m_LblBreakEven, m_LblMaxNumberOfTrades, m_LblMaxNumberOfTradesTotal, m_LblMaxNumberOfTradesPerSymbol, m_LblMaxPositionSize, m_LblMaxPositionSizeTotal, m_LblMaxPositionSizePerSymbol, m_LblMaxRisk, m_LblMaxRiskTotal, m_LblMaxRiskPerSymbol; + CEdit m_EdtEntryLevel, m_EdtSL, m_EdtTP, m_EdtAccount, m_EdtCommissionSize, m_EdtRiskPIn, m_EdtRiskPRes, m_EdtRiskMIn, m_EdtRiskMRes, m_EdtReward1, m_EdtReward2, m_EdtRR1, m_EdtRR2, m_EdtPosSize, m_EdtPointValue, m_EdtATRPeriod, m_EdtATRMultiplierSL, m_EdtATRMultiplierTP, m_EdtCurRiskM, m_EdtCurRiskP, m_EdtPotRiskM, m_EdtPotRiskP, m_EdtCurProfitM, m_EdtCurProfitP, m_EdtPotProfitM, m_EdtPotProfitP, m_EdtCurL, m_EdtPotL, m_EdtCurrentRRR, m_EdtPotentialRRR, m_EdtPosMargin, m_EdtUsedMargin, m_EdtFreeMargin, m_EdtCustomLeverage, m_EdtMaxPositionSizeByMargin, m_EdtSwapsType, m_EdtSwapsTripleDay, m_EdtSwapsNominalLong, m_EdtSwapsNominalShort, m_EdtSwapsDailyLongLot, m_EdtSwapsDailyShortLot, m_EdtSwapsDailyLongPS, m_EdtSwapsDailyShortPS, m_EdtSwapsYearlyLongLot, m_EdtSwapsYearlyShortLot, m_EdtSwapsYearlyLongPS, m_EdtSwapsYearlyShortPS, m_EdtMagicNumber, m_EdtExpiry, m_EdtCommentary, m_EdtMaxSlippage, m_EdtMaxSpread, m_EdtMaxEntrySLDistance, m_EdtMinEntrySLDistance, m_EdtMaxPositionSize, m_EdtTrailingStopPoints, m_EdtBreakEvenPoints, m_EdtMaxNumberOfTradesTotal, m_EdtMaxNumberOfTradesPerSymbol, m_EdtMaxPositionSizeTotal, m_EdtMaxPositionSizePerSymbol, m_EdtMaxRiskTotal, m_EdtMaxRiskPerSymbol; + CLabel m_LblEntryLevel, m_LblEntryWarning, m_LblSL, m_LblSLWarning, m_LblTPWarning, m_LblOrderType, m_LblCommissionSize, m_LblAdditionalFundsAsterisk, m_LblInput, m_LblResult, m_LblRisk, m_LblRiskM, m_LblReward, m_LblRR, m_LblPosSize, m_LblPointValue, m_LblATRPeriod, m_LblATRMultiplierSL, m_LblATRMultiplierTP, m_LblATRValue, m_LblATRTimeframe, m_LblCurrentRiskMoney, m_LblCurrentRiskPerc, m_LblCurrentProfitMoney, m_LblCurrentProfitPerc, m_LblPotentialRiskMoney, m_LblPotentialRiskPerc, m_LblPotentialProfitMoney, m_LblPotentialProfitPerc, m_LblCurrentLots, m_LblCurrentRRR, m_LblPotentialLots, m_LblPotentialRRR, m_LblCurrentPortfolio, m_LblPotentialPortfolio, m_LblPosMargin, m_LblUsedMargin, m_LblFreeMargin, m_LblCustomLeverage, m_LblAccLeverage, m_LblSymbolLeverage, m_LblMaxPositionSizeByMargin, m_LblSwapsType, m_LblSwapsTripleDay, m_LblSwapsLong, m_LblSwapsShort, m_LblSwapsNominal, m_LblSwapsDaily, m_LblSwapsYearly, m_LblSwapsPerLotDaily, m_LblSwapsPerPSDaily, m_LblSwapsPerLotYearly, m_LblSwapsPerPSYearly, m_LblMagicNumber, m_LblExpiry, m_LblMinutes, m_LblCommentary, m_LblTradingPoints, m_LblMaxSlippage, m_LblMaxSpread, m_LblMaxEntrySLDistance, m_LblMinEntrySLDistance, m_LblTradingLots, m_LblURL, m_LblTradingTP, m_LblTrailingStop, m_LblBreakEven, m_LblMaxNumberOfTrades, m_LblMaxNumberOfTradesTotal, m_LblMaxNumberOfTradesPerSymbol, m_LblMaxPositionSize, m_LblMaxPositionSizeTotal, m_LblMaxPositionSizePerSymbol, m_LblMaxRisk, m_LblMaxRiskTotal, m_LblMaxRiskPerSymbol; string m_FileName; double m_DPIScale; bool NoPanelMaximization; // A crutch variable to prevent panel maximization when Maximize() is called at the indicator's initialization. @@ -28,7 +28,6 @@ private: // Extra TP fields for the Main tab. CLabel AdditionalTPLabels[], AdditionalTPWarnings[]; - CEdit AdditionalTPEdits[]; CButton AdditionalTPButtonsIncrease[], AdditionalTPButtonsDecrease[]; // Store ordered and named panel objects arranged by tabs. CPanelList *MainTabList, *RiskTabList, *MarginTabList, *SwapsTabList, *TradingTabList; @@ -71,6 +70,7 @@ public: virtual void Minimize(); virtual bool IsMinimized() {return m_minimized;} virtual void IniFileLoad() {CAppDialog::IniFileLoad();ExtDialog.InitObjects();} // Need to init objects after ini file load. + virtual void EmulateMinMaxClick(); void OnClickBtnTakeProfitsNumberRemove(); void OnClickBtnTPsInward(); void OnClickBtnTPsOutward(); @@ -84,6 +84,8 @@ public: void ShowTPRelatedEdits(); void SetFileName(string file_name) {m_FileName = file_name;} void InitControlsValues(); + void SetTPButtonBackGroundColor(color); + CEdit AdditionalTPEdits[]; // Remember the panel's location to have the same location for minimized and maximized states. int remember_top, remember_left; @@ -155,6 +157,7 @@ private: void OnEndEditEdtMaxNumberOfTradesPerSymbol(); void OnEndEditEdtMaxRiskTotal(); void OnEndEditEdtMaxRiskPerSymbol(); + void OnEndEditEdtExpiry(); void OnChangeChkSubtractPositions(); void OnChangeChkSubtractPendingOrders(); void OnChangeChkDoNotApplyStopLoss(); @@ -222,6 +225,7 @@ ON_EVENT(ON_END_EDIT, m_EdtMaxNumberOfTradesTotal, OnEndEditEdtMaxNumberOfTrades ON_EVENT(ON_END_EDIT, m_EdtMaxNumberOfTradesPerSymbol, OnEndEditEdtMaxNumberOfTradesPerSymbol) ON_EVENT(ON_END_EDIT, m_EdtMaxRiskTotal, OnEndEditEdtMaxRiskTotal) ON_EVENT(ON_END_EDIT, m_EdtMaxRiskPerSymbol, OnEndEditEdtMaxRiskPerSymbol) +ON_EVENT(ON_END_EDIT, m_EdtExpiry, OnEndEditEdtExpiry) ON_EVENT(ON_CHANGE, m_ChkSubtractPositions, OnChangeChkSubtractPositions) ON_EVENT(ON_CHANGE, m_ChkSubtractPendingOrders, OnChangeChkSubtractPendingOrders) ON_EVENT(ON_CHANGE, m_ChkDoNotApplyStopLoss, OnChangeChkDoNotApplyStopLoss) @@ -266,7 +270,7 @@ CPositionSizeCalculator::~CPositionSizeCalculator(void) // Updates filename used for settings storage. void CPositionSizeCalculator::UpdateFileName() { - m_FileName = "PS_" + Symbol() + IntegerToString(ChartID()); + m_FileName = Symbol() + IntegerToString(ChartID()); StringReplace(m_FileName, ".", "_dot_"); m_FileName += ".txt"; } @@ -455,7 +459,7 @@ bool CPositionSizeCalculator::CreateObjects() y += element_height + v_spacing; string stoploss_label_text = "Stop-loss: "; - if (SLDistanceInPoints) stoploss_label_text = "SL, points: "; + if (sets.SLDistanceInPoints) stoploss_label_text = "SL, points: "; if (DefaultSL > 0) // Use button to quickly set SL. { @@ -471,7 +475,7 @@ bool CPositionSizeCalculator::CreateObjects() y += element_height + v_spacing; string takeprofit_label_text = "Take-profit: "; - if (TPDistanceInPoints) takeprofit_label_text = "TP, points: "; + if (sets.TPDistanceInPoints) takeprofit_label_text = "TP, points: "; if (!ButtonCreate(MainTabList, m_BtnTakeProfitsNumberAdd, first_column_start, y, first_column_start + v_spacing * 4 - 1, y + element_height, "m_BtnTakeProfitsNumberAdd", "+", "Add a take-profit level")) return false; if (!ButtonCreate(MainTabList, m_BtnTakeProfit, first_column_start + v_spacing * 4, y, first_column_start + v_spacing * 3 + normal_label_width, y + element_height, "m_BtnTakeProfit", takeprofit_label_text, "Set TP based on SL or enable locked TP mode")) return false; if (!EditCreate(MainTabList, m_EdtTP, second_column_start, y, second_column_start + normal_edit_width, y + element_height, "m_EdtTP", "")) return false; @@ -493,7 +497,7 @@ bool CPositionSizeCalculator::CreateObjects() ArrayResize(AdditionalOutputReward, sets.TakeProfitsNumber - 1); // Double array. string additional_tp_label_beginning = "Take-profit "; string additional_tp_label_end = ":"; - if (TPDistanceInPoints) + if (sets.TPDistanceInPoints) { additional_tp_label_beginning = "TP "; additional_tp_label_end = ", points:"; @@ -682,6 +686,7 @@ bool CPositionSizeCalculator::CreateObjects() if (!LabelCreate(RiskTabList, m_LblCurrentProfitMoney, second_risk_column_start, y, second_risk_column_start + narrow_label_width, y + element_height, "m_LblCurrentProfitMoney", "Reward $")) return false; if (!LabelCreate(RiskTabList, m_LblCurrentProfitPerc, third_risk_column_start, y, third_risk_column_start + narrowest_label_width, y + element_height, "m_LblCurrentProfitPerc", "Reward %")) return false; + if (!LabelCreate(RiskTabList, m_LblCurrentRRR, fourth_risk_column_start, y, fourth_risk_column_start + narrowest_label_width, y + element_height, "m_LblCurrentRRR", "RRR", "Risk-to-reward ratio of the current portfolio")) return false; y += element_height + v_spacing; @@ -691,6 +696,9 @@ bool CPositionSizeCalculator::CreateObjects() if (!EditCreate(RiskTabList, m_EdtCurProfitP, third_risk_column_start, y, third_risk_column_start + risk_perc_edit_width, y + element_height, "m_EdtCurProfitP", "")) return false; m_EdtCurProfitP.ReadOnly(true); m_EdtCurProfitP.ColorBackground(CONTROLS_EDIT_COLOR_DISABLE); + if (!EditCreate(RiskTabList, m_EdtCurrentRRR, fourth_risk_column_start, y, fourth_risk_column_start + risk_lot_edit, y + element_height, "m_EdtCurrentRRR", "")) return false; + m_EdtCurrentRRR.ReadOnly(true); + m_EdtCurrentRRR.ColorBackground(CONTROLS_EDIT_COLOR_DISABLE); y += element_height + v_spacing; @@ -715,6 +723,7 @@ bool CPositionSizeCalculator::CreateObjects() if (!LabelCreate(RiskTabList, m_LblPotentialProfitMoney, second_risk_column_start, y, second_risk_column_start + narrow_edit_width, y + element_height, "m_LblPotentialProfitMoney", "Reward $")) return false; if (!LabelCreate(RiskTabList, m_LblPotentialProfitPerc, third_risk_column_start, y, third_risk_column_start + narrowest_label_width, y + element_height, "m_LblPotentialProfitPerc", "Reward %")) return false; + if (!LabelCreate(RiskTabList, m_LblPotentialRRR, fourth_risk_column_start, y, fourth_risk_column_start + narrowest_label_width, y + element_height, "m_LblPotentialRRR", "RRR", "Risk-to-reward ratio of the potential portfolio")) return false; y += element_height + v_spacing; @@ -724,6 +733,9 @@ bool CPositionSizeCalculator::CreateObjects() if (!EditCreate(RiskTabList, m_EdtPotProfitP, third_risk_column_start, y, third_risk_column_start + risk_perc_edit_width, y + element_height, "m_EdtPotProfitP", "")) return false; m_EdtPotProfitP.ReadOnly(true); m_EdtPotProfitP.ColorBackground(CONTROLS_EDIT_COLOR_DISABLE); + if (!EditCreate(RiskTabList, m_EdtPotentialRRR, fourth_risk_column_start, y, fourth_risk_column_start + risk_lot_edit, y + element_height, "m_EdtPotentialRRR", "")) return false; + m_EdtPotentialRRR.ReadOnly(true); + m_EdtPotentialRRR.ColorBackground(CONTROLS_EDIT_COLOR_DISABLE); // Margin @@ -854,7 +866,10 @@ bool CPositionSizeCalculator::CreateObjects() y += element_height + v_spacing; if (!LabelCreate(TradingTabList, m_LblMagicNumber, first_column_start, y, first_column_start + normal_label_width, y + element_height, "m_LblMagicNumber", "Magic number:")) return false; - if (!EditCreate(TradingTabList, m_EdtMagicNumber, second_trading_column_start, y, second_trading_column_start + normal_edit_width, y + element_height, "m_EdtMagicNumber", "")) return false; + if (!EditCreate(TradingTabList, m_EdtMagicNumber, first_column_start + normal_label_width, y, first_column_start + normal_label_width + normal_edit_width, y + element_height, "m_EdtMagicNumber", "")) return false; + if (!LabelCreate(TradingTabList, m_LblExpiry, first_column_start + normal_label_width + normal_edit_width + v_spacing, y, first_column_start + normal_label_width + normal_edit_width + narrowest_label_width, y + element_height, "m_LblExpiry", "Expiry:", "Expiration time in minutes for the next created pending order. Minimum = 10.")) return false; + if (!EditCreate(TradingTabList, m_EdtExpiry, first_column_start + normal_label_width + normal_edit_width + narrowest_label_width, y, first_column_start + normal_label_width + normal_edit_width + narrowest_label_width + tab_button_width, y + element_height, "m_EdtExpiry", "", "Expiration time in minutes for the next created pending order. Minimum = 10.")) return false; + if (!LabelCreate(TradingTabList, m_LblMinutes, first_column_start + normal_label_width + normal_edit_width + narrowest_label_width + tab_button_width + v_spacing, y, panel_end, y + element_height, "m_LblMinutes", "min.", "Minutes")) return false; y += element_height + v_spacing; @@ -1005,11 +1020,13 @@ bool CPositionSizeCalculator::InitObjects() if (!m_EdtCurProfitM.TextAlign(align)) return false; if (!m_EdtCurProfitP.TextAlign(align)) return false; if (!m_EdtCurL.TextAlign(align)) return false; + if (!m_EdtCurrentRRR.TextAlign(align)) return false; if (!m_EdtPotRiskM.TextAlign(align)) return false; if (!m_EdtPotRiskP.TextAlign(align)) return false; if (!m_EdtPotProfitM.TextAlign(align)) return false; if (!m_EdtPotProfitP.TextAlign(align)) return false; if (!m_EdtPotL.TextAlign(align)) return false; + if (!m_EdtPotentialRRR.TextAlign(align)) return false; if (!m_EdtPosMargin.TextAlign(align)) return false; if (!m_EdtUsedMargin.TextAlign(align)) return false; if (!m_EdtFreeMargin.TextAlign(align)) return false; @@ -1043,6 +1060,7 @@ bool CPositionSizeCalculator::InitObjects() } if (!m_EdtTrailingStopPoints.TextAlign(align)) return false; if (!m_EdtBreakEvenPoints.TextAlign(align)) return false; + if (!m_EdtExpiry.TextAlign(align)) return false; if (ShowMaxParametersOnTrading) { if (!m_EdtMaxNumberOfTradesTotal.TextAlign(align)) return false; @@ -1052,8 +1070,8 @@ bool CPositionSizeCalculator::InitObjects() if (!m_EdtMaxRiskTotal.TextAlign(align)) return false; if (!m_EdtMaxRiskPerSymbol.TextAlign(align)) return false; } - if (sets.TPLockedOnSL) m_BtnTakeProfit.ColorBackground(CONTROLS_BUTTON_COLOR_ENABLE); - else m_BtnTakeProfit.ColorBackground(CONTROLS_BUTTON_COLOR_BG); + if (sets.TPLockedOnSL) m_BtnTakeProfit.ColorBackground(CONTROLS_BUTTON_COLOR_TP_LOCKED); + else m_BtnTakeProfit.ColorBackground(CONTROLS_BUTTON_COLOR_TP_UNLOCKED); HideRisk(); HideMargin(); @@ -1082,7 +1100,7 @@ void CPositionSizeCalculator::InitControlsValues() { if ((TP_Multiplier < 0.999) || (TP_Multiplier > 1.001)) { - if (!TPDistanceInPoints) + if (!sets.TPDistanceInPoints) { m_BtnTakeProfit.Text("Take-profit x " + DoubleToString(TP_Multiplier, CountDecimalPlaces(TP_Multiplier)) + ":"); } @@ -1204,6 +1222,7 @@ void CPositionSizeCalculator::InitControlsValues() m_EdtTrailingStopPoints.Text(IntegerToString(sets.TrailingStopPoints)); m_EdtBreakEvenPoints.Text(IntegerToString(sets.BreakEvenPoints)); m_EdtMagicNumber.Text(IntegerToString(sets.MagicNumber)); + m_EdtExpiry.Text(IntegerToString(sets.ExpiryMinutes)); m_EdtCommentary.Text(sets.Commentary); m_ChkCommentAutoSuffix.Checked(sets.CommentAutoSuffix); if (ShowMaxParametersOnTrading) @@ -1299,7 +1318,7 @@ bool CPositionSizeCalculator::DisplayValues() else if (ShowSpread == Ratio) // Spread / SL ratio in percentage. { double SL; - if (SLDistanceInPoints) SL = sets.StopLoss * _Point; + if (sets.SLDistanceInPoints) SL = sets.StopLoss * _Point; else SL = MathAbs(sets.StopLossLevel - sets.EntryLevel); if (SL != 0) if (!Caption(PanelCaption + " | Spread: " + DoubleToString((SymbolInfoInteger(Symbol(), SYMBOL_SPREAD) * _Point / SL) * 100, 2) + "%")) return false; } @@ -1310,7 +1329,7 @@ bool CPositionSizeCalculator::DisplayValues() if (!m_BtnEntry.Text(EnumToString(sets.TradeDirection))) return false; /* Entry Warning */ if (!m_LblEntryWarning.Text(WarningEntry)) return false; - /* Stop-Loss */ if (!SLDistanceInPoints) + /* Stop-Loss */ if (!sets.SLDistanceInPoints) { if (!m_EdtSL.Text(DoubleToString(sets.StopLossLevel, _Digits))) return false; } @@ -1318,14 +1337,14 @@ bool CPositionSizeCalculator::DisplayValues() /* SL Warning */ if (!m_LblSLWarning.Text(WarningSL)) return false; - /* Take Profit */ if (!TPDistanceInPoints) + /* Take Profit */ if (!sets.TPDistanceInPoints) { if (!m_EdtTP.Text(DoubleToString(sets.TakeProfitLevel, _Digits))) return false; } else if (!m_EdtTP.Text(IntegerToString(sets.TakeProfit))) return false; for (int i = 1; i < sets.TakeProfitsNumber; i++) { - if (!TPDistanceInPoints) + if (!sets.TPDistanceInPoints) { // Price level. if (!AdditionalTPEdits[i - 1].Text(DoubleToString(sets.TP[i], _Digits))) return false; @@ -1470,17 +1489,19 @@ bool CPositionSizeCalculator::DisplayValues() /* Current Portfolio Lots */ if (!m_EdtCurL.Text(CPL)) return false; /* Current Portfolio Profit $ */ if (!m_EdtCurProfitM.Text(PRM)) return false; /* Current Portfolio Profit % */ if (!m_EdtCurProfitP.Text(CPRew)) return false; + /* Current Portfolio RRR */ if (!m_EdtCurrentRRR.Text(CPRRR)) return false; /* Potential Portfolio Risk $ */ if (!m_EdtPotRiskM.Text(PPMR)) return false; /* Potential Portfolio Risk % */ if (!m_EdtPotRiskP.Text(PPR)) return false; /* Potential Portfolio Profit $ */ if (!m_EdtPotProfitM.Text(PPMRew)) return false; /* Potential Portfolio Profit % */ if (!m_EdtPotProfitP.Text(PPRew)) return false; /* Potential Portfolio Lots */ if (!m_EdtPotL.Text(PPL)) return false; + /* Potential Portfolio RRR */ if (!m_EdtPotentialRRR.Text(PPRRR)) return false; //=== Margin /* Position Margin */ if (!m_EdtPosMargin.Text(FormatDouble(DoubleToString(PositionMargin, 2)))) return false; /* Future Used Margin */ if (!m_EdtUsedMargin.Text(FormatDouble(DoubleToString(UsedMargin, 2)))) return false; /* Future Free Margin */ if (!m_EdtFreeMargin.Text(FormatDouble(DoubleToString(FutureMargin, 2)))) return false; - /* Custom Leverage */ if (!m_EdtCustomLeverage.Text(DoubleToString(sets.CustomLeverage, CustomLeverageDecimals))) return false; + /* Custom Leverage */ if (!m_EdtCustomLeverage.Text(DoubleToString(sets.CustomLeverage, CustomLeverageDecimals))) return false; string acc_lev = IntegerToString(AccountInfoInteger(ACCOUNT_LEVERAGE)); /* Account Leverage */ if (acc_lev != "") if (!m_LblAccLeverage.Text("(Default = 1:" + acc_lev + ")")) return false; /* Symbol Leverage */ if (SymbolLeverage) if (!m_LblSymbolLeverage.Text("(Symbol = 1:" + DoubleToString(SymbolLeverage, SymbolLeverageDecimals) + ")")) return false; @@ -1580,6 +1601,11 @@ void CPositionSizeCalculator::Maximize() if (remember_left != -1) Move(remember_left, remember_top); } +void CPositionSizeCalculator::SetTPButtonBackGroundColor(color bg_color) +{ + m_BtnTakeProfit.ColorBackground(bg_color); +} + void CPositionSizeCalculator::RefreshValues() { if (Uninitialized) @@ -1694,7 +1720,7 @@ void CPositionSizeCalculator::RefreshValues() } // Set line based on the entered SL distance. - if (SLDistanceInPoints) + if (sets.SLDistanceInPoints) { if (sets.TradeDirection == Long) sets.StopLossLevel = sets.EntryLevel - sets.StopLoss * _Point; else sets.StopLossLevel = sets.EntryLevel + sets.StopLoss * _Point; @@ -1702,7 +1728,7 @@ void CPositionSizeCalculator::RefreshValues() } // Set line based on the entered TP distance. - if (TPDistanceInPoints) + if (sets.TPDistanceInPoints) { if (sets.TakeProfit > 0) { @@ -1979,7 +2005,7 @@ void CPositionSizeCalculator::ProcessTPChange(const bool tp_button_click) sets.ATRMultiplierTP = NormalizeDouble(sets.ATRMultiplierSL * TP_Multiplier, 2); m_EdtATRMultiplierTP.Text(DoubleToString(sets.ATRMultiplierTP, 2)); } - if (!TPDistanceInPoints) m_EdtTP.Text(DoubleToString(tTakeProfitLevel, _Digits)); + if (!sets.TPDistanceInPoints) m_EdtTP.Text(DoubleToString(tTakeProfitLevel, _Digits)); else { sets.TakeProfit = (int)MathRound(MathAbs(tTakeProfitLevel - tEntryLevel) / _Point); @@ -2267,6 +2293,11 @@ void CPositionSizeCalculator::OnClickBtnLines() ObjectSetInteger(ChartID(), ObjectPrefix + "EntryLabel", OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS); ObjectSetInteger(ChartID(), ObjectPrefix + "EntryLabel", OBJPROP_BACK, DrawTextAsBackground); } + if (ShowAdditionalEntryLabel) + { + ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS); + ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_BACK, DrawTextAsBackground); + } if (StringToDouble(m_EdtTP.Text()) != 0) { ObjectSetInteger(ChartID(), ObjectPrefix + "TakeProfitLabel", OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS); @@ -2322,6 +2353,7 @@ void CPositionSizeCalculator::OnClickBtnLines() ObjectSetInteger(ChartID(), ObjectPrefix + "SLAdditionalLabel", OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); ObjectSetInteger(ChartID(), ObjectPrefix + "TakeProfitLabel", OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); ObjectSetInteger(ChartID(), ObjectPrefix + "TPAdditionalLabel", OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); + ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); } } @@ -2336,7 +2368,7 @@ void CPositionSizeCalculator::OnClickBtnStopLoss() if (tStopLossLevel != sets.StopLossLevel) { tStopLossLevel = sets.StopLossLevel; - if (!SLDistanceInPoints) m_EdtSL.Text(DoubleToString(tStopLossLevel, _Digits)); + if (!sets.SLDistanceInPoints) m_EdtSL.Text(DoubleToString(tStopLossLevel, _Digits)); else { sets.StopLoss = (int)MathRound(MathAbs(tStopLossLevel - tEntryLevel) / _Point); @@ -2351,7 +2383,7 @@ void CPositionSizeCalculator::OnClickBtnTakeProfit() // If "TP locked on SL" mode was on, turn it off. if (sets.TPLockedOnSL) { - m_BtnTakeProfit.ColorBackground(CONTROLS_BUTTON_COLOR_BG); + m_BtnTakeProfit.ColorBackground(CONTROLS_BUTTON_COLOR_TP_UNLOCKED); sets.TPLockedOnSL = false; return; } @@ -2359,7 +2391,7 @@ void CPositionSizeCalculator::OnClickBtnTakeProfit() else if (sets.TakeProfitLevel != 0) { sets.TPLockedOnSL = true; - m_BtnTakeProfit.ColorBackground(CONTROLS_BUTTON_COLOR_ENABLE); + m_BtnTakeProfit.ColorBackground(CONTROLS_BUTTON_COLOR_TP_LOCKED); } ProcessTPChange(true); @@ -2396,7 +2428,7 @@ void SwitchEntryDirection() if (sets.TakeProfitLevel > 0) { - if (TPDistanceInPoints) sets.TakeProfitLevel = sets.EntryLevel - sets.TakeProfit * _Point; + if (sets.TPDistanceInPoints) sets.TakeProfitLevel = sets.EntryLevel - sets.TakeProfit * _Point; else sets.TakeProfitLevel = sets.EntryLevel - old_tp_distance; ObjectSetDouble(ChartID(), ObjectPrefix + "TakeProfitLine", OBJPROP_PRICE, sets.TakeProfitLevel); for (int i = 1; i < sets.TakeProfitsNumber; i++) @@ -2432,7 +2464,7 @@ void SwitchEntryDirection() if (sets.TakeProfitLevel > 0) { - if (TPDistanceInPoints) sets.TakeProfitLevel = sets.EntryLevel + sets.TakeProfit * _Point; + if (sets.TPDistanceInPoints) sets.TakeProfitLevel = sets.EntryLevel + sets.TakeProfit * _Point; else sets.TakeProfitLevel = sets.EntryLevel + old_tp_distance; ObjectSetDouble(ChartID(), ObjectPrefix + "TakeProfitLine", OBJPROP_PRICE, sets.TakeProfitLevel); for (int i = 1; i < sets.TakeProfitsNumber; i++) @@ -2659,7 +2691,7 @@ void CPositionSizeCalculator::OnClickBtnStopLossIncrease() { if (ShowATROptions) return; // Stop-loss cannot be changed by +/- buttons in ATR mode. // Should actually operate in TickSize rather than point as only TickSize changes make sense. - if (!SLDistanceInPoints) + if (!sets.SLDistanceInPoints) { if (TickSize > 0) sets.StopLossLevel += TickSize; else sets.StopLossLevel += _Point; @@ -2695,7 +2727,7 @@ void CPositionSizeCalculator::OnClickBtnStopLossDecrease() { if (ShowATROptions) return; // Stop-loss cannot be changed by +/- buttons in ATR mode. // Should actually operate in TickSize rather than point as only TickSize changes make sense. - if (!SLDistanceInPoints) + if (!sets.SLDistanceInPoints) { if (TickSize > 0) sets.StopLossLevel -= TickSize; else sets.StopLossLevel -= _Point; @@ -2727,7 +2759,7 @@ void CPositionSizeCalculator::OnClickBtnStopLossDecrease() void CPositionSizeCalculator::OnClickBtnTakeProfitIncrease() { if (ShowATROptions) return; // Take-profit cannot be changed by +/- buttons in ATR mode. - if (!TPDistanceInPoints) + if (!sets.TPDistanceInPoints) { // Check and adjust for TickSize granularity. if (TickSize > 0) sets.TakeProfitLevel += TickSize; @@ -2769,7 +2801,7 @@ void CPositionSizeCalculator::OnClickBtnTakeProfitIncrease() void CPositionSizeCalculator::OnClickBtnTakeProfitDecrease() { if (ShowATROptions) return; // Take-profit cannot be changed by +/- buttons in ATR mode. - if (!TPDistanceInPoints) + if (!sets.TPDistanceInPoints) { // Check and adjust for TickSize granularity. if (TickSize > 0) sets.TakeProfitLevel -= TickSize; @@ -2807,7 +2839,7 @@ void CPositionSizeCalculator::OnClickBtnTakeProfitDecrease() void CPositionSizeCalculator::ProcessAdditionalTPButtonsIncrease(int i) { - if (!TPDistanceInPoints) // Everything is easy. + if (!sets.TPDistanceInPoints) // Everything is easy. { // Check and adjust for TickSize granularity. if (TickSize > 0) sets.TP[i] += TickSize; @@ -2837,7 +2869,7 @@ void CPositionSizeCalculator::ProcessAdditionalTPButtonsIncrease(int i) void CPositionSizeCalculator::ProcessAdditionalTPButtonsDecrease(int i) { - if (!TPDistanceInPoints) // Everything is more or less easy. + if (!sets.TPDistanceInPoints) // Everything is more or less easy. { // Check and adjust for TickSize granularity. if (TickSize > 0) sets.TP[i] -= TickSize; @@ -2910,7 +2942,7 @@ void CPositionSizeCalculator::OnClickBtnTakeProfitsNumberAdd() } string additional_tp_label_beginning = "Take-profit "; string additional_tp_label_end = ":"; - if (TPDistanceInPoints) + if (sets.TPDistanceInPoints) { additional_tp_label_beginning = "TP "; additional_tp_label_end = ", points:"; @@ -2965,7 +2997,7 @@ void CPositionSizeCalculator::OnClickBtnTakeProfitsNumberAdd() if (((ShowATROptions) && (obj.Name == "m_LblATRPeriod")) || ((!ShowATROptions) && (obj.Name == "m_LblOrderType"))) { start_moving = true; // From now on everything below should be moved down. - y = obj.Obj.Top() - col_height - remember_top; // Remember the y where the new TP fields will be inserted. Relative measurement. + y = obj.Obj.Top() - (CONTROLS_DIALOG_CAPTION_HEIGHT + 3 * CONTROLS_BORDER_WIDTH) - remember_top; // Remember the y where the new TP fields will be inserted. Relative measurement. index = MainTabList.IndexOf(obj) - 1; // Remember the index to insert the new TP in the list of Main tab fields. } } @@ -3061,7 +3093,7 @@ void CPositionSizeCalculator::OnClickBtnTakeProfitsNumberAdd() if (((ShowFusesOnTrading) && (obj.Name == "m_LblTradingPoints")) || ((ShowCheckboxesOnTrading) && (obj.Name == "m_ChkSubtractPositions")) || (obj.Name == "m_ChkAskForConfirmation")) { start_moving = true; // From now on everything below should be moved down. - y = obj.Obj.Top() - col_height - remember_top; // Remember the y where the new TP fields will be inserted. Relative measurement. + y = obj.Obj.Top() - (CONTROLS_DIALOG_CAPTION_HEIGHT + 3 * CONTROLS_BORDER_WIDTH) - remember_top; // Remember the y where the new TP fields will be inserted. Relative measurement. index = TradingTabList.IndexOf(obj) - 1; // Remember the index to insert the new TP in the list of Trading tab fields. if (sets.TakeProfitsNumber == 2) m = 3; // Will be moving three rows down: headers + main TP + first secondary TP. } @@ -3209,7 +3241,7 @@ void CPositionSizeCalculator::OnClickBtnTakeProfitsNumberAdd() if ((PrefillAdditionalTPsBasedOnMain) && (sets.TakeProfitLevel != 0)) // If added a new TP when the first TP was already set, set some value to the new one too. { - if (!TPDistanceInPoints) sets.TP[sets.TakeProfitsNumber - 1] = sets.EntryLevel + (sets.TakeProfitLevel - sets.EntryLevel) * sets.TakeProfitsNumber; + if (!sets.TPDistanceInPoints) sets.TP[sets.TakeProfitsNumber - 1] = sets.EntryLevel + (sets.TakeProfitLevel - sets.EntryLevel) * sets.TakeProfitsNumber; else { if (sets.TradeDirection == Short) sets.TP[sets.TakeProfitsNumber - 1] = sets.EntryLevel - sets.TakeProfit * _Point * sets.TakeProfitsNumber; @@ -3365,7 +3397,7 @@ void CPositionSizeCalculator::OnEndEditEdtEntryLevel() void CPositionSizeCalculator::OnEndEditEdtSL() { - if (!SLDistanceInPoints) + if (!sets.SLDistanceInPoints) { double new_value = StringToDouble(m_EdtSL.Text()); if (new_value == 0) // Not allowed. @@ -3412,7 +3444,7 @@ void CPositionSizeCalculator::OnEndEditEdtSL() void CPositionSizeCalculator::OnEndEditEdtTP() { - if (!TPDistanceInPoints) + if (!sets.TPDistanceInPoints) { sets.TakeProfitLevel = StringToDouble(m_EdtTP.Text()); // Check and adjust for TickSize granularity. @@ -3907,6 +3939,17 @@ void CPositionSizeCalculator::OnEndEditEdtMaxRiskPerSymbol() m_EdtMaxRiskPerSymbol.Text(DoubleToString(sets.MaxRiskPerSymbol, 2)); } +void CPositionSizeCalculator::OnEndEditEdtExpiry() +{ + sets.ExpiryMinutes = (int)StringToInteger(m_EdtExpiry.Text()); + if ((sets.ExpiryMinutes != 0) && (sets.ExpiryMinutes < 10)) + { + sets.ExpiryMinutes = 0; + Print("Minimum expiry duration is 10 minutes."); + } + m_EdtExpiry.Text(IntegerToString(sets.ExpiryMinutes)); +} + //+-----------------------+ //| Working with settings | //|+----------------------+ @@ -3915,10 +3958,11 @@ bool CPositionSizeCalculator::SaveSettingsOnDisk(string symbol = "") Print("Trying to save settings to file: " + m_FileName + "."); int fh; - fh = FileOpen(m_FileName, FILE_CSV | FILE_WRITE); + // Save to new format only. + fh = FileOpen("PS_Settings\\" + m_FileName, FILE_CSV | FILE_WRITE); if (fh == INVALID_HANDLE) { - Print("Failed to open file for writing: " + m_FileName + ". Error: " + IntegerToString(GetLastError())); + Print("Failed to open file for writing: PS_Settings\\" + m_FileName + ". Error: " + IntegerToString(GetLastError())); return false; } @@ -3999,6 +4043,10 @@ bool CPositionSizeCalculator::SaveSettingsOnDisk(string symbol = "") FileWrite(fh, IntegerToString(sets.MaxEntrySLDistance)); FileWrite(fh, "MinEntrySLDistance"); FileWrite(fh, IntegerToString(sets.MinEntrySLDistance)); + FileWrite(fh, "SLDistanceInPoints"); + FileWrite(fh, IntegerToString(sets.SLDistanceInPoints)); + FileWrite(fh, "TPDistanceInPoints"); + FileWrite(fh, IntegerToString(sets.TPDistanceInPoints)); FileWrite(fh, "StopLoss"); FileWrite(fh, IntegerToString(sets.StopLoss)); FileWrite(fh, "TakeProfit"); @@ -4048,6 +4096,8 @@ bool CPositionSizeCalculator::SaveSettingsOnDisk(string symbol = "") FileWrite(fh, IntegerToString(sets.TrailingStopPoints)); FileWrite(fh, "BreakEvenPoints"); FileWrite(fh, IntegerToString(sets.BreakEvenPoints)); + FileWrite(fh, "ExpiryMinutes"); + FileWrite(fh, IntegerToString(sets.ExpiryMinutes)); FileWrite(fh, "MaxNumberOfTradesTotal"); FileWrite(fh, IntegerToString(sets.MaxNumberOfTradesTotal)); FileWrite(fh, "MaxNumberOfTradesPerSymbol"); @@ -4161,6 +4211,8 @@ bool CPositionSizeCalculator::SaveSettingsOnDisk(string symbol = "") FileWrite(fh, IntegerToString(DefaultTrailingStop)); FileWrite(fh, "Parameter_DefaultBreakEven"); FileWrite(fh, IntegerToString(DefaultBreakEven)); + FileWrite(fh, "Parameter_DefaultExpiryMinutes"); + FileWrite(fh, IntegerToString(DefaultExpiryMinutes)); FileWrite(fh, "Parameter_DefaultSpreadAdjustmentSL"); FileWrite(fh, IntegerToString(DefaultSpreadAdjustmentSL)); FileWrite(fh, "Parameter_DefaultSpreadAdjustmentTP"); @@ -4175,6 +4227,10 @@ bool CPositionSizeCalculator::SaveSettingsOnDisk(string symbol = "") FileWrite(fh, DoubleToString(DefaultMaxRiskPerSymbol)); FileWrite(fh, "Parameter_DefaultTakeProfitsNumber"); FileWrite(fh, IntegerToString(DefaultTakeProfitsNumber)); + FileWrite(fh, "Parameter_DefaultSLDistanceInPoints"); + FileWrite(fh, IntegerToString(DefaultSLDistanceInPoints)); + FileWrite(fh, "Parameter_DefaultTPDistanceInPoints"); + FileWrite(fh, IntegerToString(DefaultTPDistanceInPoints)); } FileClose(fh); @@ -4187,19 +4243,30 @@ bool CPositionSizeCalculator::LoadSettingsFromDisk() { Print("Trying to load settings from file."); - if (!FileIsExist(m_FileName)) - { - Print("No settings file to load."); - return false; - } - int fh; - fh = FileOpen(m_FileName, FILE_CSV | FILE_READ); - if (fh == INVALID_HANDLE) + if (FileIsExist("PS_Settings\\" + m_FileName)) // New format settings file found. { - Print("Failed to open file for reading: " + m_FileName + ". Error: " + IntegerToString(GetLastError())); - return false; + fh = FileOpen("PS_Settings\\" + m_FileName, FILE_CSV | FILE_READ); + if (fh == INVALID_HANDLE) + { + Print("Failed to open file for reading: PS_Settings\\" + m_FileName + ". Error: " + IntegerToString(GetLastError())); + return false; + } + } + else // No new format file, try to load old format. + { + if (!FileIsExist("PS_" + m_FileName)) + { + Print("No settings file to load."); + return false; + } + fh = FileOpen("PS_" + m_FileName, FILE_CSV | FILE_READ); + if (fh == INVALID_HANDLE) + { + Print("Failed to open file for reading: PS_" + m_FileName + ". Error: " + IntegerToString(GetLastError())); + return false; + } } while (!FileIsEnding(fh)) @@ -4274,6 +4341,11 @@ bool CPositionSizeCalculator::LoadSettingsFromDisk() sets.TrailingStopPoints = (int)StringToInteger(var_content); else if (var_name == "BreakEvenPoints") sets.BreakEvenPoints = (int)StringToInteger(var_content); + else if (var_name == "ExpiryMinutes") + { + sets.ExpiryMinutes = (int)StringToInteger(var_content); + if ((sets.ExpiryMinutes != 0) && (sets.ExpiryMinutes < 10)) sets.ExpiryMinutes = 0; + } else if (var_name == "MaxNumberOfTradesTotal") sets.MaxNumberOfTradesTotal = (int)StringToInteger(var_content); else if (var_name == "MaxNumberOfTradesPerSymbol") @@ -4311,6 +4383,10 @@ bool CPositionSizeCalculator::LoadSettingsFromDisk() sets.MinEntrySLDistance = (int)StringToInteger(var_content); else if (var_name == "TradeDirection") sets.TradeDirection = (TRADE_DIRECTION)StringToInteger(var_content); + else if (var_name == "SLDistanceInPoints") + sets.SLDistanceInPoints = (bool)StringToInteger(var_content); + else if (var_name == "TPDistanceInPoints") + sets.TPDistanceInPoints = (bool)StringToInteger(var_content); else if (var_name == "StopLoss") sets.StopLoss = (int)StringToInteger(var_content); else if (var_name == "TakeProfit") @@ -4568,6 +4644,14 @@ bool CPositionSizeCalculator::LoadSettingsFromDisk() { if (StringToInteger(var_content) != DefaultBreakEven) sets.BreakEvenPoints = DefaultBreakEven; } + else if (var_name == "Parameter_DefaultExpiryMinutes") + { + if (StringToInteger(var_content) != DefaultExpiryMinutes) + { + sets.ExpiryMinutes = DefaultExpiryMinutes; + if ((sets.ExpiryMinutes != 0) && (sets.ExpiryMinutes < 10)) sets.ExpiryMinutes = 0; + } + } else if (var_name == "Parameter_DefaultSpreadAdjustmentSL") { if ((bool)StringToInteger(var_content) != DefaultSpreadAdjustmentSL) sets.SpreadAdjustmentSL = DefaultSpreadAdjustmentSL; @@ -4617,6 +4701,14 @@ bool CPositionSizeCalculator::LoadSettingsFromDisk() ArrayInitialize(TakeProfitLineIsBeingMoved, false); } } + else if (var_name == "Parameter_DefaultSLDistanceInPoints") + { + if (StringToDouble(var_content) != DefaultSLDistanceInPoints) sets.SLDistanceInPoints = DefaultSLDistanceInPoints; + } + else if (var_name == "Parameter_DefaultTPDistanceInPoints") + { + if (StringToDouble(var_content) != DefaultTPDistanceInPoints) sets.TPDistanceInPoints = DefaultTPDistanceInPoints; + } } } // Make sure total and per symbol values do not contradict each other. @@ -4765,7 +4857,7 @@ void CPositionSizeCalculator::UpdateTradingTPEdit(int i) TradingTPEdits[i].Text(s); if (i > 0) { - if (!TPDistanceInPoints) AdditionalTPEdits[i - 1].Text(s); // TP as level. + if (!sets.TPDistanceInPoints) AdditionalTPEdits[i - 1].Text(s); // TP as level. else AdditionalTPEdits[i - 1].Text(IntegerToString((int)MathRound(MathAbs(new_value - sets.EntryLevel) / _Point))); // TP as distance. } else if (sets.ATRMultiplierTP > 0) @@ -4782,7 +4874,7 @@ void CPositionSizeCalculator::UpdateTradingTPEdit(int i) // If it was the first TP field on the Trading tab, and the TP field on the Main tab was empty - fill it and show the line. if ((i == 0) && (sets.TakeProfitLevel == 0) && (new_value > 0)) { - if (TPDistanceInPoints) + if (sets.TPDistanceInPoints) { if (sets.TradeDirection == Long) m_EdtTP.Text(IntegerToString((int)MathRound(MathAbs(new_value - sets.EntryLevel) / _Point))); @@ -4809,7 +4901,7 @@ void CPositionSizeCalculator::UpdateAdditionalTPEdit(int i) double new_value = StringToDouble(AdditionalTPEdits[i - 1].Text()); // TP as level. - if (!TPDistanceInPoints) + if (!sets.TPDistanceInPoints) { // Adjust for tick size granularity. if (TickSize > 0) new_value = NormalizeDouble(MathRound(new_value / TickSize) * TickSize, _Digits); @@ -4923,6 +5015,22 @@ void CPositionSizeCalculator::UpdateTradingTPShareEdit(int i) } } +void CPositionSizeCalculator::EmulateMinMaxClick() +{ + CBmpButton * minmax_button; + minmax_button = Control(5); // MinMax button inside Dialog.mqh + if (IsMinimized()) + { + Maximize(); + minmax_button.Pressed(false); // Shown as _ + } + else + { + Minimize(); + minmax_button.Pressed(true); // Shown as two small windows. + } +} + // Check if all required lines exist and restore them if they have been accidentally deleted. void CPositionSizeCalculator::CheckAndRestoreLines() { @@ -5044,7 +5152,7 @@ bool StopOut; //---- string WarningEntry = "", WarningSL = "", WarningTP = "", AdditionalWarningTP[]; double DisplayRisk, RiskMoney, PositionMargin, UsedMargin, FutureMargin, PreHedgingPositionMargin, PortfolioLossMoney = 0; -string InputRR, OutputRR, MainOutputRR, PLM, CPR, PRM, CPRew, PPMR, PPR, PPMRew, PPRew, CPL, PPL, AdditionalOutputRR[]; +string InputRR, OutputRR, MainOutputRR, PLM, CPR, PRM, CPRew, PPMR, PPR, PPMRew, PPRew, CPL, PPL, CPRRR, PPRRR, AdditionalOutputRR[]; string InputReward; double OutputReward, AdditionalOutputReward[], MainOutputReward; string OutputPointValue = "", OutputSwapsType = "Unknown", SwapsTripleDay = "?", @@ -5089,8 +5197,8 @@ void Initialization() if (DefaultTP > 0) sets.TakeProfitLevel = sets.EntryLevel - DefaultTP * _Point; if (sets.EntryLevel == sets.StopLossLevel) sets.StopLossLevel += Point; } - if ((SLDistanceInPoints) && (sets.StopLoss <= 0)) sets.StopLoss = (int)MathRound(MathAbs((sets.EntryLevel - sets.StopLossLevel) / _Point)); - if ((TPDistanceInPoints) && (sets.TakeProfit <= 0) && (sets.TakeProfitLevel != 0)) sets.TakeProfit = (int)MathRound(MathAbs((sets.EntryLevel - sets.TakeProfitLevel) / _Point)); + if ((sets.SLDistanceInPoints) && (sets.StopLoss <= 0)) sets.StopLoss = (int)MathRound(MathAbs((sets.EntryLevel - sets.StopLossLevel) / _Point)); + if ((sets.TPDistanceInPoints) && (sets.TakeProfit <= 0) && (sets.TakeProfitLevel != 0)) sets.TakeProfit = (int)MathRound(MathAbs((sets.EntryLevel - sets.TakeProfitLevel) / _Point)); } // Loaded template with TP line - delete the line. if ((sets.TakeProfit == 0) && (sets.TakeProfitLevel == 0) && (ObjectFind(0, ObjectPrefix + "TakeProfitLine") == 0)) @@ -5106,7 +5214,7 @@ void Initialization() } } // Using TP distance in points but just switched from the TP given as a level on an already attached indicator. - if ((TPDistanceInPoints) && (sets.TakeProfit == 0) && (sets.TakeProfitLevel != 0)) sets.TakeProfit = (int)MathRound(MathAbs((sets.TakeProfitLevel - sets.EntryLevel) / _Point)); + if ((sets.TPDistanceInPoints) && (sets.TakeProfit == 0) && (sets.TakeProfitLevel != 0)) sets.TakeProfit = (int)MathRound(MathAbs((sets.TakeProfitLevel - sets.EntryLevel) / _Point)); if (sets.EntryLevel - sets.StopLossLevel == 0) { Alert("Entry and Stop-Loss levels should be different and non-zero."); @@ -5137,8 +5245,8 @@ void Initialization() if ((DefaultSL > 0) && (sets.StopLossLevel == 0)) sets.StopLossLevel = sets.EntryLevel + DefaultSL * _Point; if ((DefaultTP > 0) && (sets.TakeProfitLevel == 0)) sets.TakeProfitLevel = sets.EntryLevel - DefaultTP * _Point; } - if ((SLDistanceInPoints) && (sets.StopLoss <= 0)) sets.StopLoss = (int)MathRound(MathAbs((sets.EntryLevel - sets.StopLossLevel) / _Point)); - if ((TPDistanceInPoints) && (sets.TakeProfit <= 0) && (sets.TakeProfitLevel != 0)) sets.TakeProfit = (int)MathRound(MathAbs((sets.EntryLevel - sets.TakeProfitLevel) / _Point)); + if ((sets.SLDistanceInPoints) && (sets.StopLoss <= 0)) sets.StopLoss = (int)MathRound(MathAbs((sets.EntryLevel - sets.StopLossLevel) / _Point)); + if ((sets.TPDistanceInPoints) && (sets.TakeProfit <= 0) && (sets.TakeProfitLevel != 0)) sets.TakeProfit = (int)MathRound(MathAbs((sets.EntryLevel - sets.TakeProfitLevel) / _Point)); bool line_existed = false; // Will be used to preserve OBJPROP_SELECTED through timeframe changes and the like. if (ObjectFind(ChartID(), ObjectPrefix + "EntryLine") == -1) ObjectCreate(ChartID(), ObjectPrefix + "EntryLine", OBJ_HLINE, 0, TimeCurrent(), sets.EntryLevel); @@ -5222,6 +5330,18 @@ void Initialization() ObjectSetInteger(ChartID(), ObjectPrefix + "EntryLabel", OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(ChartID(), ObjectPrefix + "EntryLabel", OBJPROP_BACK, DrawTextAsBackground); ObjectSetString(ChartID(), ObjectPrefix + "EntryLabel", OBJPROP_TOOLTIP, "Entry Distance, points"); + if ((ShowAdditionalEntryLabel) && (ObjectFind(0, ObjectPrefix + "EntryAdditionalLabel") == -1)) + { + ObjectCreate(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJ_LABEL, 0, 0, 0); + if (sets.ShowLines) ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS); + else ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); + ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_COLOR, clrNONE); + ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_SELECTABLE, false); + ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_HIDDEN, false); + ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_CORNER, CORNER_LEFT_UPPER); + ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_BACK, DrawTextAsBackground); + ObjectSetString(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_TOOLTIP, "Position Size, lots"); + } } if (ObjectFind(ChartID(), ObjectPrefix + "TakeProfitLine") == -1) @@ -5499,6 +5619,12 @@ void RecalculatePositionSize() if (sets.ShowLines) ObjectSetInteger(ChartID(), ObjectPrefix + "SLAdditionalLabel", OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS); else ObjectSetInteger(ChartID(), ObjectPrefix + "SLAdditionalLabel", OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); } + if (ShowAdditionalEntryLabel) + { + DrawLineLabel(ObjectPrefix + "EntryAdditionalLabel", FormatDouble(DoubleToString(OutputPositionSize, LotStep_digits), LotStep_digits) + " lot", tEntryLevel, entry_label_font_color, true); + if (sets.ShowLines) ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS); + else ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); + } if (sets.EntryType == Pending) { DrawLineLabel(ObjectPrefix + "EntryLabel", IntegerToString((int)MathRound((MathAbs(tEntryLevel - AskBid) / _Point))), tEntryLevel, entry_label_font_color); @@ -6294,6 +6420,32 @@ void CalculatePortfolioRisk(const CALCULATE_RISK_FOR_TRADING_TAB calculate_risk_ CPL = FormatDouble(DoubleToString(volume, LotStep_digits), LotStep_digits); PPL = FormatDouble(DoubleToString(volume + OutputPositionSize, LotStep_digits), LotStep_digits); + + if (PortfolioRewardMoney == DBL_MAX) + { + if (PortfolioLossMoney == DBL_MAX) CPRRR = "-"; + else CPRRR = "Infinity"; + } + else if (PortfolioLossMoney == DBL_MAX) CPRRR = "0.00"; + else if (PortfolioLossMoney == 0) + { + if (PortfolioRewardMoney != 0) CPRRR = "Infinity"; + else CPRRR = "-"; + } + else CPRRR = FormatDouble(DoubleToString(PortfolioRewardMoney / PortfolioLossMoney, 2)); + + if ((PortfolioRewardMoney == DBL_MAX) || (OutputReward == 0)) + { + if (PortfolioLossMoney == DBL_MAX) PPRRR = "-"; + else PPRRR = "Infinity"; + } + else if (PortfolioLossMoney == DBL_MAX) PPRRR = "0.00"; + else if (PortfolioLossMoney + OutputRiskMoney == 0) + { + if (PortfolioRewardMoney + OutputReward != 0) PPRRR = "Infinity"; + else PPRRR = "-"; + } + else PPRRR = FormatDouble(DoubleToString((PortfolioRewardMoney + OutputReward) / (PortfolioLossMoney + OutputRiskMoney), 2)); } //+------------------------------------------------------------------+ @@ -6856,6 +7008,9 @@ void CPanelList::SetHiddenByName(const string name, const bool hidden) void DissectHotKeyCombination(const string hotkey, bool &shift_required, bool &ctrl_required, uchar &main_key) { ushort separator; + // Set these to false because they could be set to true during previous EA initialization. + shift_required = false; + ctrl_required = false; if (StringFind(hotkey, "+") > -1) separator = StringGetCharacter("+", 0); else if (StringFind(hotkey, "-") > -1) separator = StringGetCharacter("-", 0); else separator = 0; @@ -6877,6 +7032,7 @@ void DissectHotKeyCombination(const string hotkey, bool &shift_required, bool &c else if ((keys[n - 1] == "BACKSPACE") || (keys[n - 1] == "BACK") || (keys[n - 1] == "BS") || (keys[n - 1] == "BKSP")) main_key = 8; else if ((keys[n - 1] == "CAPS") || (keys[n - 1] == "CAPS LOCK") || (keys[n - 1] == "CAPSLOCK") || (keys[n - 1] == "CAPSLK")) main_key = 20; else main_key = (uchar)StringGetCharacter(keys[n - 1], 0); + if (main_key == 96) main_key = 192; // A hack to use ` as a hotkey. } void WarnAboutZeroUnitCost() diff --git a/MQL5/Experts/Position Sizer/Defines.mqh b/MQL5/Experts/Position Sizer/Defines.mqh index 3f4c2f9..f73e926 100644 --- a/MQL5/Experts/Position Sizer/Defines.mqh +++ b/MQL5/Experts/Position Sizer/Defines.mqh @@ -21,7 +21,9 @@ color DARKMODE_MAIN_AREA_BORDER_COLOR = 0x333333; color DARKMODE_MAIN_AREA_BG_COLOR = 0x666666; color DARKMODE_EDIT_BG_COLOR = 0xAAAAAA; color DARKMODE_BUTTON_BG_COLOR = 0xA19999; -color DARKMODE_TEXT_COLOR = 0x000000;; +color DARKMODE_TEXT_COLOR = 0x000000; + +color CONTROLS_BUTTON_COLOR_TP_UNLOCKED, CONTROLS_BUTTON_COLOR_TP_LOCKED; enum ENTRY_TYPE { @@ -134,6 +136,8 @@ struct Settings int MaxEntrySLDistance; int MinEntrySLDistance; // For SL/TP distance modes: + bool SLDistanceInPoints; + bool TPDistanceInPoints; int StopLoss; int TakeProfit; // Only for SL distance mode: @@ -155,6 +159,7 @@ struct Settings double MaxPositionSizePerSymbol; double MaxRiskTotal; double MaxRiskPerSymbol; + int ExpiryMinutes; // For ATR: int ATRPeriod; double ATRMultiplierSL; diff --git a/MQL5/Experts/Position Sizer/Position Sizer Trading.mqh b/MQL5/Experts/Position Sizer/Position Sizer Trading.mqh index 1a135f6..d3ff5e4 100644 Binary files a/MQL5/Experts/Position Sizer/Position Sizer Trading.mqh and b/MQL5/Experts/Position Sizer/Position Sizer Trading.mqh differ diff --git a/MQL5/Experts/Position Sizer/Position Sizer.mq5 b/MQL5/Experts/Position Sizer/Position Sizer.mq5 index e54c5d2..c1050f2 100644 --- a/MQL5/Experts/Position Sizer/Position Sizer.mq5 +++ b/MQL5/Experts/Position Sizer/Position Sizer.mq5 @@ -6,8 +6,8 @@ #property copyright "EarnForex.com" #property link "https://www.earnforex.com/metatrader-expert-advisors/Position-Sizer/" #property icon "EF-Icon-64x64px.ico" -#property version "3.06" -string Version = "3.06"; +#property version "3.07" +string Version = "3.07"; #include "Translations\English.mqh" //#include "Translations\Arabic.mqh" @@ -37,6 +37,7 @@ input group "Compactness" input bool ShowLineLabels = true; // ShowLineLabels: Show point distance for TP/SL near lines? input bool ShowAdditionalSLLabel = false; // ShowAdditionalSLLabel: Show SL $/% label? input bool ShowAdditionalTPLabel = false; // ShowAdditionalTPLabel: Show TP $/% + R/R label? +input bool ShowAdditionalEntryLabel = false; // ShowAdditionalEntryLabel: Show Position Size label? input bool DrawTextAsBackground = false; // DrawTextAsBackground: Draw label objects as background? input bool HideAccSize = false; // HideAccSize: Hide account size? input bool ShowPointValue = false; // ShowPointValue: Show point value? @@ -47,16 +48,16 @@ input bool ShowMaxParametersOnTrading = true; // Show max parameters on Trading input bool ShowFusesOnTrading = true; // Show trading "fuses" on Trading tab? input bool ShowCheckboxesOnTrading = true; // Show checkboxes on Trading tab? input group "Fonts" -input color sl_label_font_color = clrLime; // SL Label Color -input color tp_label_font_color = clrYellow; // TP Label Color +input color sl_label_font_color = clrGreen; // SL Label Color +input color tp_label_font_color = clrGoldenrod; // TP Label Color input color sp_label_font_color = clrPurple; // Stop Price Label Color input color entry_label_font_color = clrBlue; // Entry Label Font Color input uint font_size = 13; // Labels Font Size input string font_face = "Courier"; // Labels Font Face input group "Lines" input color entry_line_color = clrBlue; // Entry Line Color -input color stoploss_line_color = clrLime; // Stop-Loss Line Color -input color takeprofit_line_color = clrYellow; // Take-Profit Line Color +input color stoploss_line_color = clrGreen; // Stop-Loss Line Color +input color takeprofit_line_color = clrGoldenrod; // Take-Profit Line Color input color stopprice_line_color = clrPurple; // Stop Price Line Color input color be_line_color = clrNONE; // BE Line Color input ENUM_LINE_STYLE entry_line_style = STYLE_SOLID; // Entry Line Style @@ -115,10 +116,13 @@ input ENUM_BASE_CORNER DefaultPanelPositionCorner = CORNER_LEFT_UPPER; // PanelP input bool DefaultTPLockedOnSL = false; // TPLockedOnSL: Lock TP to (multiplied) SL distance. input int DefaultTrailingStop = 0; // TrailingStop: For the Trading tab. input int DefaultBreakEven = 0; // BreakEven: For the Trading tab. +input int DefaultExpiryMinutes = 0; // ExpiryMinutes: Pending order expiration in minutes. Min = 2. input int DefaultMaxNumberOfTradesTotal = 0; // MaxNumberOfTradesTotal: For the Trading tab. 0 - no limit. input int DefaultMaxNumberOfTradesPerSymbol = 0; // MaxNumberOfTradesPerSymbol: For the Trading tab. 0 - no limit. input double DefaultMaxRiskTotal = 0; // MaxRiskTotal: For the Trading tab. 0 - no limit. input double DefaultMaxRiskPerSymbol = 0; // MaxRiskPerSymbol: For the Trading tab. 0 - no limit. +input bool DefaultSLDistanceInPoints = false; // SLDistanceInPoints: SL distance in points instead of a level. +input bool DefaultTPDistanceInPoints = false; // TPDistanceInPoints: TP distance in points instead of a level. input group "Keyboard shortcuts" input string ____ = "Case-insensitive hotkey. Supports Ctrl, Shift."; input string TradeHotKey = "Shift+T"; // TradeHotKey: Execute a trade. @@ -128,14 +132,15 @@ input string SwitchHideShowLinesHotKey = "H"; // SwitchHideShowLinesHotKey: Swit input string SetStopLossHotKey = "S"; // SetStopLossHotKey: Set SL to where mouse pointer is. input string SetTakeProfitHotKey = "P"; // SetTakeProfitHotKey: Set TP to where mouse pointer is. input string SetEntryHotKey = "E"; // SetEntryHotKey: Set Entry to where mouse pointer is. +input string MinimizeMaximizeHotkey = "`"; // MinimizeMaximizeHotkey: Minimize/maximize the panel. +input string SwitchSLPointsLevelHotKey = "Shift+S"; // SwitchSLPointsLevelHotKey: Switch SL between points and level. +input string SwitchTPPointsLevelHotKey = "Shift+P"; // SwitchTPPointsLevelHotKey: Switch TP between points and level. input group "Miscellaneous" input double TP_Multiplier = 1; // TP Multiplier for SL value, appears in Take-profit button. input bool UseCommissionToSetTPDistance = false; // UseCommissionToSetTPDistance: For TP button. input SHOW_SPREAD ShowSpread = No; // ShowSpread: Show current spread in points or as an SL ratio. input double AdditionalFunds = 0; // AdditionalFunds: Added to account balance for risk calculation. input double CustomBalance = 0; // CustomBalance: Overrides AdditionalFunds value. -input bool SLDistanceInPoints = false; // SLDistanceInPoints: SL distance in points instead of a level. -input bool TPDistanceInPoints = false; // TPDistanceInPoints: TP distance in points instead of a level. input CANDLE_NUMBER ATRCandle = Current_Candle; // ATRCandle: Candle to get ATR value from. input bool CalculateUnadjustedPositionSize = false; // CalculateUnadjustedPositionSize: Ignore broker's restrictions. input bool SurpassBrokerMaxPositionSize = false; // Surpass Broker Max Position Size with multiple trades. @@ -160,9 +165,9 @@ bool Dont_Move_the_Panel_to_Default_Corner_X_Y = true; uint LastRecalculationTime = 0; bool StopLossLineIsBeingMoved = false; bool TakeProfitLineIsBeingMoved[]; // Separate for each TP. -uchar MainKey_TradeHotKey = 0, MainKey_SwitchOrderTypeHotKey = 0, MainKey_SwitchEntryDirectionHotKey = 0, MainKey_SwitchHideShowLinesHotKey = 0, MainKey_SetStopLossHotKey = 0, MainKey_SetTakeProfitHotKey = 0, MainKey_SetEntryHotKey = 0; -bool CtrlRequired_TradeHotKey = false, CtrlRequired_SwitchOrderTypeHotKey = false, CtrlRequired_SwitchEntryDirectionHotKey = false, CtrlRequired_SwitchHideShowLinesHotKey = false, CtrlRequired_SetStopLossHotKey = false, CtrlRequired_SetTakeProfitHotKey = false, CtrlRequired_SetEntryHotKey = false;; -bool ShiftRequired_TradeHotKey = false, ShiftRequired_SwitchOrderTypeHotKey = false, ShiftRequired_SwitchEntryDirectionHotKey = false, ShiftRequired_SwitchHideShowLinesHotKey = false, ShiftRequired_SetStopLossHotKey = false, ShiftRequired_SetTakeProfitHotKey = false, ShiftRequired_SetEntryHotKey = false; +uchar MainKey_TradeHotKey = 0, MainKey_SwitchOrderTypeHotKey = 0, MainKey_SwitchEntryDirectionHotKey = 0, MainKey_SwitchHideShowLinesHotKey = 0, MainKey_SetStopLossHotKey = 0, MainKey_SetTakeProfitHotKey = 0, MainKey_SetEntryHotKey = 0, MainKey_MinimizeMaximizeHotkey = 0, MainKey_SwitchSLPointsLevelHotKey = 0, MainKey_SwitchTPPointsLevelHotKey = 0; +bool CtrlRequired_TradeHotKey = false, CtrlRequired_SwitchOrderTypeHotKey = false, CtrlRequired_SwitchEntryDirectionHotKey = false, CtrlRequired_SwitchHideShowLinesHotKey = false, CtrlRequired_SetStopLossHotKey = false, CtrlRequired_SetTakeProfitHotKey = false, CtrlRequired_SetEntryHotKey = false, CtrlRequired_MinimizeMaximizeHotkey = false, CtrlRequired_SwitchSLPointsLevelHotKey = false, CtrlRequired_SwitchTPPointsLevelHotKey = false; +bool ShiftRequired_TradeHotKey = false, ShiftRequired_SwitchOrderTypeHotKey = false, ShiftRequired_SwitchEntryDirectionHotKey = false, ShiftRequired_SwitchHideShowLinesHotKey = false, ShiftRequired_SetStopLossHotKey = false, ShiftRequired_SetTakeProfitHotKey = false, ShiftRequired_SetEntryHotKey = false, ShiftRequired_MinimizeMaximizeHotkey = false, ShiftRequired_SwitchSLPointsLevelHotKey = false, ShiftRequired_SwitchTPPointsLevelHotKey = false; bool AdditionalTPLineMoved = false; int DeinitializationReason = -1; string OldSymbol = ""; @@ -178,6 +183,8 @@ int OnInit() CONTROLS_EDIT_COLOR_DISABLE = 0x999999; CONTROLS_BUTTON_COLOR_ENABLE = DARKMODE_BUTTON_BG_COLOR; CONTROLS_BUTTON_COLOR_DISABLE = 0x919999; + CONTROLS_BUTTON_COLOR_TP_UNLOCKED = DARKMODE_BUTTON_BG_COLOR; + CONTROLS_BUTTON_COLOR_TP_LOCKED = 0x909090; } else { @@ -185,6 +192,8 @@ int OnInit() CONTROLS_EDIT_COLOR_DISABLE = C'221,221,211'; CONTROLS_BUTTON_COLOR_ENABLE = C'200,200,200'; CONTROLS_BUTTON_COLOR_DISABLE = C'224,224,224'; + CONTROLS_BUTTON_COLOR_TP_UNLOCKED = CONTROLS_BUTTON_COLOR_BG; + CONTROLS_BUTTON_COLOR_TP_LOCKED = CONTROLS_BUTTON_COLOR_ENABLE; } TickSize = -1; @@ -309,6 +318,8 @@ int OnInit() sets.TPLockedOnSL = DefaultTPLockedOnSL; sets.TrailingStopPoints = DefaultTrailingStop; sets.BreakEvenPoints = DefaultBreakEven; + sets.ExpiryMinutes = DefaultExpiryMinutes; + if ((sets.ExpiryMinutes != 0) && (sets.ExpiryMinutes < 2)) sets.ExpiryMinutes = 0; sets.MaxNumberOfTradesTotal = DefaultMaxNumberOfTradesTotal; sets.MaxNumberOfTradesPerSymbol = DefaultMaxNumberOfTradesPerSymbol; if ((sets.MaxNumberOfTradesTotal < sets.MaxNumberOfTradesPerSymbol) && (sets.MaxNumberOfTradesTotal != 0)) sets.MaxNumberOfTradesTotal = sets.MaxNumberOfTradesPerSymbol; @@ -318,9 +329,20 @@ int OnInit() // Because it is the first load: Dont_Move_the_Panel_to_Default_Corner_X_Y = false; sets.ShareVolumeMode = Decreasing; + sets.SLDistanceInPoints = DefaultSLDistanceInPoints; + sets.TPDistanceInPoints = DefaultTPDistanceInPoints; if (DeinitializationReason == REASON_CHARTCHANGE) is_InitControlsValues_required = true; } - if (sets.TakeProfitsNumber < 1) sets.TakeProfitsNumber = 1; // At least one TP. + if (sets.TakeProfitsNumber < 1) // Read an old settings file with absent or bogus TakeProfitNumber parameter + { + sets.TakeProfitsNumber = 1; // At least one TP. + ArrayResize(sets.TP, sets.TakeProfitsNumber); + ArrayResize(sets.TPShare, sets.TakeProfitsNumber); + ArrayResize(TakeProfitLineIsBeingMoved, sets.TakeProfitsNumber); + ArrayInitialize(sets.TP, 0); + ArrayInitialize(sets.TPShare, 100 / sets.TakeProfitsNumber); + ArrayResize(sets.WasSelectedAdditionalTakeProfitLine, sets.TakeProfitsNumber - 1); // -1 because the flag for the main TP is saved elsewhere. + } if (DeinitializationReason != REASON_CHARTCHANGE) { @@ -342,6 +364,9 @@ int OnInit() if (SetStopLossHotKey != "") DissectHotKeyCombination(SetStopLossHotKey, ShiftRequired_SetStopLossHotKey, CtrlRequired_SetStopLossHotKey, MainKey_SetStopLossHotKey); if (SetTakeProfitHotKey != "") DissectHotKeyCombination(SetTakeProfitHotKey, ShiftRequired_SetTakeProfitHotKey, CtrlRequired_SetTakeProfitHotKey, MainKey_SetTakeProfitHotKey); if (SetEntryHotKey != "") DissectHotKeyCombination(SetEntryHotKey, ShiftRequired_SetEntryHotKey, CtrlRequired_SetEntryHotKey, MainKey_SetEntryHotKey); + if (MinimizeMaximizeHotkey != "") DissectHotKeyCombination(MinimizeMaximizeHotkey, ShiftRequired_MinimizeMaximizeHotkey, CtrlRequired_MinimizeMaximizeHotkey, MainKey_MinimizeMaximizeHotkey); + if (SwitchSLPointsLevelHotKey != "") DissectHotKeyCombination(SwitchSLPointsLevelHotKey, ShiftRequired_SwitchSLPointsLevelHotKey, CtrlRequired_SwitchSLPointsLevelHotKey, MainKey_SwitchSLPointsLevelHotKey); + if (SwitchTPPointsLevelHotKey != "") DissectHotKeyCombination(SwitchTPPointsLevelHotKey, ShiftRequired_SwitchTPPointsLevelHotKey, CtrlRequired_SwitchTPPointsLevelHotKey, MainKey_SwitchTPPointsLevelHotKey); } else if (OldSymbol != _Symbol) { @@ -458,7 +483,6 @@ int OnInit() { string obj_name = ObjectName(ChartID(), i); if (StringSubstr(obj_name, 0, StringLen(ExtDialog.Name())) != ExtDialog.Name()) continue; // Skip non-panel objects. - //if (ObjectType(obj_name) != OBJ_RECTANGLE_LABEL) continue; if (obj_name == ExtDialog.Name() + "Back") { @@ -480,6 +504,10 @@ int OnInit() ObjectSetInteger(ChartID(), obj_name, OBJPROP_BGCOLOR, DARKMODE_EDIT_BG_COLOR); ObjectSetInteger(ChartID(), obj_name, OBJPROP_BORDER_COLOR, DARKMODE_CONTROL_BRODER_COLOR); } + else if (obj_name == ExtDialog.Name() + "m_BtnTakeProfit") // TakeProfit button has its own colors. + { + ObjectSetInteger(ChartID(), obj_name, OBJPROP_BORDER_COLOR, DARKMODE_CONTROL_BRODER_COLOR); + } else if (StringSubstr(obj_name, 0, StringLen(ExtDialog.Name() + "m_Btn")) == ExtDialog.Name() + "m_Btn") { ObjectSetInteger(ChartID(), obj_name, OBJPROP_BGCOLOR, DARKMODE_BUTTON_BG_COLOR); @@ -570,7 +598,7 @@ void OnChartEvent(const int id, Mouse_Last_Y = (int)dparam; if (((uint)sparam & 1) == 1) // While left mouse button is down. { - if ((SLDistanceInPoints) || ((ShowATROptions) && (sets.ATRMultiplierSL > 0))) + if ((sets.SLDistanceInPoints) || ((ShowATROptions) && (sets.ATRMultiplierSL > 0))) { double current_line_price = NormalizeDouble(ObjectGetDouble(ChartID(), ObjectPrefix + "StopLossLine", OBJPROP_PRICE, 0), _Digits); if (MathAbs(current_line_price - tStopLossLevel) > _Point / 2.0) // != for doubles. @@ -579,7 +607,7 @@ void OnChartEvent(const int id, } else StopLossLineIsBeingMoved = false; } - if ((TPDistanceInPoints) || ((ShowATROptions) && (sets.ATRMultiplierTP > 0))) + if ((sets.TPDistanceInPoints) || ((ShowATROptions) && (sets.ATRMultiplierTP > 0))) { ArrayInitialize(TakeProfitLineIsBeingMoved, false); double current_line_price = NormalizeDouble(ObjectGetDouble(ChartID(), ObjectPrefix + "TakeProfitLine", OBJPROP_PRICE, 0), _Digits); @@ -682,111 +710,148 @@ void OnChartEvent(const int id, if (id == CHARTEVENT_KEYDOWN) { // Trade direction: - if ((MainKey_SwitchEntryDirectionHotKey != 0) && (lparam == MainKey_SwitchEntryDirectionHotKey)) + if ((MainKey_SwitchEntryDirectionHotKey != 0) && (lparam == MainKey_SwitchEntryDirectionHotKey) + && ((((!ShiftRequired_SwitchEntryDirectionHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_SwitchEntryDirectionHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_SwitchEntryDirectionHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_SwitchEntryDirectionHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0)))) // Control + ) { - if (((!ShiftRequired_SwitchEntryDirectionHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0)) // Shift - && ((!CtrlRequired_SwitchEntryDirectionHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))) // Control - { - SwitchEntryDirection(); - } + SwitchEntryDirection(); } // Order type: - else if ((MainKey_SwitchOrderTypeHotKey != 0) && (lparam == MainKey_SwitchOrderTypeHotKey)) + else if ((MainKey_SwitchOrderTypeHotKey != 0) && (lparam == MainKey_SwitchOrderTypeHotKey) + && ((((!ShiftRequired_SwitchOrderTypeHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_SwitchOrderTypeHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_SwitchOrderTypeHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_SwitchOrderTypeHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))))) // Control { - if (((!ShiftRequired_SwitchOrderTypeHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0)) // Shift - && ((!CtrlRequired_SwitchOrderTypeHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))) // Control - { - ExtDialog.OnClickBtnOrderType(); - ChartRedraw(); - } + ExtDialog.OnClickBtnOrderType(); + ChartRedraw(); } // Hide/Show lines: - else if ((MainKey_SwitchHideShowLinesHotKey != 0) && (lparam == MainKey_SwitchHideShowLinesHotKey)) + else if ((MainKey_SwitchHideShowLinesHotKey != 0) && (lparam == MainKey_SwitchHideShowLinesHotKey) + && ((((!ShiftRequired_SwitchHideShowLinesHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_SwitchHideShowLinesHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_SwitchHideShowLinesHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_SwitchHideShowLinesHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))))) // Control { - if (((!ShiftRequired_SwitchHideShowLinesHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0)) // Shift - && ((!CtrlRequired_SwitchHideShowLinesHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))) // Control - { - ExtDialog.OnClickBtnLines(); - } + ExtDialog.OnClickBtnLines(); } // Trade: - else if ((MainKey_TradeHotKey != 0) && (lparam == MainKey_TradeHotKey)) + else if ((MainKey_TradeHotKey != 0) && (lparam == MainKey_TradeHotKey) + && ((((!ShiftRequired_TradeHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_TradeHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_TradeHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_TradeHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))))) // Control { - if (((!ShiftRequired_TradeHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0)) // Shift - && ((!CtrlRequired_TradeHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))) // Control + Trade(); + } + // Set stop-loss: + else if ((MainKey_SetStopLossHotKey != 0) && (lparam == MainKey_SetStopLossHotKey) + && ((((!ShiftRequired_SetStopLossHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_SetStopLossHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_SetStopLossHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_SetStopLossHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))))) // Control + { + // Capture point price location. + int subwindow; + double price; + datetime time; // Dummy. + ChartXYToTimePrice(ChartID(), Mouse_Last_X, Mouse_Last_Y, subwindow, time, price); + // If valid, move the SL line there. + if ((subwindow == 0) && (price > 0)) { - Trade(); + if (TickSize > 0) price = NormalizeDouble(MathRound(price / TickSize) * TickSize, _Digits); + ObjectSetDouble(ChartID(), ObjectPrefix + "StopLossLine", OBJPROP_PRICE, price); + if ((sets.SLDistanceInPoints) || (ShowATROptions)) ExtDialog.UpdateFixedSL(); + ExtDialog.RefreshValues(); } } - // Set stop-loss: - else if ((MainKey_SetStopLossHotKey != 0) && (lparam == MainKey_SetStopLossHotKey)) + // Set take-profit: + else if ((MainKey_SetTakeProfitHotKey != 0) && (lparam == MainKey_SetTakeProfitHotKey) + && ((((!ShiftRequired_SetTakeProfitHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_SetTakeProfitHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_SetTakeProfitHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_SetTakeProfitHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))))) // Control { - if (((!ShiftRequired_SetStopLossHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0)) // Shift - && ((!CtrlRequired_SetStopLossHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))) // Control + // Capture point price location. + int subwindow; + double price; + datetime time; // Dummy. + ChartXYToTimePrice(ChartID(), Mouse_Last_X, Mouse_Last_Y, subwindow, time, price); + // If valid, move the TP line there. + if ((subwindow == 0) && (price > 0)) { - // Capture point price location. - int subwindow; - double price; - datetime time; // Dummy. - ChartXYToTimePrice(ChartID(), Mouse_Last_X, Mouse_Last_Y, subwindow, time, price); - // If valid, move the SL line there. - if ((subwindow == 0) && (price > 0)) + // If "TP locked on SL" mode was on, turn it off. + if (sets.TPLockedOnSL) { - if (TickSize > 0) price = NormalizeDouble(MathRound(price / TickSize) * TickSize, _Digits); - ObjectSetDouble(ChartID(), ObjectPrefix + "StopLossLine", OBJPROP_PRICE, price); - if ((SLDistanceInPoints) || (ShowATROptions)) ExtDialog.UpdateFixedSL(); - ExtDialog.RefreshValues(); + ExtDialog.SetTPButtonBackGroundColor(CONTROLS_BUTTON_COLOR_TP_UNLOCKED); + sets.TPLockedOnSL = false; } + if (TickSize > 0) price = NormalizeDouble(MathRound(price / TickSize) * TickSize, _Digits); + ObjectSetDouble(ChartID(), ObjectPrefix + "TakeProfitLine", OBJPROP_PRICE, price); + if (sets.ShowLines) ObjectSetInteger(ChartID(), ObjectPrefix + "TakeProfitLine", OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS); + if ((sets.TPDistanceInPoints) || (ShowATROptions)) ExtDialog.UpdateFixedTP(); + ExtDialog.ShowTPRelatedEdits(); + ExtDialog.RefreshValues(); + ExtDialog.HideShowMaximize(); + ExtDialog.MoveAndResize(); } } - // Set take-profit: - else if ((MainKey_SetTakeProfitHotKey != 0) && (lparam == MainKey_SetTakeProfitHotKey)) + // Set entry: + else if ((MainKey_SetEntryHotKey != 0) && (lparam == MainKey_SetEntryHotKey) + && ((((!ShiftRequired_SetEntryHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_SetEntryHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_SetEntryHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_SetEntryHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))))) // Control { - if (((!ShiftRequired_SetTakeProfitHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0)) // Shift - && ((!CtrlRequired_SetTakeProfitHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))) // Control + // Capture point price location. + int subwindow; + double price; + datetime time; // Dummy. + ChartXYToTimePrice(ChartID(), Mouse_Last_X, Mouse_Last_Y, subwindow, time, price); + // If valid, move the Entry line there and switch from Instant to Pending if necessary. + if ((subwindow == 0) && (price > 0)) { - // Capture point price location. - int subwindow; - double price; - datetime time; // Dummy. - ChartXYToTimePrice(ChartID(), Mouse_Last_X, Mouse_Last_Y, subwindow, time, price); - // If valid, move the TP line there. - if ((subwindow == 0) && (price > 0)) + if (TickSize > 0) price = NormalizeDouble(MathRound(price / TickSize) * TickSize, _Digits); + ObjectSetDouble(ChartID(), ObjectPrefix + "EntryLine", OBJPROP_PRICE, price); + if (sets.EntryType == Instant) { - if (TickSize > 0) price = NormalizeDouble(MathRound(price / TickSize) * TickSize, _Digits); - ObjectSetDouble(ChartID(), ObjectPrefix + "TakeProfitLine", OBJPROP_PRICE, price); - if (sets.ShowLines) ObjectSetInteger(ChartID(), ObjectPrefix + "TakeProfitLine", OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS); - if ((TPDistanceInPoints) || (ShowATROptions)) ExtDialog.UpdateFixedTP(); - ExtDialog.ShowTPRelatedEdits(); - ExtDialog.RefreshValues(); - ExtDialog.HideShowMaximize(); - ExtDialog.MoveAndResize(); + ExtDialog.OnClickBtnOrderType(); // Includes RefreshValues(). } + else ExtDialog.RefreshValues(); } } - // Set entry: - else if ((MainKey_SetEntryHotKey != 0) && (lparam == MainKey_SetEntryHotKey)) + // Minimize/maximize: + else if ((MainKey_MinimizeMaximizeHotkey != 0) && (lparam == MainKey_MinimizeMaximizeHotkey) + && ((((!ShiftRequired_MinimizeMaximizeHotkey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_MinimizeMaximizeHotkey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_MinimizeMaximizeHotkey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_MinimizeMaximizeHotkey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))))) // Control + { + ExtDialog.EmulateMinMaxClick(); + } + // Switch SL between points and level: + else if ((MainKey_SwitchSLPointsLevelHotKey != 0) && (lparam == MainKey_SwitchSLPointsLevelHotKey) + && ((((!ShiftRequired_SwitchSLPointsLevelHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_SwitchSLPointsLevelHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_SwitchSLPointsLevelHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_SwitchSLPointsLevelHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))))) // Control + { + if (sets.SLDistanceInPoints) sets.SLDistanceInPoints = false; // If was in points, set to level. + else + { + sets.SLDistanceInPoints = true; // If was in level, set to points. + sets.StopLoss = (int)MathRound(MathAbs(sets.StopLossLevel - sets.EntryLevel) / _Point); + } + ExtDialog.RefreshValues(); + } + // Switch TP between points and level: + else if ((MainKey_SwitchTPPointsLevelHotKey != 0) && (lparam == MainKey_SwitchTPPointsLevelHotKey) + && ((((!ShiftRequired_SwitchTPPointsLevelHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) >= 0)) || ((ShiftRequired_SwitchTPPointsLevelHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0))) // Shift + && (((!CtrlRequired_SwitchTPPointsLevelHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) >= 0)) || ((CtrlRequired_SwitchTPPointsLevelHotKey) && (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))))) // Control { - if (((!ShiftRequired_SetEntryHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0)) // Shift - && ((!CtrlRequired_SetEntryHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))) // Control + if (sets.TPDistanceInPoints) sets.TPDistanceInPoints = false; // If was in points, set to level. + else { - // Capture point price location. - int subwindow; - double price; - datetime time; // Dummy. - ChartXYToTimePrice(ChartID(), Mouse_Last_X, Mouse_Last_Y, subwindow, time, price); - // If valid, move the Entry line there and switch from Instant to Pending if necessary. - if ((subwindow == 0) && (price > 0)) + sets.TPDistanceInPoints = true; // If was in level, set to points. + sets.TakeProfit = (int)MathRound(MathAbs(sets.TakeProfitLevel - sets.EntryLevel) / _Point); + // Additional take-profits. + if (sets.TakeProfitsNumber > 1) { - if (TickSize > 0) price = NormalizeDouble(MathRound(price / TickSize) * TickSize, _Digits); - ObjectSetDouble(ChartID(), ObjectPrefix + "EntryLine", OBJPROP_PRICE, price); - if (sets.EntryType == Instant) + for (int i = 1; i < sets.TakeProfitsNumber; i++) { - ExtDialog.OnClickBtnOrderType(); // Includes RefreshValues(). + if (sets.TP[i] != 0) // With zero points TP, keep the TP lines at zero level - as with the main TP level. + { + ExtDialog.AdditionalTPEdits[i - 1].Text(DoubleToString(MathRound((sets.TP[i] - sets.EntryLevel) / _Point), 0)); + } } - else ExtDialog.RefreshValues(); } } + ExtDialog.RefreshValues(); } } @@ -804,7 +869,7 @@ void OnChartEvent(const int id, if (id == CHARTEVENT_OBJECT_DRAG) { // Moving lines when fixed SL/TP distance is enabled. Should set a new fixed SL/TP distance. - if ((SLDistanceInPoints) || (TPDistanceInPoints) || (ShowATROptions)) + if ((sets.SLDistanceInPoints) || (sets.TPDistanceInPoints) || (ShowATROptions)) { if (sparam == ObjectPrefix + "StopLossLine") ExtDialog.UpdateFixedSL(); else if (sparam == ObjectPrefix + "TakeProfitLine") ExtDialog.UpdateFixedTP(); @@ -816,7 +881,7 @@ void OnChartEvent(const int id, } } // Update required for additional TP fields on the Trading panel. - if ((!TPDistanceInPoints) && (sets.TakeProfitsNumber > 1) && (StringFind(sparam, ObjectPrefix + "TakeProfitLine") != -1)) + if ((!sets.TPDistanceInPoints) && (sets.TakeProfitsNumber > 1) && (StringFind(sparam, ObjectPrefix + "TakeProfitLine") != -1)) { int len = StringLen(ObjectPrefix + "TakeProfitLine"); int i = (int)StringToInteger(StringSubstr(sparam, len)); diff --git a/MQL5/Experts/Position Sizer/Position Sizer.mqh b/MQL5/Experts/Position Sizer/Position Sizer.mqh index 83fe21e..4159fa6 100644 --- a/MQL5/Experts/Position Sizer/Position Sizer.mqh +++ b/MQL5/Experts/Position Sizer/Position Sizer.mqh @@ -10,8 +10,8 @@ class CPositionSizeCalculator : public CAppDialog private: CButton m_BtnTabMain, m_BtnTabRisk, m_BtnTabMargin, m_BtnTabSwaps, m_BtnTabTrading, m_BtnOrderType, m_BtnAccount, m_BtnLines, m_BtnStopLoss, m_BtnTakeProfit, m_BtnEntry, m_BtnATRTimeframe, m_BtnCommissionType, m_BtnMaxPS, m_BtnTrade, m_BtnTPsInward, m_BtnTPsOutward, m_BtnTradingTPShare, m_BtnQuickRisk1, m_BtnQuickRisk2, m_BtnEntryIncrease, m_BtnEntryDecrease, m_BtnStopLossIncrease, m_BtnStopLossDecrease, m_BtnTakeProfitIncrease, m_BtnTakeProfitDecrease, m_BtnStopPriceIncrease, m_BtnStopPriceDecrease, m_BtnTakeProfitsNumberAdd, m_BtnTakeProfitsNumberRemove;; CCheckBox m_ChkSpreadAdjustmentSL, m_ChkSpreadAdjustmentTP, m_ChkCountPendings, m_ChkIgnoreOrdersWithoutSL, m_ChkIgnoreOrdersWithoutTP, m_ChkIgnoreOtherSymbols, m_ChkDisableTradingWhenLinesAreHidden, m_ChkSubtractPositions, m_ChkSubtractPendingOrders, m_ChkDoNotApplyStopLoss, m_ChkDoNotApplyTakeProfit, m_ChkAskForConfirmation, m_ChkCommentAutoSuffix; - CEdit m_EdtEntryLevel, m_EdtSL, m_EdtTP, m_EdtStopPrice, m_EdtAccount, m_EdtCommissionSize, m_EdtRiskPIn, m_EdtRiskPRes, m_EdtRiskMIn, m_EdtRiskMRes, m_EdtReward1, m_EdtReward2, m_EdtRR1, m_EdtRR2, m_EdtPosSize, m_EdtPointValue, m_EdtATRPeriod, m_EdtATRMultiplierSL, m_EdtATRMultiplierTP, m_EdtCurRiskM, m_EdtCurRiskP, m_EdtPotRiskM, m_EdtPotRiskP, m_EdtCurProfitM, m_EdtCurProfitP, m_EdtPotProfitM, m_EdtPotProfitP, m_EdtCurL, m_EdtPotL, m_EdtPosMargin, m_EdtUsedMargin, m_EdtFreeMargin, m_EdtCustomLeverage, m_EdtMaxPositionSizeByMargin, m_EdtSwapsType, m_EdtSwapsTripleDay, m_EdtSwapsNominalLong, m_EdtSwapsNominalShort, m_EdtSwapsDailyLongLot, m_EdtSwapsDailyShortLot, m_EdtSwapsDailyLongPS, m_EdtSwapsDailyShortPS, m_EdtSwapsYearlyLongLot, m_EdtSwapsYearlyShortLot, m_EdtSwapsYearlyLongPS, m_EdtSwapsYearlyShortPS, m_EdtMagicNumber, m_EdtCommentary, m_EdtMaxSlippage, m_EdtMaxSpread, m_EdtMaxEntrySLDistance, m_EdtMinEntrySLDistance, m_EdtMaxPositionSize, m_EdtTrailingStopPoints, m_EdtBreakEvenPoints, m_EdtMaxNumberOfTradesTotal, m_EdtMaxNumberOfTradesPerSymbol, m_EdtMaxPositionSizeTotal, m_EdtMaxPositionSizePerSymbol, m_EdtMaxRiskTotal, m_EdtMaxRiskPerSymbol; - CLabel m_LblEntryLevel, m_LblEntryWarning, m_LblSL, m_LblSLWarning, m_LblTPWarning, m_LblStopPrice, m_LblStopPriceWarning, m_LblOrderType, m_LblCommissionSize, m_LblAdditionalFundsAsterisk, m_LblInput, m_LblResult, m_LblRisk, m_LblRiskM, m_LblReward, m_LblRR, m_LblPosSize, m_LblPointValue, m_LblATRPeriod, m_LblATRMultiplierSL, m_LblATRMultiplierTP, m_LblATRValue, m_LblATRTimeframe, m_LblCurrentRiskMoney, m_LblCurrentRiskPerc, m_LblCurrentProfitMoney, m_LblCurrentProfitPerc, m_LblPotentialRiskMoney, m_LblPotentialRiskPerc, m_LblPotentialProfitMoney, m_LblPotentialProfitPerc, m_LblCurrentLots, m_LblPotentialLots, m_LblCurrentPortfolio, m_LblPotentialPortfolio, m_LblPosMargin, m_LblUsedMargin, m_LblFreeMargin, m_LblCustomLeverage, m_LblAccLeverage, m_LblSymbolLeverage, m_LblMaxPositionSizeByMargin, m_LblSwapsType, m_LblSwapsTripleDay, m_LblSwapsLong, m_LblSwapsShort, m_LblSwapsNominal, m_LblSwapsDaily, m_LblSwapsYearly, m_LblSwapsPerLotDaily, m_LblSwapsPerPSDaily, m_LblSwapsPerLotYearly, m_LblSwapsPerPSYearly, m_LblMagicNumber, m_LblCommentary, m_LblTradingPoints, m_LblMaxSlippage, m_LblMaxSpread, m_LblMaxEntrySLDistance, m_LblMinEntrySLDistance, m_LblTradingLots, m_LblURL, m_LblTradingTP, m_LblTrailingStop, m_LblBreakEven, m_LblMaxNumberOfTrades, m_LblMaxNumberOfTradesTotal, m_LblMaxNumberOfTradesPerSymbol, m_LblMaxPositionSize, m_LblMaxPositionSizeTotal, m_LblMaxPositionSizePerSymbol, m_LblMaxRisk, m_LblMaxRiskTotal, m_LblMaxRiskPerSymbol;; + CEdit m_EdtEntryLevel, m_EdtSL, m_EdtTP, m_EdtStopPrice, m_EdtAccount, m_EdtCommissionSize, m_EdtRiskPIn, m_EdtRiskPRes, m_EdtRiskMIn, m_EdtRiskMRes, m_EdtReward1, m_EdtReward2, m_EdtRR1, m_EdtRR2, m_EdtPosSize, m_EdtPointValue, m_EdtATRPeriod, m_EdtATRMultiplierSL, m_EdtATRMultiplierTP, m_EdtCurRiskM, m_EdtCurRiskP, m_EdtPotRiskM, m_EdtPotRiskP, m_EdtCurProfitM, m_EdtCurProfitP, m_EdtPotProfitM, m_EdtPotProfitP, m_EdtCurL, m_EdtPotL, m_EdtCurrentRRR, m_EdtPotentialRRR, m_EdtPosMargin, m_EdtUsedMargin, m_EdtFreeMargin, m_EdtCustomLeverage, m_EdtMaxPositionSizeByMargin, m_EdtSwapsType, m_EdtSwapsTripleDay, m_EdtSwapsNominalLong, m_EdtSwapsNominalShort, m_EdtSwapsDailyLongLot, m_EdtSwapsDailyShortLot, m_EdtSwapsDailyLongPS, m_EdtSwapsDailyShortPS, m_EdtSwapsYearlyLongLot, m_EdtSwapsYearlyShortLot, m_EdtSwapsYearlyLongPS, m_EdtSwapsYearlyShortPS, m_EdtMagicNumber, m_EdtExpiry, m_EdtCommentary, m_EdtMaxSlippage, m_EdtMaxSpread, m_EdtMaxEntrySLDistance, m_EdtMinEntrySLDistance, m_EdtMaxPositionSize, m_EdtTrailingStopPoints, m_EdtBreakEvenPoints, m_EdtMaxNumberOfTradesTotal, m_EdtMaxNumberOfTradesPerSymbol, m_EdtMaxPositionSizeTotal, m_EdtMaxPositionSizePerSymbol, m_EdtMaxRiskTotal, m_EdtMaxRiskPerSymbol; + CLabel m_LblEntryLevel, m_LblEntryWarning, m_LblSL, m_LblSLWarning, m_LblTPWarning, m_LblStopPrice, m_LblStopPriceWarning, m_LblOrderType, m_LblCommissionSize, m_LblAdditionalFundsAsterisk, m_LblInput, m_LblResult, m_LblRisk, m_LblRiskM, m_LblReward, m_LblRR, m_LblPosSize, m_LblPointValue, m_LblATRPeriod, m_LblATRMultiplierSL, m_LblATRMultiplierTP, m_LblATRValue, m_LblATRTimeframe, m_LblCurrentRiskMoney, m_LblCurrentRiskPerc, m_LblCurrentProfitMoney, m_LblCurrentProfitPerc, m_LblPotentialRiskMoney, m_LblPotentialRiskPerc, m_LblPotentialProfitMoney, m_LblPotentialProfitPerc, m_LblCurrentLots, m_LblCurrentRRR, m_LblPotentialLots, m_LblPotentialRRR, m_LblCurrentPortfolio, m_LblPotentialPortfolio, m_LblPosMargin, m_LblUsedMargin, m_LblFreeMargin, m_LblCustomLeverage, m_LblAccLeverage, m_LblSymbolLeverage, m_LblMaxPositionSizeByMargin, m_LblSwapsType, m_LblSwapsTripleDay, m_LblSwapsLong, m_LblSwapsShort, m_LblSwapsNominal, m_LblSwapsDaily, m_LblSwapsYearly, m_LblSwapsPerLotDaily, m_LblSwapsPerPSDaily, m_LblSwapsPerLotYearly, m_LblSwapsPerPSYearly, m_LblMagicNumber, m_LblExpiry, m_LblMinutes, m_LblCommentary, m_LblTradingPoints, m_LblMaxSlippage, m_LblMaxSpread, m_LblMaxEntrySLDistance, m_LblMinEntrySLDistance, m_LblTradingLots, m_LblURL, m_LblTradingTP, m_LblTrailingStop, m_LblBreakEven, m_LblMaxNumberOfTrades, m_LblMaxNumberOfTradesTotal, m_LblMaxNumberOfTradesPerSymbol, m_LblMaxPositionSize, m_LblMaxPositionSizeTotal, m_LblMaxPositionSizePerSymbol, m_LblMaxRisk, m_LblMaxRiskTotal, m_LblMaxRiskPerSymbol;; string m_FileName; double m_DPIScale; @@ -25,7 +25,6 @@ private: // Extra TP fields for the Main tab. CLabel AdditionalTPLabels[], AdditionalTPWarnings[]; - CEdit AdditionalTPEdits[]; CButton AdditionalTPButtonsIncrease[], AdditionalTPButtonsDecrease[]; // Store ordered and named panel objects arranged by tabs. CPanelList *MainTabList, *RiskTabList, *MarginTabList, *SwapsTabList, *TradingTabList; @@ -74,6 +73,7 @@ public: virtual void DummyObjectSelect(string dummy_name); virtual bool IsMinimized() {return m_minimized;} virtual void IniFileLoad() {CAppDialog::IniFileLoad(); InitObjects();} // Need to init objects after ini file load. + virtual void EmulateMinMaxClick(); void OnClickBtnTakeProfitsNumberRemove(); void OnClickBtnTPsInward(); void OnClickBtnTPsOutward(); @@ -87,9 +87,12 @@ public: void ShowTPRelatedEdits(); void SetFileName(string file_name) {m_FileName = file_name;} void InitControlsValues(); + virtual void Maximize(); + virtual void Minimize(); + void SetTPButtonBackGroundColor(color); + CEdit AdditionalTPEdits[]; // Remember the panel's location to have the same location for minimized and maximized states. int remember_top, remember_left; - private: virtual void ShowMain(); @@ -112,8 +115,6 @@ private: virtual bool CheckBoxCreate (CList* list, CCheckBox& Chk, int X1, int Y1, int X2, int Y2, string Name, string Text, string Tooltip = "\n"); virtual bool EditCreate (CList* list, CEdit& Edt, int X1, int Y1, int X2, int Y2, string Name, string Text, string Tooltip = "\n"); virtual bool LabelCreate (CList* list, CLabel& Lbl, int X1, int Y1, int X2, int Y2, string Name, string Text, string Tooltip = "\n"); - virtual void Maximize(); - virtual void Minimize(); void SeekAndDestroyDuplicatePanels(); // Event handlers @@ -162,6 +163,7 @@ private: void OnEndEditEdtMaxNumberOfTradesPerSymbol(); void OnEndEditEdtMaxRiskTotal(); void OnEndEditEdtMaxRiskPerSymbol(); + void OnEndEditEdtExpiry(); void OnChangeChkSubtractPositions(); void OnChangeChkSubtractPendingOrders(); void OnChangeChkDoNotApplyStopLoss(); @@ -232,6 +234,7 @@ ON_EVENT(ON_END_EDIT, m_EdtMaxNumberOfTradesTotal, OnEndEditEdtMaxNumberOfTrades ON_EVENT(ON_END_EDIT, m_EdtMaxNumberOfTradesPerSymbol, OnEndEditEdtMaxNumberOfTradesPerSymbol) ON_EVENT(ON_END_EDIT, m_EdtMaxRiskTotal, OnEndEditEdtMaxRiskTotal) ON_EVENT(ON_END_EDIT, m_EdtMaxRiskPerSymbol, OnEndEditEdtMaxRiskPerSymbol) +ON_EVENT(ON_END_EDIT, m_EdtExpiry, OnEndEditEdtExpiry) ON_EVENT(ON_CHANGE, m_ChkSubtractPositions, OnChangeChkSubtractPositions) ON_EVENT(ON_CHANGE, m_ChkSubtractPendingOrders, OnChangeChkSubtractPendingOrders) ON_EVENT(ON_CHANGE, m_ChkDoNotApplyStopLoss, OnChangeChkDoNotApplyStopLoss) @@ -276,7 +279,7 @@ CPositionSizeCalculator::~CPositionSizeCalculator(void) // Updates filename used for settings storage. void CPositionSizeCalculator::UpdateFileName() { - m_FileName = "PS_" + Symbol() + IntegerToString(ChartID()); + m_FileName = Symbol() + IntegerToString(ChartID()); StringReplace(m_FileName, ".", "_dot_"); m_FileName += ".txt"; } @@ -510,7 +513,7 @@ bool CPositionSizeCalculator::CreateObjects() y += element_height + v_spacing; string stoploss_label_text = TRANSLATION_LABEL_STOPLOSS + ":"; - if (SLDistanceInPoints) stoploss_label_text = TRANSLATION_BUTTON_SL + ":"; + if (sets.SLDistanceInPoints) stoploss_label_text = TRANSLATION_BUTTON_SL + ":"; if (DefaultSL > 0) // Use button to quickly set SL. { @@ -526,7 +529,7 @@ bool CPositionSizeCalculator::CreateObjects() y += element_height + v_spacing; string takeprofit_label_text = TRANSLATION_LABEL_TAKEPROFIT + ":"; - if (TPDistanceInPoints) takeprofit_label_text = TRANSLATION_BUTTON_TP + ":"; + if (sets.TPDistanceInPoints) takeprofit_label_text = TRANSLATION_BUTTON_TP + ":"; if (!ButtonCreate(MainTabList, m_BtnTakeProfitsNumberAdd, first_column_start, y, first_column_start + v_spacing * 4 - 1, y + element_height, "m_BtnTakeProfitsNumberAdd", "+", TRANSLATION_TOOLTIP_TAKEPROFIT_ADD)) return false; if (!ButtonCreate(MainTabList, m_BtnTakeProfit, first_column_start + v_spacing * 4, y, first_column_start + v_spacing * 3 + normal_label_width, y + element_height, "m_BtnTakeProfit", takeprofit_label_text, TRANSLATION_TOOLTIP_BUTTON_TP)) return false; if (!EditCreate(MainTabList, m_EdtTP, second_column_start, y, second_column_start + normal_edit_width, y + element_height, "m_EdtTP", "")) return false; @@ -548,7 +551,7 @@ bool CPositionSizeCalculator::CreateObjects() ArrayResize(AdditionalOutputReward, sets.TakeProfitsNumber - 1); // Double array. string additional_tp_label_beginning = TRANSLATION_LABEL_TAKEPROFIT + " "; string additional_tp_label_end = ":"; - if (TPDistanceInPoints) + if (sets.TPDistanceInPoints) { additional_tp_label_beginning = TRANSLATION_LABEL_TAKEPROFIT_MULTIPLE_DISTANCE + " "; additional_tp_label_end = ", " + TRANSLATION_LABEL_TAKEPROFIT_MULTIPLE_POINTS + ":"; @@ -760,6 +763,7 @@ bool CPositionSizeCalculator::CreateObjects() if (!LabelCreate(RiskTabList, m_LblCurrentProfitMoney, second_risk_column_start, y, second_risk_column_start + narrow_label_width, y + element_height, "m_LblCurrentProfitMoney", TRANSLATION_LABEL_REWARD + " $")) return false; if (!LabelCreate(RiskTabList, m_LblCurrentProfitPerc, third_risk_column_start, y, third_risk_column_start + narrowest_label_width, y + element_height, "m_LblCurrentProfitPerc", TRANSLATION_LABEL_REWARD + " %")) return false; + if (!LabelCreate(RiskTabList, m_LblCurrentRRR, fourth_risk_column_start, y, fourth_risk_column_start + narrowest_label_width, y + element_height, "m_LblCurrentRRR", "RRR", TRANSLATION_LABEL_CRRR_TOOLTIP)) return false; y += element_height + v_spacing; @@ -769,6 +773,9 @@ bool CPositionSizeCalculator::CreateObjects() if (!EditCreate(RiskTabList, m_EdtCurProfitP, third_risk_column_start, y, third_risk_column_start + risk_perc_edit_width, y + element_height, "m_EdtCurProfitP", "")) return false; m_EdtCurProfitP.ReadOnly(true); m_EdtCurProfitP.ColorBackground(CONTROLS_EDIT_COLOR_DISABLE); + if (!EditCreate(RiskTabList, m_EdtCurrentRRR, fourth_risk_column_start, y, fourth_risk_column_start + risk_lot_edit, y + element_height, "m_EdtCurrentRRR", "")) return false; + m_EdtCurrentRRR.ReadOnly(true); + m_EdtCurrentRRR.ColorBackground(CONTROLS_EDIT_COLOR_DISABLE); y += element_height + v_spacing; @@ -793,6 +800,7 @@ bool CPositionSizeCalculator::CreateObjects() if (!LabelCreate(RiskTabList, m_LblPotentialProfitMoney, second_risk_column_start, y, second_risk_column_start + narrow_edit_width, y + element_height, "m_LblPotentialProfitMoney", TRANSLATION_LABEL_REWARD + " $")) return false; if (!LabelCreate(RiskTabList, m_LblPotentialProfitPerc, third_risk_column_start, y, third_risk_column_start + narrowest_label_width, y + element_height, "m_LblPotentialProfitPerc", TRANSLATION_LABEL_REWARD + " %")) return false; + if (!LabelCreate(RiskTabList, m_LblPotentialRRR, fourth_risk_column_start, y, fourth_risk_column_start + narrowest_label_width, y + element_height, "m_LblPotentialRRR", "RRR", TRANSLATION_LABEL_PRRR_TOOLTIP)) return false; y += element_height + v_spacing; @@ -802,6 +810,9 @@ bool CPositionSizeCalculator::CreateObjects() if (!EditCreate(RiskTabList, m_EdtPotProfitP, third_risk_column_start, y, third_risk_column_start + risk_perc_edit_width, y + element_height, "m_EdtPotProfitP", "")) return false; m_EdtPotProfitP.ReadOnly(true); m_EdtPotProfitP.ColorBackground(CONTROLS_EDIT_COLOR_DISABLE); + if (!EditCreate(RiskTabList, m_EdtPotentialRRR, fourth_risk_column_start, y, fourth_risk_column_start + risk_lot_edit, y + element_height, "m_EdtPotentialRRR", "")) return false; + m_EdtPotentialRRR.ReadOnly(true); + m_EdtPotentialRRR.ColorBackground(CONTROLS_EDIT_COLOR_DISABLE); // Margin @@ -933,8 +944,14 @@ bool CPositionSizeCalculator::CreateObjects() y += element_height + v_spacing; +// if (!LabelCreate(TradingTabList, m_LblMagicNumber, first_column_start, y, first_column_start + normal_label_width, y + element_height, "m_LblMagicNumber", TRANSLATION_LABEL_MAGIC_NUMBER + ":")) return false; + //if (!EditCreate(TradingTabList, m_EdtMagicNumber, second_trading_column_start, y, second_trading_column_start + normal_edit_width, y + element_height, "m_EdtMagicNumber", "")) return false; + if (!LabelCreate(TradingTabList, m_LblMagicNumber, first_column_start, y, first_column_start + normal_label_width, y + element_height, "m_LblMagicNumber", TRANSLATION_LABEL_MAGIC_NUMBER + ":")) return false; - if (!EditCreate(TradingTabList, m_EdtMagicNumber, second_trading_column_start, y, second_trading_column_start + normal_edit_width, y + element_height, "m_EdtMagicNumber", "")) return false; + if (!EditCreate(TradingTabList, m_EdtMagicNumber, first_column_start + normal_label_width, y, first_column_start + normal_label_width + normal_edit_width, y + element_height, "m_EdtMagicNumber", "")) return false; + if (!LabelCreate(TradingTabList, m_LblExpiry, first_column_start + normal_label_width + normal_edit_width + v_spacing, y, first_column_start + normal_label_width + normal_edit_width + narrowest_label_width, y + element_height, "m_LblExpiry", TRANSLATION_LABEL_EXPIRY + ":", TRANSLATION_TOOLTIP_EXPIRY)) return false; + if (!EditCreate(TradingTabList, m_EdtExpiry, first_column_start + normal_label_width + normal_edit_width + narrowest_label_width, y, first_column_start + normal_label_width + normal_edit_width + narrowest_label_width + tab_button_width, y + element_height, "m_EdtExpiry", "", TRANSLATION_TOOLTIP_EXPIRY)) return false; + if (!LabelCreate(TradingTabList, m_LblMinutes, first_column_start + normal_label_width + normal_edit_width + narrowest_label_width + tab_button_width + v_spacing, y, panel_end, y + element_height, "m_LblMinutes", TRANSLATION_LABEL_MINUTES, TRANSLATION_TOOLTIP_MINUTES)) return false; y += element_height + v_spacing; @@ -1099,11 +1116,13 @@ bool CPositionSizeCalculator::InitObjects() if (!m_EdtCurProfitM.TextAlign(align)) return false; if (!m_EdtCurProfitP.TextAlign(align)) return false; if (!m_EdtCurL.TextAlign(align)) return false; + if (!m_EdtCurrentRRR.TextAlign(align)) return false; if (!m_EdtPotRiskM.TextAlign(align)) return false; if (!m_EdtPotRiskP.TextAlign(align)) return false; if (!m_EdtPotProfitM.TextAlign(align)) return false; if (!m_EdtPotProfitP.TextAlign(align)) return false; if (!m_EdtPotL.TextAlign(align)) return false; + if (!m_EdtPotentialRRR.TextAlign(align)) return false; if (!m_EdtPosMargin.TextAlign(align)) return false; if (!m_EdtUsedMargin.TextAlign(align)) return false; if (!m_EdtFreeMargin.TextAlign(align)) return false; @@ -1137,6 +1156,7 @@ bool CPositionSizeCalculator::InitObjects() } if (!m_EdtTrailingStopPoints.TextAlign(align)) return false; if (!m_EdtBreakEvenPoints.TextAlign(align)) return false; + if (!m_EdtExpiry.TextAlign(align)) return false; if (ShowMaxParametersOnTrading) { if (!m_EdtMaxNumberOfTradesTotal.TextAlign(align)) return false; @@ -1146,8 +1166,8 @@ bool CPositionSizeCalculator::InitObjects() if (!m_EdtMaxRiskTotal.TextAlign(align)) return false; if (!m_EdtMaxRiskPerSymbol.TextAlign(align)) return false; } - if (sets.TPLockedOnSL) m_BtnTakeProfit.ColorBackground(CONTROLS_BUTTON_COLOR_ENABLE); - else m_BtnTakeProfit.ColorBackground(CONTROLS_BUTTON_COLOR_BG); + if (sets.TPLockedOnSL) m_BtnTakeProfit.ColorBackground(CONTROLS_BUTTON_COLOR_TP_LOCKED); + else m_BtnTakeProfit.ColorBackground(CONTROLS_BUTTON_COLOR_TP_UNLOCKED); HideRisk(); HideMargin(); @@ -1182,7 +1202,7 @@ void CPositionSizeCalculator::InitControlsValues() { if ((TP_Multiplier < 0.999) || (TP_Multiplier > 1.001)) { - if (!TPDistanceInPoints) + if (!sets.TPDistanceInPoints) { m_BtnTakeProfit.Text(TRANSLATION_LABEL_TAKEPROFIT_MULTIPLE_DISTANCE + " x " + DoubleToString(TP_Multiplier, CountDecimalPlaces(TP_Multiplier)) + ":"); } @@ -1316,6 +1336,7 @@ void CPositionSizeCalculator::InitControlsValues() m_EdtTrailingStopPoints.Text(IntegerToString(sets.TrailingStopPoints)); m_EdtBreakEvenPoints.Text(IntegerToString(sets.BreakEvenPoints)); m_EdtMagicNumber.Text(IntegerToString(sets.MagicNumber)); + m_EdtExpiry.Text(IntegerToString(sets.ExpiryMinutes)); m_EdtCommentary.Text(sets.Commentary); m_ChkCommentAutoSuffix.Checked(sets.CommentAutoSuffix); if (ShowMaxParametersOnTrading) @@ -1490,7 +1511,7 @@ bool CPositionSizeCalculator::DisplayValues() else if (ShowSpread == Ratio) // Spread / SL ratio in percentage. { double SL; - if (SLDistanceInPoints) SL = sets.StopLoss * _Point; + if (sets.SLDistanceInPoints) SL = sets.StopLoss * _Point; else SL = MathAbs(sets.StopLossLevel - sets.EntryLevel); if (SL != 0) if (!Caption(PanelCaption + " " + TRANSLATION_LABEL_SPREAD + ": " + DoubleToString((SymbolInfoInteger(Symbol(), SYMBOL_SPREAD) * _Point / SL) * 100, 2) + "%")) return false; } @@ -1502,7 +1523,7 @@ bool CPositionSizeCalculator::DisplayValues() else if (sets.TradeDirection == Short) m_BtnEntry.Text(TRANSLATION_BUTTON_SHORT); /* Entry Warning */ if (!m_LblEntryWarning.Text(WarningEntry)) return false; - /* Stop-Loss */ if (!SLDistanceInPoints) + /* Stop-Loss */ if (!sets.SLDistanceInPoints) { if (!m_EdtSL.Text(DoubleToString(sets.StopLossLevel, _Digits))) return false; } @@ -1510,14 +1531,14 @@ bool CPositionSizeCalculator::DisplayValues() /* SL Warning */ if (!m_LblSLWarning.Text(WarningSL)) return false; - /* Take Profit */ if (!TPDistanceInPoints) + /* Take Profit */ if (!sets.TPDistanceInPoints) { if (!m_EdtTP.Text(DoubleToString(sets.TakeProfitLevel, _Digits))) return false; } else if (!m_EdtTP.Text(IntegerToString(sets.TakeProfit))) return false; for (int i = 1; i < sets.TakeProfitsNumber; i++) { - if (!TPDistanceInPoints) + if (!sets.TPDistanceInPoints) { // Price level. if (!AdditionalTPEdits[i - 1].Text(DoubleToString(sets.TP[i], _Digits))) return false; @@ -1676,11 +1697,13 @@ bool CPositionSizeCalculator::DisplayValues() /* Current Portfolio Lots */ if (!m_EdtCurL.Text(CPL)) return false; /* Current Portfolio Profit $ */ if (!m_EdtCurProfitM.Text(PRM)) return false; /* Current Portfolio Profit % */ if (!m_EdtCurProfitP.Text(CPRew)) return false; + /* Current Portfolio RRR */ if (!m_EdtCurrentRRR.Text(CPRRR)) return false; /* Potential Portfolio Risk $ */ if (!m_EdtPotRiskM.Text(PPMR)) return false; /* Potential Portfolio Risk % */ if (!m_EdtPotRiskP.Text(PPR)) return false; /* Potential Portfolio Profit $ */ if (!m_EdtPotProfitM.Text(PPMRew)) return false; /* Potential Portfolio Profit % */ if (!m_EdtPotProfitP.Text(PPRew)) return false; /* Potential Portfolio Lots */ if (!m_EdtPotL.Text(PPL)) return false; + /* Potential Portfolio RRR */ if (!m_EdtPotentialRRR.Text(PPRRR)) return false; //=== Show/hide margin /* Position Margin */ if (!m_EdtPosMargin.Text(FormatDouble(DoubleToString(PositionMargin, AccountCurrencyDigits), AccountCurrencyDigits))) return false; @@ -1794,6 +1817,11 @@ void CPositionSizeCalculator::Maximize() if (remember_left != -1) Move(remember_left, remember_top); } +void CPositionSizeCalculator::SetTPButtonBackGroundColor(color bg_color) +{ + m_BtnTakeProfit.ColorBackground(bg_color); +} + void CPositionSizeCalculator::CalculateSettingsBasedOnLines() { if ((ShowATROptions) && ((sets.ATRMultiplierSL > 0) || (sets.ATRMultiplierTP > 0))) @@ -1907,7 +1935,7 @@ void CPositionSizeCalculator::CalculateSettingsBasedOnLines() } // Set line based on the entered SL distance. - if (SLDistanceInPoints) + if (sets.SLDistanceInPoints) { if (sets.TradeDirection == Long) sets.StopLossLevel = sets.EntryLevel - sets.StopLoss * _Point; else sets.StopLossLevel = sets.EntryLevel + sets.StopLoss * _Point; @@ -1915,7 +1943,7 @@ void CPositionSizeCalculator::CalculateSettingsBasedOnLines() } // Set lines based on the entered TP distance. - if (TPDistanceInPoints) + if (sets.TPDistanceInPoints) { if (sets.TakeProfit > 0) { @@ -2221,7 +2249,7 @@ void CPositionSizeCalculator::ProcessTPChange(const bool tp_button_click) sets.ATRMultiplierTP = NormalizeDouble(sets.ATRMultiplierSL * TP_Multiplier, 2); m_EdtATRMultiplierTP.Text(DoubleToString(sets.ATRMultiplierTP, 2)); } - if (!TPDistanceInPoints) m_EdtTP.Text(DoubleToString(tTakeProfitLevel, _Digits)); + if (!sets.TPDistanceInPoints) m_EdtTP.Text(DoubleToString(tTakeProfitLevel, _Digits)); else { sets.TakeProfit = (int)MathRound(MathAbs(tTakeProfitLevel - tEntryLevel) / _Point); @@ -2561,6 +2589,11 @@ void CPositionSizeCalculator::OnClickBtnLines() ObjectSetInteger(ChartID(), ObjectPrefix + "EntryLabel", OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS); ObjectSetInteger(ChartID(), ObjectPrefix + "EntryLabel", OBJPROP_BACK, DrawTextAsBackground); } + if (ShowAdditionalEntryLabel) + { + ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS); + ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_BACK, DrawTextAsBackground); + } if (StringToDouble(m_EdtTP.Text()) != 0) { ObjectSetInteger(ChartID(), ObjectPrefix + "TakeProfitLabel", OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS); @@ -2626,6 +2659,7 @@ void CPositionSizeCalculator::OnClickBtnLines() ObjectSetInteger(ChartID(), ObjectPrefix + "TakeProfitLabel", OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); ObjectSetInteger(ChartID(), ObjectPrefix + "TPAdditionalLabel", OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); ObjectSetInteger(ChartID(), ObjectPrefix + "StopPriceLabel", OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); + ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); } } @@ -2640,7 +2674,7 @@ void CPositionSizeCalculator::OnClickBtnStopLoss() if (tStopLossLevel != sets.StopLossLevel) { tStopLossLevel = sets.StopLossLevel; - if (!SLDistanceInPoints) m_EdtSL.Text(DoubleToString(tStopLossLevel, _Digits)); + if (!sets.SLDistanceInPoints) m_EdtSL.Text(DoubleToString(tStopLossLevel, _Digits)); else { sets.StopLoss = (int)MathRound(MathAbs(tStopLossLevel - tEntryLevel) / _Point); @@ -2655,7 +2689,7 @@ void CPositionSizeCalculator::OnClickBtnTakeProfit() // If "TP locked on SL" mode was on, turn it off. if (sets.TPLockedOnSL) { - m_BtnTakeProfit.ColorBackground(CONTROLS_BUTTON_COLOR_BG); + m_BtnTakeProfit.ColorBackground(CONTROLS_BUTTON_COLOR_TP_UNLOCKED); sets.TPLockedOnSL = false; return; } @@ -2663,7 +2697,7 @@ void CPositionSizeCalculator::OnClickBtnTakeProfit() else if (sets.TakeProfitLevel != 0) { sets.TPLockedOnSL = true; - m_BtnTakeProfit.ColorBackground(CONTROLS_BUTTON_COLOR_ENABLE); + m_BtnTakeProfit.ColorBackground(CONTROLS_BUTTON_COLOR_TP_LOCKED); } ProcessTPChange(true); @@ -2700,7 +2734,7 @@ void SwitchEntryDirection() if (sets.TakeProfitLevel > 0) { - if (TPDistanceInPoints) sets.TakeProfitLevel = sets.EntryLevel - sets.TakeProfit * _Point; + if (sets.TPDistanceInPoints) sets.TakeProfitLevel = sets.EntryLevel - sets.TakeProfit * _Point; else sets.TakeProfitLevel = sets.EntryLevel - old_tp_distance; ObjectSetDouble(ChartID(), ObjectPrefix + "TakeProfitLine", OBJPROP_PRICE, sets.TakeProfitLevel); for (int i = 1; i < sets.TakeProfitsNumber; i++) @@ -2746,7 +2780,7 @@ void SwitchEntryDirection() if (sets.TakeProfitLevel > 0) { - if (TPDistanceInPoints) sets.TakeProfitLevel = sets.EntryLevel + sets.TakeProfit * _Point; + if (sets.TPDistanceInPoints) sets.TakeProfitLevel = sets.EntryLevel + sets.TakeProfit * _Point; else sets.TakeProfitLevel = sets.EntryLevel + old_tp_distance; ObjectSetDouble(ChartID(), ObjectPrefix + "TakeProfitLine", OBJPROP_PRICE, sets.TakeProfitLevel); for (int i = 1; i < sets.TakeProfitsNumber; i++) @@ -3024,7 +3058,7 @@ void CPositionSizeCalculator::OnClickBtnStopLossIncrease() { if (ShowATROptions) return; // Stop-loss cannot be changed by +/- buttons in ATR mode. // Should actually operate in TickSize rather than point as only TickSize changes make sense. - if (!SLDistanceInPoints) + if (!sets.SLDistanceInPoints) { if (TickSize > 0) sets.StopLossLevel += TickSize; else sets.StopLossLevel += _Point; @@ -3060,7 +3094,7 @@ void CPositionSizeCalculator::OnClickBtnStopLossDecrease() { if (ShowATROptions) return; // Stop-loss cannot be changed by +/- buttons in ATR mode. // Should actually operate in TickSize rather than point as only TickSize changes make sense. - if (!SLDistanceInPoints) + if (!sets.SLDistanceInPoints) { if (TickSize > 0) sets.StopLossLevel -= TickSize; else sets.StopLossLevel -= _Point; @@ -3092,7 +3126,7 @@ void CPositionSizeCalculator::OnClickBtnStopLossDecrease() void CPositionSizeCalculator::OnClickBtnTakeProfitIncrease() { if (ShowATROptions) return; // Take-profit cannot be changed by +/- buttons in ATR mode. - if (!TPDistanceInPoints) + if (!sets.TPDistanceInPoints) { // Check and adjust for TickSize granularity. if (TickSize > 0) sets.TakeProfitLevel += TickSize; @@ -3138,7 +3172,7 @@ void CPositionSizeCalculator::OnClickBtnTakeProfitIncrease() void CPositionSizeCalculator::OnClickBtnTakeProfitDecrease() { if (ShowATROptions) return; // Take-profit cannot be changed by +/- buttons in ATR mode. - if (!TPDistanceInPoints) + if (!sets.TPDistanceInPoints) { // Check and adjust for TickSize granularity. if (TickSize > 0) sets.TakeProfitLevel -= TickSize; @@ -3180,7 +3214,7 @@ void CPositionSizeCalculator::OnClickBtnTakeProfitDecrease() void CPositionSizeCalculator::ProcessAdditionalTPButtonsIncrease(int i) { - if (!TPDistanceInPoints) // Everything is easy. + if (!sets.TPDistanceInPoints) // Everything is easy. { // Check and adjust for TickSize granularity. if (TickSize > 0) sets.TP[i] += TickSize; @@ -3216,7 +3250,7 @@ void CPositionSizeCalculator::ProcessAdditionalTPButtonsIncrease(int i) void CPositionSizeCalculator::ProcessAdditionalTPButtonsDecrease(int i) { - if (!TPDistanceInPoints) // Everything is more or less easy. + if (!sets.TPDistanceInPoints) // Everything is more or less easy. { // Check and adjust for TickSize granularity. if (TickSize > 0) sets.TP[i] -= TickSize; @@ -3323,7 +3357,7 @@ void CPositionSizeCalculator::OnClickBtnTakeProfitsNumberAdd() } string additional_tp_label_beginning = TRANSLATION_LABEL_TAKEPROFIT + " "; string additional_tp_label_end = ":"; - if (TPDistanceInPoints) + if (sets.TPDistanceInPoints) { additional_tp_label_beginning = TRANSLATION_LABEL_TAKEPROFIT_MULTIPLE_DISTANCE + " "; additional_tp_label_end = ", " + TRANSLATION_LABEL_TAKEPROFIT_MULTIPLE_POINTS + ":"; @@ -3379,7 +3413,7 @@ void CPositionSizeCalculator::OnClickBtnTakeProfitsNumberAdd() if (obj.Name == "m_LblStopPrice") { start_moving = true; // From now on, everything below should be moved down. - y = obj.Obj.Top() - col_height - remember_top; // Remember the y where the new TP fields will be inserted. Relative measurement. + y = obj.Obj.Top() - (CONTROLS_DIALOG_CAPTION_HEIGHT + 3 * CONTROLS_BORDER_WIDTH) - remember_top; // Remember the y where the new TP fields will be inserted. Relative measurement. index = MainTabList.IndexOf(obj) - 1; // Remember the index to insert the new TP in the list of Main tab fields. } } @@ -3388,7 +3422,6 @@ void CPositionSizeCalculator::OnClickBtnTakeProfitsNumberAdd() obj.Obj.Move(obj.Obj.Left(), obj.Obj.Top() + col_height); // Down. } } - string name = "m_BtnTakeProfitsNumberRemove"; // If it is the first additional TP: if (sets.TakeProfitsNumber == 2) @@ -3459,7 +3492,7 @@ void CPositionSizeCalculator::OnClickBtnTakeProfitsNumberAdd() } MainTabList.MoveListElementByName(name, index + 4); } - + // Proceed to generating new panel fields for the Trading tab. // Move everything on the Trading tab down by one or two lines to insert the new take-profit. @@ -3475,7 +3508,7 @@ void CPositionSizeCalculator::OnClickBtnTakeProfitsNumberAdd() if (((ShowFusesOnTrading) && (obj.Name == "m_LblTradingPoints")) || ((ShowCheckboxesOnTrading) && (obj.Name == "m_ChkSubtractPositions")) || (obj.Name == "m_ChkAskForConfirmation")) { start_moving = true; // From now on everything below should be moved down. - y = obj.Obj.Top() - col_height - remember_top; // Remember the y where the new TP fields will be inserted. Relative measurement. + y = obj.Obj.Top() - (CONTROLS_DIALOG_CAPTION_HEIGHT + 3 * CONTROLS_BORDER_WIDTH) - remember_top; // Remember the y where the new TP fields will be inserted. Relative measurement. index = TradingTabList.IndexOf(obj) - 1; // Remember the index to insert the new TP in the list of Trading tab fields. if (sets.TakeProfitsNumber == 2) m = 3; // Will be moving three rows down: headers + main TP + first secondary TP. } @@ -3623,7 +3656,7 @@ void CPositionSizeCalculator::OnClickBtnTakeProfitsNumberAdd() if ((PrefillAdditionalTPsBasedOnMain) && (sets.TakeProfitLevel != 0)) // If added a new TP when the first TP was already set, set some value to the new one too. { - if (!TPDistanceInPoints) sets.TP[sets.TakeProfitsNumber - 1] = NormalizeDouble(sets.EntryLevel + (sets.TakeProfitLevel - sets.EntryLevel) * sets.TakeProfitsNumber, _Digits); + if (!sets.TPDistanceInPoints) sets.TP[sets.TakeProfitsNumber - 1] = NormalizeDouble(sets.EntryLevel + (sets.TakeProfitLevel - sets.EntryLevel) * sets.TakeProfitsNumber, _Digits); else { if (sets.TradeDirection == Short) sets.TP[sets.TakeProfitsNumber - 1] = NormalizeDouble(sets.EntryLevel - sets.TakeProfit * _Point * sets.TakeProfitsNumber, _Digits); @@ -3784,7 +3817,7 @@ void CPositionSizeCalculator::OnEndEditEdtEntryLevel() void CPositionSizeCalculator::OnEndEditEdtSL() { - if (!SLDistanceInPoints) + if (!sets.SLDistanceInPoints) { double new_value = StringToDouble(m_EdtSL.Text()); if (new_value == 0) // Not allowed. @@ -3833,7 +3866,7 @@ void CPositionSizeCalculator::OnEndEditEdtSL() void CPositionSizeCalculator::OnEndEditEdtTP() { - if (!TPDistanceInPoints) + if (!sets.TPDistanceInPoints) { sets.TakeProfitLevel = StringToDouble(m_EdtTP.Text()); // Check and adjust for TickSize granularity. @@ -4368,6 +4401,17 @@ void CPositionSizeCalculator::OnEndEditEdtMaxRiskPerSymbol() m_EdtMaxRiskPerSymbol.Text(DoubleToString(sets.MaxRiskPerSymbol, 2)); } +void CPositionSizeCalculator::OnEndEditEdtExpiry() +{ + sets.ExpiryMinutes = (int)StringToInteger(m_EdtExpiry.Text()); + if ((sets.ExpiryMinutes != 0) && (sets.ExpiryMinutes < 2)) + { + sets.ExpiryMinutes = 0; + Print(TRANSLATION_MESSAGE_MINIMUM_EXPIRY); + } + m_EdtExpiry.Text(IntegerToString(sets.ExpiryMinutes)); +} + //+-----------------------+ //| Working with settings | //|+----------------------+ @@ -4376,10 +4420,11 @@ bool CPositionSizeCalculator::SaveSettingsOnDisk(string symbol = "") Print(TRANSLATION_MESSAGE_TRYING_TO_SAVE_FILE + ": " + m_FileName + "."); int fh; - fh = FileOpen(m_FileName, FILE_CSV | FILE_WRITE); + // Save to new format only. + fh = FileOpen("PS_Settings\\" + m_FileName, FILE_CSV | FILE_WRITE); if (fh == INVALID_HANDLE) { - Print(TRANSLATION_MESSAGE_FAILED_TO_OPEN_FOR_WRITING + ": " + m_FileName + ". " + TRANSLATION_MESSAGE_ERROR + ": " + IntegerToString(GetLastError())); + Print(TRANSLATION_MESSAGE_FAILED_TO_OPEN_FOR_WRITING + ": PS_Settings\\" + m_FileName + ". " + TRANSLATION_MESSAGE_ERROR + ": " + IntegerToString(GetLastError())); return false; } @@ -4462,6 +4507,10 @@ bool CPositionSizeCalculator::SaveSettingsOnDisk(string symbol = "") FileWrite(fh, IntegerToString(sets.MaxEntrySLDistance)); FileWrite(fh, "MinEntrySLDistance"); FileWrite(fh, IntegerToString(sets.MinEntrySLDistance)); + FileWrite(fh, "SLDistanceInPoints"); + FileWrite(fh, IntegerToString(sets.SLDistanceInPoints)); + FileWrite(fh, "TPDistanceInPoints"); + FileWrite(fh, IntegerToString(sets.TPDistanceInPoints)); FileWrite(fh, "StopLoss"); FileWrite(fh, IntegerToString(sets.StopLoss)); FileWrite(fh, "TakeProfit"); @@ -4513,6 +4562,8 @@ bool CPositionSizeCalculator::SaveSettingsOnDisk(string symbol = "") FileWrite(fh, IntegerToString(sets.TrailingStopPoints)); FileWrite(fh, "BreakEvenPoints"); FileWrite(fh, IntegerToString(sets.BreakEvenPoints)); + FileWrite(fh, "ExpiryMinutes"); + FileWrite(fh, IntegerToString(sets.ExpiryMinutes)); FileWrite(fh, "MaxNumberOfTradesTotal"); FileWrite(fh, IntegerToString(sets.MaxNumberOfTradesTotal)); FileWrite(fh, "MaxNumberOfTradesPerSymbol"); @@ -4626,6 +4677,8 @@ bool CPositionSizeCalculator::SaveSettingsOnDisk(string symbol = "") FileWrite(fh, IntegerToString(DefaultTrailingStop)); FileWrite(fh, "Parameter_DefaultBreakEven"); FileWrite(fh, IntegerToString(DefaultBreakEven)); + FileWrite(fh, "Parameter_DefaultExpiryMinutes"); + FileWrite(fh, IntegerToString(DefaultExpiryMinutes)); FileWrite(fh, "Parameter_DefaultSpreadAdjustmentSL"); FileWrite(fh, IntegerToString(DefaultSpreadAdjustmentSL)); FileWrite(fh, "Parameter_DefaultSpreadAdjustmentTP"); @@ -4641,6 +4694,10 @@ bool CPositionSizeCalculator::SaveSettingsOnDisk(string symbol = "") // Not a part of sets, but needed for proper deletion of unnecessary additional TP lines. FileWrite(fh, "Parameter_DefaultTakeProfitsNumber"); FileWrite(fh, IntegerToString(DefaultTakeProfitsNumber)); + FileWrite(fh, "Parameter_DefaultSLDistanceInPoints"); + FileWrite(fh, IntegerToString(DefaultSLDistanceInPoints)); + FileWrite(fh, "Parameter_DefaultTPDistanceInPoints"); + FileWrite(fh, IntegerToString(DefaultTPDistanceInPoints)); } FileClose(fh); @@ -4653,19 +4710,30 @@ bool CPositionSizeCalculator::LoadSettingsFromDisk() { Print(TRANSLATION_MESSAGE_TRYING_TO_LOAD_FILE); - if (!FileIsExist(m_FileName)) - { - Print(TRANSLATION_MESSAGE_NO_SETTINGS_FILE_TO_LOAD); - return false; - } - int fh; - fh = FileOpen(m_FileName, FILE_CSV | FILE_READ); - if (fh == INVALID_HANDLE) + if (FileIsExist("PS_Settings\\" + m_FileName)) // New format settings file found. { - Print(TRANSLATION_MESSAGE_FAILED_TO_OPEN_FOR_READING + ": " + m_FileName + ". " + TRANSLATION_MESSAGE_ERROR + ": " + IntegerToString(GetLastError())); - return false; + fh = FileOpen("PS_Settings\\" + m_FileName, FILE_CSV | FILE_READ); + if (fh == INVALID_HANDLE) + { + Print(TRANSLATION_MESSAGE_FAILED_TO_OPEN_FOR_READING + ": PS_Settings\\" + m_FileName + ". " + TRANSLATION_MESSAGE_ERROR + ": " + IntegerToString(GetLastError())); + return false; + } + } + else // No new format file, try to load old format. + { + if (!FileIsExist("PS_" + m_FileName)) + { + Print(TRANSLATION_MESSAGE_NO_SETTINGS_FILE_TO_LOAD); + return false; + } + fh = FileOpen("PS_" + m_FileName, FILE_CSV | FILE_READ); + if (fh == INVALID_HANDLE) + { + Print(TRANSLATION_MESSAGE_FAILED_TO_OPEN_FOR_READING + ": PS_" + m_FileName + ". " + TRANSLATION_MESSAGE_ERROR + ": " + IntegerToString(GetLastError())); + return false; + } } while (!FileIsEnding(fh)) @@ -4742,6 +4810,11 @@ bool CPositionSizeCalculator::LoadSettingsFromDisk() sets.TrailingStopPoints = (int)StringToInteger(var_content); else if (var_name == "BreakEvenPoints") sets.BreakEvenPoints = (int)StringToInteger(var_content); + else if (var_name == "ExpiryMinutes") + { + sets.ExpiryMinutes = (int)StringToInteger(var_content); + if ((sets.ExpiryMinutes != 0) && (sets.ExpiryMinutes < 2)) sets.ExpiryMinutes = 0; + } else if (var_name == "MaxNumberOfTradesTotal") sets.MaxNumberOfTradesTotal = (int)StringToInteger(var_content); else if (var_name == "MaxNumberOfTradesPerSymbol") @@ -4779,6 +4852,10 @@ bool CPositionSizeCalculator::LoadSettingsFromDisk() sets.MinEntrySLDistance = (int)StringToInteger(var_content); else if (var_name == "TradeDirection") sets.TradeDirection = (TRADE_DIRECTION)StringToInteger(var_content); + else if (var_name == "SLDistanceInPoints") + sets.SLDistanceInPoints = (bool)StringToInteger(var_content); + else if (var_name == "TPDistanceInPoints") + sets.TPDistanceInPoints = (bool)StringToInteger(var_content); else if (var_name == "StopLoss") sets.StopLoss = (int)StringToInteger(var_content); else if (var_name == "TakeProfit") @@ -5038,6 +5115,14 @@ bool CPositionSizeCalculator::LoadSettingsFromDisk() { if (StringToInteger(var_content) != DefaultBreakEven) sets.BreakEvenPoints = DefaultBreakEven; } + else if (var_name == "Parameter_DefaultExpiryMinutes") + { + if (StringToInteger(var_content) != DefaultExpiryMinutes) + { + sets.ExpiryMinutes = DefaultExpiryMinutes; + if ((sets.ExpiryMinutes != 0) && (sets.ExpiryMinutes < 2)) sets.ExpiryMinutes = 0; + } + } else if (var_name == "Parameter_DefaultSpreadAdjustmentSL") { if ((bool)StringToInteger(var_content) != DefaultSpreadAdjustmentSL) sets.SpreadAdjustmentSL = DefaultSpreadAdjustmentSL; @@ -5087,6 +5172,14 @@ bool CPositionSizeCalculator::LoadSettingsFromDisk() ArrayInitialize(TakeProfitLineIsBeingMoved, false); } } + else if (var_name == "Parameter_DefaultSLDistanceInPoints") + { + if (StringToDouble(var_content) != DefaultSLDistanceInPoints) sets.SLDistanceInPoints = DefaultSLDistanceInPoints; + } + else if (var_name == "Parameter_DefaultTPDistanceInPoints") + { + if (StringToDouble(var_content) != DefaultTPDistanceInPoints) sets.TPDistanceInPoints = DefaultTPDistanceInPoints; + } } } @@ -5251,7 +5344,7 @@ void CPositionSizeCalculator::UpdateTradingTPEdit(int i) sets.TP[i] = NormalizeDouble(new_value, _Digits); if (i > 0) { - if (!TPDistanceInPoints) AdditionalTPEdits[i - 1].Text(s); // TP as level. + if (!sets.TPDistanceInPoints) AdditionalTPEdits[i - 1].Text(s); // TP as level. else AdditionalTPEdits[i - 1].Text(IntegerToString((int)MathRound(MathAbs(new_value - sets.EntryLevel) / _Point))); // TP as distance. } else if (sets.ATRMultiplierTP > 0) @@ -5264,7 +5357,7 @@ void CPositionSizeCalculator::UpdateTradingTPEdit(int i) // If it was the first TP field on the Trading tab, and the TP field on the Main tab was empty - fill it and show the line. if ((i == 0) && (sets.TakeProfitLevel == 0) && (new_value > 0)) { - if (TPDistanceInPoints) + if (sets.TPDistanceInPoints) { if (sets.TradeDirection == Long) m_EdtTP.Text(IntegerToString((int)MathRound(MathAbs(new_value - sets.EntryLevel) / _Point))); @@ -5292,7 +5385,7 @@ void CPositionSizeCalculator::UpdateAdditionalTPEdit(int i) double new_value = StringToDouble(AdditionalTPEdits[i - 1].Text()); // TP as level. - if (!TPDistanceInPoints) + if (!sets.TPDistanceInPoints) { // Adjust for tick size granularity. if (TickSize > 0) new_value = NormalizeDouble(MathRound(new_value / TickSize) * TickSize, _Digits); @@ -5413,6 +5506,22 @@ void CPositionSizeCalculator::UpdateAdditionalTradingPanelTP(int i) TradingTPEdits[i].Text(DoubleToString(sets.TP[i], _Digits)); } +void CPositionSizeCalculator::EmulateMinMaxClick() +{ + CBmpButton * minmax_button; + minmax_button = Control(5); // MinMax button inside Dialog.mqh + if (IsMinimized()) + { + Maximize(); + minmax_button.Pressed(false); // Shown as _ + } + else + { + Minimize(); + minmax_button.Pressed(true); // Shown as two small windows. + } +} + // Check if all required lines exist and restore them if they have been accidentally deleted. void CPositionSizeCalculator::CheckAndRestoreLines() { @@ -5574,7 +5683,7 @@ bool StopOut; //----- string WarningEntry = "", WarningSL = "", WarningTP = "", WarningSP = "", AdditionalWarningTP[]; double DisplayRisk, RiskMoney, PositionMargin, UsedMargin, FutureMargin, PreHedgingPositionMargin, PortfolioLossMoney = 0; -string InputRR, OutputRR, MainOutputRR, PLM, CPR, PRM, CPRew, PPMR, PPR, PPMRew, PPRew, CPL, PPL, AdditionalOutputRR[]; +string InputRR, OutputRR, MainOutputRR, PLM, CPR, PRM, CPRew, PPMR, PPR, PPMRew, PPRew, CPL, PPL, CPRRR, PPRRR, AdditionalOutputRR[]; string InputReward; double OutputReward, AdditionalOutputReward[], MainOutputReward; string OutputPointValue = "", OutputSwapsType = TRANSLATION_LABEL_UNKNOWN, SwapsTripleDay = "?", @@ -5623,8 +5732,8 @@ void Initialization() if (sets.StopPriceLevel == sets.EntryLevel) sets.StopPriceLevel -= _Point; } } - if ((SLDistanceInPoints) && (sets.StopLoss == 0)) sets.StopLoss = (int)MathRound(MathAbs((sets.EntryLevel - sets.StopLossLevel) / _Point)); - if ((TPDistanceInPoints) && (sets.TakeProfit <= 0) && (sets.TakeProfitLevel != 0)) sets.TakeProfit = (int)MathRound(MathAbs((sets.EntryLevel - sets.TakeProfitLevel) / _Point)); + if ((sets.SLDistanceInPoints) && (sets.StopLoss == 0)) sets.StopLoss = (int)MathRound(MathAbs((sets.EntryLevel - sets.StopLossLevel) / _Point)); + if ((sets.TPDistanceInPoints) && (sets.TakeProfit <= 0) && (sets.TakeProfitLevel != 0)) sets.TakeProfit = (int)MathRound(MathAbs((sets.EntryLevel - sets.TakeProfitLevel) / _Point)); } // Loaded template with TP line - delete the line. if ((sets.TakeProfit == 0) && (sets.TakeProfitLevel == 0) && (ObjectFind(0, ObjectPrefix + "TakeProfitLine") == 0)) @@ -5644,7 +5753,7 @@ void Initialization() ArrayResize(ArrayPositionSize, sets.TakeProfitsNumber); // Using TP distance in points but just switched from the TP given as a level on an already attached indicator. - if ((TPDistanceInPoints) && (sets.TakeProfit == 0) && (sets.TakeProfitLevel != 0)) sets.TakeProfit = (int)MathRound(MathAbs((sets.TakeProfitLevel - sets.EntryLevel) / _Point)); + if ((sets.TPDistanceInPoints) && (sets.TakeProfit == 0) && (sets.TakeProfitLevel != 0)) sets.TakeProfit = (int)MathRound(MathAbs((sets.TakeProfitLevel - sets.EntryLevel) / _Point)); if (sets.EntryLevel - sets.StopLossLevel == 0) { Alert(TRANSLATION_MESSAGE_ENTRY_SL_DIFFERENT_NON_ZERO); @@ -5677,8 +5786,8 @@ void Initialization() if ((DefaultSL > 0) && (sets.StopLossLevel == 0)) sets.StopLossLevel = sets.EntryLevel + DefaultSL * _Point; if ((DefaultTP > 0) && (sets.TakeProfitLevel == 0)) sets.TakeProfitLevel = sets.EntryLevel - DefaultTP * _Point; } - if ((SLDistanceInPoints) && (sets.StopLoss <= 0)) sets.StopLoss = (int)MathRound(MathAbs((sets.EntryLevel - sets.StopLossLevel) / _Point)); - if ((TPDistanceInPoints) && (sets.TakeProfit <= 0) && (sets.TakeProfitLevel != 0)) sets.TakeProfit = (int)MathRound(MathAbs((sets.EntryLevel - sets.TakeProfitLevel) / _Point)); + if ((sets.SLDistanceInPoints) && (sets.StopLoss <= 0)) sets.StopLoss = (int)MathRound(MathAbs((sets.EntryLevel - sets.StopLossLevel) / _Point)); + if ((sets.TPDistanceInPoints) && (sets.TakeProfit <= 0) && (sets.TakeProfitLevel != 0)) sets.TakeProfit = (int)MathRound(MathAbs((sets.EntryLevel - sets.TakeProfitLevel) / _Point)); ExtDialog.DummyObjectSelect(); // To prevent buggy deselection of line objects after indicator parameters change. bool line_existed = false; // Will be used to preserve OBJPROP_SELECTED through timeframe changes and the like. @@ -5771,6 +5880,18 @@ void Initialization() ObjectSetInteger(ChartID(), ObjectPrefix + "EntryLabel", OBJPROP_CORNER, CORNER_LEFT_UPPER); ObjectSetInteger(ChartID(), ObjectPrefix + "EntryLabel", OBJPROP_BACK, DrawTextAsBackground); ObjectSetString(ChartID(), ObjectPrefix + "EntryLabel", OBJPROP_TOOLTIP, TRANSLATION_TOOLTIP_ENTRY_LABEL); + if ((ShowAdditionalEntryLabel) && (ObjectFind(0, ObjectPrefix + "EntryAdditionalLabel") == -1)) + { + ObjectCreate(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJ_LABEL, 0, 0, 0); + if (sets.ShowLines) ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS); + else ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); + ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_COLOR, clrNONE); + ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_SELECTABLE, false); + ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_HIDDEN, false); + ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_CORNER, CORNER_LEFT_UPPER); + ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_BACK, DrawTextAsBackground); + ObjectSetString(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_TOOLTIP, TRANSLATION_TOOLTIP_ENTRY_LABEL_ADDITIONAL); + } } if (ObjectFind(ChartID(), ObjectPrefix + "TakeProfitLine") == -1) @@ -6135,6 +6256,12 @@ void RecalculatePositionSize() if (sets.ShowLines) ObjectSetInteger(ChartID(), ObjectPrefix + "SLAdditionalLabel", OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS); else ObjectSetInteger(ChartID(), ObjectPrefix + "SLAdditionalLabel", OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); } + if (ShowAdditionalEntryLabel) + { + DrawLineLabel(ObjectPrefix + "EntryAdditionalLabel", FormatDouble(DoubleToString(OutputPositionSize, LotStep_digits), LotStep_digits), tEntryLevel, entry_label_font_color, true); + if (sets.ShowLines) ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_TIMEFRAMES, OBJ_ALL_PERIODS); + else ObjectSetInteger(ChartID(), ObjectPrefix + "EntryAdditionalLabel", OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS); + } if (sets.EntryType != Instant) { DrawLineLabel(ObjectPrefix + "EntryLabel", IntegerToString((int)MathRound((MathAbs(tEntryLevel - AskBid) / _Point))), tEntryLevel, entry_label_font_color); @@ -6870,6 +6997,32 @@ void CalculatePortfolioRisk(const CALCULATE_RISK_FOR_TRADING_TAB calculate_risk_ CPL = FormatDouble(DoubleToString(volume, LotStep_digits), LotStep_digits); PPL = FormatDouble(DoubleToString(volume + OutputPositionSize, LotStep_digits), LotStep_digits); + + if (PortfolioRewardMoney == DBL_MAX) + { + if (PortfolioLossMoney == DBL_MAX) CPRRR = "-"; + else CPRRR = "\x221E"; + } + else if (PortfolioLossMoney == DBL_MAX) CPRRR = "0.00"; + else if (PortfolioLossMoney == 0) + { + if (PortfolioRewardMoney != 0) CPRRR = "\x221E"; + else CPRRR = "-"; + } + else CPRRR = FormatDouble(DoubleToString(PortfolioRewardMoney / PortfolioLossMoney, 2)); + + if ((PortfolioRewardMoney == DBL_MAX) || (OutputReward == 0)) + { + if (PortfolioLossMoney == DBL_MAX) PPRRR = "-"; + else PPRRR = "\x221E"; + } + else if (PortfolioLossMoney == DBL_MAX) PPRRR = "0.00"; + else if (PortfolioLossMoney + OutputRiskMoney == 0) + { + if (PortfolioRewardMoney + OutputReward != 0) PPRRR = "\x221E"; + else PPRRR = "-"; + } + else PPRRR = FormatDouble(DoubleToString((PortfolioRewardMoney + OutputReward) / (PortfolioLossMoney + OutputRiskMoney), 2)); } //+------------------------------------------------------------------+ @@ -6879,12 +7032,12 @@ void CalculateMargin() { if (TickValue == 0) return; - double initial_margin_rate = 0, maintenance_margin_rate = 0; + double initial_margin_rate = 0, maintenance_margin_rate = 0, max_margin_rate = 0; SymbolInfoMarginRate(Symbol(), OrderType, initial_margin_rate, maintenance_margin_rate); if (maintenance_margin_rate == 0) maintenance_margin_rate = initial_margin_rate; PositionMargin = 0; - double _PositionMargin; // Based on initial margin requirements - used when needed for Future Free Margin check. + double _PositionMargin = 0; // Based on initial margin requirements - used when needed for Future Free Margin check. // Multiplication or division by 1 is safe. double CurrencyCorrectionCoefficient = 1; double PriceCorrectionCoefficient = 1; @@ -7018,6 +7171,7 @@ void CalculateMargin() else { if (ContractSize == 0) return; + double HedgedRatio = MarginHedging / ContractSize; // Hedging on partial or no margin. @@ -7073,18 +7227,31 @@ void CalculateMargin() // There is position to hedge and new position is in opposite direction. if ((volume > 0) && (type != PositionDirection)) { - double calculated_volume; + double calculated_volume, margin_rate_to_use; if (OutputPositionSize <= volume) calculated_volume = OutputPositionSize * (HedgedRatio - 1); else calculated_volume = volume * HedgedRatio + OutputPositionSize - 2 * volume; PositionMargin = (calculated_volume * ContractSize * PriceCorrectionCoefficient / Leverage) * maintenance_margin_rate; PositionMargin *= CurrencyCorrectionCoefficient; + // If initial margin requirement are bigger than maintenance margin requirement, we need to calculate a separate position margin value + // to check if we have enough necessary free margin before placing a trade. + if ((InitialMargin > MaintenanceMargin) || (initial_margin_rate > maintenance_margin_rate)) + { + if (InitialMargin > 0) ContractSize = InitialMargin; + _PositionMargin = (calculated_volume * ContractSize * PriceCorrectionCoefficient / Leverage) * initial_margin_rate; + _PositionMargin *= CurrencyCorrectionCoefficient; + margin_rate_to_use = initial_margin_rate; + } + else // Based on maintenance margin. + { + margin_rate_to_use = maintenance_margin_rate; + } // Calculations for maximum position size: // 1. Find maximum position size for a given maximum position margin if the size is kept less than or equal to existing opposite volume. for (MaxPositionSizeByMargin = 0; MaxPositionSizeByMargin <= volume; MaxPositionSizeByMargin += LotStep) { - if ((HedgedRatio - 1) * MaxPositionSizeByMargin * ContractSize * PriceCorrectionCoefficient * maintenance_margin_rate * CurrencyCorrectionCoefficient / Leverage > MaxPositionMargin) + if ((HedgedRatio - 1) * MaxPositionSizeByMargin * ContractSize * PriceCorrectionCoefficient * margin_rate_to_use * CurrencyCorrectionCoefficient / Leverage > MaxPositionMargin) { MaxPositionSizeByMargin -= LotStep; break; @@ -7094,18 +7261,28 @@ void CalculateMargin() if (PriceCorrectionCoefficient * maintenance_margin_rate * CurrencyCorrectionCoefficient != 0) { double MPS_gv = 0; - MPS_gv = MaxPositionMargin / (ContractSize * PriceCorrectionCoefficient * maintenance_margin_rate * CurrencyCorrectionCoefficient / Leverage) - volume * (HedgedRatio - 2); + MPS_gv = MaxPositionMargin / (ContractSize * PriceCorrectionCoefficient * margin_rate_to_use * CurrencyCorrectionCoefficient / Leverage) - volume * (HedgedRatio - 2); if (MPS_gv > MaxPositionSizeByMargin) MaxPositionSizeByMargin = MPS_gv; } } } - - _PositionMargin = PositionMargin; + if ((InitialMargin > MaintenanceMargin) || (initial_margin_rate > maintenance_margin_rate)) + { + if (InitialMargin > 0) ContractSize = InitialMargin; + _PositionMargin = (OutputPositionSize * ContractSize * PriceCorrectionCoefficient / Leverage) * initial_margin_rate; + _PositionMargin *= CurrencyCorrectionCoefficient; + } + else + { + _PositionMargin = PositionMargin; + } } // Max position size. - if ((MaxPositionSizeByMargin == -1) && (ContractSize != 0) && (PriceCorrectionCoefficient != 0) && (maintenance_margin_rate != 0) && (CurrencyCorrectionCoefficient != 0)) - MaxPositionSizeByMargin = (MaxPositionMargin * Leverage) / (ContractSize * PriceCorrectionCoefficient * maintenance_margin_rate * CurrencyCorrectionCoefficient); + double margin_rate_to_use = maintenance_margin_rate; + if ((InitialMargin > MaintenanceMargin) || (initial_margin_rate > maintenance_margin_rate)) margin_rate_to_use = initial_margin_rate; + if ((MaxPositionSizeByMargin == -1) && (ContractSize != 0) && (PriceCorrectionCoefficient != 0) && (margin_rate_to_use != 0) && (CurrencyCorrectionCoefficient != 0)) + MaxPositionSizeByMargin = (MaxPositionMargin * Leverage) / (ContractSize * PriceCorrectionCoefficient * margin_rate_to_use * CurrencyCorrectionCoefficient); MaxPositionSizeByMargin = Round(MaxPositionSizeByMargin, LotStep_digits, RoundDown); @@ -7639,6 +7816,9 @@ void CPanelList::SetHiddenByName(const string name, const bool hidden) void DissectHotKeyCombination(const string hotkey, bool &shift_required, bool &ctrl_required, uchar &main_key) { ushort separator; + // Set these to false because they could be set to true during previous EA initialization. + shift_required = false; + ctrl_required = false; if (StringFind(hotkey, "+") > -1) separator = StringGetCharacter("+", 0); else if (StringFind(hotkey, "-") > -1) separator = StringGetCharacter("-", 0); else separator = 0; @@ -7660,6 +7840,7 @@ void DissectHotKeyCombination(const string hotkey, bool &shift_required, bool &c else if ((keys[n - 1] == "BACKSPACE") || (keys[n - 1] == "BACK") || (keys[n - 1] == "BS") || (keys[n - 1] == "BKSP")) main_key = 8; else if ((keys[n - 1] == "CAPS") || (keys[n - 1] == "CAPS LOCK") || (keys[n - 1] == "CAPSLOCK") || (keys[n - 1] == "CAPSLK")) main_key = 20; else main_key = (uchar)StringGetCharacter(keys[n - 1], 0); + if (main_key == 96) main_key = 192; // A hack to use ` as a hotkey. } void WarnAboutZeroUnitCost() diff --git a/MQL5/Experts/Position Sizer/Translations/English.mqh b/MQL5/Experts/Position Sizer/Translations/English.mqh index edc01ee..f489d24 100644 --- a/MQL5/Experts/Position Sizer/Translations/English.mqh +++ b/MQL5/Experts/Position Sizer/Translations/English.mqh @@ -111,7 +111,8 @@ #define TRANSLATION_TOOLTIP_CURRENT_PORTFOLIO "Trades that are currently open" #define TRANSLATION_LABEL_POTENTIAL_PORTFOLIO "Potential portfolio" #define TRANSLATION_TOOLTIP_POTENTIAL_PORTFOLIO "Including the position being calculated" - +#define TRANSLATION_LABEL_CRRR_TOOLTIP "Risk-to-reward ratio of the current portfolio" +#define TRANSLATION_LABEL_PRRR_TOOLTIP "Risk-to-reward ratio of the potential portfolio" // Margin tab #define TRANSLATION_LABEL_POSITION_MARGIN "Position margin" @@ -181,7 +182,10 @@ #define TRANSLATION_TOOLTIP_DO_NOT_APPLY_TAKEPROFIT "The EA won't apply take-profit to the trade it opens." #define TRANSLATION_CHECKBOX_ASK_FOR_CONFIRMATION "Ask for confirmation" #define TRANSLATION_TOOLTIP_ASK_FOR_CONFIRMATION "The EA will ask for confirmation before opening a trade." - +#define TRANSLATION_LABEL_EXPIRY "Expiry" +#define TRANSLATION_TOOLTIP_EXPIRY "Expiration time in minutes for the next created pending order. Minimum = 2." +#define TRANSLATION_LABEL_MINUTES "min." +#define TRANSLATION_TOOLTIP_MINUTES "Minutes" // Chart objects #define TRANSLATION_TOOLTIP_STOP_PRICE_LINE "Stop Price (for Stop Limit orders)" @@ -189,6 +193,7 @@ #define TRANSLATION_TOOLTIP_TP_LABEL "TP Distance, points" #define TRANSLATION_TOOLTIP_ENTRY_LABEL "Entry Distance, points" #define TRANSLATION_TOOLTIP_STOP_PRICE_LABEL "Stop Price Distance, points" +#define TRANSLATION_TOOLTIP_ENTRY_LABEL_ADDITIONAL "Position Size, lots" // Warnings @@ -197,6 +202,7 @@ #define TRANSLATION_LABEL_WARNING_INVALID_TP "Invalid TP" #define TRANSLATION_TOOLTIP_WARNING_PS "Greater than maximum position size by margin!" + // Messages #define TRANSLATION_MESSAGE_SL_SHOULD_BE_POSITIVE "Stop-loss should be positive." #define TRANSLATION_MESSAGE_TRYING_TO_SAVE_FILE "Trying to save settings to file" @@ -300,4 +306,5 @@ #define TRANSLATION_MESSAGE_FAILED_DELETE_INI "Failed to delete the PS panel's .ini file" #define TRANSLATION_MESSAGE_CANNOT_CONVERT "Cannot convert" #define TRANSLATION_MESSAGE_CANNOT_CONVERT_TO "to" -#define TRANSLATION_MESSAGE_CANNOT_CONVERT_CALCULATION "Calculations might be wrong for" \ No newline at end of file +#define TRANSLATION_MESSAGE_CANNOT_CONVERT_CALCULATION "Calculations might be wrong for" +#define TRANSLATION_MESSAGE_MINIMUM_EXPIRY "Minimum expiry duration is 2 minutes." \ No newline at end of file diff --git a/MQL5/Experts/Position Sizer/Translations/Russian.mqh b/MQL5/Experts/Position Sizer/Translations/Russian.mqh index b4f2bae..5d1da85 100644 --- a/MQL5/Experts/Position Sizer/Translations/Russian.mqh +++ b/MQL5/Experts/Position Sizer/Translations/Russian.mqh @@ -107,6 +107,8 @@ #define TRANSLATION_TOOLTIP_CURRENT_PORTFOLIO "Сделки, которые сейчас открыты" #define TRANSLATION_LABEL_POTENTIAL_PORTFOLIO "Потенц. портфол." #define TRANSLATION_TOOLTIP_POTENTIAL_PORTFOLIO "Включая позицию в расчете" +#define TRANSLATION_LABEL_CRRR_TOOLTIP "Соотношение риска и прибыли текущего портфолио" +#define TRANSLATION_LABEL_PRRR_TOOLTIP "Соотношение риска и прибыли потенциального портфолио" // Margin tab @@ -177,6 +179,10 @@ #define TRANSLATION_TOOLTIP_DO_NOT_APPLY_TAKEPROFIT "Советник откроет сделку без тейк-профита." #define TRANSLATION_CHECKBOX_ASK_FOR_CONFIRMATION "Спрашивать подтверждение" #define TRANSLATION_TOOLTIP_ASK_FOR_CONFIRMATION "Советник будет спрашивать подтверждение перед открытием сделки." +#define TRANSLATION_LABEL_EXPIRY "Срок" +#define TRANSLATION_TOOLTIP_EXPIRY "Срок истечения в минутах для следующего созданного отложенного ордера. Минимум = 2." +#define TRANSLATION_LABEL_MINUTES "мин." +#define TRANSLATION_TOOLTIP_MINUTES "Минуты" // Chart objects @@ -185,6 +191,7 @@ #define TRANSLATION_TOOLTIP_TP_LABEL "Расстояние до ТП, пункты" #define TRANSLATION_TOOLTIP_ENTRY_LABEL "Расстояние до Входа, пункты" #define TRANSLATION_TOOLTIP_STOP_PRICE_LABEL "Расстояние до стоп-цены, пункты" +#define TRANSLATION_TOOLTIP_ENTRY_LABEL_ADDITIONAL "Размер позиции, лоты" // Warnings #define TRANSLATION_LABEL_WARNING_TOO_CLOSE "(Близко!)" @@ -295,4 +302,5 @@ #define TRANSLATION_MESSAGE_FAILED_DELETE_INI "Не удалось удалить ini-файл панели" #define TRANSLATION_MESSAGE_CANNOT_CONVERT "Не получается перевести" #define TRANSLATION_MESSAGE_CANNOT_CONVERT_TO "в" -#define TRANSLATION_MESSAGE_CANNOT_CONVERT_CALCULATION "Расчет может быть неверен для" \ No newline at end of file +#define TRANSLATION_MESSAGE_CANNOT_CONVERT_CALCULATION "Расчет может быть неверен для" +#define TRANSLATION_MESSAGE_MINIMUM_EXPIRY "Минимальный срок действия отложенного ордера - 2 минуты." \ No newline at end of file diff --git a/MQL5/Experts/Position Sizer/Translations/Ukrainian.mqh b/MQL5/Experts/Position Sizer/Translations/Ukrainian.mqh index 1d96686..312e7dd 100644 --- a/MQL5/Experts/Position Sizer/Translations/Ukrainian.mqh +++ b/MQL5/Experts/Position Sizer/Translations/Ukrainian.mqh @@ -107,6 +107,8 @@ #define TRANSLATION_TOOLTIP_CURRENT_PORTFOLIO "Угоди, що зараз є відкритими" #define TRANSLATION_LABEL_POTENTIAL_PORTFOLIO "Потенц. портфол." #define TRANSLATION_TOOLTIP_POTENTIAL_PORTFOLIO "Включно з позицією у розрахунку" +#define TRANSLATION_LABEL_CRRR_TOOLTIP "Співвідношення ризику та прибутку для поточного портфоліо" +#define TRANSLATION_LABEL_PRRR_TOOLTIP "Співвідношення ризику та прибутку для потенційного портфоліо" // Margin tab @@ -177,6 +179,10 @@ #define TRANSLATION_TOOLTIP_DO_NOT_APPLY_TAKEPROFIT "Експерт відкриє угоду без тейк-профіту." #define TRANSLATION_CHECKBOX_ASK_FOR_CONFIRMATION "Запитувати підтвердження" #define TRANSLATION_TOOLTIP_ASK_FOR_CONFIRMATION "Експерт буде запитувати підтвердження перед відкриттям угоди." +#define TRANSLATION_LABEL_EXPIRY "Термін" +#define TRANSLATION_TOOLTIP_EXPIRY "Термін дії у хвилинах для наступного створеного відкладеного ордеру. Мінімум = 2." +#define TRANSLATION_LABEL_MINUTES "хв." +#define TRANSLATION_TOOLTIP_MINUTES "Хвилини" // Chart objects @@ -185,6 +191,7 @@ #define TRANSLATION_TOOLTIP_TP_LABEL "Відстань до ТП, пункти" #define TRANSLATION_TOOLTIP_ENTRY_LABEL "Відстань до Входу, пункти" #define TRANSLATION_TOOLTIP_STOP_PRICE_LABEL "Відстань до стоп-ціни, пункти" +#define TRANSLATION_TOOLTIP_ENTRY_LABEL_ADDITIONAL "Розмір позиції, лоти" // Warnings @@ -297,4 +304,5 @@ #define TRANSLATION_MESSAGE_FAILED_DELETE_INI "Не вдалося видалити ini-файл панелі" #define TRANSLATION_MESSAGE_CANNOT_CONVERT "Не можна перевести" #define TRANSLATION_MESSAGE_CANNOT_CONVERT_TO "у" -#define TRANSLATION_MESSAGE_CANNOT_CONVERT_CALCULATION "Розрахунок може бути хибним для" \ No newline at end of file +#define TRANSLATION_MESSAGE_CANNOT_CONVERT_CALCULATION "Розрахунок може бути хибним для" +#define TRANSLATION_MESSAGE_MINIMUM_EXPIRY "Мінімальний термін дії відкладеного ордеру - 2 хвилини." \ No newline at end of file