ADX MACD Strategie
ADX MACD verbindet die Trendstärke des Average Directional Index mit Momentum-Wechseln des MACD. Wenn der ADX steigt, haben Ausbrüche eine höhere Chance, sich fortzusetzen, insbesondere wenn der MACD in dieselbe Richtung kreuzt.
Tests zeigen eine durchschnittliche jährliche Rendite von etwa 139%. Die Strategie funktioniert am besten auf dem Aktienmarkt.
Die Strategie handelt diese ausgerichteten Signale und steigt aus, sobald der ADX zu schwächen beginnt oder der MACD gegen die Position dreht.
Ein moderater prozentualer Stop begrenzt Verluste in seitwärts laufenden Märkten.
Details
- Einstiegskriterien: Indikatorsignal
- Long/Short: Beide
- Ausstiegskriterien: Stop-Loss oder entgegengesetztes Signal
- Stops: Ja, prozentbasiert
- Standardwerte:
CandleType= 15 minuteStopLoss= 2%
- Filter:
- Kategorie: Trendfolge
- Richtung: Beide
- Indikatoren: ADX, MACD
- Stops: Ja
- Komplexität: Mittel
- Zeitrahmen: Intraday
- Saisonalität: Nein
- Neuronale Netze: Nein
- Divergenz: Nein
- Risikolevel: Mittel
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>
/// Strategy combining ADX and MACD indicators.
/// Enters on MACD crossover when ADX indicates strong trend.
/// </summary>
public class AdxMacdStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _adxPeriod;
private readonly StrategyParam<decimal> _adxThreshold;
private readonly StrategyParam<int> _cooldownBars;
private decimal _adxValue;
private int _cooldown;
/// <summary>
/// Data type for candles.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Period for ADX calculation.
/// </summary>
public int AdxPeriod
{
get => _adxPeriod.Value;
set => _adxPeriod.Value = value;
}
/// <summary>
/// ADX threshold for trend strength.
/// </summary>
public decimal AdxThreshold
{
get => _adxThreshold.Value;
set => _adxThreshold.Value = value;
}
/// <summary>
/// Cooldown bars between trades.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="AdxMacdStrategy"/>.
/// </summary>
public AdxMacdStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_adxPeriod = Param(nameof(AdxPeriod), 14)
.SetRange(5, 30)
.SetDisplay("ADX Period", "Period for ADX calculation", "ADX Settings");
_adxThreshold = Param(nameof(AdxThreshold), 25m)
.SetDisplay("ADX Threshold", "ADX threshold for trend strength", "ADX Settings");
_cooldownBars = Param(nameof(CooldownBars), 100)
.SetDisplay("Cooldown Bars", "Bars between trades", "General")
.SetRange(5, 500);
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_adxValue = 0;
_cooldown = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var adx = new AverageDirectionalIndex { Length = AdxPeriod };
var macd = new MovingAverageConvergenceDivergenceSignal();
var subscription = SubscribeCandles(CandleType);
// Bind ADX with BindEx (composite indicator)
subscription.BindEx(adx, OnAdx);
// Bind MACD for main logic
subscription
.BindEx(macd, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
var adxArea = CreateChartArea();
if (adxArea != null)
DrawIndicator(adxArea, adx);
var macdArea = CreateChartArea();
if (macdArea != null)
DrawIndicator(macdArea, macd);
}
}
private void OnAdx(ICandleMessage candle, IIndicatorValue adxValue)
{
var typed = (AverageDirectionalIndexValue)adxValue;
if (typed.MovingAverage is decimal adx)
_adxValue = adx;
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var macdTyped = (MovingAverageConvergenceDivergenceSignalValue)macdValue;
if (macdTyped.Macd is not decimal macdLine || macdTyped.Signal is not decimal signalLine)
return;
if (_cooldown > 0)
{
_cooldown--;
return;
}
var strongTrend = _adxValue > AdxThreshold;
// Entry: strong trend + MACD bullish = buy
if (strongTrend && macdLine > signalLine && Position == 0)
{
BuyMarket();
_cooldown = CooldownBars;
}
// Entry: strong trend + MACD bearish = sell
else if (strongTrend && macdLine < signalLine && Position == 0)
{
SellMarket();
_cooldown = CooldownBars;
}
// Exit on MACD crossover against position
if (Position > 0 && macdLine < signalLine)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position < 0 && macdLine > signalLine)
{
BuyMarket();
_cooldown = CooldownBars;
}
}
}
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 AverageDirectionalIndex, MovingAverageConvergenceDivergenceSignal
from StockSharp.Algo.Strategies import Strategy
class adx_macd_strategy(Strategy):
"""
ADX + MACD strategy.
Enters on MACD crossover when ADX indicates strong trend.
"""
def __init__(self):
super(adx_macd_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._adx_period = self.Param("AdxPeriod", 14).SetDisplay("ADX Period", "Period for ADX calculation", "ADX Settings")
self._adx_threshold = self.Param("AdxThreshold", 25.0).SetDisplay("ADX Threshold", "ADX threshold for trend strength", "ADX Settings")
self._cooldown_bars = self.Param("CooldownBars", 100).SetDisplay("Cooldown Bars", "Bars between trades", "General")
self._adx_value = 0.0
self._cooldown = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(adx_macd_strategy, self).OnReseted()
self._adx_value = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(adx_macd_strategy, self).OnStarted2(time)
self._adx_value = 0.0
self._cooldown = 0
adx = AverageDirectionalIndex()
adx.Length = self._adx_period.Value
macd = MovingAverageConvergenceDivergenceSignal()
subscription = self.SubscribeCandles(self.candle_type)
# Bind ADX with BindEx (composite indicator)
subscription.BindEx(adx, self._on_adx)
# Bind MACD for main logic
subscription.BindEx(macd, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
adx_area = self.CreateChartArea()
if adx_area is not None:
self.DrawIndicator(adx_area, adx)
macd_area = self.CreateChartArea()
if macd_area is not None:
self.DrawIndicator(macd_area, macd)
def _on_adx(self, candle, adx_iv):
if adx_iv.MovingAverage is not None:
self._adx_value = float(adx_iv.MovingAverage)
def _process_candle(self, candle, macd_iv):
if candle.State != CandleStates.Finished:
return
if macd_iv.Macd is None or macd_iv.Signal is None:
return
macd_line = float(macd_iv.Macd)
signal_line = float(macd_iv.Signal)
cd = self._cooldown_bars.Value
threshold = float(self._adx_threshold.Value)
if self._cooldown > 0:
self._cooldown -= 1
return
strong_trend = self._adx_value > threshold
# Entry: strong trend + MACD bullish = buy
if strong_trend and macd_line > signal_line and self.Position == 0:
self.BuyMarket()
self._cooldown = cd
# Entry: strong trend + MACD bearish = sell
elif strong_trend and macd_line < signal_line and self.Position == 0:
self.SellMarket()
self._cooldown = cd
# Exit on MACD crossover against position
if self.Position > 0 and macd_line < signal_line:
self.SellMarket()
self._cooldown = cd
elif self.Position < 0 and macd_line > signal_line:
self.BuyMarket()
self._cooldown = cd
def CreateClone(self):
return adx_macd_strategy()