Bruno Trend Strategy es una StockSharp versión del MetaTrader asesor experto "Bruno_v1". La estrategia opera con velas de 30 minutos y se centra en señales alcistas sincronizadas de varios indicadores clásicos de seguimiento de tendencias y de impulso. Sólo se abren posiciones largas, imitando al experto original que se concentraba en las rupturas alcistas confirmadas por la alineación de los indicadores.
Lógica de trading
Plazo: velas de 30 minutos.
Indicadores:
Media móvil simple (SMA) con longitud 4 utilizada como indicador de impulso a corto plazo.
Medias móviles exponenciales (EMA) con longitudes 8 y 21 para definir la dirección de la tendencia principal.
Índice direccional promedio (ADX) con período 13 para garantizar la fuerza direccional a través de los componentes +DI y -DI.
Stochastic Oscilador con parámetros %K=21, %D=3, desaceleración=3 para confirmar el impulso y evitar niveles de sobrecompra.
MACD (13, 34, 8) para confirmación de histograma y línea de señal.
Parabolic SAR (paso 0.055, máximo 0.21) para verificar la aceleración ascendente y gestionar las salidas.
Reglas de entrada:
EMA(8) debe estar por encima de EMA(21).
Filtro ADX: +DI mayor que -DI y superior a 20.
Filtro Stochastic: %K por encima de %D pero aún por debajo de 80 para mantenerse alejado de los extremos de sobrecompra.
MACD histograma por encima de cero y por encima de la línea de señal.
Parabolic SAR aumentando (el SAR actual más alto que la lectura anterior).
La posición actual debe ser plana o corta. Cualquier posición corta se cierra antes de ingresar a la nueva operación larga.
Reglas de salida:
Cierre la posición larga cuando el cierre de la vela anterior caiga por debajo del valor Parabolic SAR anterior, replicando el activador de salida MetaTrader.
Gestión del riesgo
Tamaño de lote predeterminado: 0,1 lotes.
Protección opcional estilo MetaTrader: toma de ganancias de 50 pips y stop-loss de 30 pips, configurada con StartProtection. Las paradas finales están deshabilitadas de forma predeterminada para reflejar el script original.
Notas
La estrategia ignora la configuración corta no utilizada del código MetaTrader, coincidiendo con el comportamiento original donde las operaciones cortas se desactivaron efectivamente.
Los valores del indicador se procesan a través del nivel alto API de StockSharp para evitar el almacenamiento en búfer manual y mantenerse alineados con las pautas del proyecto.
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;
}
}