The Fortrader 10 Pips Strategy is a StockSharp port of the MetaTrader 4 expert advisor 10pips.mq4 (strategy ID 8074). The robot simultaneously keeps one long and one short position open. Each leg uses fixed take-profit, stop-loss and trailing-stop distances measured in symbol points.
This conversion recreates the hedging behaviour within StockSharp's high-level API. Immediately after the strategy starts it sends a market buy and a market sell order. Whenever a protective order closes a leg the strategy instantly opens a new order in the same direction, keeping two opposing positions alive at all times.
Parameters
Name
Description
Take Profit Buy
Take-profit distance for the long leg, in points.
Stop Loss Buy
Stop-loss distance for the long leg, in points.
Trailing Stop Buy
Trailing-stop distance for the long leg, in points. Set to zero to disable trailing.
Take Profit Sell
Take-profit distance for the short leg, in points.
Stop Loss Sell
Stop-loss distance for the short leg, in points.
Trailing Stop Sell
Trailing-stop distance for the short leg, in points. Set to zero to disable trailing.
Volume
Volume of every market order in lots.
All distances are multiplied by the instrument's PriceStep to convert from points to absolute price values. Each parameter is exposed through StrategyParam<T> so the strategy can be tuned or optimised via the GUI.
Trading Logic
Startup – OnStarted subscribes to Level 1 data to track the current best bid and ask prices. The strategy immediately sends one market buy and one market sell order.
Protective orders – After each entry fill (OnNewMyTrade) the strategy creates the associated stop-loss and take-profit orders if the distances are greater than zero. Orders are rounded to the nearest price step.
Re-entry – When a stop-loss or take-profit order executes, the closed leg is reopened instantly with a new market order so the two-directional exposure persists.
Trailing stops – Level 1 updates trigger UpdateTrailingStops, which adjusts the stop-loss orders whenever the current bid/ask has moved beyond the configured trailing distance from the entry price. The logic mirrors the original EA: trailing starts once the profit exceeds the trailing distance, and stops are moved only in the direction of profit.
Implementation Notes
The original MT4 code waited 10 seconds between the initial buy and sell orders. StockSharp does not require this delay, therefore both orders are sent right away.
Because StockSharp uses net positions by default, true hedging may depend on the broker/connector supporting opposing positions. The strategy keeps track of each leg independently and re-establishes them after every exit.
StartProtection() is called once during OnStarted so that global risk protections are active if configured in the framework settings.
Usage Tips
Ensure the selected connector supports simultaneous long and short positions if the hedging behaviour is required.
Set trailing distances to zero to disable trailing for the corresponding leg.
Optimise the risk parameters (Take Profit, Stop Loss, Trailing Stop) on historical data to fit the traded symbol and timeframe.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class Fortrader10PipsStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast; private decimal _prevSlow; private bool _hasPrev;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public Fortrader10PipsStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 7).SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 21).SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev) { _prevFast = fast; _prevSlow = slow; _hasPrev = true; return; }
if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
{ if (Position < 0) BuyMarket(); BuyMarket(); }
else if (_prevFast >= _prevSlow && fast < slow && Position >= 0)
{ if (Position > 0) SellMarket(); SellMarket(); }
_prevFast = fast; _prevSlow = slow;
}
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_hasPrev = false;
}
}
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 fortrader_10_pips_strategy(Strategy):
"""
Fortrader 10 Pips: Simple EMA crossover (fast 7, slow 21).
Buys when fast crosses above slow, sells on reverse.
"""
def __init__(self):
super(fortrader_10_pips_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 7) \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 21) \
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(fortrader_10_pips_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(fortrader_10_pips_strategy, self).OnStarted2(time)
self._has_prev = False
fast = ExponentialMovingAverage()
fast.Length = self._fast_period.Value
slow = ExponentialMovingAverage()
slow.Length = self._slow_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast, slow, self._process_candle).Start()
def _process_candle(self, candle, fast_val, slow_val):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_val)
slow_val = float(slow_val)
if not self._has_prev:
self._prev_fast = fast_val
self._prev_slow = slow_val
self._has_prev = True
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()
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._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return fortrader_10_pips_strategy()