Die Zone-Recovery-Formula-Strategie ist eine Portierung des MetaTrader-4 Expert Advisors "Zone Recovery Formula". Der Algorithmus folgt einer durch gleitende Durchschnitte bestimmten Trendrichtung und wendet anschließend eine Zone-Recovery-Technik an, um ungünstige Preisbewegungen abzufedern. Die Kernidee besteht darin, Long- und Short-Zyklen mit allmählich steigendem Volumen abzuwechseln, bis die Preisbewegung die definierte Recovery-Zone verlässt und selbst nach mehreren Umkehrungen Gewinn sichert.
Funktionsweise
Signalerkennung - Die Strategie abonniert Zeitrahmenkerzen (standardmäßig 15 Minuten) und verfolgt einen schnellen und einen langsamen einfachen gleitenden Durchschnitt. Eine bullische Kreuzung startet einen Long-Recovery-Zyklus, während eine bärische Kreuzung einen Short-Zyklus startet.
Initialorder - Wenn ein neuer Zyklus beginnt, eröffnet die Strategie eine Marktposition mit dem Basis-Volumenmultiplikator. Take-Profit- und Recovery-Distanzen werden aus den Pip-Einstellungen und der Tickgröße des Instruments berechnet.
Zone Recovery - Wenn sich der Preis um die konfigurierte Recovery-Distanz gegen die offene Position bewegt, kehrt die Strategie die Richtung um und erhöht die Ordergröße anhand der ursprünglichen Formelsequenz (bis zur maximalen Anzahl von Trades). Dadurch entsteht eine alternierende Nettoexposure, die frühere Verluste decken soll, sobald der Preis zum Gewinnziel zurückkehrt.
Gewinnmanagement - Der Algorithmus überwacht unrealisierten Gewinn:
Geld- und prozentbasierte Take-Profit-Bedingungen können alle Positionen sofort schließen.
Optionales Trailing-Management erfasst Gewinne nach einem vordefinierten Gewinn und schützt sie mit einer Trailing-Stop-Distanz.
Zyklus-Reset - Wenn Gewinnziele erreicht werden oder Trailing-Schutz die Position schließt, wird der Recovery-Zyklus zurückgesetzt und die Strategie wartet auf das nächste Signal des gleitenden Durchschnitts.
TP % verwenden / TP Prozent - Prozentualen Take-Profit auf Basis des Portfoliosaldos aktivieren und konfigurieren.
Trailing aktivieren / Trailing TP / Trailing SL - Trailing-Gewinnsicherung aktivieren und Aktivierungsniveau zusammen mit Schutzdistanz definieren.
TP Pips / Zone Pips - Distanzen (in Pips), die Take-Profit-Ziel und Recovery-Auslösezone definieren.
Basisvolumen / Max. Trades - Anfangsordergröße und Anzahl der erlaubten Recovery-Schritte in einem Zyklus.
Schnelle MA / Langsame MA - Gleitende Durchschnitte, die Einstiegssignale erzeugen.
Gewinn-Offset - Optionale Anpassung, die in der ursprünglichen Recovery-Volumenformel verwendet wird.
Hinweise
Die Strategie verwendet die High-Level-API von StockSharp mit Kerzenabonnements und Indikatorbindung.
Hedging-Positionen werden emuliert, indem die Nettopositionsrichtung gewechselt und das Volumen skaliert wird; dadurch bleibt die Logik mit StockSharps Nettopositionsrechnung kompatibel.
Trailing- und Take-Profit-Prüfungen beruhen auf unrealisiertem Gewinn, der aus dem aktuellen Positionspreis berechnet wird. Passen Sie Geldwerte an den Tickwert des Instruments an.
Testen Sie immer in einer simulierten Umgebung, bevor Sie auf einem Live-Konto handeln.
Dateien
CS/ZoneRecoveryFormulaStrategy.cs - C#-Implementierung der Strategie.
README.md - diese Dokumentationsdatei auf Englisch.
README_ru.md - Dokumentation auf Russisch.
README_zh.md - Dokumentation auf Chinesisch.
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;
public class ZoneRecoveryFormulaStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _stopLossPoints;
private readonly StrategyParam<int> _takeProfitPoints;
private ExponentialMovingAverage _fast;
private ExponentialMovingAverage _slow;
private decimal _prevFast;
private decimal _prevSlow;
private decimal _entryPrice;
private int _cooldown;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }
public ZoneRecoveryFormulaStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
}
protected override void OnReseted()
{
base.OnReseted();
_fast = null; _slow = null;
_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_fast = new ExponentialMovingAverage { Length = FastPeriod };
_slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
subscription.Bind(_fast, _slow, ProcessCandle);
subscription.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }
var close = candle.ClosePrice;
var step = Security?.PriceStep ?? 1m;
if (Position > 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
else if (Position < 0 && _entryPrice > 0)
{
if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
}
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }
_prevFast = fastValue; _prevSlow = slowValue;
}
}
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 zone_recovery_formula_strategy(Strategy):
def __init__(self):
super(zone_recovery_formula_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 14) \
.SetDisplay("Fast Period", "Fast MA period", "Indicator")
self._slow_period = self.Param("SlowPeriod", 50) \
.SetDisplay("Slow Period", "Slow MA period", "Indicator")
self._stop_loss_points = self.Param("StopLossPoints", 200) \
.SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk")
self._take_profit_points = self.Param("TakeProfitPoints", 400) \
.SetDisplay("Take Profit", "Take-profit in price steps", "Risk")
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
@property
def fast_period(self):
return self._fast_period.Value
@property
def slow_period(self):
return self._slow_period.Value
@property
def stop_loss_points(self):
return self._stop_loss_points.Value
@property
def take_profit_points(self):
return self._take_profit_points.Value
def OnReseted(self):
super(zone_recovery_formula_strategy, self).OnReseted()
self._fast = None
self._slow = None
self._prev_fast = 0.0
self._prev_slow = 0.0
self._entry_price = 0.0
self._cooldown = 0
def OnStarted2(self, time):
super(zone_recovery_formula_strategy, self).OnStarted2(time)
self._fast = ExponentialMovingAverage()
self._fast.Length = self.fast_period
self._slow = ExponentialMovingAverage()
self._slow.Length = self.slow_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(5)))
subscription.Bind(self._fast, self._slow, self._process_candle)
subscription.Start()
def _process_candle(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fast_val = float(fast_value)
slow_val = float(slow_value)
if not self._fast.IsFormed or not self._slow.IsFormed:
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._cooldown > 0:
self._cooldown -= 1
self._prev_fast = fast_val
self._prev_slow = slow_val
return
close = float(candle.ClosePrice)
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
if self.Position > 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close <= self._entry_price - self.stop_loss_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close >= self._entry_price + self.take_profit_points * step:
self.SellMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
elif self.Position < 0 and self._entry_price > 0:
if self.stop_loss_points > 0 and close >= self._entry_price + self.stop_loss_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self.take_profit_points > 0 and close <= self._entry_price - self.take_profit_points * step:
self.BuyMarket()
self._entry_price = 0.0
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
return
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._entry_price = close
self._cooldown = 100
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._entry_price = close
self._cooldown = 100
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return zone_recovery_formula_strategy()