The X MAN strategy recreates the core logic of the MetaTrader expert advisor X_MAN.mq4 within the StockSharp high-level API. The system trades breakouts driven by a fast and slow linear weighted moving average (LWMA) while filtering entries with multi-timeframe momentum and a monthly MACD confirmation. It is designed for trend continuation trades that are triggered only when momentum and trend structure align.
Trading Logic
Primary Trend Filter – Two LWMAs calculated on the selected primary timeframe must be separated by at least the configurable DistancePoints. A long setup requires the fast LWMA to be above the slow LWMA by that margin, while a short setup needs the slow LWMA to dominate.
Momentum Confirmation – The strategy subscribes to a higher timeframe candle series and feeds it into a momentum indicator. The absolute distance of the last three momentum readings from the neutral value (100) must exceed the corresponding buy or sell threshold at least once to allow trading in that direction.
MACD Filter – A monthly candle series drives a standard (12, 26, 9) MACD. Long trades are allowed only when the MACD line is above the signal line, and short trades require the opposite relationship.
Order Execution – When all filters agree, the strategy enters using market orders. Positions are flipped only if the opposite setup appears and the current position is flat or in the opposite direction.
Parameters
Parameter
Description
CandleType
Primary timeframe used for the LWMA calculations.
HigherCandleType
Higher timeframe feeding the momentum filter.
MacdCandleType
Timeframe for the MACD confirmation (monthly by default).
FastMaPeriod
Length of the fast LWMA.
SlowMaPeriod
Length of the slow LWMA.
MomentumPeriod
Lookback window of the momentum oscillator.
MomentumBuyThreshold
Minimum distance from 100 required for bullish momentum.
MomentumSellThreshold
Minimum distance from 100 required for bearish momentum.
DistancePoints
Minimal separation between the fast and slow LWMA expressed in price points.
TakeProfitPoints
Optional protective take profit distance in points.
StopLossPoints
Optional protective stop loss distance in points.
All parameters are exposed through StrategyParam<T> so they can be optimized inside StockSharp Designer or configured at run time.
Risk Management
If either TakeProfitPoints or StopLossPoints is greater than zero, the strategy enables StockSharp's built-in protection module using market exits. No additional trailing or breakeven logic from the original MQL expert is implemented yet.
Differences from the Original Expert
The MetaTrader implementation handled equity stops, break-even moves, and complex money-management options. This conversion focuses on the core directional filters and market entries; portfolio-level money management is intentionally omitted.
Order sizing is delegated to the hosting environment. The original lot-exponent logic is not reproduced.
Alerts, e-mail notifications, and manual trailing-stop modifications are not included.
These changes keep the strategy concise and leverage StockSharp's high-level API while preserving the main trading concept.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// X-MAN strategy: Stochastic + SMA trend filter.
/// </summary>
public class XManStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _smaPeriod;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int SmaPeriod { get => _smaPeriod.Value; set => _smaPeriod.Value = value; }
public XManStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_smaPeriod = Param(nameof(SmaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("SMA Period", "SMA period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var sma = new SimpleMovingAverage { Length = SmaPeriod };
var rsi = new RelativeStrengthIndex { Length = 14 };
decimal? prevClose = null;
decimal? prevSma = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma, rsi, (candle, smaVal, rsiVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
if (prevClose.HasValue && prevSma.HasValue)
{
var crossUp = prevClose.Value <= prevSma.Value && close > smaVal;
var crossDown = prevClose.Value >= prevSma.Value && close < smaVal;
if (crossUp && rsiVal < 70 && Position <= 0)
BuyMarket();
else if (crossDown && rsiVal > 30 && Position >= 0)
SellMarket();
}
prevClose = close;
prevSma = smaVal;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
}
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 SimpleMovingAverage, RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class x_man_strategy(Strategy):
def __init__(self):
super(x_man_strategy, self).__init__()
self._sma_period = self.Param("SmaPeriod", 20) \
.SetDisplay("SMA Period", "SMA period", "Indicators")
self._sma = None
self._rsi = None
self._prev_close = None
self._prev_sma = None
@property
def sma_period(self):
return self._sma_period.Value
def OnReseted(self):
super(x_man_strategy, self).OnReseted()
self._sma = None
self._rsi = None
self._prev_close = None
self._prev_sma = None
def OnStarted2(self, time):
super(x_man_strategy, self).OnStarted2(time)
self._sma = SimpleMovingAverage()
self._sma.Length = self.sma_period
self._rsi = RelativeStrengthIndex()
self._rsi.Length = 14
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(30)))
subscription.Bind(self._sma, self._rsi, self._process_candle)
subscription.Start()
def _process_candle(self, candle, sma_value, rsi_value):
if candle.State != CandleStates.Finished:
return
if not self._sma.IsFormed or not self._rsi.IsFormed:
return
close = float(candle.ClosePrice)
sma_val = float(sma_value)
rsi_val = float(rsi_value)
if self._prev_close is not None and self._prev_sma is not None:
cross_up = self._prev_close <= self._prev_sma and close > sma_val
cross_down = self._prev_close >= self._prev_sma and close < sma_val
if cross_up and rsi_val < 70.0 and self.Position <= 0:
self.BuyMarket()
elif cross_down and rsi_val > 30.0 and self.Position >= 0:
self.SellMarket()
self._prev_close = close
self._prev_sma = sma_val
def CreateClone(self):
return x_man_strategy()