MACD-Ausbruch
Die MACD-Ausbruch-Strategie beobachtet den MACD auf plötzliche Expansionen. Wenn die Werte über ihren normalen Bereich hinausspringen, beginnt der Preis oft eine neue Bewegung.
Tests zeigen eine durchschnittliche jährliche Rendite von etwa 94%. Die Strategie funktioniert am besten am Aktienmarkt.
Eine Position wird eröffnet, sobald der Indikator ein Band durchbricht, das aus aktuellen Daten und einem Abweichungsmultiplikator abgeleitet wird. Long- und Short-Trades sind mit einem Stop möglich.
Dieses System eignet sich für Momentum-Trader, die frühe Ausbrüche suchen. Trades schließen, wenn der MACD zur Mitte zurückkehrt. Standardwerte beginnen mit FastEmaPeriod = 12.
Details
- Einstiegskriterien: Indikator überschreitet den Durchschnitt um den Abweichungsmultiplikator.
- Long/Short: Beide Richtungen.
- Ausstiegskriterien: Indikator kehrt zum Durchschnitt zurück.
- Stops: Ja.
- Standardwerte:
FastEmaPeriod= 12SlowEmaPeriod= 26SignalPeriod= 9SmaPeriod= 20DeviationMultiplier= 2.0mStopLossPercent= 2.0mCandleType= TimeSpan.FromMinutes(5)
- Filter:
- Kategorie: Ausbruch
- Richtung: Beide
- Indikatoren: MACD
- Stops: Ja
- Komplexität: Mittel
- Zeitrahmen: Kurzfristig
- Saisonalität: Nein
- Neuronale Netze: Nein
- Divergenz: Nein
- Risikolevel: Mittel
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// MACD Breakout Strategy that enters positions when MACD Histogram breaks out of its normal range.
/// </summary>
public class MacdBreakoutStrategy : Strategy
{
private readonly StrategyParam<int> _fastEmaPeriod;
private readonly StrategyParam<int> _slowEmaPeriod;
private readonly StrategyParam<int> _signalPeriod;
private readonly StrategyParam<int> _smaPeriod;
private readonly StrategyParam<decimal> _deviationMultiplier;
private readonly StrategyParam<decimal> _stopLossPercent;
private readonly StrategyParam<DataType> _candleType;
private MovingAverageConvergenceDivergenceSignal _macd;
private SimpleMovingAverage _macdHistSma;
private StandardDeviation _macdHistStdDev;
private decimal _prevMacdHistValue;
private decimal _prevMacdHistSmaValue;
/// <summary>
/// MACD Fast EMA period.
/// </summary>
public int FastEmaPeriod
{
get => _fastEmaPeriod.Value;
set => _fastEmaPeriod.Value = value;
}
/// <summary>
/// MACD Slow EMA period.
/// </summary>
public int SlowEmaPeriod
{
get => _slowEmaPeriod.Value;
set => _slowEmaPeriod.Value = value;
}
/// <summary>
/// MACD Signal line period.
/// </summary>
public int SignalPeriod
{
get => _signalPeriod.Value;
set => _signalPeriod.Value = value;
}
/// <summary>
/// Period for MACD Histogram moving average.
/// </summary>
public int SmaPeriod
{
get => _smaPeriod.Value;
set => _smaPeriod.Value = value;
}
/// <summary>
/// Standard deviation multiplier for breakout threshold.
/// </summary>
public decimal DeviationMultiplier
{
get => _deviationMultiplier.Value;
set => _deviationMultiplier.Value = value;
}
/// <summary>
/// Stop-loss percentage.
/// </summary>
public decimal StopLossPercent
{
get => _stopLossPercent.Value;
set => _stopLossPercent.Value = value;
}
/// <summary>
/// Type of candles to use.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public MacdBreakoutStrategy()
{
_fastEmaPeriod = Param(nameof(FastEmaPeriod), 12)
.SetGreaterThanZero()
.SetDisplay("Fast EMA Period", "Period for MACD fast EMA", "MACD Settings")
.SetOptimize(8, 20, 4);
_slowEmaPeriod = Param(nameof(SlowEmaPeriod), 26)
.SetGreaterThanZero()
.SetDisplay("Slow EMA Period", "Period for MACD slow EMA", "MACD Settings")
.SetOptimize(20, 40, 4);
_signalPeriod = Param(nameof(SignalPeriod), 9)
.SetGreaterThanZero()
.SetDisplay("Signal Period", "Period for MACD signal line", "MACD Settings")
.SetOptimize(5, 15, 2);
_smaPeriod = Param(nameof(SmaPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("SMA Period", "Period for MACD Histogram moving average", "Indicator Settings")
.SetOptimize(10, 30, 5);
_deviationMultiplier = Param(nameof(DeviationMultiplier), 2.0m)
.SetGreaterThanZero()
.SetDisplay("Deviation Multiplier", "Standard deviation multiplier for breakout threshold", "Breakout Settings")
.SetOptimize(1.0m, 3.0m, 0.5m);
_stopLossPercent = Param(nameof(StopLossPercent), 2.0m)
.SetGreaterThanZero()
.SetDisplay("Stop Loss %", "Stop loss percentage from entry price", "Risk Management")
.SetOptimize(1.0m, 4.0m, 0.5m);
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevMacdHistSmaValue = default;
_prevMacdHistValue = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
// Initialize indicators
_macd = new MovingAverageConvergenceDivergenceSignal
{
Macd =
{
ShortMa = { Length = FastEmaPeriod },
LongMa = { Length = SlowEmaPeriod },
},
SignalMa = { Length = SignalPeriod }
};
_macdHistSma = new SMA { Length = SmaPeriod };
_macdHistStdDev = new StandardDeviation { Length = SmaPeriod };
// Create subscription and bind indicators
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(_macd, ProcessCandle)
.Start();
// Enable position protection
StartProtection(
new Unit(StopLossPercent, UnitTypes.Percent),
new Unit(StopLossPercent * 1.5m, UnitTypes.Percent));
// Setup chart visualization
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, _macd);
DrawOwnTrades(area);
}
base.OnStarted2(time);
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue)
{
// Skip unfinished candles
if (candle.State != CandleStates.Finished)
return;
// Check if strategy is ready for trading
if (!IsFormedAndOnlineAndAllowTrading())
return;
var macdTyped = (MovingAverageConvergenceDivergenceSignalValue)macdValue;
// Extract the histogram value (MACD Line - Signal Line)
if (macdTyped.Macd is not decimal macd || macdTyped.Signal is not decimal signal)
{
return;
}
// Process indicators for MACD histogram
var macdHistSmaValue = _macdHistSma.Process(new DecimalIndicatorValue(_macdHistSma, macd, candle.ServerTime)).ToDecimal();
var macdHistStdDevValue = _macdHistStdDev.Process(new DecimalIndicatorValue(_macdHistStdDev, macd, candle.ServerTime)).ToDecimal();
// Store previous values on first call
if (_prevMacdHistValue == 0 && _prevMacdHistSmaValue == 0)
{
_prevMacdHistValue = macd;
_prevMacdHistSmaValue = macdHistSmaValue;
return;
}
// Calculate breakout thresholds
var upperThreshold = macdHistSmaValue + DeviationMultiplier * macdHistStdDevValue;
var lowerThreshold = macdHistSmaValue - DeviationMultiplier * macdHistStdDevValue;
// Trading logic
if (macd > upperThreshold && Position <= 0)
{
// MACD Histogram broke above upper threshold - buy signal (long)
BuyMarket(Volume);
LogInfo($"Buy signal: MACD Hist({macd}) > Upper Threshold({upperThreshold})");
}
else if (macd < lowerThreshold && Position >= 0)
{
// MACD Histogram broke below lower threshold - sell signal (short)
SellMarket(Volume + Math.Abs(Position));
LogInfo($"Sell signal: MACD Hist({macd}) < Lower Threshold({lowerThreshold})");
}
// Exit conditions
else if (Position > 0 && macd < macdHistSmaValue)
{
// Exit long position when MACD Histogram returns below its mean
SellMarket(Math.Abs(Position));
LogInfo($"Exit long: MACD Hist({macd}) < SMA({macdHistSmaValue})");
}
else if (Position < 0 && macd > macdHistSmaValue)
{
// Exit short position when MACD Histogram returns above its mean
BuyMarket(Math.Abs(Position));
LogInfo($"Exit short: MACD Hist({macd}) > SMA({macdHistSmaValue})");
}
// Update previous values
_prevMacdHistValue = macd;
_prevMacdHistSmaValue = macdHistSmaValue;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Indicators import MovingAverageConvergenceDivergenceSignal, SimpleMovingAverage, StandardDeviation
from StockSharp.Algo.Strategies import Strategy
from indicator_extensions import *
class macd_breakout_strategy(Strategy):
"""
MACD Breakout: enters when MACD histogram breaks out of its normal range.
"""
def __init__(self):
super(macd_breakout_strategy, self).__init__()
self._fast_ema = self.Param("FastEmaPeriod", 12).SetDisplay("Fast EMA", "Fast EMA period", "MACD")
self._slow_ema = self.Param("SlowEmaPeriod", 26).SetDisplay("Slow EMA", "Slow EMA period", "MACD")
self._signal_period = self.Param("SignalPeriod", 9).SetDisplay("Signal Period", "Signal line period", "MACD")
self._sma_period = self.Param("SmaPeriod", 20).SetDisplay("SMA Period", "Histogram SMA period", "Indicators")
self._dev_mult = self.Param("DeviationMultiplier", 2.0).SetDisplay("Dev Mult", "Stddev multiplier", "Breakout")
self._sl_pct = self.Param("StopLossPercent", 2.0).SetDisplay("SL %", "Stop loss percent", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Timeframe", "General")
self._macd_hist_sma = None
self._macd_hist_stddev = None
self._prev_macd_hist_value = 0.0
self._prev_macd_hist_sma_value = 0.0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(macd_breakout_strategy, self).OnReseted()
self._prev_macd_hist_value = 0.0
self._prev_macd_hist_sma_value = 0.0
def OnStarted2(self, time):
super(macd_breakout_strategy, self).OnStarted2(time)
macd = MovingAverageConvergenceDivergenceSignal()
macd.Macd.ShortMa.Length = self._fast_ema.Value
macd.Macd.LongMa.Length = self._slow_ema.Value
macd.SignalMa.Length = self._signal_period.Value
self._macd_hist_sma = SimpleMovingAverage()
self._macd_hist_sma.Length = self._sma_period.Value
self._macd_hist_stddev = StandardDeviation()
self._macd_hist_stddev.Length = self._sma_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(macd, self._process_candle).Start()
sl = self._sl_pct.Value
self.StartProtection(Unit(sl, UnitTypes.Percent), Unit(sl * 1.5, UnitTypes.Percent))
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, macd)
self.DrawOwnTrades(area)
def _process_candle(self, candle, macd_value):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
typed_val = macd_value
if typed_val.Macd is None or typed_val.Signal is None:
return
macd_val = float(typed_val.Macd)
macd_hist_sma_value = float(process_float(self._macd_hist_sma, macd_val, candle.ServerTime, True))
macd_hist_stddev_value = float(process_float(self._macd_hist_stddev, macd_val, candle.ServerTime, True))
# Store previous values on first call
if self._prev_macd_hist_value == 0.0 and self._prev_macd_hist_sma_value == 0.0:
self._prev_macd_hist_value = macd_val
self._prev_macd_hist_sma_value = macd_hist_sma_value
return
# Calculate breakout thresholds
dm = float(self._dev_mult.Value)
upper_threshold = macd_hist_sma_value + dm * macd_hist_stddev_value
lower_threshold = macd_hist_sma_value - dm * macd_hist_stddev_value
# Trading logic
if macd_val > upper_threshold and self.Position <= 0:
self.BuyMarket(self.Volume)
elif macd_val < lower_threshold and self.Position >= 0:
self.SellMarket(self.Volume + Math.Abs(self.Position))
elif self.Position > 0 and macd_val < macd_hist_sma_value:
self.SellMarket(Math.Abs(self.Position))
elif self.Position < 0 and macd_val > macd_hist_sma_value:
self.BuyMarket(Math.Abs(self.Position))
self._prev_macd_hist_value = macd_val
self._prev_macd_hist_sma_value = macd_hist_sma_value
def CreateClone(self):
return macd_breakout_strategy()