Die MA Reverse Strategy ist eine StockSharp-Umwandlung des einfachen MetaTrader 4 Expert Advisors „MA_Reverse“. Der ursprüngliche Roboter
überwacht, wie lange der Gebotspreis über oder unter einem einfachen gleitenden 14-Perioden-Durchschnitt (SMA) bleibt. Nach einer ausreichend langen Serie in einem
Richtung eröffnet es eine Position, die auf eine kurzfristige Umkehr setzt. Der StockSharp-Port behält die gleiche Idee bei, indem er die Anzahl zählt
von aufeinanderfolgenden fertigen Kerzen, die über oder unter SMA schließen und eine Marktorder ausführen, sobald der konfigurierte Schwellenwert erreicht ist
erreicht.
Handelslogik
Abonnieren Sie Kerzen des ausgewählten Zeitrahmens und berechnen Sie einen einfachen gleitenden Durchschnitt mit dem durch SmaPeriod definierten Zeitraum.
Pflegen Sie einen ganzzahligen Zähler (StreakThreshold steuert die Ziellänge), der sich erhöht, während der Kerzenschluss darüber bleibt
der gleitende Durchschnitt und sinkt, während der Schlusskurs darunter bleibt. Durch Berühren des gleitenden Durchschnitts wird der Zähler zurückgesetzt.
Sobald der Zähler StreakThreshold erreicht und der Schlusskurs mindestens MinimumDeviation über SMA liegt, wird die Strategie mit a verkauft
Marktordnung. Es wird davon ausgegangen, dass eine längere zinsbullische Abweichung vom gleitenden Durchschnitt wahrscheinlich zu einer Rückkehr zum Mittelwert führt.
Wenn der Zähler -StreakThreshold erreicht und der Schlusskurs mindestens MinimumDeviation unter SMA liegt, spiegelt die Logik den Wert wider
Verhalten und eröffnet eine Long-Position.
Nach jedem Trade behält der Zähler seinen laufenden Wert, genau wie die Quelle EA, sodass er sofort mit der Messung beginnen kann
nächste Serie.
Auftragsverwaltung
Markteinträge verwenden den Parameter TradeVolume. Wenn es eine entgegengesetzte Position auf dem Buch gibt, schließt die Strategie diese zunächst und
Anschließend wird der neue Trade in einer einzelnen Marktorder eröffnet, sodass Umkehrungen dem MetaTrader-Verhalten entsprechen.
Ein globaler Take-Profit wird über den StartProtection-Helfer von StockSharp konfiguriert. Die Entfernung beträgt TakeProfitPoints
multipliziert mit der Wertpapierpreisstufe, was das Gewinnziel „30 * Punkte“ aus dem MQL-Code reproduziert. Wenn das Ziel getroffen wird
Die Position wird mit einer Marktorder geschlossen.
Im ursprünglichen Experten ist kein Stop-Loss implementiert und daher wird im Port auch kein Stop-Loss hinzugefügt. Die Risikokontrolle liegt vollständig bei
vom Take-Profit und von den Geldverwaltungseinstellungen des Benutzers.
Parameter
Parameter
Beschreibung
TradeVolume
Für jeden Markteintritt verwendete Losgröße. Der Wert wird auch zur Dimensionierung von Umkehrungen beim Richtungswechsel verwendet.
SmaPeriod
Anzahl der Kerzen, die vom einfachen gleitenden Durchschnitt verwendet werden. Der Standard entspricht dem gleitenden 14-Perioden-Durchschnitt von EA.
StreakThreshold
Anzahl aufeinanderfolgender Schließungen, die auf einer Seite des SMA bleiben müssen, bevor eine Umkehrorder zulässig ist.
MinimumDeviation
Minimaler absoluter Abstand zwischen dem Schlusskurs und dem SMA, der die Ausbruchsbedingung bestätigt.
TakeProfitPoints
Take-Profit-Distanz, ausgedrückt in Preisschritten. Er wird mit dem PriceStep des Instruments multipliziert, um den absoluten Preisversatz zu erhalten.
CandleType
Kerzentyp (Zeitrahmen), der zur Berechnung des SMA und zur Auswertung der Streak-Zähler verwendet wird.
Notizen
Die Zählerlogik funktioniert mit fertigen Kerzen, die von SubscribeCandles bereitgestellt werden, was die Implementierung robust und robust macht
kompatibel mit historischen Tests. Das Verhalten entspricht der Tick-basierten MetaTrader-Version, solange die Kerzen in Ordnung sind
körnig genug, um kurzfristige Ausflüge festzuhalten.
Da StockSharp standardmäßig Positionen aggregiert, werden mehrere aufeinanderfolgende Einträge als eine einzelne Position mit einem einzigen verwaltet
Floating Take-Profit-Distanz. Dies ist gleichbedeutend damit, dass MetaTrader bei jeder Bestellung den gleichen Take-Profit erzielt, weil die
Der Abstand zum aktuellen durchschnittlichen Einstiegspreis bleibt konstant.
Die Strategie fügt Strategy.Indicators keinen eigenen Indikator hinzu, da die Bindungsinfrastruktur den Indikator verwaltet
Lebenszeit automatisch.
Überprüfen Sie immer die Preisschritt- und Volumeneinstellungen für Ihre spezifischen Brokersymbole, damit der Parameter TakeProfitPoints
ergibt die gewünschte absolute Zielgröße.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Moving average reversal strategy converted from the MetaTrader MA_Reverse expert advisor.
/// Counts how many consecutive closes remain on one side of the SMA and opens a trade once the streak is long enough.
/// </summary>
public class MaReverseStrategy : Strategy
{
private readonly StrategyParam<int> _smaPeriod;
private readonly StrategyParam<int> _streakThreshold;
private readonly StrategyParam<decimal> _minimumDeviation;
private readonly StrategyParam<DataType> _candleType;
private int _streak;
public MaReverseStrategy()
{
_smaPeriod = Param(nameof(SmaPeriod), 14)
.SetDisplay("SMA Period", "Number of candles used by the moving average.", "Indicator");
_streakThreshold = Param(nameof(StreakThreshold), 3)
.SetDisplay("Streak Threshold", "Number of consecutive closes required before reversing.", "Logic");
_minimumDeviation = Param(nameof(MinimumDeviation), 0.0001m)
.SetDisplay("Minimum Deviation", "Minimum distance between price and SMA to confirm the reversal.", "Logic");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Timeframe used for SMA calculation.", "General");
}
public int SmaPeriod
{
get => _smaPeriod.Value;
set => _smaPeriod.Value = value;
}
public int StreakThreshold
{
get => _streakThreshold.Value;
set => _streakThreshold.Value = value;
}
public decimal MinimumDeviation
{
get => _minimumDeviation.Value;
set => _minimumDeviation.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_streak = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_streak = 0;
var sma = new SimpleMovingAverage { Length = SmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal smaValue)
{
if (candle.State != CandleStates.Finished)
return;
var closePrice = candle.ClosePrice;
var deviation = closePrice - smaValue;
if (deviation == 0m)
{
_streak = 0;
return;
}
if (deviation > 0m)
{
// Price above SMA
if (_streak < 0)
_streak = 0;
_streak++;
if (_streak >= StreakThreshold && deviation > MinimumDeviation)
{
// Long streak above SMA => sell (reversal)
if (Position >= 0)
{
SellMarket();
_streak = 0;
}
}
}
else
{
// Price below SMA
if (_streak > 0)
_streak = 0;
_streak--;
if (-_streak >= StreakThreshold && -deviation > MinimumDeviation)
{
// Long streak below SMA => buy (reversal)
if (Position <= 0)
{
BuyMarket();
_streak = 0;
}
}
}
}
}
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 SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class ma_reverse_strategy(Strategy):
"""
MA reversal: counts consecutive closes on one side of SMA.
After streak threshold, opens a reversal trade.
"""
def __init__(self):
super(ma_reverse_strategy, self).__init__()
self._sma_period = self.Param("SmaPeriod", 14).SetDisplay("SMA Period", "SMA period", "Indicators")
self._streak_threshold = self.Param("StreakThreshold", 3).SetDisplay("Streak", "Consecutive closes needed", "Logic")
self._min_deviation = self.Param("MinDeviation", 0.0001).SetDisplay("Min Deviation", "Min distance from SMA", "Logic")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Timeframe", "General")
self._streak = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(ma_reverse_strategy, self).OnReseted()
self._streak = 0
def OnStarted2(self, time):
super(ma_reverse_strategy, self).OnStarted2(time)
sma = SimpleMovingAverage()
sma.Length = self._sma_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sma, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, sma)
self.DrawOwnTrades(area)
def _process_candle(self, candle, sma_val):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
sma = float(sma_val)
deviation = close - sma
if deviation == 0:
self._streak = 0
return
if deviation > 0:
if self._streak < 0:
self._streak = 0
self._streak += 1
if self._streak >= self._streak_threshold.Value and deviation > self._min_deviation.Value:
if self.Position >= 0:
self.SellMarket()
self._streak = 0
else:
if self._streak > 0:
self._streak = 0
self._streak -= 1
if -self._streak >= self._streak_threshold.Value and -deviation > self._min_deviation.Value:
if self.Position <= 0:
self.BuyMarket()
self._streak = 0
def CreateClone(self):
return ma_reverse_strategy()