Skip to content

Commit

Permalink
3.06
Browse files Browse the repository at this point in the history
1. Added a hotkey to set the Entry line to the price level at the mouse pointer's current position (SetEntryHotKey).
2. Added files with Arabic, Chinese (Simplified), and Spanish translations of the panel for the MT5 version of the expert advisor.
3. Fixed a bug that caused TP levels (when set in points) to drift from their given values.
4. Fixed a bug where incorrect previous SL was reported upon application of a trailing stop or breakeven.
5. Fixed a potential 'array out of range' error when switching symbols.
6. Fixed a bug with SL not resetting to default on symbol change when required by the SymbolChange parameter.
7. Fixed a bug when SL and TP lines could get set to levels that don't respect the symbol's tick sizer property.
8. Removed the possibility for the Stop-Loss to be set to zero.
  • Loading branch information
EarnForex authored Aug 14, 2023
1 parent 87872f5 commit d70c970
Show file tree
Hide file tree
Showing 9 changed files with 1,145 additions and 105 deletions.
6 changes: 4 additions & 2 deletions MQL4/Experts/Position Sizer/Position Sizer Trading.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -575,11 +575,12 @@ void DoBreakEven()
if ((be_line_color != clrNONE) && (BE_price > OrderStopLoss())) DrawBELine(OrderTicket(), BE_threshold, BE_price); // Only draw if not triggered yet.
if ((Bid >= BE_threshold) && (Bid >= BE_price) && (BE_price > OrderStopLoss())) // Only move to BE if the price reached the necessary threshold, the price is above the calculated BE price, and the current stop-loss is lower.
{
double prev_sl = OrderStopLoss(); // Remember old SL for reporting.
// Write Open price to the SL field.
if (!OrderModify(OrderTicket(), OrderOpenPrice(), BE_price, OrderTakeProfit(), OrderExpiration()))
Print("OrderModify Buy BE failed " + ErrorDescription(GetLastError()) + ".");
else
Print("Breakeven was applied to position - " + Symbol() + " BUY-order #" + IntegerToString(OrderTicket()) + " Lotsize = " + DoubleToString(OrderLots(), LotStep_digits) + ", OpenPrice = " + DoubleToString(OrderOpenPrice(), _Digits) + ", Stop-Loss was moved from " + DoubleToString(OrderStopLoss(), _Digits) + ".");
Print("Breakeven was applied to position - " + Symbol() + " BUY-order #" + IntegerToString(OrderTicket()) + " Lotsize = " + DoubleToString(OrderLots(), LotStep_digits) + ", OpenPrice = " + DoubleToString(OrderOpenPrice(), _Digits) + ", Stop-Loss was moved from " + DoubleToString(prev_sl, _Digits) + ".");
}
}
else if (OrderType() == OP_SELL)
Expand All @@ -589,11 +590,12 @@ void DoBreakEven()
if ((be_line_color != clrNONE) && ((BE_price < OrderStopLoss()) || (OrderStopLoss() == 0))) DrawBELine(OrderTicket(), BE_threshold, BE_price);
if ((Ask <= BE_threshold) && (Ask <= BE_price) && ((BE_price < OrderStopLoss()) || (OrderStopLoss() == 0))) // Only move to BE if the price reached the necessary threshold, the price below the calculated BE price, and the current stop-loss is higher (or zero).
{
double prev_sl = OrderStopLoss(); // Remember old SL for reporting.
// Write Open price to the SL field.
if (!OrderModify(OrderTicket(), OrderOpenPrice(), BE_price, OrderTakeProfit(), OrderExpiration()))
Print("OrderModify Sell BE failed " + ErrorDescription(GetLastError()) + ".");
else
Print("Breakeven was applied to position - " + Symbol() + " SELL-order #" + IntegerToString(OrderTicket()) + " Lotsize = " + DoubleToString(OrderLots(), LotStep_digits) + ", OpenPrice = " + DoubleToString(OrderOpenPrice(), _Digits) + ", Stop-Loss was moved from " + DoubleToString(OrderStopLoss(), _Digits) + ".");
Print("Breakeven was applied to position - " + Symbol() + " SELL-order #" + IntegerToString(OrderTicket()) + " Lotsize = " + DoubleToString(OrderLots(), LotStep_digits) + ", OpenPrice = " + DoubleToString(OrderOpenPrice(), _Digits) + ", Stop-Loss was moved from " + DoubleToString(prev_sl, _Digits) + ".");
}
}
}
Expand Down
42 changes: 35 additions & 7 deletions MQL4/Experts/Position Sizer/Position Sizer.mq4
Original file line number Diff line number Diff line change
Expand Up @@ -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.05"
string Version = "3.05";
#property version "3.06"
string Version = "3.06";
#property strict

#property description "Calculates risk-based position size for your account."
Expand Down Expand Up @@ -112,6 +112,7 @@ input string SwitchEntryDirectionHotKey = "TAB"; // SwitchEntryDirectionHotKey:
input string SwitchHideShowLinesHotKey = "H"; // SwitchHideShowLinesHotKey: Switch Hide/Show lines.
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 group "Miscellaneous"
input string ____Miscellaneous = "";
input double TP_Multiplier = 1; // TP Multiplier for SL value, appears in Take-profit button.
Expand Down Expand Up @@ -143,9 +144,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;
bool CtrlRequired_TradeHotKey = false, CtrlRequired_SwitchOrderTypeHotKey = false, CtrlRequired_SwitchEntryDirectionHotKey = false, CtrlRequired_SwitchHideShowLinesHotKey = false, CtrlRequired_SetStopLossHotKey = false, CtrlRequired_SetTakeProfitHotKey = false;
bool ShiftRequired_TradeHotKey = false, ShiftRequired_SwitchOrderTypeHotKey = false, ShiftRequired_SwitchEntryDirectionHotKey = false, ShiftRequired_SwitchHideShowLinesHotKey = false, ShiftRequired_SetStopLossHotKey = false, ShiftRequired_SetTakeProfitHotKey = false;
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;
bool NeedToCheckToggleScaleOffOn;
int PrevChartWidth = -1;
int DeinitializationReason = -1;
Expand Down Expand Up @@ -324,6 +325,7 @@ int OnInit()
if (SwitchHideShowLinesHotKey != "") DissectHotKeyCombination(SwitchHideShowLinesHotKey, ShiftRequired_SwitchHideShowLinesHotKey, CtrlRequired_SwitchHideShowLinesHotKey, MainKey_SwitchHideShowLinesHotKey);
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);
}
else if (OldSymbol != _Symbol)
{
Expand Down Expand Up @@ -694,9 +696,10 @@ void OnChartEvent(const int id,
double price;
datetime time; // Dummy.
ChartXYToTimePrice(ChartID(), Mouse_Last_X, Mouse_Last_Y, subwindow, time, price);
// If valid, move line SL there.
// If valid, move the SL line there.
if ((subwindow == 0) && (price > 0))
{
if (TickSize > 0) price = NormalizeDouble(MathRound(price / TickSize) * TickSize, _Digits);
ObjectSetDouble(ChartID(), ObjectPrefix + "StopLossLine", OBJPROP_PRICE, price);
if ((SLDistanceInPoints) || (ShowATROptions)) ExtDialog.UpdateFixedSL();
ExtDialog.RefreshValues();
Expand All @@ -714,9 +717,10 @@ void OnChartEvent(const int id,
double price;
datetime time; // Dummy.
ChartXYToTimePrice(ChartID(), Mouse_Last_X, Mouse_Last_Y, subwindow, time, price);
// If valid, move line SL there.
// 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 + "TakeProfitLine", OBJPROP_PRICE, price);
if ((TPDistanceInPoints) || (ShowATROptions)) ExtDialog.UpdateFixedTP();
ExtDialog.ShowTPRelatedEdits();
Expand All @@ -726,6 +730,30 @@ void OnChartEvent(const int id,
}
}
}
// Set entry:
else if ((MainKey_SetEntryHotKey != 0) && (lparam == MainKey_SetEntryHotKey))
{
if (((!ShiftRequired_SetEntryHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0)) // Shift
&& ((!CtrlRequired_SetEntryHotKey) || (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))
{
if (TickSize > 0) price = NormalizeDouble(MathRound(price / TickSize) * TickSize, _Digits);
ObjectSetDouble(ChartID(), ObjectPrefix + "EntryLine", OBJPROP_PRICE, price);
if (sets.EntryType == Instant)
{
ExtDialog.OnClickBtnOrderType(); // Includes RefreshValues().
}
else ExtDialog.RefreshValues();
}
}
}
}

// Call Panel's event handler only if it is not a CHARTEVENT_CHART_CHANGE - workaround for minimization bug on chart switch.
Expand Down
77 changes: 36 additions & 41 deletions MQL4/Experts/Position Sizer/Position Sizer.mqh
Original file line number Diff line number Diff line change
Expand Up @@ -1656,16 +1656,31 @@ void CPositionSizeCalculator::RefreshValues()

if (sets.EntryType == Instant)
{
if (!SLDistanceInPoints)
{
if (sets.StopLossLevel < SymbolInfoDouble(Symbol(), SYMBOL_ASK)) sets.EntryLevel = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
else sets.EntryLevel = SymbolInfoDouble(Symbol(), SYMBOL_BID);
}
else
if ((Ask > 0) && (Bid > 0))
{
if (sets.TradeDirection == Long) sets.EntryLevel = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
else sets.EntryLevel = SymbolInfoDouble(Symbol(), SYMBOL_BID);
if (sets.ShowLines)
{
double read_tStopLossLevel;
if (!ObjectGetDouble(ChartID(), ObjectPrefix + "StopLossLine", OBJPROP_PRICE, 0, read_tStopLossLevel)) return; // Line was deleted, waiting for automatic restoration.
tStopLossLevel = Round(read_tStopLossLevel, _Digits);
}
else
tStopLossLevel = sets.StopLossLevel;

// Long entry
if (tStopLossLevel < Bid) tEntryLevel = Ask;
// Short entry
else if (tStopLossLevel > Ask) tEntryLevel = Bid;
// Undefined entry
else
{
// Move tEntryLevel to the nearest line.
if ((tEntryLevel - Bid) < (tEntryLevel - Ask)) tEntryLevel = Bid;
else tEntryLevel = Ask;
}
ObjectSetDouble(0, ObjectPrefix + "EntryLine", OBJPROP_PRICE, 0, tEntryLevel);
}
sets.EntryLevel = tEntryLevel;
}
else // Pending
{
Expand Down Expand Up @@ -2904,6 +2919,7 @@ void CPositionSizeCalculator::OnClickBtnTakeProfitsNumberAdd()
{
ArrayResize(sets.TP, sets.TakeProfitsNumber);
ArrayResize(TakeProfitLineIsBeingMoved, sets.TakeProfitsNumber);
ArrayInitialize(TakeProfitLineIsBeingMoved, false);
ArrayResize(sets.TPShare, sets.TakeProfitsNumber);
if (sets.ShareVolumeMode == Decreasing) // Do the previous method because sets.ShareVolumeMode gets switched over once you click the button.
{
Expand Down Expand Up @@ -3351,9 +3367,15 @@ void CPositionSizeCalculator::OnEndEditEdtSL()
{
if (!SLDistanceInPoints)
{
double new_value = StringToDouble(m_EdtSL.Text());
if (new_value == 0) // Not allowed.
{
m_EdtSL.Text(DoubleToString(sets.StopLossLevel, _Digits)); // Change back.
return;
}
sets.StopLossLevel = new_value;
// Check and adjust for TickSize granularity.
if (TickSize > 0) sets.StopLossLevel = NormalizeDouble(MathRound(sets.StopLossLevel / TickSize) * TickSize, _Digits);
sets.StopLossLevel = StringToDouble(m_EdtSL.Text());
}
else
{
Expand Down Expand Up @@ -3392,9 +3414,9 @@ void CPositionSizeCalculator::OnEndEditEdtTP()
{
if (!TPDistanceInPoints)
{
sets.TakeProfitLevel = StringToDouble(m_EdtTP.Text());
// Check and adjust for TickSize granularity.
if (TickSize > 0) sets.TakeProfitLevel = NormalizeDouble(MathRound(sets.TakeProfitLevel / TickSize) * TickSize, _Digits);
sets.TakeProfitLevel = StringToDouble(m_EdtTP.Text());
}
else
{
Expand Down Expand Up @@ -4205,6 +4227,7 @@ bool CPositionSizeCalculator::LoadSettingsFromDisk()
ArrayResize(sets.WasSelectedAdditionalTakeProfitLine, sets.TakeProfitsNumber - 1); // -1 because the flag for the main TP is saved elsewhere.
}
ArrayResize(TakeProfitLineIsBeingMoved, sets.TakeProfitsNumber);
ArrayInitialize(TakeProfitLineIsBeingMoved, false);
}
else if (var_name == "Risk")
sets.Risk = StringToDouble(var_content);
Expand Down Expand Up @@ -4591,6 +4614,7 @@ bool CPositionSizeCalculator::LoadSettingsFromDisk()
ArrayResize(sets.WasSelectedAdditionalTakeProfitLine, sets.TakeProfitsNumber - 1); // -1 because the flag for the main TP is saved elsewhere.
}
ArrayResize(TakeProfitLineIsBeingMoved, sets.TakeProfitsNumber);
ArrayInitialize(TakeProfitLineIsBeingMoved, false);
}
}
}
Expand Down Expand Up @@ -5051,15 +5075,15 @@ void Initialization()
{
if (sets.TradeDirection == Long)
{
sets.EntryLevel = High[0];
sets.EntryLevel = Ask;
if (DefaultSL > 0) sets.StopLossLevel = sets.EntryLevel - DefaultSL * _Point;
else sets.StopLossLevel = Low[0];
if (DefaultTP > 0) sets.TakeProfitLevel = sets.EntryLevel + DefaultTP * _Point;
if (sets.EntryLevel == sets.StopLossLevel) sets.StopLossLevel -= Point;
}
else
{
sets.EntryLevel = Low[0];
sets.EntryLevel = Bid;
if (DefaultSL > 0) sets.StopLossLevel = sets.EntryLevel + DefaultSL * _Point;
else sets.StopLossLevel = High[0];
if (DefaultTP > 0) sets.TakeProfitLevel = sets.EntryLevel - DefaultTP * _Point;
Expand Down Expand Up @@ -5375,41 +5399,12 @@ void Initialization()
//+------------------------------------------------------------------+
void RecalculatePositionSize()
{
// Update Entry to Ask/Bid if needed.
RefreshRates();
WarningEntry = "";
WarningSL = "";
WarningTP = "";
for (int i = 1; i < sets.TakeProfitsNumber; i++) AdditionalWarningTP[i - 1] = "";

if (sets.EntryType == Instant)
{
if ((Ask > 0) && (Bid > 0))
{
if (sets.ShowLines)
{
double read_tStopLossLevel;
if (!ObjectGetDouble(ChartID(), ObjectPrefix + "StopLossLine", OBJPROP_PRICE, 0, read_tStopLossLevel)) return; // Line was deleted, waiting for automatic restoration.
tStopLossLevel = Round(read_tStopLossLevel, _Digits);
}
else
tStopLossLevel = sets.StopLossLevel;

// Long entry
if (tStopLossLevel < Bid) tEntryLevel = Ask;
// Short entry
else if (tStopLossLevel > Ask) tEntryLevel = Bid;
// Undefined entry
else
{
// Move tEntryLevel to the nearest line.
if ((tEntryLevel - Bid) < (tEntryLevel - Ask)) tEntryLevel = Bid;
else tEntryLevel = Ask;
}
ObjectSetDouble(0, ObjectPrefix + "EntryLine", OBJPROP_PRICE, 0, tEntryLevel);
}
}

// If could not find account currency, probably not connected.
if ((AccountCurrency() == "") || (!TerminalInfoInteger(TERMINAL_CONNECTED))) return;

Expand Down
Binary file modified MQL5/Experts/Position Sizer/Position Sizer Trading.mqh
Binary file not shown.
Loading

0 comments on commit d70c970

Please sign in to comment.