Skip to content

Commit d70c970

Browse files
author
EarnForex
authored
3.06
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.
1 parent 87872f5 commit d70c970

File tree

9 files changed

+1145
-105
lines changed

9 files changed

+1145
-105
lines changed

MQL4/Experts/Position Sizer/Position Sizer Trading.mqh

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -575,11 +575,12 @@ void DoBreakEven()
575575
if ((be_line_color != clrNONE) && (BE_price > OrderStopLoss())) DrawBELine(OrderTicket(), BE_threshold, BE_price); // Only draw if not triggered yet.
576576
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.
577577
{
578+
double prev_sl = OrderStopLoss(); // Remember old SL for reporting.
578579
// Write Open price to the SL field.
579580
if (!OrderModify(OrderTicket(), OrderOpenPrice(), BE_price, OrderTakeProfit(), OrderExpiration()))
580581
Print("OrderModify Buy BE failed " + ErrorDescription(GetLastError()) + ".");
581582
else
582-
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) + ".");
583+
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) + ".");
583584
}
584585
}
585586
else if (OrderType() == OP_SELL)
@@ -589,11 +590,12 @@ void DoBreakEven()
589590
if ((be_line_color != clrNONE) && ((BE_price < OrderStopLoss()) || (OrderStopLoss() == 0))) DrawBELine(OrderTicket(), BE_threshold, BE_price);
590591
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).
591592
{
593+
double prev_sl = OrderStopLoss(); // Remember old SL for reporting.
592594
// Write Open price to the SL field.
593595
if (!OrderModify(OrderTicket(), OrderOpenPrice(), BE_price, OrderTakeProfit(), OrderExpiration()))
594596
Print("OrderModify Sell BE failed " + ErrorDescription(GetLastError()) + ".");
595597
else
596-
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) + ".");
598+
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) + ".");
597599
}
598600
}
599601
}

MQL4/Experts/Position Sizer/Position Sizer.mq4

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@
66
#property copyright "EarnForex.com"
77
#property link "https://www.earnforex.com/metatrader-expert-advisors/Position-Sizer/"
88
#property icon "EF-Icon-64x64px.ico"
9-
#property version "3.05"
10-
string Version = "3.05";
9+
#property version "3.06"
10+
string Version = "3.06";
1111
#property strict
1212

1313
#property description "Calculates risk-based position size for your account."
@@ -112,6 +112,7 @@ input string SwitchEntryDirectionHotKey = "TAB"; // SwitchEntryDirectionHotKey:
112112
input string SwitchHideShowLinesHotKey = "H"; // SwitchHideShowLinesHotKey: Switch Hide/Show lines.
113113
input string SetStopLossHotKey = "S"; // SetStopLossHotKey: Set SL to where mouse pointer is.
114114
input string SetTakeProfitHotKey = "P"; // SetTakeProfitHotKey: Set TP to where mouse pointer is.
115+
input string SetEntryHotKey = "E"; // SetEntryHotKey: Set Entry to where mouse pointer is.
115116
input group "Miscellaneous"
116117
input string ____Miscellaneous = "";
117118
input double TP_Multiplier = 1; // TP Multiplier for SL value, appears in Take-profit button.
@@ -143,9 +144,9 @@ bool Dont_Move_the_Panel_to_Default_Corner_X_Y;
143144
uint LastRecalculationTime = 0;
144145
bool StopLossLineIsBeingMoved = false;
145146
bool TakeProfitLineIsBeingMoved[]; // Separate for each TP.
146-
uchar MainKey_TradeHotKey = 0, MainKey_SwitchOrderTypeHotKey = 0, MainKey_SwitchEntryDirectionHotKey = 0, MainKey_SwitchHideShowLinesHotKey = 0, MainKey_SetStopLossHotKey = 0, MainKey_SetTakeProfitHotKey = 0;
147-
bool CtrlRequired_TradeHotKey = false, CtrlRequired_SwitchOrderTypeHotKey = false, CtrlRequired_SwitchEntryDirectionHotKey = false, CtrlRequired_SwitchHideShowLinesHotKey = false, CtrlRequired_SetStopLossHotKey = false, CtrlRequired_SetTakeProfitHotKey = false;
148-
bool ShiftRequired_TradeHotKey = false, ShiftRequired_SwitchOrderTypeHotKey = false, ShiftRequired_SwitchEntryDirectionHotKey = false, ShiftRequired_SwitchHideShowLinesHotKey = false, ShiftRequired_SetStopLossHotKey = false, ShiftRequired_SetTakeProfitHotKey = false;
147+
uchar MainKey_TradeHotKey = 0, MainKey_SwitchOrderTypeHotKey = 0, MainKey_SwitchEntryDirectionHotKey = 0, MainKey_SwitchHideShowLinesHotKey = 0, MainKey_SetStopLossHotKey = 0, MainKey_SetTakeProfitHotKey = 0, MainKey_SetEntryHotKey = 0;
148+
bool CtrlRequired_TradeHotKey = false, CtrlRequired_SwitchOrderTypeHotKey = false, CtrlRequired_SwitchEntryDirectionHotKey = false, CtrlRequired_SwitchHideShowLinesHotKey = false, CtrlRequired_SetStopLossHotKey = false, CtrlRequired_SetTakeProfitHotKey = false, CtrlRequired_SetEntryHotKey = false;;
149+
bool ShiftRequired_TradeHotKey = false, ShiftRequired_SwitchOrderTypeHotKey = false, ShiftRequired_SwitchEntryDirectionHotKey = false, ShiftRequired_SwitchHideShowLinesHotKey = false, ShiftRequired_SetStopLossHotKey = false, ShiftRequired_SetTakeProfitHotKey = false, ShiftRequired_SetEntryHotKey = false;
149150
bool NeedToCheckToggleScaleOffOn;
150151
int PrevChartWidth = -1;
151152
int DeinitializationReason = -1;
@@ -324,6 +325,7 @@ int OnInit()
324325
if (SwitchHideShowLinesHotKey != "") DissectHotKeyCombination(SwitchHideShowLinesHotKey, ShiftRequired_SwitchHideShowLinesHotKey, CtrlRequired_SwitchHideShowLinesHotKey, MainKey_SwitchHideShowLinesHotKey);
325326
if (SetStopLossHotKey != "") DissectHotKeyCombination(SetStopLossHotKey, ShiftRequired_SetStopLossHotKey, CtrlRequired_SetStopLossHotKey, MainKey_SetStopLossHotKey);
326327
if (SetTakeProfitHotKey != "") DissectHotKeyCombination(SetTakeProfitHotKey, ShiftRequired_SetTakeProfitHotKey, CtrlRequired_SetTakeProfitHotKey, MainKey_SetTakeProfitHotKey);
328+
if (SetEntryHotKey != "") DissectHotKeyCombination(SetEntryHotKey, ShiftRequired_SetEntryHotKey, CtrlRequired_SetEntryHotKey, MainKey_SetEntryHotKey);
327329
}
328330
else if (OldSymbol != _Symbol)
329331
{
@@ -694,9 +696,10 @@ void OnChartEvent(const int id,
694696
double price;
695697
datetime time; // Dummy.
696698
ChartXYToTimePrice(ChartID(), Mouse_Last_X, Mouse_Last_Y, subwindow, time, price);
697-
// If valid, move line SL there.
699+
// If valid, move the SL line there.
698700
if ((subwindow == 0) && (price > 0))
699701
{
702+
if (TickSize > 0) price = NormalizeDouble(MathRound(price / TickSize) * TickSize, _Digits);
700703
ObjectSetDouble(ChartID(), ObjectPrefix + "StopLossLine", OBJPROP_PRICE, price);
701704
if ((SLDistanceInPoints) || (ShowATROptions)) ExtDialog.UpdateFixedSL();
702705
ExtDialog.RefreshValues();
@@ -714,9 +717,10 @@ void OnChartEvent(const int id,
714717
double price;
715718
datetime time; // Dummy.
716719
ChartXYToTimePrice(ChartID(), Mouse_Last_X, Mouse_Last_Y, subwindow, time, price);
717-
// If valid, move line SL there.
720+
// If valid, move the TP line there.
718721
if ((subwindow == 0) && (price > 0))
719722
{
723+
if (TickSize > 0) price = NormalizeDouble(MathRound(price / TickSize) * TickSize, _Digits);
720724
ObjectSetDouble(ChartID(), ObjectPrefix + "TakeProfitLine", OBJPROP_PRICE, price);
721725
if ((TPDistanceInPoints) || (ShowATROptions)) ExtDialog.UpdateFixedTP();
722726
ExtDialog.ShowTPRelatedEdits();
@@ -726,6 +730,30 @@ void OnChartEvent(const int id,
726730
}
727731
}
728732
}
733+
// Set entry:
734+
else if ((MainKey_SetEntryHotKey != 0) && (lparam == MainKey_SetEntryHotKey))
735+
{
736+
if (((!ShiftRequired_SetEntryHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_SHIFT) < 0)) // Shift
737+
&& ((!CtrlRequired_SetEntryHotKey) || (TerminalInfoInteger(TERMINAL_KEYSTATE_CONTROL) < 0))) // Control
738+
{
739+
// Capture point price location.
740+
int subwindow;
741+
double price;
742+
datetime time; // Dummy.
743+
ChartXYToTimePrice(ChartID(), Mouse_Last_X, Mouse_Last_Y, subwindow, time, price);
744+
// If valid, move the Entry line there and switch from Instant to Pending if necessary.
745+
if ((subwindow == 0) && (price > 0))
746+
{
747+
if (TickSize > 0) price = NormalizeDouble(MathRound(price / TickSize) * TickSize, _Digits);
748+
ObjectSetDouble(ChartID(), ObjectPrefix + "EntryLine", OBJPROP_PRICE, price);
749+
if (sets.EntryType == Instant)
750+
{
751+
ExtDialog.OnClickBtnOrderType(); // Includes RefreshValues().
752+
}
753+
else ExtDialog.RefreshValues();
754+
}
755+
}
756+
}
729757
}
730758

731759
// Call Panel's event handler only if it is not a CHARTEVENT_CHART_CHANGE - workaround for minimization bug on chart switch.

MQL4/Experts/Position Sizer/Position Sizer.mqh

Lines changed: 36 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1656,16 +1656,31 @@ void CPositionSizeCalculator::RefreshValues()
16561656

16571657
if (sets.EntryType == Instant)
16581658
{
1659-
if (!SLDistanceInPoints)
1660-
{
1661-
if (sets.StopLossLevel < SymbolInfoDouble(Symbol(), SYMBOL_ASK)) sets.EntryLevel = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
1662-
else sets.EntryLevel = SymbolInfoDouble(Symbol(), SYMBOL_BID);
1663-
}
1664-
else
1659+
if ((Ask > 0) && (Bid > 0))
16651660
{
1666-
if (sets.TradeDirection == Long) sets.EntryLevel = SymbolInfoDouble(Symbol(), SYMBOL_ASK);
1667-
else sets.EntryLevel = SymbolInfoDouble(Symbol(), SYMBOL_BID);
1661+
if (sets.ShowLines)
1662+
{
1663+
double read_tStopLossLevel;
1664+
if (!ObjectGetDouble(ChartID(), ObjectPrefix + "StopLossLine", OBJPROP_PRICE, 0, read_tStopLossLevel)) return; // Line was deleted, waiting for automatic restoration.
1665+
tStopLossLevel = Round(read_tStopLossLevel, _Digits);
1666+
}
1667+
else
1668+
tStopLossLevel = sets.StopLossLevel;
1669+
1670+
// Long entry
1671+
if (tStopLossLevel < Bid) tEntryLevel = Ask;
1672+
// Short entry
1673+
else if (tStopLossLevel > Ask) tEntryLevel = Bid;
1674+
// Undefined entry
1675+
else
1676+
{
1677+
// Move tEntryLevel to the nearest line.
1678+
if ((tEntryLevel - Bid) < (tEntryLevel - Ask)) tEntryLevel = Bid;
1679+
else tEntryLevel = Ask;
1680+
}
1681+
ObjectSetDouble(0, ObjectPrefix + "EntryLine", OBJPROP_PRICE, 0, tEntryLevel);
16681682
}
1683+
sets.EntryLevel = tEntryLevel;
16691684
}
16701685
else // Pending
16711686
{
@@ -2904,6 +2919,7 @@ void CPositionSizeCalculator::OnClickBtnTakeProfitsNumberAdd()
29042919
{
29052920
ArrayResize(sets.TP, sets.TakeProfitsNumber);
29062921
ArrayResize(TakeProfitLineIsBeingMoved, sets.TakeProfitsNumber);
2922+
ArrayInitialize(TakeProfitLineIsBeingMoved, false);
29072923
ArrayResize(sets.TPShare, sets.TakeProfitsNumber);
29082924
if (sets.ShareVolumeMode == Decreasing) // Do the previous method because sets.ShareVolumeMode gets switched over once you click the button.
29092925
{
@@ -3351,9 +3367,15 @@ void CPositionSizeCalculator::OnEndEditEdtSL()
33513367
{
33523368
if (!SLDistanceInPoints)
33533369
{
3370+
double new_value = StringToDouble(m_EdtSL.Text());
3371+
if (new_value == 0) // Not allowed.
3372+
{
3373+
m_EdtSL.Text(DoubleToString(sets.StopLossLevel, _Digits)); // Change back.
3374+
return;
3375+
}
3376+
sets.StopLossLevel = new_value;
33543377
// Check and adjust for TickSize granularity.
33553378
if (TickSize > 0) sets.StopLossLevel = NormalizeDouble(MathRound(sets.StopLossLevel / TickSize) * TickSize, _Digits);
3356-
sets.StopLossLevel = StringToDouble(m_EdtSL.Text());
33573379
}
33583380
else
33593381
{
@@ -3392,9 +3414,9 @@ void CPositionSizeCalculator::OnEndEditEdtTP()
33923414
{
33933415
if (!TPDistanceInPoints)
33943416
{
3417+
sets.TakeProfitLevel = StringToDouble(m_EdtTP.Text());
33953418
// Check and adjust for TickSize granularity.
33963419
if (TickSize > 0) sets.TakeProfitLevel = NormalizeDouble(MathRound(sets.TakeProfitLevel / TickSize) * TickSize, _Digits);
3397-
sets.TakeProfitLevel = StringToDouble(m_EdtTP.Text());
33983420
}
33993421
else
34003422
{
@@ -4205,6 +4227,7 @@ bool CPositionSizeCalculator::LoadSettingsFromDisk()
42054227
ArrayResize(sets.WasSelectedAdditionalTakeProfitLine, sets.TakeProfitsNumber - 1); // -1 because the flag for the main TP is saved elsewhere.
42064228
}
42074229
ArrayResize(TakeProfitLineIsBeingMoved, sets.TakeProfitsNumber);
4230+
ArrayInitialize(TakeProfitLineIsBeingMoved, false);
42084231
}
42094232
else if (var_name == "Risk")
42104233
sets.Risk = StringToDouble(var_content);
@@ -4591,6 +4614,7 @@ bool CPositionSizeCalculator::LoadSettingsFromDisk()
45914614
ArrayResize(sets.WasSelectedAdditionalTakeProfitLine, sets.TakeProfitsNumber - 1); // -1 because the flag for the main TP is saved elsewhere.
45924615
}
45934616
ArrayResize(TakeProfitLineIsBeingMoved, sets.TakeProfitsNumber);
4617+
ArrayInitialize(TakeProfitLineIsBeingMoved, false);
45944618
}
45954619
}
45964620
}
@@ -5051,15 +5075,15 @@ void Initialization()
50515075
{
50525076
if (sets.TradeDirection == Long)
50535077
{
5054-
sets.EntryLevel = High[0];
5078+
sets.EntryLevel = Ask;
50555079
if (DefaultSL > 0) sets.StopLossLevel = sets.EntryLevel - DefaultSL * _Point;
50565080
else sets.StopLossLevel = Low[0];
50575081
if (DefaultTP > 0) sets.TakeProfitLevel = sets.EntryLevel + DefaultTP * _Point;
50585082
if (sets.EntryLevel == sets.StopLossLevel) sets.StopLossLevel -= Point;
50595083
}
50605084
else
50615085
{
5062-
sets.EntryLevel = Low[0];
5086+
sets.EntryLevel = Bid;
50635087
if (DefaultSL > 0) sets.StopLossLevel = sets.EntryLevel + DefaultSL * _Point;
50645088
else sets.StopLossLevel = High[0];
50655089
if (DefaultTP > 0) sets.TakeProfitLevel = sets.EntryLevel - DefaultTP * _Point;
@@ -5375,41 +5399,12 @@ void Initialization()
53755399
//+------------------------------------------------------------------+
53765400
void RecalculatePositionSize()
53775401
{
5378-
// Update Entry to Ask/Bid if needed.
53795402
RefreshRates();
53805403
WarningEntry = "";
53815404
WarningSL = "";
53825405
WarningTP = "";
53835406
for (int i = 1; i < sets.TakeProfitsNumber; i++) AdditionalWarningTP[i - 1] = "";
53845407

5385-
if (sets.EntryType == Instant)
5386-
{
5387-
if ((Ask > 0) && (Bid > 0))
5388-
{
5389-
if (sets.ShowLines)
5390-
{
5391-
double read_tStopLossLevel;
5392-
if (!ObjectGetDouble(ChartID(), ObjectPrefix + "StopLossLine", OBJPROP_PRICE, 0, read_tStopLossLevel)) return; // Line was deleted, waiting for automatic restoration.
5393-
tStopLossLevel = Round(read_tStopLossLevel, _Digits);
5394-
}
5395-
else
5396-
tStopLossLevel = sets.StopLossLevel;
5397-
5398-
// Long entry
5399-
if (tStopLossLevel < Bid) tEntryLevel = Ask;
5400-
// Short entry
5401-
else if (tStopLossLevel > Ask) tEntryLevel = Bid;
5402-
// Undefined entry
5403-
else
5404-
{
5405-
// Move tEntryLevel to the nearest line.
5406-
if ((tEntryLevel - Bid) < (tEntryLevel - Ask)) tEntryLevel = Bid;
5407-
else tEntryLevel = Ask;
5408-
}
5409-
ObjectSetDouble(0, ObjectPrefix + "EntryLine", OBJPROP_PRICE, 0, tEntryLevel);
5410-
}
5411-
}
5412-
54135408
// If could not find account currency, probably not connected.
54145409
if ((AccountCurrency() == "") || (!TerminalInfoInteger(TERMINAL_CONNECTED))) return;
54155410

648 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)