The TenPips Strategy is a StockSharp port of the MetaTrader "10PIPS" expert advisor. It combines fast/slow linear weighted moving averages calculated on the trading timeframe with a multi-timeframe momentum confirmation and a macro (monthly) MACD filter. The conversion mirrors the original money-management module, including break-even protection, pip-based trailing, and equity/absolute profit targets.
Signal Logic
Primary timeframe (parameter CandleType, default 15 minutes) supplies the price stream used for the fast and slow LWMAs computed on the typical price (H + L + C) / 3.
Higher timeframe momentum (MomentumCandleType, default 1 hour) converts the StockSharp momentum difference into the MetaTrader ratio. The absolute distance from 100 over the last three completed bars must exceed MomentumThreshold for a trade to arm.
Macro MACD filter (MacdCandleType, default 30-day candles approximating MetaTrader's monthly period) requires the MACD main line to be above the signal line for buys and below for sells.
A long position opens when the previous candle:
closed above the fast LWMA after dipping below it,
the fast LWMA is above the slow LWMA,
any of the last three momentum readings meets the MomentumThreshold,
the macro MACD is bullish.
A short position uses the symmetric conditions (previous close below the fast LWMA, fast below slow, momentum above the threshold, MACD bearish).
Because StockSharp operates with a net position model, the port opens at most one aggregate position per side. Sending a buy while short automatically closes the short portion and leaves the requested long volume.
Risk and Money Management
Protective distances – StopLossPips and TakeProfitPips translate MetaTrader pips into price offsets using the security PriceStep. When either boundary is hit, the strategy closes the entire position with a market order.
Trailing stop – TrailingStopPips follows the highest (long) or lowest (short) price since entry.
Break-even – when enabled, BreakEvenTriggerPips arms the stop and shifts it to the entry plus the optional BreakEvenOffsetPips.
Money targets – the trio UseMoneyTakeProfit, UsePercentTakeProfit, and EnableMoneyTrailing replicate the EA's TP_In_Money, TP_In_Percent, and the balance-based trailing lock. Unrealized PnL is measured per candle close.
Equity stop – UseEquityStop with EquityRiskPercent implements the original UseEquityStop / TotalEquityRisk guard by closing positions once the drawdown from the equity peak exceeds the threshold.
MACD exit flag – UseMacdExit mirrors the EA's Exit switch, closing positions early when the macro MACD flips against the trade.
Parameters
Parameter
Default
Description
TradeVolume
0.01
Net position volume used for market orders (MetaTrader lot size equivalent).
CandleType
15m time frame
Primary timeframe for the fast/slow LWMAs and trade execution.
MomentumCandleType
1h time frame
Higher timeframe candles feeding the momentum confirmation.
MacdCandleType
30d time frame
Macro timeframe (monthly approximation) for MACD confirmation.
FastMaPeriod
8
Period of the fast linear weighted moving average.
SlowMaPeriod
50
Period of the slow linear weighted moving average.
MomentumPeriod
14
Lookback for the momentum ratio.
MomentumThreshold
0.3
Minimum absolute distance from 100 (MetaTrader momentum) required over the last three higher timeframe bars.
StopLossPips
20
Protective stop-loss in MetaTrader pips. Set to zero to disable.
TakeProfitPips
50
Protective take-profit in MetaTrader pips. Set to zero to disable.
TrailingStopPips
40
Trailing stop distance in pips (zero disables trailing).
UseBreakEven
true
Enables move-to-break-even behaviour.
BreakEvenTriggerPips
30
Profit (pips) required before break-even activates.
BreakEvenOffsetPips
30
Extra pips added to the break-even stop once activated.
UseMoneyTakeProfit
false
Close positions after reaching the absolute profit target MoneyTakeProfit.
MoneyTakeProfit
10
Profit target expressed in account currency.
UsePercentTakeProfit
false
Close positions after earning PercentTakeProfit percent of the initial equity.
PercentTakeProfit
10
Percentage target based on starting equity.
EnableMoneyTrailing
true
Enable balance-based trailing stop using MoneyTrailTarget / MoneyTrailStop.
MoneyTrailTarget
40
Profit (currency) required before the money trail is armed.
MoneyTrailStop
10
Allowed give-back after arming the money trail.
UseEquityStop
true
Enable equity drawdown protection.
EquityRiskPercent
1
Maximum drawdown from the equity peak before forcing a flat position.
UseMacdExit
false
Close positions on an opposite MACD signal from the macro timeframe.
Implementation Notes
Pip conversion follows the EA logic: if the broker tick size is 0.00001 or 0.001, a pip equals ten ticks; otherwise the raw PriceStep is used.
StockSharp's momentum indicator outputs a price difference. The strategy converts it to the MetaTrader ratio (Close / Close(period) * 100) before applying MomentumThreshold.
The port operates in a netting environment and therefore does not replicate the EA's multi-ticket martingale (IncreaseFactor, LotExponent, Max_Trades). Instead, it adjusts order volume automatically when flipping between long and short positions.
Protective exits and profit management submit market orders, matching the original advisor's behaviour when modifying open tickets.
Charts display the processed indicators (fast LWMA, slow LWMA, momentum, MACD) when visualization is available.
Usage
Configure the candle timeframes to match the MetaTrader chart and higher timeframe used by the EA.
Adjust the pip-based risk parameters to the instrument point size. Zero disables the corresponding component.
Enable or disable money/percent targets, equity stop, and MACD exit according to your risk preferences.
Launch the strategy; it will subscribe to the three required timeframes, manage positions according to the original rules, and log any protective exits triggered by the balance-based or equity protections.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class TenPipsMomentumStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _stopLossPoints;
private readonly StrategyParam<int> _takeProfitPoints;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public TenPipsMomentumStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
}
protected override void OnReseted()
{
base.OnReseted();
_fast = null; _slow = null;
_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fast = new ExponentialMovingAverage { Length = FastPeriod };
_slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
subscription.Bind(_fast, _slow, ProcessCandle);
subscription.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }
var close = candle.ClosePrice;
var step = Security?.PriceStep ?? 1m;
if (Position > 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
else if (Position < 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }
_prevFast = fastValue; _prevSlow = slowValue;
}
}
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 ten_pips_momentum_strategy(Strategy):
def __init__(self):
super(ten_pips_momentum_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 14) \
.SetDisplay("Fast Period", "Fast MA period", "Indicator")
self._slow_period = self.Param("SlowPeriod", 50) \
.SetDisplay("Slow Period", "Slow MA period", "Indicator")
self._stop_loss_points = self.Param("StopLossPoints", 200) \
.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk")
self._take_profit_points = self.Param("TakeProfitPoints", 400) \
.SetDisplay("Take Profit", "Take-profit in price steps", "Risk")
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def stop_loss_points(self):
return self._stop_loss_points.Value
@property
def take_profit_points(self):
return self._take_profit_points.Value
def OnReseted(self):
super(ten_pips_momentum_strategy, self).OnReseted()
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(ten_pips_momentum_strategy, self).OnStarted2(time)
self._fast = ExponentialMovingAverage()
self._fast.Length = self.fast_period
self._slow = ExponentialMovingAverage()
self._slow.Length = self.slow_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
subscription.Bind(self._fast, self._slow, self._process_candle)
subscription.Start()
def _process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_value)
slow_val = float(slow_value)
if not self._fast.IsFormed or not self._slow.IsFormed:
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast_val
self._prev_slow = slow_val
return
close = float(candle.ClosePrice)
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
if self.Position > 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close <= self._entry_price - self.stop_loss_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close >= self._entry_price + self.take_profit_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
elif self.Position < 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close >= self._entry_price + self.stop_loss_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close <= self._entry_price - self.take_profit_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._cooldown = 100
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._entry_price = close
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return ten_pips_momentum_strategy()