Diese Strategie ist eine StockSharp-Portierung des Pedroxxmod MetaTrader 4-Expertenberaters. Der ursprüngliche EA wartet darauf, dass sich der Markt a bewegt
wenige Pips von einem Referenzpreis entfernt und eröffnet dann eine konträre Position. Nachfolgende Bestellungen werden in die gleiche Richtung gemittelt
immer dann, wenn der Preis um eine konfigurierbare Distanz zurückgeht. Die StockSharp-Implementierung behält das Verhalten während der Offenlegung bei
stark typisierte Parameter über das übergeordnete Strategy API.
Handelslogik
Abonnieren Sie die besten Bid/Ask-Kurse der Stufe 1 und speichern Sie die neuesten Werte im Cache.
Wenn keine Geschäfte offen sind, speichern Sie den aktuellen Briefkurs als Referenzeinstiegsniveau. Der Handel ist nur zwischen erlaubt
StartHour und EndHour und ab StartYear.
Wenn der beste Brief um Gap MetaTrader Pips über die Referenz steigt, erteilen Sie einen Marktverkaufsauftrag. Wenn es um Gap Pips sinkt,
eine Market-Buy-Order einreichen. Durch den Aufruf werden automatisch schützende Stop-Loss- und Take-Profit-Levels festgelegt
SetStopLoss / SetTakeProfit mit den gleichen Pip-Abständen wie der Expert Advisor.
Sobald eine Korbrichtung festgelegt ist, führt die Strategie eine FIFO-Liste der synthetischen Positionen, um die Absicherung zu emulieren
Stil von MetaTrader. Solange die aktuelle Warenkorbgröße unter MaxTrades liegt, werden durchschnittliche Bestellungen hinzugefügt, wenn die beste Nachfrage besteht
Die Rendite liegt innerhalb von ReEntryGap Pips vom letzten Einstiegspreis.
Die Geldverwaltung kann entweder den festen Parameter Lots verwenden oder das Volumen gemäß der Regel EA dynamisch zuweisen
floor(Equity / 20000), begrenzt durch MaxLots. Alle Volumina werden anhand der Volumenschritte/Min./Max. des Wertpapiers normalisiert.
Aktualisierungen außerhalb der Geschäftszeiten setzen die internen Einstiegsanker zurück, um falsche Trades zu vermeiden, wenn die nächste Sitzung beginnt.
Parameter
Name
Beschreibung
Lots
Das Auftragsvolumen wurde behoben, wenn die Geldverwaltung deaktiviert ist.
StopLoss
Schutzstoppdistanz in MetaTrader Pips. Auf 0 setzen, um den Stopp zu deaktivieren.
TakeProfit
Gewinnzielentfernung in MetaTrader Pips. Auf 0 setzen, um das Ziel zu deaktivieren.
Gap
Abstand in MetaTrader Pips, um den sich der Brief von der Referenz entfernen muss, bevor der erste Handel eröffnet wird.
MaxTrades
Maximale Anzahl gleichzeitig geöffneter Trades (Korbgröße).
ReEntryGap
Abstand in MetaTrader Pips, der durchschnittliche Orders in Korbrichtung auslöst.
MoneyManagement
Aktiviert die dynamische Lautstärkeregel floor(Equity / 20000), wenn sie auf true eingestellt ist.
MaxLots
Obergrenze für das dynamisch berechnete Volumen.
StartHour / EndHour
Handelsfenster in Börsenserverzeit (einschließlich).
StartYear
Kalenderjahr, ab dem der Handel erlaubt ist. Frühere Daten werden ignoriert.
Notizen
Die Strategie verbraucht nur Level1-Daten und fordert keine Kerzen an. Es ist daher leicht und reagiert sofort
Zitatänderungen, genau wie der MT4-Tick-Handler start().
Stopps und Ziele stützen sich auf die Hilfsmethoden von Strategy, um MetaTrader Pip-Abstände in Broker-spezifische zu übersetzen
Preisniveaus. Stellen Sie sicher, dass der verbundene Veranstaltungsort die korrekten Werte für PriceStep, StepPrice und VolumeStep bereitstellt.
Der synthetische Korbzähler ermöglicht es der Strategie, Sicherungskonten nachzuahmen, obwohl StockSharp die Position aggregiert.
Teilfüllungen und Stopptreffer werden über den Callback OnPositionChanged verarbeitet, der die FIFO-Warteschlangen verwaltet.
Gemäß den Repository-Richtlinien wird bewusst auf eine Python-Implementierung verzichtet.
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using StockSharp.Algo;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
/// <summary>
/// Pedro Mod mean reversion strategy using Bollinger Bands.
/// Buy when price touches the lower band, sell when price touches the upper band.
/// </summary>
public class PedroModStrategy : Strategy
{
private readonly StrategyParam<int> _bollingerPeriod;
private readonly StrategyParam<decimal> _bollingerWidth;
private readonly StrategyParam<DataType> _candleType;
public int BollingerPeriod { get => _bollingerPeriod.Value; set => _bollingerPeriod.Value = value; }
public decimal BollingerWidth { get => _bollingerWidth.Value; set => _bollingerWidth.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public PedroModStrategy()
{
_bollingerPeriod = Param(nameof(BollingerPeriod), 20)
.SetDisplay("Bollinger Period", "Bollinger Bands period", "Indicators");
_bollingerWidth = Param(nameof(BollingerWidth), 1.5m)
.SetDisplay("Bollinger Width", "Standard deviation multiplier", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var bb = new BollingerBands { Length = BollingerPeriod, Width = BollingerWidth };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(bb, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue bbValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!bbValue.IsFinal)
return;
var bb = (BollingerBandsValue)bbValue;
if (bb.UpBand is not decimal upper || bb.LowBand is not decimal lower || bb.MovingAverage is not decimal middle)
return;
// Buy when price touches lower band (mean reversion)
if (Position <= 0 && candle.ClosePrice <= lower)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// Sell when price touches upper band
else if (Position >= 0 && candle.ClosePrice >= upper)
{
if (Position > 0)
SellMarket();
SellMarket();
}
// Exit at middle band
else if (Position > 0 && candle.ClosePrice >= middle)
{
SellMarket();
}
else if (Position < 0 && candle.ClosePrice <= middle)
{
BuyMarket();
}
}
}
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
from StockSharp.Algo.Indicators import BollingerBands
from StockSharp.Algo.Strategies import Strategy
class pedro_mod_strategy(Strategy):
"""Pedro Mod mean reversion strategy using Bollinger Bands.
Buy when price touches the lower band, sell when price touches the upper band.
Exit at the middle band."""
def __init__(self):
super(pedro_mod_strategy, self).__init__()
self._bollinger_period = self.Param("BollingerPeriod", 20) \
.SetDisplay("Bollinger Period", "Bollinger Bands period", "Indicators")
self._bollinger_width = self.Param("BollingerWidth", 1.5) \
.SetDisplay("Bollinger Width", "Standard deviation multiplier", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def BollingerPeriod(self):
return self._bollinger_period.Value
@property
def BollingerWidth(self):
return self._bollinger_width.Value
def OnReseted(self):
super(pedro_mod_strategy, self).OnReseted()
def OnStarted2(self, time):
super(pedro_mod_strategy, self).OnStarted2(time)
bb = BollingerBands()
bb.Length = self.BollingerPeriod
bb.Width = self.BollingerWidth
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(bb, self._process_candle).Start()
def _process_candle(self, candle, bb_value):
if candle.State != CandleStates.Finished:
return
if not bb_value.IsFinal:
return
up_band = bb_value.UpBand if hasattr(bb_value, 'UpBand') else None
low_band = bb_value.LowBand if hasattr(bb_value, 'LowBand') else None
mid_band = bb_value.MovingAverage if hasattr(bb_value, 'MovingAverage') else None
if up_band is None or low_band is None or mid_band is None:
return
upper = float(up_band)
lower = float(low_band)
middle = float(mid_band)
close = float(candle.ClosePrice)
# Buy when price touches lower band (mean reversion)
if self.Position <= 0 and close <= lower:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Sell when price touches upper band
elif self.Position >= 0 and close >= upper:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
# Exit at middle band
elif self.Position > 0 and close >= middle:
self.SellMarket()
elif self.Position < 0 and close <= middle:
self.BuyMarket()
def CreateClone(self):
return pedro_mod_strategy()