Diese Strategie handelt auf Basis des BrakeExp-Indikators, der einen exponentiellen Kanal um Kursbewegungen aufbaut. Der Indikator wechselt zwischen Long- und Short-Regimen und erzeugt Kauf- oder Verkaufssignale, wenn der Preis die dynamischen Kanalgrenzen kreuzt.
Funktionsweise
Der Indikator pflegt eine Exponentialkurve, die dem Preis folgt.
Wenn die Kurve unter dem Preis liegt (Aufwärtstrend), sucht die Strategie nach Kaufsignalen.
Wenn die Kurve über dem Preis liegt (Abwärtstrend), sucht die Strategie nach Verkaufssignalen.
Ein Wechsel von einer Seite zur anderen erzeugt ein Einstiegssignal in die neue Richtung und schließt die entgegengesetzte Position.
Parameter
Candle Type – Zeitrahmen der verarbeiteten Kerzen.
Volume – Ordervolumen für Markteintritte.
A, B – Parameter, die die Form der BrakeExp-Kurve definieren.
Buy Open / Sell Open – Erlaubnis zum Öffnen von Long- oder Short-Positionen.
Buy Close / Sell Close – Erlaubnis zum Schließen von Short- oder Long-Positionen.
Hinweise
Diese Implementierung konzentriert sich auf die Kernlogik des BrakeExp-Indikators und enthält kein Stop-Loss- oder Take-Profit-Management. Zusätzliche Risikokontrollen können bei Bedarf hinzugefügt werden.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Channel breakout strategy using EMA and price crossover.
/// </summary>
public class BrakeExpChannelStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaPeriod;
private decimal _prevClose;
private decimal _prevEma;
private bool _hasPrev;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public BrakeExpChannelStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle type", "General");
_emaPeriod = Param(nameof(EmaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "EMA period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevClose = 0;
_prevEma = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
SubscribeCandles(CandleType)
.Bind(ema, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal emaVal)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
if (!_hasPrev)
{
_prevClose = close;
_prevEma = emaVal;
_hasPrev = true;
return;
}
var crossUp = _prevClose <= _prevEma && close > emaVal;
var crossDown = _prevClose >= _prevEma && close < emaVal;
if (crossUp && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (crossDown && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevClose = close;
_prevEma = emaVal;
}
}
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 brake_exp_channel_strategy(Strategy):
def __init__(self):
super(brake_exp_channel_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle type", "General")
self._ema_period = self.Param("EmaPeriod", 20) \
.SetDisplay("EMA Period", "EMA period", "Indicators")
self._prev_close = 0.0
self._prev_ema = 0.0
self._has_prev = False
@property
def candle_type(self):
return self._candle_type.Value
@property
def ema_period(self):
return self._ema_period.Value
def OnReseted(self):
super(brake_exp_channel_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_ema = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(brake_exp_channel_strategy, self).OnStarted2(time)
ema = ExponentialMovingAverage()
ema.Length = self.ema_period
self.SubscribeCandles(self.candle_type).Bind(ema, self.process_candle).Start()
def process_candle(self, candle, ema_val):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
ev = float(ema_val)
if not self._has_prev:
self._prev_close = close
self._prev_ema = ev
self._has_prev = True
return
cross_up = self._prev_close <= self._prev_ema and close > ev
cross_down = self._prev_close >= self._prev_ema and close < ev
if cross_up and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif cross_down and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_close = close
self._prev_ema = ev
def CreateClone(self):
return brake_exp_channel_strategy()