Die Test-MACD-Strategie ist eine getreue Konvertierung des MetaTrader-Expert-Advisors TestMACD in die StockSharp-High-Level-API. Sie nutzt den Moving Average Convergence Divergence (MACD)-Indikator, um Momentum-Wechsel zu erkennen, und führt Trades aus, wenn die MACD-Linie auf geschlossenen Kerzen die Signallinie kreuzt. Die Strategie arbeitet auf einem einzelnen Instrument und Zeitrahmen, der über den Parameter CandleType geliefert wird.
Handelslogik
Kerzendaten gemäß CandleType abonnieren und einen MACD-Indikator mit konfigurierbaren schnellen, langsamen und Signalperioden berechnen.
Die MACD-Wertdifferenz (MACD - Signal) auf jeder abgeschlossenen Kerze überwachen.
Einen bullischen Einstieg auslösen, wenn die Differenz von nicht positiv zu positiv wechselt, was bedeutet, dass die MACD-Linie die Signallinie nach oben gekreuzt hat. Jede Short-Exposure wird vor Eröffnung der Long-Position geschlossen.
Einen bärischen Einstieg auslösen, wenn die Differenz von nicht negativ zu negativ wechselt, was bedeutet, dass die MACD-Linie die Signallinie nach unten gekreuzt hat. Jede Long-Exposure wird vor Eröffnung der Short-Position geschlossen.
Alle Orders werden zum Markt mit dem durch TradeVolume konfigurierten festen Volumen gesendet.
Jeder Einstieg wird automatisch mit Stop-Loss- und Take-Profit-Niveaus in Preisschritten geschützt, um das punktbasierte Risikomanagement des ursprünglichen Experten nachzubilden.
Risikomanagement
Stop-Loss- und Take-Profit-Distanzen spiegeln die MetaTrader-Eingaben und werden in Preisschritten angegeben. Fehlt der Security PriceStep, nutzt die Strategie absolute Preisdistanzen mit MinPriceStep oder 1 als Multiplikator.
Schutzorders werden einmal beim Start der Strategie über StartProtection erstellt, sodass sie ohne Neukonfiguration für jeden späteren Trade gelten.
Parameter
Parameter
Beschreibung
Standard
FastPeriod
Schnelle EMA-Länge für MACD-Berechnungen.
12
SlowPeriod
Langsame EMA-Länge für MACD-Berechnungen.
24
SignalPeriod
Signal-EMA-Länge für MACD-Glättung.
9
StopLossPoints
Stop-Loss-Distanz in Preisschritten.
90
TakeProfitPoints
Take-Profit-Distanz in Preisschritten.
110
TradeVolume
Festes Volumen für alle Marktorders.
1
CandleType
Von der Strategie abonnierter Kerzendatentyp und Zeitrahmen.
30-Minuten-Zeitrahmen
Nutzungshinweise
Binden Sie die Strategie vor dem Start an eine Security, damit PriceStep und MinPriceStep verfügbar sind.
Stellen Sie sicher, dass Marktdaten für den gewählten CandleType bereitgestellt werden; andernfalls bildet sich der MACD-Indikator nicht und es findet kein Handel statt.
Die Strategie protokolliert jedes Crossover-Ereignis, wodurch Handelsentscheidungen in Backtests leicht nachvollziehbar sind.
Konvertierungsdetails
Die ursprünglichen MetaTrader-Klassen CSignalMACD, CTrailingNone und CMoneyFixedLot werden durch StockSharp-Indikatorbindung und StartProtection-Mechanismen ersetzt.
Die Logik aus ExtStateMACD, die MACD-Kreuzungen prüfte, wird durch einen Vorzeichenwechsel-Detektor auf der MACD-Differenz zwischen aufeinanderfolgenden abgeschlossenen Kerzen dargestellt.
Geldmanagement wird auf einen festen Volumenparameter vereinfacht und ähnelt stark dem Fixed-Lot-Verhalten von CMoneyFixedLot, wenn prozentbasiertes Sizing deaktiviert ist.
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Test MACD strategy: MACD histogram zero-cross.
/// Buys when MACD histogram crosses above zero.
/// Sells when MACD histogram crosses below zero.
/// </summary>
public class TestMacdStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public TestMacdStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var macd = new MovingAverageConvergenceDivergenceSignal
{
Macd = { ShortMa = { Length = 12 }, LongMa = { Length = 26 } },
SignalMa = { Length = 9 }
};
decimal? prevHistogram = null;
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(macd, (candle, macdVal) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (macdVal.IsEmpty)
return;
var v = (MovingAverageConvergenceDivergenceSignalValue)macdVal;
if (v.Macd is not decimal macdDec || v.Signal is not decimal signalDec)
return;
var histogram = macdDec - signalDec;
if (prevHistogram.HasValue)
{
if (prevHistogram.Value <= 0m && histogram > 0m && Position <= 0)
BuyMarket();
else if (prevHistogram.Value >= 0m && histogram < 0m && Position >= 0)
SellMarket();
}
prevHistogram = histogram;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, macd);
DrawOwnTrades(area);
}
}
}
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 MovingAverageConvergenceDivergenceSignal
from StockSharp.Algo.Strategies import Strategy
class test_macd_strategy(Strategy):
def __init__(self):
super(test_macd_strategy, self).__init__()
self._prev_histogram = None
self._macd = None
def OnReseted(self):
super(test_macd_strategy, self).OnReseted()
self._prev_histogram = None
self._macd = None
def OnStarted2(self, time):
super(test_macd_strategy, self).OnStarted2(time)
self._macd = MovingAverageConvergenceDivergenceSignal()
self._macd.Macd.ShortMa.Length = 12
self._macd.Macd.LongMa.Length = 26
self._macd.SignalMa.Length = 9
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(30)))
subscription.BindEx(self._macd, self._process_candle)
subscription.Start()
def _process_candle(self, candle, macd_val):
if candle.State != CandleStates.Finished:
return
if not self._macd.IsFormed:
return
macd_v = float(macd_val.Macd)
signal_v = float(macd_val.Signal)
histogram = macd_v - signal_v
if self._prev_histogram is not None:
if self._prev_histogram <= 0.0 and histogram > 0.0 and self.Position <= 0:
self.BuyMarket()
elif self._prev_histogram >= 0.0 and histogram < 0.0 and self.Position >= 0:
self.SellMarket()
self._prev_histogram = histogram
def CreateClone(self):
return test_macd_strategy()