The Multi Currency Template Strategy is a conversion of the MetaTrader 4 expert advisor Multi Currency Template v4. It reproduces the original EMA crossover entry logic together with martingale style averaging, pip based protective levels and trailing management using the StockSharp high-level API. The default time frame is five-minute candles, but it can be changed through a parameter.
Trade Logic
Two exponential moving averages (EMA 20 and EMA 50) are calculated on every finished candle of the selected time frame.
A long signal appears when the fast EMA (20) closes above the slow EMA (50). A short signal appears when the fast EMA closes below the slow EMA.
The Order Method parameter decides whether the strategy acts on both signals or restricts trading to long-only or short-only operation.
Only one net position per direction is maintained. When a new signal arrives, the strategy closes any opposite position before opening the requested side.
Position Management
Stop Loss / Take Profit – distances are entered in MetaTrader pips. They are converted to price units using the security price step, reproducing the original handling of 4- and 5-digit Forex symbols.
Trailing Stop – activates once price moves in favor of the position by Trailing Stop (pts) and is tightened after every additional improvement of Trailing Step (pts).
Martingale Averaging – when enabled, additional market orders are sent every Step (pts) against the current position. Each new order volume is scaled by Lot Multiplier and the process repeats until the position is closed.
Average Take Profit – when two or more averaging orders are open, the take profit target can optionally use the weighted position price plus Average TP Offset (pts) to emulate the MetaTrader “TP average” behaviour.
Parameters
Name
Description
Default
Order Method
Trade direction (Buy & Sell, Buy only, Sell only).
Buy & Sell
Volume (lots)
Base market order size.
0.01
Stop Loss (pips)
Protective stop distance in MetaTrader pips.
50
Take Profit (pips)
Profit target distance in MetaTrader pips.
100
Trailing Stop (pts)
Activation threshold for the trailing stop in MetaTrader points.
15
Trailing Step (pts)
Minimal improvement needed before the trailing stop is moved.
5
Enable Martingale
Enables averaging down/up with increasing volume.
true
Lot Multiplier
Volume multiplier applied to every new averaging order.
1.2
Step (pts)
MetaTrader point distance before placing the next averaging order.
150
Average Take Profit
Switch between fixed or averaged take profit when multiple orders exist.
true
Average TP Offset (pts)
MetaTrader point offset applied to the averaged take profit.
20
Candle Type
Candle type (time frame) used for indicator calculations.
5-minute candles
Differences from the Original Expert Advisor
StockSharp executes net positions instead of managing individual MetaTrader tickets. The martingale module increases the net position size rather than attaching separate ticket-specific targets.
Multi-symbol trading has to be achieved by launching several strategy instances, one per security. The original expert advisor supported a built-in multi-currency list inside one EA instance.
Money management checks (CheckMoneyForTrade, CheckVolumeValue) and broker specific restrictions are replaced by StockSharp order validation.
Usage Notes
Ensure that the security metadata (price step and decimals) match the instrument so pip conversion remains accurate.
Trailing stop and martingale logic act on candle close prices by default. For more reactive behaviour hook additional data sources (quotes or trades) and call the management helpers from there.
Because market orders are used, slippage control is delegated to the connected broker or simulator.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Multi Currency Template strategy: EMA crossover with trend confirmation.
/// Buys when fast EMA crosses above slow EMA, sells on the opposite cross.
/// </summary>
public class MultiCurrencyTemplateStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public MultiCurrencyTemplateStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow EMA period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0m;
_prevSlow = 0m;
_hasPrev = false;
}
/// <inheritdoc />
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)
{
if (_prevFast <= _prevSlow && fast > slow && Position <= 0) BuyMarket();
else if (_prevFast >= _prevSlow && fast < slow && Position >= 0) SellMarket();
}
_prevFast = fast;
_prevSlow = slow;
_hasPrev = true;
}
}
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 multi_currency_template_strategy(Strategy):
"""
Multi Currency Template: fast/slow EMA crossover.
"""
def __init__(self):
super(multi_currency_template_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 20).SetDisplay("Fast", "Fast EMA", "Indicators")
self._slow_period = self.Param("SlowPeriod", 50).SetDisplay("Slow", "Slow EMA", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Candles", "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(multi_currency_template_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(multi_currency_template_strategy, self).OnStarted2(time)
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()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def _process_candle(self, candle, fast_val, slow_val):
if candle.State != CandleStates.Finished:
return
fast = float(fast_val)
slow = float(slow_val)
if not self._has_prev:
self._prev_fast = fast
self._prev_slow = slow
self._has_prev = True
return
if self._prev_fast <= self._prev_slow and fast > slow and self.Position <= 0:
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and fast < slow and self.Position >= 0:
self.SellMarket()
self._prev_fast = fast
self._prev_slow = slow
def CreateClone(self):
return multi_currency_template_strategy()