Persistent Lock: Add a 'Lock' feature for both Risk % (23%) and RR Ratio so they remain fixed and do not need to be adjusted manually.
You can set that via input parameters.
Dynamic Management:
  • BE Profit Trigger: Move SL to Entry (Breakeven) when trade hits +50% of the distance to TP.(not units)
  • BE Loss/Exit Trigger: If the trade goes against me by -50% of the initial SL distance, move the TP to the Entry Price (to exit the trade at zero/breakeven).
I will probably consider the negative breakeven (for TP), but the percentage BE isn't likely be added in the future.
 
Hi,


I'm experiencing a serious performance issue with the Position Sizer EA (latest version).


After a few seconds of running the EA on a live chart, the chart freezes:- New candles stop updating or appear with heavy delay- Other indicators (Volume Profile Daily/Weekly, VWAP, etc.) stop working completely- Price lines and objects become laggy


When I remove the EA, everything immediately starts working normally again. It feels like the EA is blocking the terminal's event loop / chart processing.


This happens even with default settings and no trading activity. The problem is reproducible on different symbols and timeframes.


I suspect heavy calculations inside OnTimer / RefreshValues, frequent ChartRedraw calls, loops over PositionsTotal/OrdersTotal, and the large number of graphical objects are the main causes.


Has anyone else noticed this? Are there known workarounds or planned optimizations for reducing CPU load and preventing the chart from freezing?


Thank you.
 
Hi,


I'm experiencing a serious performance issue with the Position Sizer EA (latest version).


After a few seconds of running the EA on a live chart, the chart freezes:- New candles stop updating or appear with heavy delay- Other indicators (Volume Profile Daily/Weekly, VWAP, etc.) stop working completely- Price lines and objects become laggy


When I remove the EA, everything immediately starts working normally again. It feels like the EA is blocking the terminal's event loop / chart processing.


This happens even with default settings and no trading activity. The problem is reproducible on different symbols and timeframes.


I suspect heavy calculations inside OnTimer / RefreshValues, frequent ChartRedraw calls, loops over PositionsTotal/OrdersTotal, and the large number of graphical objects are the main causes.


Has anyone else noticed this? Are there known workarounds or planned optimizations for reducing CPU load and preventing the chart from freezing?


Thank you.
Is it on MT4 or on MT5?
You say 'latest version' of Position Sizer. Is it 3.16b? Or 3.16?
What build of MT4/MT5 are you running?
What is your account currency and which symbols did you experience this on?
Do you experience the same issue when you add the Position Sizer to a bare chart (without any other indicators)?
 
Is it on MT4 or on MT5?
You say 'latest version' of Position Sizer. Is it 3.16b? Or 3.16?
What build of MT4/MT5 are you running?
What is your account currency and which symbols did you experience this on?
Do you experience the same issue when you add the Position Sizer to a bare chart (without any other indicators)?
Thank you for the questions.


  • It is on MT5.
  • Version is 3.16b.
  • MT5 build: 6182
  • The issue happens on all symbols I trade.
**Also test the old version btw during last year!
Important finding from my tests:


  • When I put the Position Sizer on a completely bare chart (no other indicators), it works fine and does not freeze.
  • When I use it on my normal charts that already have indicators (Volume Profile, VWAP, and my other tools), after a few seconds the chart freezes: candles stop updating properly and the other indicators stop working. As soon as I remove the Position Sizer, everything returns to normal immediately.

So the problem only appears when the chart already has other indicators loaded. It looks like the Position Sizer is consuming too much processing time (probably from frequent RefreshValues() + ChartRedraw() calls in the timer and event handlers) and starves the rest of the chart.


I also have a much simpler custom position size tool that I use daily. It is incomplete compared to yours, but it never freezes the chart even with all my indicators running. This makes me think the issue is related to how heavy the refresh/calculation cycle is in the current Position Sizer.


Could you please look into reducing the frequency of full recalculations and ChartRedraw calls, especially when the panel is just sitting idle? This would make the EA usable together with other indicators.


Thank you.
 
  • When I put the Position Sizer on a completely bare chart (no other indicators), it works fine and does not freeze.
  • When I use it on my normal charts that already have indicators (Volume Profile, VWAP, and my other tools), after a few seconds the chart freezes: candles stop updating properly and the other indicators stop working. As soon as I remove the Position Sizer, everything returns to normal immediately.
Could you please send me those indicators so I could test this? If not, could you please try removing those indicators from the chart one by one to find the one, with which the Position Sizer halts?

I also still need to know your account currency and the broker you tried this on because this can also affect the Position Sizer's performance.

Could you please look into reducing the frequency of full recalculations and ChartRedraw calls, especially when the panel is just sitting idle?
There shouldn't be excessive ChartRedraw calls under normal conditions. I would first need to reproduce your issue to start working on fixing it.
 
I explain my problem to Antigravity and it send me fixed Position Sizer.mq5 file. everything works fine now!
if there is any bug please let me know. I'm not a programmer.
I'm fan of EARNFOREX!

here is the changelogs:

---

### **Subject: Performance Optimization & Critical Chart Freeze Fix in Version 3.16b**

Hi everyone / @Enivid,

First of all, thank you for developing and actively maintaining this indispensable tool.

I recently encountered a critical issue when running Position Sizer (v3.16b MT5) on live charts alongside resource-heavy indicators (such as Volume Profile, VWAP, and Market Profile). After a few seconds on a live chart, the chart would freeze:
* New incoming candles were severely delayed or stalled.
* Third-party indicators stopped updating completely.
* Dragging lines caused noticeable UI lag.
* As soon as Position Sizer was removed, the chart and all indicators immediately returned to normal smooth execution.

After profiling the code, we identified the exact bottlenecks causing this event-loop blockage and applied a series of clean, non-breaking performance optimizations. The chart now runs completely smooth with zero lag.

Below is the breakdown of the root causes found and the proposed changelog/patches:

---

### **Root Causes Identified**

1. **Redraw Storm in `DummyObjectSelect()` (Most Critical)**:
In MT5, `DummyObjectSelect()` was designed to work around an MT5 deselection glitch by calling `ObjectDelete()` followed immediately by `ObjectCreate()`. Deleting and recreating an object forces MT5 to trigger an internal chart redraw and recalculation cycle across all attached indicators.
2. **Frequency of `CheckAndRestoreLines()`**:
Inside `OnTimer()`, `CheckAndRestoreLines()` was guarded only by a 50ms check. Because of this, `DummyObjectSelect()` was deleting and recreating an object up to 20 times per second, effectively flooding the terminal's message queue.
3. **Unthrottled `OnTick()` Executions**:
During active market sessions or news events, `OnTick()` was executing `ExtDialog.RefreshValues()` on every single tick (10–20+ times per second). Each pass called full recalculation routines, chart object position updates, and account queries.
4. **Redundant Static Symbol Queries in `GetSymbolAndAccountData()`**:
Over 15 static symbol parameters (`SYMBOL_TRADE_TICK_SIZE`, `SYMBOL_VOLUME_MIN/MAX/STEP`, `SYMBOL_TRADE_CONTRACT_SIZE`, margin modes, currencies) were being re-queried via `SymbolInfoDouble`/`Integer`/`String` on every single tick, none of which change dynamically.
5. **Continuous `CalculateAutoCommission()` Calls**:
When `AutoCommission` was enabled, the broker deal history and tier specifications were being scanned and calculated repeatedly on every tick.

---

### **Proposed Changelog / Fixes**

#### 1. `Position Sizer.mqh` — `DummyObjectSelect()` Lazy-Initialization
Instead of deleting and recreating the dummy object on every call, the object is created only once (hidden from chart/timeframes) and merely toggled for selection:
```mql5
void CPositionSizeCalculator:😀ummyObjectSelect(string dummy_name = "DummyObject")
{
string full_name = ObjectPrefix + dummy_name;
if (ObjectFind(ChartID(), full_name) < 0)
{
ObjectCreate(0, full_name, OBJ_HLINE, 0, TimeCurrent(), 0);
ObjectSetInteger(ChartID(), full_name, OBJPROP_COLOR, clrNONE);
ObjectSetInteger(ChartID(), full_name, OBJPROP_TIMEFRAMES, OBJ_NO_PERIODS);
ObjectSetInteger(ChartID(), full_name, OBJPROP_HIDDEN, true);
ObjectSetInteger(ChartID(), full_name, OBJPROP_BACK, true);
}
ObjectSetInteger(ChartID(), full_name, OBJPROP_SELECTED, true);
ObjectSetInteger(ChartID(), full_name, OBJPROP_SELECTED, false);
}
```

#### 2. `Position Sizer.mq5` — Decoupled Timer Throttling in `OnTimer()`
Separated line restoration checks from UI recalculations. Line restoration now runs once every 5 seconds (more than fast enough if a line is accidentally deleted) instead of every 50ms:
```mql5
void OnTimer()
{
ulong now = GetTickCount64();

if (now - LastLineCheckTime >= 5000)
{
ExtDialog.CheckAndRestoreLines();
LastLineCheckTime = now;
}

if (now - LastRecalculationTime < 1000) return;
ExtDialog.RefreshValues();
ChartRedraw();
}
```

#### 3. `Position Sizer.mq5` — 250ms Throttle on `OnTick()`
Added a 250ms guard to `OnTick()` to cap tick-driven recalculations to max 4 times per second. This keeps calculations virtually instantaneous for the user while preventing tick-bursts from starving the terminal's thread:
```mql5
void OnTick()
{
if ((bool)MQLInfoInteger(MQL_VISUAL_MODE))
{
ListenToChartEvents(ExtDialog.Name());
ExtDialog.UpdateStrategyTesterTrades();
}

ulong now = GetTickCount64();
if (now - LastTickRefreshTime < 250) return;
LastTickRefreshTime = now;

ExtDialog.RefreshValues();

if (sets.TrailingStopPoints > 0) DoTrailingStop();
}
```

#### 4. `Position Sizer.mqh` — Static Symbol Specifications Cached (60s)
Cached immutable symbol properties inside `GetSymbolAndAccountData()` for 60 seconds or until the symbol changes, reducing ~15 API roundtrips per tick:
```mql5
ulong LastSymbolStaticDataTime = 0;
string LastSymbolForStaticData = "";

void ResetSymbolDataCache()
{
LastSymbolStaticDataTime = 0;
LastSymbolForStaticData = "";
}

void GetSymbolAndAccountData()
{
ulong now = GetTickCount64();
bool force_refresh = (SymbolForTrading != LastSymbolForStaticData) ||
(now - LastSymbolStaticDataTime > 60000);

if (force_refresh)
{
TickSize = SymbolInfoDouble(SymbolForTrading, SYMBOL_TRADE_TICK_SIZE);
MinLot = SymbolInfoDouble(SymbolForTrading, SYMBOL_VOLUME_MIN);
MaxLot = SymbolInfoDouble(SymbolForTrading, SYMBOL_VOLUME_MAX);
LotStep = SymbolInfoDouble(SymbolForTrading, SYMBOL_VOLUME_STEP);
if (!CalculateUnadjustedPositionSize) LotStep_digits = CountDecimalPlaces(LotStep);
else LotStep_digits = 8;
ContractSize = SymbolInfoDouble(SymbolForTrading, SYMBOL_TRADE_CONTRACT_SIZE);
CalcMode = (ENUM_SYMBOL_CALC_MODE)SymbolInfoInteger(SymbolForTrading, SYMBOL_TRADE_CALC_MODE);
MarginHedging = SymbolInfoDouble(SymbolForTrading, SYMBOL_MARGIN_HEDGED);
MarginCurrency = SymbolInfoString(SymbolForTrading, SYMBOL_CURRENCY_MARGIN);
if (MarginCurrency == "RUR") MarginCurrency = "RUB";
ProfitCurrency = SymbolInfoString(SymbolForTrading, SYMBOL_CURRENCY_PROFIT);
if (ProfitCurrency == "RUR") ProfitCurrency = "RUB";
BaseCurrency = SymbolInfoString(SymbolForTrading, SYMBOL_CURRENCY_BASE);
if (BaseCurrency == "RUR") BaseCurrency = "RUB";
InitialMargin = SymbolInfoDouble(SymbolForTrading, SYMBOL_MARGIN_INITIAL);
MaintenanceMargin = SymbolInfoDouble(SymbolForTrading, SYMBOL_MARGIN_MAINTENANCE);
if (MaintenanceMargin == 0) MaintenanceMargin = InitialMargin;
LastSymbolStaticDataTime = now;
LastSymbolForStaticData = SymbolForTrading;
}

AccountMarginMode = (ENUM_ACCOUNT_MARGIN_MODE)AccountInfoInteger(ACCOUNT_MARGIN_MODE);
AccountCurrency = AccountInfoString(ACCOUNT_CURRENCY);
AccountCurrencyDigits = (int)AccountInfoInteger(ACCOUNT_CURRENCY_DIGITS);
if (AccountCurrency == "RUR") AccountCurrency = "RUB";

AccStopoutMode = AccountInfoInteger(ACCOUNT_MARGIN_SO_MODE);
AccStopoutLevel = AccountInfoDouble(ACCOUNT_MARGIN_SO_SO);
TickValue = SymbolInfoDouble(SymbolForTrading, SYMBOL_TRADE_TICK_VALUE);
SwapsTripleDay = WeekdayToString((int)SymbolInfoInteger(SymbolForTrading, SYMBOL_SWAP_ROLLOVER3DAYS));
}
```

#### 5. `Position Sizer.mqh` — AutoCommission Cached (30s) with Trade Invalidation
Auto-commission calculations are cached for 30 seconds and automatically invalidated immediately whenever a trade is placed (`OnTrade()`) or the chart symbol changes:
```mql5
ulong LastAutoCommissionTime = 0;
double CachedAutoCommission = -1;

void ResetAutoCommissionCache()
{
LastAutoCommissionTime = 0;
CachedAutoCommission = -1;
}

double CalculateCommission()
{
if (AutoCommission)
{
ulong now = GetTickCount64();
if (CachedAutoCommission < 0 || (now - LastAutoCommissionTime > 30000))
{
CachedAutoCommission = CalculateAutoCommission();
LastAutoCommissionTime = now;
}
double auto_commission = CachedAutoCommission;
if (auto_commission >= 0)
{
if (auto_commission > 0 && NormalizeDouble(auto_commission, AccountCurrencyDigits) == 0) auto_commission = MathPow(0.1, AccountCurrencyDigits);
sets.CommissionType = COMMISSION_CURRENCY;
if (CommissionProfitOnly) sets.CommissionPerLot = CommissionReward;
else sets.CommissionPerLot = auto_commission;
return auto_commission;
}
}
double commission = sets.CommissionPerLot;
if (sets.CommissionType == COMMISSION_PERCENT)
commission = CalculateContractValue() * sets.CommissionPerLot / 100;
CommissionReward = commission;
CommissionProfitOnly = false;
return commission;
}
```

#### 6. Proper Deinit Cleanup
In `Position Sizer.mq5` under `OnDeinit()`, added explicit cleanup for the dummy objects (`DummyObject` and `DummyObject2`) so no hidden objects are left behind upon removal.

---

### **Result**
After applying these changes, CPU utilization dropped significantly, third-party indicators (Volume Profile, VWAP) remain perfectly responsive, and live candles render without any delay or stuttering.

Hopefully these optimizations can be considered for the next official release!
 

Attached File(s)

#### 1. `Position Sizer.mqh` — `DummyObjectSelect()` Lazy-Initialization
Sorry, this doesn't work. If the dummy object isn't deleted/recreated, it doesn't become the latest one. Then you get unselected TP lines even they should be selected.
#### 2. `Position Sizer.mq5` — Decoupled Timer Throttling in `OnTimer()`
This doesn't have much point because the timer function is set to run only once per second, so there is never a situation when the function fires 20 times per second.
#### 3. `Position Sizer.mq5` — 250ms Throttle on `OnTick()`
#### 4. `Position Sizer.mqh` — Static Symbol Specifications Cached (60s)
This isn't a good idea. Perhaps this will fix your problem, but this will just cause other issues.
#### 5. `Position Sizer.mqh` — AutoCommission Cached (30s) with Trade Invalidation
This could be useful overall but is unlikely to have been causing your specific problem.
Hopefully these optimizations can be considered for the next official release!
Once again: I cannot fix an issue without being able to reproduce it. To reproduce the issue, I need your set of indicators.
 
Sorry, this doesn't work. If the dummy object isn't deleted/recreated, it doesn't become the latest one. Then you get unselected TP lines even they should be selected.

This doesn't have much point because the timer function is set to run only once per second, so there is never a situation when the function fires 20 times per second.


This isn't a good idea. Perhaps this will fix your problem, but this will just cause other issues.

This could be useful overall but is unlikely to have been causing your specific problem.

Once again: I cannot fix an issue without being able to reproduce it. To reproduce the issue, I need your set of indicators.
This Expert Advisor is one of the best ones I've seen in the past 7 years. Without it, I'm completely stuck!
I've tried everything and still couldn't solve its problem. Even Antigravity couldn't fix it properly either.


I've converted many indicators from Sierra Chart to MT5 and customized them. The most important one was Volume Profile EarnForex, which I added a lot of features to!


Do you need the .set files right now to fix the problem?
The Expert Advisor works perfectly on a blank chart!
 
This Expert Advisor is one of the best ones I've seen in the past 7 years. Without it, I'm completely stuck!
I've tried everything and still couldn't solve its problem. Even Antigravity couldn't fix it properly either.


I've converted many indicators from Sierra Chart to MT5 and customized them. The most important one was Volume Profile EarnForex, which I added a lot of features to!


Do you need the .set files right now to fix the problem?
The Expert Advisor works perfectly on a blank chart!
Yes, I would need the indicator files (.ex5 would suffice) and preferably the .set files with the settings you use. That way I will be able to test this issue, reproduce it, and, hopefully, fix it.