TrendManager TM Plus is a trend-following strategy converted from the original MetaTrader 5 expert advisor Exp_TrendManager_Tm_Plus.mq5. The strategy relies on the TrendManager custom indicator, which compares two smoothed moving averages and highlights the distance between them. When the distance exceeds a configurable threshold the strategy opens positions in the direction of the prevailing trend and closes positions when the trend reverses or when protective rules are triggered.
Trading Logic
Build two moving averages on the selected candle series. The smoothing methods and lengths of both lines are configurable.
Calculate the distance between the fast and slow averages. If the distance is greater than or equal to the threshold, the indicator reports an uptrend. If the distance is less than or equal to the negative threshold, the indicator reports a downtrend. Otherwise there is no actionable signal.
Store the color states (0 for uptrend, 1 for downtrend, 3 for neutral) in a short history. The SignalBar parameter selects how many closed bars back are evaluated, following the original MQL logic.
When a new uptrend color appears the strategy optionally closes existing short positions and can open a long position if long entries are allowed. Conversely, a new downtrend color can close longs and open shorts.
Optional time-based and price-based exits close open trades when the holding time exceeds MaxPositionAge, when the price drops below StopLossDistance for longs (or above for shorts), or when TakeProfitDistance is reached.
Parameters
Candle Type – timeframe used for signal generation (default: 4-hour candles to match the original script).
Fast MA Method / Slow MA Method – smoothing algorithms for the fast and slow lines. Available options: Simple, Exponential, Smoothed, Weighted, Jurik, and Kaufman Adaptive.
Fast Length / Slow Length – periods for the moving averages.
Distance Threshold (DvLimit) – minimum absolute distance between the fast and slow averages that is required to detect a trend. Convert original MT5 point-based values into price units (e.g., 70 points on a 5-digit symbol ≈ 0.00070).
Signal Bar – number of closed bars back used to confirm a fresh signal. A value of 1 reproduces the default behaviour of the MQL strategy.
Allow Long Entries / Allow Short Entries – enable or disable entries for each direction.
Close Long / Close Short on Opposite Signal – immediately close open positions when a signal of the opposite color appears.
Use Time Exit / Max Position Age – enable and configure the maximum holding time before a position is forcefully closed.
Order Volume – fixed volume sent with market orders. This parameter replaces the money-management settings of the MetaTrader version.
Stop Loss Distance / Take Profit Distance – optional protective price offsets measured in absolute price units (set to zero to disable).
Implementation Notes
StockSharp indicators are used to reproduce TrendManager behaviour. Unsupported exotic smoothing modes from the original library fall back to the closest available StockSharp moving average.
Signal processing keeps a small history buffer so the SignalBar check can detect transitions just like the MT5 advisor.
Protective exits are evaluated on completed candles. Intrabar fills from the original environment are approximated by comparing candle highs and lows to the configured distances.
MT5-specific parameters such as Deviation and margin-based position sizing have been replaced with StockSharp-friendly counterparts.
Usage Recommendations
Choose a candle type that matches the intended trading horizon. H4 is kept as the default for parity with the source code.
Calibrate the threshold to the instrument’s volatility. Instruments with larger ticks or volatility require higher values.
Combine the time exit with stop-loss and take-profit distances to emulate the original advisor’s risk controls.
For assets that trade in both directions, keep both entry toggles enabled so the strategy can reverse positions when the trend changes.
Differences from the Original Expert Advisor
Order sizing uses a fixed OrderVolume instead of the MT5 money-management module.
Stop-loss and take-profit orders are simulated using candle data rather than immediate MT5 order placement.
The strategy uses StockSharp’s native moving averages. Some smoothing options (e.g., Jurik, Kaufman adaptive) are mapped directly, while unsupported MT5 variants revert to the closest match.
Time-based exits rely on MaxPositionAge with TimeSpan precision instead of raw minute counters.
This document provides the essential information required to configure, run, and extend the TrendManager TM Plus strategy inside the StockSharp ecosystem.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// TrendManager TM Plus strategy. Uses fast/slow EMA crossover with distance threshold.
/// </summary>
public class TrendManagerTmPlusStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private decimal? _prevFast;
private decimal? _prevSlow;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
public TrendManagerTmPlusStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
_fastLength = Param(nameof(FastLength), 10).SetGreaterThanZero().SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowLength = Param(nameof(SlowLength), 30).SetGreaterThanZero().SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = null;
_prevSlow = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = null; _prevSlow = null;
var fast = new ExponentialMovingAverage { Length = FastLength };
var slow = new ExponentialMovingAverage { Length = SlowLength };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!IsFormedAndOnlineAndAllowTrading()) { _prevFast = fast; _prevSlow = slow; return; }
if (_prevFast == null || _prevSlow == null) { _prevFast = fast; _prevSlow = slow; return; }
var prevAbove = _prevFast.Value > _prevSlow.Value;
var currAbove = fast > slow;
_prevFast = fast; _prevSlow = slow;
if (!prevAbove && currAbove && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
else if (prevAbove && !currAbove && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class trend_manager_tm_plus_strategy(Strategy):
def __init__(self):
super(trend_manager_tm_plus_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_length = self.Param("FastLength", 10) \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_length = self.Param("SlowLength", 30) \
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastLength(self):
return self._fast_length.Value
@property
def SlowLength(self):
return self._slow_length.Value
def OnReseted(self):
super(trend_manager_tm_plus_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(trend_manager_tm_plus_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast = ExponentialMovingAverage()
fast.Length = self.FastLength
slow = ExponentialMovingAverage()
slow.Length = self.SlowLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, slow, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if self._prev_fast is None or self._prev_slow is None:
self._prev_fast = fv
self._prev_slow = sv
return
prev_above = self._prev_fast > self._prev_slow
curr_above = fv > sv
self._prev_fast = fv
self._prev_slow = sv
if not prev_above and curr_above and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif prev_above and not curr_above and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return trend_manager_tm_plus_strategy()