Die Pull-Back-Strategie reproduziert die Logik des ursprünglichen MetaTrader "PULL BACK" Expert Advisors unter Verwendung der StockSharp High-Level-APIs. Der Ansatz sucht nach Pullbacks zu einem schnellen gewichteten gleitenden Durchschnitt auf einem höheren Zeitrahmen, bestätigt die Momentum-Stärke über mehrere Balken und handelt in Richtung des monatlichen MACD-Trends. Sobald eine Position eröffnet ist, wendet der Algorithmus Geldmanagement-Regeln an, die Stop-Loss, Take-Profit, Break-Even und Trailing-Stop-Handling umfassen.
Momentum-Indikator mit absolutem Abstand vom neutralen Wert (100).
Pull-Back-Erkennung, wenn die vorherige Kerze die schnelle WMA berührt.
MACD-Zeitrahmen: separates Abonnement (MacdCandleType, Standard: 30-Tage-Kerzen) zum Lesen der MACD-Signallinienrichtung.
Indikatoren:
Gewichteter Gleitender Durchschnitt (WMA) auf Handels- und höherem Zeitrahmen.
Momentum (konfigurierbarer Zeitraum) auf dem höheren Zeitrahmen.
Moving Average Convergence Divergence (MACD) auf dem langen Zeitrahmen.
Handelslogik
Long-Setup
Die schnelle WMA des höheren Zeitrahmens liegt über der langsamen WMA.
Die zuletzt abgeschlossene Kerze des höheren Zeitrahmens öffnete über der schnellen WMA und berührte sie mit ihrem Tief (Pull-Back-Bestätigung).
Mindestens eine der letzten drei absoluten Momentum-Messungen überschreitet MomentumBuyThreshold.
Die MACD-Hauptlinie liegt über ihrer Signallinie im MACD-Zeitrahmen.
Auf dem Handelszeitrahmen liegt die schnelle WMA über der langsamen WMA.
Wenn alle Regeln erfüllt sind, sendet die Strategie eine Market-Kauforder. Der Einstiegspreis wird aufgezeichnet, um Risikoparameter zu steuern.
Short-Setup
Die schnelle WMA des höheren Zeitrahmens liegt unter der langsamen WMA.
Die neuere Kerze öffnete unter der schnellen WMA und berührte sie mit ihrem Hoch.
Einer der letzten drei Momentum-Werte überschreitet MomentumSellThreshold.
Die MACD-Hauptlinie liegt unter der Signallinie.
Die schnelle WMA des Handelszeitframens liegt unter der langsamen WMA.
Eine Market-Verkaufsorder wird gesendet, wenn die Bedingungen übereinstimmen.
Positionsmanagement
Stop-Loss:StopLossTicks-Abstand vom Einstieg (in absoluten Preis mit dem Kursschritt des Wertpapiers umgerechnet).
Take-Profit:TakeProfitTicks-Abstand vom Einstieg.
Break-Even: Wenn der Kurs um BreakEvenTriggerTicks fortschreitet, wird der Stop auf Einstieg plus BreakEvenOffsetTicks in Handelsrichtung verschoben, wenn UseBreakEven aktiviert ist.
Trailing-Stop: Wenn UseTrailingStop true ist, folgt der Stop dem Kurs um TrailingStopTicks, sobald sich die Position im Gewinn befindet.
Ausstiegsprüfungen: laufen bei jeder abgeschlossenen Handelszeitrahmkerze. Wenn Stop oder Ziel erreicht wird, schließt die Strategie die gesamte Position mit einer Market-Order.
Parameter
Parameter
Beschreibung
FastMaLength
Schnelle WMA-Länge im Handelszeitrahmen (Standard: 6).
SlowMaLength
Langsame WMA-Länge im Handelszeitrahmen (Standard: 85).
BounceSlowLength
Langsame WMA-Länge im Bestätigungszeitrahmen (Standard: 200).
MomentumLength
Momentum-Lookback im höheren Zeitrahmen (Standard: 14).
MomentumBuyThreshold
Minimum
Momentum-100
für Long-Einstiege (Standard: 0.3).
MomentumSellThreshold
Minimum
Momentum-100
für Short-Einstiege (Standard: 0.3).
StopLossTicks
Stop-Loss-Abstand in Ticks (Standard: 200).
TakeProfitTicks
Take-Profit-Abstand in Ticks (Standard: 500).
UseTrailingStop
Trailing-Stop-Logik aktivieren (Standard: true).
TrailingStopTicks
Trailing-Stop-Abstand in Ticks (Standard: 400).
UseBreakEven
Break-Even-Anpassung aktivieren (Standard: true).
BreakEvenTriggerTicks
Gewinn-Trigger für Break-Even in Ticks (Standard: 300).
BreakEvenOffsetTicks
Offset zum Break-Even-Stop in Ticks (Standard: 300).
MacdFastLength
Schnelle EMA-Periode des MACD (Standard: 12).
MacdSlowLength
Langsame EMA-Periode des MACD (Standard: 26).
MacdSignalLength
Signal-EMA-Periode des MACD (Standard: 9).
CandleType
Kerzentyp des Handelszeitrahmens.
HigherCandleType
Kerzentyp des Bestätigungszeitrahmens.
MacdCandleType
Kerzentyp des MACD-Zeitrahmens.
Hinweise
Die Strategie erwartet, dass Security.PriceStep befüllt ist, damit tick-basierte Risikokontrollen korrekt in Preisabstände übersetzt werden.
Es wird immer nur eine Nettoposition gehalten; entgegengesetzte Signale werden ignoriert, bis die aktuelle Position geschlossen ist.
Die Logik verarbeitet nur abgeschlossene Kerzen, um nicht auf Teildaten zu reagieren.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class PullBackStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal? _prevFast, _prevSlow;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public PullBackStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 5).SetGreaterThanZero().SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 15).SetGreaterThanZero().SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = null;
_prevSlow = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = null; _prevSlow = null;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!IsFormedAndOnlineAndAllowTrading()) { _prevFast = fast; _prevSlow = slow; return; }
if (_prevFast == null || _prevSlow == null) { _prevFast = fast; _prevSlow = slow; return; }
var prevAbove = _prevFast.Value > _prevSlow.Value;
var currAbove = fast > slow;
_prevFast = fast; _prevSlow = slow;
if (!prevAbove && currAbove && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
else if (prevAbove && !currAbove && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
}
}
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 pull_back_strategy(Strategy):
def __init__(self):
super(pull_back_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 5) \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 15) \
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
def OnReseted(self):
super(pull_back_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(pull_back_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast = ExponentialMovingAverage()
fast.Length = self.FastPeriod
slow = ExponentialMovingAverage()
slow.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, slow, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if self._prev_fast is None or self._prev_slow is None:
self._prev_fast = fv
self._prev_slow = sv
return
prev_above = self._prev_fast > self._prev_slow
curr_above = fv > sv
self._prev_fast = fv
self._prev_slow = sv
if not prev_above and curr_above and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif prev_above and not curr_above and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return pull_back_strategy()