Bruno Trend Strategy ist eine StockSharp-Portierung des MetaTrader-Expertenberaters „Bruno_v1“. Die Strategie handelt auf 30-Minuten-Kerzen und konzentriert sich auf synchronisierte bullische Signale mehrerer klassischer Trendfolge- und Momentumindikatoren. Es werden nur Long-Positionen eröffnet, was den ursprünglichen Experten nachahmt, der sich auf bullische Ausbrüche konzentrierte, die durch die Ausrichtung der Indikatoren bestätigt wurden.
Handelslogik
Zeitrahmen: 30-Minuten-Kerzen.
Indikatoren:
Einfacher gleitender Durchschnitt (SMA) mit der Länge 4, der als kurzfristiger Impulsmesser verwendet wird.
Exponentielle gleitende Durchschnitte (EMAs) mit den Längen 8 und 21 zur Definition der primären Trendrichtung.
Durchschnittlicher Richtungsindex (ADX) mit Periode 13, um Richtungsstärke über +DI- und -DI-Komponenten sicherzustellen.
Stochastic Oszillator mit den Parametern %K=21, %D=3, Slowing=3, um die Dynamik zu bestätigen und gleichzeitig überkaufte Niveaus zu vermeiden.
MACD (13, 34, 8) für Histogramm und Signallinienbestätigung.
Parabolic SAR (Schritt 0,055, maximal 0,21), um die Aufwärtsbeschleunigung zu überprüfen und Ausgänge zu verwalten.
Teilnahmebedingungen:
EMA(8) muss über EMA(21) liegen.
ADX-Filter: +DI größer als -DI und über 20.
Stochastic-Filter: %K über %D, aber immer noch unter 80, um überkaufte Extreme zu vermeiden.
MACD Histogramm über Null und über der Signallinie.
Parabolic SAR steigt (aktuell SAR höher als der vorherige Messwert).
Die aktuelle Position muss flach oder kurz sein. Jede Short-Position wird geschlossen, bevor der neue Long-Trade eingegangen wird.
Ausgangsregeln:
Schließen Sie die Long-Position, wenn der vorherige Kerzenschluss unter den vorherigen Parabolic SAR-Wert fällt, wodurch der MetaTrader-Exit-Trigger reproduziert wird.
Risikomanagement
Standardlosgröße: 0,1 Lose.
Optionaler Schutz im MetaTrader-Stil: 50 Pip Take-Profit und 30 Pip Stop-Loss, konfiguriert mit StartProtection. Nachgestellte Stopps sind standardmäßig deaktiviert, um das ursprüngliche Skript widerzuspiegeln.
Notizen
Die Strategie ignoriert die ungenutzte Short-Einrichtung aus dem MetaTrader-Code und entspricht dem ursprünglichen Verhalten, bei dem Short-Trades effektiv deaktiviert waren.
Indikatorwerte werden über die übergeordnete Ebene API von StockSharp verarbeitet, um eine manuelle Pufferung zu vermeiden und mit den Projektrichtlinien in Einklang zu bleiben.
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;
}
}