Bruno Trend Strategy is a StockSharp port of the MetaTrader expert advisor "Bruno_v1". The strategy trades on 30-minute candles and focuses on synchronized bullish signals from several classic trend-following and momentum indicators. Only long positions are opened, mimicking the original expert that concentrated on bullish breakouts confirmed by indicator alignment.
Trading Logic
Timeframe: 30-minute candles.
Indicators:
Simple Moving Average (SMA) with length 4 used as a short-term momentum gauge.
Exponential Moving Averages (EMAs) with lengths 8 and 21 to define the primary trend direction.
Average Directional Index (ADX) with period 13 to ensure directional strength via +DI and -DI components.
Stochastic Oscillator with parameters %K=21, %D=3, slowing=3 to confirm momentum while avoiding overbought levels.
MACD (13, 34, 8) for histogram and signal line confirmation.
Parabolic SAR (step 0.055, maximum 0.21) to verify upward acceleration and manage exits.
Entry Rules:
EMA(8) must be above EMA(21).
ADX filter: +DI greater than -DI and above 20.
Stochastic filter: %K above %D but still below 80 to stay out of overbought extremes.
MACD histogram above zero and above the signal line.
Parabolic SAR rising (current SAR higher than the previous reading).
Current position must be flat or short. Any short position is closed before entering the new long trade.
Exit Rules:
Close the long position when the previous candle close falls below the previous Parabolic SAR value, replicating the MetaTrader exit trigger.
Risk Management
Default lot size: 0.1 lots.
Optional MetaTrader-style protection: 50 pip take-profit and 30 pip stop-loss, configured with StartProtection. Trailing stops are disabled by default to mirror the original script.
Notes
The strategy ignores the unused short setup from the MetaTrader code, matching the original behavior where short trades were effectively disabled.
Indicator values are processed via StockSharp's high-level API to avoid manual buffering and stay aligned with the project guidelines.
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>
/// Bruno trend strategy - EMA trend following with RSI confirmation.
/// Buys when fast EMA is above slow EMA and RSI is rising.
/// Sells when fast EMA crosses below slow EMA.
/// </summary>
public class BrunoTrendStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _prevRsi;
private bool _hasPrev;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public BrunoTrendStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 8)
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 21)
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetDisplay("RSI Period", "RSI period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _prevRsi = 0m; _hasPrev = false; }
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, rsi, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow, decimal rsi)
{
if (candle.State != CandleStates.Finished)
return;
if (!_hasPrev)
{
_prevFast = fast;
_prevSlow = slow;
_prevRsi = rsi;
_hasPrev = true;
return;
}
var crossUp = _prevFast <= _prevSlow && fast > slow;
var crossDown = _prevFast >= _prevSlow && fast < slow;
// Buy on bullish crossover with rising RSI
if (crossUp && rsi > _prevRsi && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// Sell on bearish crossover
else if (crossDown && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevFast = fast;
_prevSlow = slow;
_prevRsi = rsi;
}
}