TrailingStopManager - Automated Profit Protection¶
Description¶
🧩 TrailingStopManager is an automated orchestrator designed to PROTECT PROFITS on open positions. It continuously monitors all positions and automatically moves stop-loss orders as price moves favorably, locking in gains without manual intervention. Perfect for trending markets where you want to let winners run while protecting accumulated profits.
Strategy Principle: Once a position reaches a specified profit threshold, the manager activates a trailing stop mechanism:
- BUY positions: Stop loss moves UPWARD only as price rises (never down)
- SELL positions: Stop loss moves DOWNWARD only as price falls (never up)
- Maintains fixed distance from current price (e.g., 200 points behind)
- Locks in profits automatically during reversals
- Works 24/7 managing multiple positions simultaneously
- No manual chart watching required
File: examples/demos/orchestrators/11_trailing_stop.go
IMPORTANT DISCLAIMER - EDUCATIONAL EXAMPLE ONLY
This orchestrator is a demonstration showing how GoMT5 methods function and combine into automated strategies. NOT a production-ready trading strategy! Always test on demo accounts first.
⚙️ Architecture¶
TRAILING STOP MANAGER ORCHESTRATOR
|
MT5Sugar Instance
|
| | |
GetOpenPositions GetPriceInfo ModifyPositionSL
(monitoring) (tracking) (adjusting)
Dependencies¶
- MT5Sugar: High-level convenience API (
GetOpenPositions,GetPriceInfo,ModifyPositionSL) - BaseOrchestrator: Foundation pattern with metrics tracking and lifecycle management
- protobuf types:
pb.PositionInfofor position data structures
Configuration Parameters¶
| Parameter | Type | Default | Description |
|---|---|---|---|
TrailingDistance |
float64 | 200 |
Distance in points to trail behind current price |
ActivationProfit |
float64 | 300 |
Profit in points needed to activate trailing |
UpdateInterval |
time.Duration | 2s |
How often to check and update positions |
Symbols |
[]string | [] |
Symbols to manage (empty = all symbols) |
MinDistance |
float64 | 100 |
Minimum distance from current price (safety) |
StepSize |
float64 | 50 |
Minimum step size for SL adjustments (avoid excessive mods) |
Configuration Example¶
config := orchestrators.TrailingStopConfig{
TrailingDistance: 200, // Tail 200 points behind price
ActivationProfit: 300, // Activate after +300 points profit
UpdateInterval: 2 * time.Second, // Check every 2 seconds
Symbols: []string{}, // Manage all symbols
MinDistance: 100, // Min 100pts from current price
StepSize: 50, // Adjust in 50pt increments
}
tsManager := orchestrators.NewTrailingStopManager(sugar, config)
How to Run¶
You can execute this orchestrator using several command variations:
# Navigate to examples directory
cd examples/demos
# Option 1: By number
go run main.go 11
# Option 2: By keyword
go run main.go trailing
Both commands will launch the TrailingStopManager orchestrator with the configuration specified in main.go -> RunOrchestrator_TrailingStop().
Algorithm¶
🟢 Flowchart¶
START
|
Initialize TrailingStopManager
|
Create empty tracker map for positions
|
MONITORING LOOP (every UpdateInterval):
| Get all open positions
|
FOR each position:
| Check if symbol is tracked (if Symbols list specified)
| Get or create position tracker
| Get current price (Bid for BUY, Ask for SELL)
| Calculate profit in points
|
| Is profit >= ActivationProfit?
-> NO -> YES
Skip (not active) Activate trailing
|
Calculate new SL:
| BUY: newSL = currentPrice - TrailingDistance
| SELL: newSL = currentPrice + TrailingDistance
|
Is new SL better than current SL?
| BUY: newSL > currentSL?
| SELL: newSL < currentSL?
|
YES -> Modify position SL
NO -> Skip (don't move SL unfavorably)
|
Clean up trackers for closed positions
|
REPEAT until stopped
|
ON STOP:
| Cancel monitoring loop
| Clear all trackers
|
END
🛠️ Step-by-step Description¶
1. Initialization¶
Source:
examples/demos/orchestrators/11_trailing_stop.go
Lines:169–179
func NewTrailingStopManager(sugar *mt5.MT5Sugar, config TrailingStopConfig) *TrailingStopManager {
return &TrailingStopManager{
BaseOrchestrator: NewBaseOrchestrator("Trailing Stop Manager"),
sugar: sugar,
config: config,
trackedPositions: make(map[uint64]*positionTracker),
symbolDigits: make(map[string]int),
symbolPoints: make(map[string]float64),
}
}
What happens:
- Creates new manager instance with provided configuration
- Initializes empty tracker maps for positions and symbol parameters
- Each position gets a dedicated tracker storing its state
- Symbol parameters (digits, point value) are cached for efficiency
2. Starting the Manager¶
Lines
182–198
func (t *TrailingStopManager) Start() error {
if t.IsRunning() {
return fmt.Errorf("trailing stop manager already running")
}
// Create context
ctx, cancel := context.WithCancel(context.Background())
t.SetContext(ctx, cancel)
// Mark as started
t.MarkStarted()
// Start monitoring loop
go t.monitorLoop()
return nil
}
What happens:
- Checks if already running (prevents duplicate starts)
- Creates cancellable context for graceful shutdown
- Marks orchestrator as started in metrics
- Launches monitoring loop in separate goroutine
- Returns immediately (non-blocking)
3. Monitoring Loop¶
Lines
218–231
func (t *TrailingStopManager) monitorLoop() {
ticker := time.NewTicker(t.config.UpdateInterval)
defer ticker.Stop()
for {
select {
case <-t.GetContext().Done():
return
case <-ticker.C:
t.updateAllTrailingStops()
}
}
}
Monitoring actions every UpdateInterval:
- Ticker triggers: Every 2 seconds by default
- Context check: Monitors for stop signal
- Update all: Calls
updateAllTrailingStops()to process positions - Graceful exit: Stops cleanly when context is cancelled
Visual Example¶
Scenario: BUY EURUSD Position with Trailing¶
Configuration: - Entry: 1.10000 - TrailingDistance: 200 points - ActivationProfit: 300 points - StepSize: 50 points
TIME 0: Position Opened
Price: 1.10000 (Entry)
SL: 0 (no stop loss yet)
Profit: 0 points
Status: Waiting for activation (need +300pts)
TIME 1: Price Rises to 1.10300
Price: 1.10300
SL: 0 -> unchanged
Profit: +300 points
Status: TRAILING ACTIVATED!
Next update will set SL
TIME 2: Price at 1.10400 (First SL Update)
Price: 1.10400
Calculation: newSL = 1.10400 - 0.00200 = 1.10200
SL: 0 -> 1.10200 UPDATED
Profit: +400 points
Locked: +200 points guaranteed
TIME 3: Price at 1.10500
Price: 1.10500
Calculation: newSL = 1.10500 - 0.00200 = 1.10300
SL: 1.10200 -> 1.10300 UPDATED
Profit: +500 points
Locked: +300 points guaranteed
TIME 4: Price Drops to 1.10450
Price: 1.10450
Calculation: newSL = 1.10450 - 0.00200 = 1.10250
Check: 1.10250 < 1.10300? NO
SL: 1.10300 -> unchanged (SL only moves UP for BUY)
Profit: +450 points (floating)
Locked: +300 points guaranteed
TIME 5: Price Reverses to 1.10300
Price: 1.10300
Event: STOP LOSS TRIGGERED @ 1.10300
Position: CLOSED
Final Profit: +300 points = $30 (for 0.01 lots)
Result: Profit protected from reversal!
WITHOUT TRAILING STOP:
Price reached 1.10500 (+500pts)
Then reversed to 1.10000 (entry)
Final result: $0 profit (or worse if continues down)
WITH TRAILING STOP:
Price reached 1.10500 (+500pts)
Trailing activated, SL moved to 1.10300
Price reversed, stopped out at 1.10300
Final result: +300pts = $30 profit LOCKED IN
💡 Used MT5Sugar Methods¶
1. GetOpenPositions¶
Purpose: Retrieves all currently open positions across all symbols.
Usage in TrailingStopManager: - Called every UpdateInterval (default 2 seconds) - Returns full list of positions with: ticket, symbol, type, open price, current SL/TP, profit - Used to identify which positions need trailing stop management
Returns: Slice of position info or error
2. GetPriceInfo¶
Purpose: Gets current Bid/Ask prices for a symbol.
Usage in TrailingStopManager: - Called for each position to get current price - BUY positions use Bid price (exit price) - SELL positions use Ask price (exit price) - Used to calculate profit in points and new trailing SL
Returns: PriceInfo with Bid, Ask, and other quote data
3. ModifyPositionSL¶
Purpose: Modifies only the stop loss for an existing position (keeps TP unchanged).
Usage in TrailingStopManager: - Called when new calculated SL is more favorable than current - Updates stop loss on MT5 server - Preserves existing take profit settings - Core method for implementing trailing logic
Parameters:
- ticket: Position ticket number
- newSL: New stop loss price
Risk Management¶
Protection Benefits¶
TrailingStopManager provides:
- Profit Protection:
- Locks in gains automatically
- Prevents giving back large profits
-
No manual monitoring required
-
Psychological Benefit:
- Removes emotion from profit-taking
- Enforces discipline on winning trades
-
Lets winners run without fear
-
Risk Reduction:
- Converts open profit to guaranteed minimum
- Reduces risk as position becomes profitable
- Provides downside protection on winning trades
Risk Considerations¶
- Premature Exits:
- Too tight TrailingDistance -> stopped out on normal volatility
- Solution: Match TrailingDistance to symbol's ATR
-
Example: EURUSD 200pts, XAUUSD 500pts
-
Late Activation:
- Too high ActivationProfit -> miss protection on smaller winners
- Solution: Set based on average winning trade size
-
Example: Scalping 100pts, Swing 300pts
-
Excessive Modifications:
- Too small StepSize -> many server calls, slippage
- Solution: Set StepSize to 25-50% of TrailingDistance
-
Example: TrailingDistance 200pts -> StepSize 50pts
-
Gap Risk:
- Stop loss can be triggered at worse price during gaps
- Trailing doesn't protect against weekend gaps
- Solution: Close positions before high-risk events
Configuration Profiles¶
Conservative (Wider Safety)¶
TrailingDistance: 200, // Wide buffer to avoid premature exits
ActivationProfit: 300, // Wait for solid profit before activating
UpdateInterval: 2s
Aggressive (Tighter Trailing)¶
TrailingDistance: 100, // Closer trailing = higher risk/reward
ActivationProfit: 150, // Activate sooner
UpdateInterval: 1s // More frequent checks
Scalping (Very Tight)¶
TrailingDistance: 50, // Very tight trailing for quick exits
ActivationProfit: 100, // Activate on small profits
UpdateInterval: 500ms // Near real-time monitoring
When to Use Trailing Stops¶
Suitable Conditions¶
- Trending markets: Strong directional movement (uptrend for BUY, downtrend for SELL)
- Breakout trades: After level breaks, let winners run
- Momentum strategies: When price moves quickly in your favor
- Swing trading: Multi-hour or multi-day positions
- Hands-off management: When you can't watch charts constantly
- Multiple positions: Managing several trades simultaneously
- Profit protection: Want to lock in gains on winning trades
Unsuitable Conditions¶
- Range-bound markets: Sideways price action will trigger stops prematurely
- High volatility: Wide swings can stop you out on normal fluctuations
- News events: Spikes can trigger stops before reversal
- Scalping with fixed targets: Better to use fixed TP for quick exits
- Mean reversion strategies: Trailing fights the core strategy
- Very tight stops: Sub-20 pip stops get triggered by noise
Configuration Location¶
Runtime configuration is located in: examples/demos/main.go -> RunOrchestrator_TrailingStop()
This separation exists because:
- Code Reusability: Same orchestrator runs with different parameters
- Quick Testing: Change numbers without modifying strategy logic
- User Examples: Shows how to properly configure the orchestrator
- Centralized Entry Point: Single place for all orchestrator launches