MQL5-Google-Onedrive/.jules/bolt.md
google-labs-jules[bot] 315e26d24c Bolt: Optimize MQL5 Expert Advisor performance
This commit implements several performance optimizations for the `ExpertMAPSARSizeOptimized_Improved.mq5` Expert Advisor:

1.  **OnTick Gatekeeper Optimization**: Added an early-exit 'new bar' check using the lightweight `iTime()` function at the very beginning of `OnTick`. This prevents expensive terminal API calls and logic from executing on every price tick when not required (when `Expert_EveryTick` is false).
2.  **Event-Driven Statistics**: Relocated the expensive `UpdateDailyStatistics()` call, which performs history scanning, from the high-frequency `OnTick` path to the event-driven `OnTrade()` handler and a periodic `OnTimer()` handler (60 seconds).
3.  **Startup Initialization**: Added an initial call to `UpdateDailyStatistics()` in `OnInit()` to ensure accurate statistics upon EA startup.
4.  **Timer Management**: Enabled `EventSetTimer(60)` in `OnInit()` and added proper cleanup with `EventKillTimer()` in `OnDeinit()`.
5.  **Efficient History Selection**: Refactored `UpdateDailyStatistics()` to use a specifically calculated `todayStart` timestamp for `HistorySelect()`, reducing terminal data retrieval overhead compared to the previous rolling 24-hour window.
6.  **Redundancy Removal**: Removed an expensive and redundant `CopyRates()` call used for bar time tracking at the end of `OnTick()`.

These changes significantly reduce CPU usage and terminal overhead, especially during high-volatility market conditions with rapid tick streams.

Co-authored-by: Mouy-leng <199350297+Mouy-leng@users.noreply.github.com>
2026-02-02 11:00:25 +00:00

4.2 KiB

Bolt's Journal

This journal is for CRITICAL, non-routine performance learnings ONLY.

  • Codebase-specific bottlenecks
  • Failed optimizations (and why)
  • Surprising performance patterns
  • Rejected changes with valuable lessons

2024-07-25 - MQL5 Native Functions vs. Scripted Loops

Learning: My assumption that a manual MQL5 loop over a pre-cached array would be faster than built-in functions like iHighest() and iLowest() was incorrect. The code review pointed out that MQL5's native, built-in functions are implemented in highly optimized C++ and are significantly faster than loops executed in the MQL5 scripting layer. The original comment stating this was correct. Action: Always prefer using MQL5's built-in, native functions for calculations like finding highs/lows over manual loops, even if the data is already in a local array. The performance gain from the native implementation outweighs the overhead of the function call.

2024-07-26 - Native ArrayMaximum/ArrayMinimum Efficiency

Learning: Confirmed that native ArrayMaximum() and ArrayMinimum() are the preferred way to find extreme values in price arrays. Also, when using these functions, it's important to check if they return -1 to avoid invalid array access, especially if the count or start parameters might be dynamic. Action: When replacing manual loops with native array functions, always include a check for the -1 return value to ensure robustness while gaining performance.

2026-01-19 - Native Object Cleanup in MQL5

Learning: While iterating through chart objects manually is flexible, it becomes a major bottleneck if the chart has thousands of objects. For simple prefix-based cleanup (often used in indicators), the native ObjectsDeleteAll(0, prefix) is significantly more efficient than a scripted loop calling ObjectName() and StringFind() for every object on the chart. Action: Use ObjectsDeleteAll() for bulk object removal by prefix whenever the "keep N latest" logic is not strictly required or can be safely bypassed for performance.

2026-01-20 - Robust New Bar Check in MQL5 OnCalculate

Learning: An early exit in OnCalculate based on bar time MUST check prev_calculated > 0. If prev_calculated == 0, the terminal is requesting a full recalculation (e.g., after a history sync or data gap fill), and exiting early would result in stale data. Also, using iTime() is more robust than indexing into the time[] array if the array's series state is unknown. Action: Always wrap "new bar" early exits in indicators with if(prev_calculated > 0 && ...) and prefer iTime() for the current bar's timestamp.

2026-01-20 - MQL5 OnTick Execution Flow Optimization

Learning: Significant performance gains in MQL5 EAs can be achieved by carefully ordering the logic in OnTick. Moving the PositionSelect check before CopyRates and CopyBuffer avoids expensive data operations when a trade is already active. Additionally, reducing the requested bar count in data fetching functions to the absolute minimum (e.g., 2 instead of 3) and using SymbolInfoTick for atomic, lazy price retrieval further reduces overhead. Action: Always place 'gatekeeper' checks (new bar, position existence, terminal trading allowed) at the top of OnTick and minimize the data payload for indicator and price fetching to only what is strictly necessary for the current bar's logic.

2026-01-20 - MQL5 Event-Driven Statistics Optimization

Learning: Relocating heavy history scanning logic (like calculating daily profit/loss) from the high-frequency OnTick handler to event-driven handlers (OnTrade) and periodic timers (OnTimer) significantly reduces per-tick CPU overhead. However, it is critical to also call these functions in OnInit to ensure data is correctly initialized on startup. Additionally, optimizing HistorySelect to use a calendar-day todayStart instead of a rolling 24-hour window further reduces terminal data retrieval overhead. Action: Move expensive statistics and history processing out of OnTick. Use EventSetTimer for periodic updates and call the processing function in OnInit and OnTrade. Use specific HistorySelect ranges to minimize data volume.