Building a Manual Trade Manager Panel in MQL5 — A Design Walkthrough
How I turned a decade of manual trading habits into a single on-chart panel — and what I learned about broker quirks, slow servers, and dragging lines that refuse to stay horizontal.
Why a Manual Trade Manager
There is a strange gap in the MQL5 ecosystem. On one side are fully automated Expert Advisors that take trades you never see. On the other side are bare MT5 charts where every click is manual and every calculation is in your head.
Most discretionary traders live in the middle. They want to decide when to trade and in which direction — but they do not want to manually compute lot sizes, pip distances, break-even buffers, or the correct SL/TP for the sixth position of a grid. That work is arithmetic, not judgment.
Trade Manager EA fills that gap. It is a single on-chart panel that handles the arithmetic while leaving the decisions to the trader. Market buy/sell buttons, pending limit/stop orders, a grid mode, break-even, partial closes, trailing stop, drag-line price triggers, a news notice, and error logging — all in one interface.
This blog walks through the design decisions behind it. The source is not posted — the EA is on the MQL5 Market — but the patterns here are worth sharing.
The Core Inputs
The panel is organized around ten groups of settings:
Order Sizing: default lot, default TP, default SL, TP ladder step Grid Orders: grid step between orders, default order count Lot/Position Lists: which lot values and position counts appear in the dropdowns Execution: magic number, slippage, stop-level buffer, modify retries, cooldown Trailing Stop: activation distance, trail distance, runner-only mode Volatility Blocker: block trades when ATR(14) exceeds a threshold News Filter: tracked currencies, minutes before news to warn Panel UI: X/Y position, compact vs rectangle layout Drag Lines: enable, offset from price, line length, colors Sound Alerts: separate sound files for TP hit, SL hit, and successful order
Four design choices stand out:
- The lot and position lists are user-editable strings. Instead of hardcoding dropdown contents, the EA parses comma-separated lists from inputs. A trader who prefers Fibonacci lot progression types "0.01,0.02,0.03,0.05,0.08,0.13" and gets exactly that dropdown.
- Pip size is auto-detected per symbol. Gold on a 2-digit quote has a different pip definition than EURUSD on a 5-digit quote. The EA checks the symbol name and digit count and returns the correct pip size automatically.
- Every protective feature has an on/off toggle. Volatility blocker, news filter, trailing stop, drag lines — all can be disabled independently. Nothing is forced.
- Error state is visible on the panel. Instead of only logging to the journal, the last four errors show directly on the panel with a title that changes from green ("no errors") to red ("errors").
Pip Size — The Foundation of Everything
Almost every input in the panel is expressed in pips. If pip size is wrong, everything downstream is wrong. So the EA computes it defensively:
If a manual pip size is set in inputs, use it.
Otherwise:
Read the symbol digits and point size.
If the symbol name contains GOLD, XAU, SILVER, or XAG,
and the digits are 2 or fewer:
Return 0.10 (metals convention).
If the digits are 5 (forex) or 3 (JPY crosses):
Return 10 × point.
Otherwise (4 or 2 digits):
Return 1 × point.
This one function is called throughout the EA — for TP, for SL, for grid steps, for trailing distances, for volatility thresholds. Getting it right once means every downstream calculation is correct on every symbol.
Market Execution
Opening a market order is more than m_trade.Buy() . There are several edge cases that must be handled:
On BUY or SELL click:
Read the lot size from the panel.
If the lot size is invalid, show an error and stop.
Check the volatility blocker. If ATR(14) in pips exceeds the threshold,
show a message and refuse to open.
Read the position count from the dropdown. If 2 or more,
switch to ladder mode (see below).
For each position to open:
Send a market order with no SL/TP attached.
Wait for the fill and find the ticket of the new position.
Compute the SL and TP from the actual fill price.
Apply them via a safe modify.
Play a success sound when at least one position opens.
Three details matter here:
- SL/TP are attached after the fill, not during the order. Some brokers reject attached stops on the initial market order, especially during fast markets. Sending the order clean and then modifying is more reliable.
- The modify uses the actual fill price, not the requested price. On a fast market, the fill can be several pips away from the request. Using the fill price ensures the SL/TP distances are exactly what the user specified.
- The new position's ticket is found by searching the position list. MT5 does not always return the ticket directly after a market order. A short retry loop with a small sleep finds it reliably.
The Safe Modify Pattern
This is the single most important pattern in the entire EA. On a slow server or during fast markets, a naive PositionModify() call can fail repeatedly. Without protection, two management routines (trailing stop and break-even) can alternate rejections on every tick — a condition that vendors call a "stop storm."
The safe modify handles four cases:
1. Skip if the ticket no longer exists or the level has not changed. 2. Clamp SL and TP into the broker-valid zone using fresh quotes. BUY: SL must be below bid minus gap, TP above ask plus gap. SELL: SL must be above ask plus gap, TP below bid minus gap. The gap is the broker STOPLEVEL plus a user buffer. 3. Per-ticket cooldown: if the same ticket was modified within the last N milliseconds, skip this call entirely. 4. Retry on transient rejections (Invalid stops, Requote, Price changed, Timeout) with fresh re-clamping each time. 5. After a successful modify, verify the level was actually applied by re-selecting the position and reading its SL/TP.
The cooldown is the key. Without it, a trailing routine and a break-even routine can ping-pong the same position, each retrying on every tick, each triggering the other's retry logic. With it, the same position can only be modified once every two seconds — which is more than enough for real trading and dramatically reduces server load.
Pending Orders and Grid Mode
Buy Limit, Sell Limit, Buy Stop, and Sell Stop are all placed from the same panel section. A single toggle switches the pending type between LIMIT and STOP, and the button labels update accordingly.
Grid mode is where the panel earns its keep. Instead of placing one order at the specified price, the EA places N orders spaced evenly by a grid step:
On place pending order:
Read the price, SL, and TP from the edit fields.
Validate the price against the current bid/ask:
Buy Limit must be below ask.
Sell Limit must be above bid.
Buy Stop must be above bid.
Sell Stop must be below ask.
Validate TP and SL on the correct side of the price.
If grid mode is on:
Read N from the grid count edit.
Read step from the grid step input.
For i from 0 to N-1:
Order price = base price ± i × step
TP = order price ± tp_distance
SL = order price ∓ sl_distance
Place the pending order.
Otherwise:
Place a single pending order.
All grid orders share the same TP and SL distances from their own entry price — not absolute TP/SL prices. This is important: each grid level needs its own TP and SL, computed relative to its own entry.
Break-Even and Partial Closes
Break-even is a single-button action. It iterates over all positions on the symbol and moves SL to entry ± a small buffer:
On Break Even click:
For each position on the symbol:
Read type, entry price, current SL, current price.
Compute be_price:
BUY: entry + buffer
SELL: entry - buffer
Only move SL if:
BUY: current price > be_price AND current SL < be_price
SELL: current price < be_price AND current SL > be_price
Ensure the new SL is at least the broker minimum distance
from the current price.
Apply via safe modify.
The two conditions — price is far enough, and SL has not already been moved — prevent the routine from doing anything when no action is warranted. On a market with no position in profit, the button does nothing except report that.
Partial close works the same way. Four buttons (10%, 30%, 50%, 90%) each close that percentage of every position on the symbol. The EA computes the exact volume to close, rounds it down to the broker's volume step, and skips any position where the computed volume would be below the broker minimum.
The TP Ladder and Runner Mode
When the position count from the dropdown is 2 or more, the EA opens a ladder of positions with progressively further TP targets:
For i from 0 to count - 1:
TP distance for this position = base TP + i × ladder step
If this is the last position AND runner mode is on:
Set no TP at all.
Open the market position.
Apply SL/TP from the actual fill price.
Record the ticket and its TP distance.
The last position of a 2+ batch is called the runner. It has no TP target — it runs until either the trailing stop catches it or the trader closes it manually. This is a common pattern: take most of the position off at multiple TP levels, let one position run for the extended move.
The runner also gets a special trailing rule: it only starts trailing after all the earlier ladder positions have closed. That way the runner does not stop out before the ladder has a chance to complete.
SL Ratcheting After Each TP
When a TP ladder position closes, the remaining positions of the same batch get a protective SL move:
After each tick:
For each batch still active:
Count how many leading ladder positions have closed.
If the first TP closed and the batch has not yet moved SL to break-even:
Move SL of all remaining positions to break-even.
Record that stage 1 was applied.
If a later TP (stage 2, 3, ...) closed and that stage has not yet
been applied:
Move SL of all remaining positions to the previous TP level.
Record that stage was applied.
The result is a graduated stop-loss that follows the ladder up (or down) as each TP is hit. By the time the runner is the only remaining position, its SL is already at the last TP level — so the runner cannot give back more than the difference between the last two TPs.
The Drag Trigger Lines
This is my favourite feature of the panel and the one that took the most iterations to get right. Two buttons — BUY LINE and SELL LINE — place horizontal lines on the chart a configurable distance away from the current price:
On BUY LINE click:
Read current bid.
Compute line price = bid + offset.
Create a trendline object with two anchor points,
both at the same price, separated by N bars.
Mark the line as armed.
Set the color to the buy line color.
On SELL LINE click:
Same but line price = ask - offset.
Set the color to the sell line color.

The trader then drags the line to whatever price they want. When price touches the line, the EA fires the same action as pressing the BUY or SELL button. The line disarms after firing but stays on the chart.
Keeping the line horizontal during drag was the tricky part. MT5 allows you to drag a trendline's endpoints independently, so the line can become diagonal while being dragged. The EA intercepts the drag event and clamps the two endpoints to the same price:
On CHARTEVENT_OBJECT_DRAG for one of our trigger lines:
Read the two anchor prices.
Compute the average of the two.
If either anchor price differs from the average:
Set both anchor prices to the average.
Mark the line as armed (dragging re-arms the trigger).
Update the label with the new price.
The result feels natural — the line stays horizontal no matter where you drag it — and dragging automatically re-arms a line that has previously fired.
The News Filter
The EA queries the built-in MT5 economic calendar, checks for high-impact events on user-specified currencies, and shows a warning on the panel if an event is approaching:
Every 60 seconds:
Request calendar events for the next 24 hours.
For each event:
Skip if the event time has already passed.
Skip if the event is not HIGH importance.
Determine the event's currency from its country.
Skip if the currency is not in the tracked list.
If the event is within N minutes:
Record the event name, currency, and time.
Break out of the loop.
Update the news label:
If a relevant event is approaching:
Show the event name, currency, and minutes remaining.
Color the label red.
Else:
Show "News in next N min" with a neutral color.
The label is deliberately non-intrusive. It does not block trades automatically (some traders want to trade the news), but it makes the trader aware so they can decide.
TP/SL Hit Detection and Sounds
MT5 does not natively notify an EA when a position is closed by its own TP or SL. The EA builds this detection manually by tracking position state across ticks:
On every call to TrackPositions():
Build a snapshot of all open positions on the symbol:
ticket, TP, SL, and type for each.
For each position in the previous snapshot:
If it is no longer in the current snapshot:
It was closed between the two calls.
Compare the last known price to the TP and SL:
If price is at or near TP: play TP sound.
If price is at or near SL: play SL sound.
Store the current snapshot for the next call.
Small tolerance windows are used when comparing the last price to TP/SL, because the terminal's last tick and the position close may not be identical. The result is a reliable sound alert when a TP or SL is hit, without needing to subscribe to any additional MT5 events.
Two Panel Layouts
The EA ships with two panel layouts, both driven by the same underlying logic:
Compact layout (default):
Single column, ~370 pixels wide.
Everything stacked vertically.
Good for charts that are not very wide.
Rectangle layout (optional):
Three columns, ~770 pixels wide.
Column 1: sizing, TP/SL, risk, P&L.
Column 2: pending orders and grid.
Column 3: management (BE, partials, close by P&L).
Good for wide monitors and multi-chart setups.
Both layouts use the same button handlers, the same modify functions, the same everything. Only the control creation differs. This keeps the EA maintainable — one set of business logic, two ways to present it.
What I Learned Building It
- Pip size auto-detection is not optional. I cannot count how many hours I have spent debugging "why is my SL always 10 pips off" — the answer was always that the pip size was wrong for that symbol. Handle it once, correctly, and everything downstream works.
- Safe modify is the difference between a working EA and a rage-inducing one. The per-ticket cooldown and the retry loop are not optional polish — they are core functionality. Without them, the EA fights the broker on every tick.
- Attach SL/TP after the fill, not during the order. Some brokers reject the initial market order if stops are attached, especially on volatile instruments. Sending clean and modifying after is more reliable across more brokers.
- Object drag events are the only way to build interactive tools. The trigger lines would not be possible without CHARTEVENT_OBJECT_DRAG. Once you understand the pattern — intercept the drag, clamp the anchors, re-arm the trigger — a whole class of interactive tools opens up.
- Error visibility on the panel matters. Without an on-panel error log, a failed order looks like nothing happened. With one, the trader immediately knows why.
Wrapping Up
Trade Manager EA is a manual trader's tool. It does not decide when to trade, it does not place trades automatically, and it does not claim to be profitable. What it does is handle the arithmetic — lot sizing, pip distances, grid layouts, break-even, partial closes, laddered TPs, trailing stops — so the trader can focus on the decision instead of the calculation.
The full version is available on the MQL5 Market — the link is in my profile. If you find any of the design principles here useful — safe modify with per-ticket cooldown, pip size auto-detection, drag-line triggers, or TP/SL hit detection — feel free to apply them in your own tools. Those patterns are not unique to this EA; they are worth knowing regardless of what you build.
Trade safely.
— Jose Rodrigues Chaves
About the author: Independent MQL5 developer. Interested in manual trading tools that stay out of the trader's way. All opinions are my own.


