A port of the historical "Gordago EA" MetaTrader 5 expert advisor. The strategy trades the base timeframe (default M3) while reading MACD signals from a higher intraday chart and a stochastic filter from an hourly chart. It preserves the original stop/take parameters and trailing logic, but uses the StockSharp high-level API for data subscriptions and order management.
Strategy Logic
Market data
Main execution candles: configurable, default three-minute candles.
MACD (fast 12, slow 26, signal 9) computed on the MACD timeframe.
Stochastic oscillator (length 5, %K smoothing 3, %D 3) computed on the stochastic timeframe.
Entry conditions
Buy: current MACD value above the previous one, previous MACD below zero, stochastic %K below the buy threshold (default 37) and rising compared to the prior value.
Sell: current MACD value below the previous one, previous MACD above zero, stochastic %K above the sell threshold (default 96) and falling compared to the prior value.
Order placement
Order volume is fixed; switching direction automatically offsets any opposite position before opening a new one.
Separate stop-loss/take-profit distances exist for long and short trades (defaults: 40/70 pips for long, 10/40 pips for short).
Exits
Protective stop-loss and take-profit levels are checked on every finished base candle.
A trailing stop activates when price advances beyond the configured trailing distance plus trailing step; once triggered it keeps ratcheting toward the market by the trailing distance.
Trailing can introduce a protective stop even when the original stop was disabled, mirroring the source EA.
Parameters
OrderVolume – trade volume in lots.
StopLossBuyPips / TakeProfitBuyPips – long-side stop-loss and take-profit distances (in pips).
StopLossSellPips / TakeProfitSellPips – short-side stop-loss and take-profit distances (in pips).
TrailingStopPips – trailing distance in pips; set to zero to disable trailing.
TrailingStepPips – minimum additional profit (in pips) before the trailing stop can advance.
StochasticBuyLevel / StochasticSellLevel – oscillator thresholds for long and short entries.
CandleType – working timeframe for execution logic.
MacdCandleType – timeframe used to feed the MACD indicator.
StochasticCandleType – timeframe used to feed the stochastic oscillator.
Pip distances are converted to prices using the security's PriceStep. If the step has three or five fractional digits the strategy multiplies it by ten, reproducing the pip adjustment used in the original MQL implementation for 3/5-digit forex quotes.
Trailing stop is ignored when TrailingStopPips is positive but TrailingStepPips is not; a warning is logged in that case.
Because the StockSharp version works on candle close events, protective logic executes once per finished candle instead of on every tick as in the MT5 version. The trade management behaviour otherwise follows the original rules.
Only the C# implementation is provided; no Python translation or folder is included by request.
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>
/// Gordago EA strategy. Uses EMA crossover with RSI filter.
/// </summary>
public class GordagoEaStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal? _prevFast;
private decimal? _prevSlow;
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 GordagoEaStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 12)
.SetGreaterThanZero()
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 26)
.SetGreaterThanZero()
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(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 = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
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 fastVal, decimal slowVal)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevFast = fastVal;
_prevSlow = slowVal;
return;
}
if (_prevFast == null || _prevSlow == null)
{
_prevFast = fastVal;
_prevSlow = slowVal;
return;
}
var prevAbove = _prevFast.Value > _prevSlow.Value;
var currAbove = fastVal > slowVal;
_prevFast = fastVal;
_prevSlow = slowVal;
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 gordago_ea_strategy(Strategy):
def __init__(self):
super(gordago_ea_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 12) \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 26) \
.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 FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
def OnReseted(self):
super(gordago_ea_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(gordago_ea_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast = ExponentialMovingAverage()
fast.Length = self.FastPeriod
slow = ExponentialMovingAverage()
slow.Length = self.SlowPeriod
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 gordago_ea_strategy()