Diese Strategie ist eine StockSharp-Portierung des MetaTrader Expert Advisors "Fibonacci Time Zones". Sie bewahrt den diskretionären Charakter des ursprünglichen Skripts, indem sie einen MACD-Filter auf höherem Zeitrahmen mit Bollinger-Band-Ausstiegen und einem umfangreichen Money-Management-Modul kombiniert. Alle Trade-Management-Routinen wurden mit der High-Level-API neu geschrieben: Die Strategie abonniert zwei Kerzenströme (einen Handelszeitrahmen und einen langsameren Zeitrahmen für die MACD-Bestätigung) und bindet Indikatoren direkt über Bind/BindEx-Callbacks.
Kernlogik
Momentum-Filter - Ein monatliches (konfigurierbares) MACD-Histogramm wird berechnet. Eine bullische Kreuzung über die Signallinie plant Long-Einstiege, während eine bärische Kreuzung Short-Einstiege plant. Die tatsächliche Position wird auf der nächsten Handelskerze eröffnet, um wiederholte Orders auf derselben Kreuzung zu vermeiden.
Einstiegsausführung - Jedes Signal sendet eine benutzerdefinierte Anzahl von Marktorders. Bestehende Gegenexposure wird vor dem Eröffnen einer neuen Position glattgestellt.
Ausstiegsregeln - Mehrere Verteidigungsebenen werden angewendet:
Bollinger-Band-Ausstieg: Longs werden geschlossen, wenn der Preis das obere Band berührt; Shorts, wenn das untere Band erreicht wird.
Klassischer Stop/Ziel: Statische Stop-Loss-, Take-Profit- und Trailing-Stop-Distanzen werden von Pips in Preiseinheiten umgerechnet und an StartProtection übergeben.
Break-even: Nachdem der Preis eine konfigurierbare Anzahl von Pips zurückgelegt hat, wird der Stop auf Break-even plus Offset gezogen. Fällt der Preis auf dieses Niveau zurück, wird die Position geschlossen.
Money-Trailing: Offener und realisierter PnL werden überwacht. Wenn der schwebende Gewinn einen Schwellenwert erreicht, beginnt die Strategie ihn zu trailen und schließt nach einem konfigurierbaren Drawdown alles.
Equity-Ziele: Optionale absolute oder prozentuale Gewinnziele schließen alle Trades sofort, wenn sie erreicht werden.
Parameter
Parameter
Beschreibung
UseTakeProfitMoney, TakeProfitMoney
Schließt alle Positionen, wenn der kombinierte Gewinn (realisiert + unrealisiert) den angegebenen Betrag in Kontowährung erreicht.
UseTakeProfitPercent, TakeProfitPercent
Ähnlich der vorherigen Option, jedoch als Prozentsatz des Start-Equity gemessen.
Anzahl der für jedes Signal gesendeten Marktorders (imitiert den ursprünglichen EA, der Einstiege stapeln konnte).
CandleType, MacdCandleType
Zeitrahmen für die Management-Kerzen und den MACD-Filter.
Unterschiede zum ursprünglichen EA
Chart-Schaltflächen und grafische Fibonacci-Objekte werden nicht nachgebildet; die StockSharp-Portierung konzentriert sich ausschließlich auf systematische Ausführung.
Der ursprüngliche Expert Advisor handelte über manuelle Schaltflächenklicks. Die Portierung steigt automatisch bei MACD-Kreuzungen ein, um eine deterministische und backtestbare Strategie zu liefern.
MetaTrader-spezifische Kontofunktionen wurden durch StockSharp-Entsprechungen ersetzt (Portfolio-Werte und PnL).
Nutzungstipps
Wählen Sie geeignete Kerzentypen, bevor Sie die Strategie starten. Die Standardwerte entsprechen einem 15-Minuten-Handelschart mit monatlichem MACD-Filter.
Stimmen Sie die pipbasierten Distanzen auf die Tickgröße des Instruments ab. Die Strategie rechnet Pips intern über Security.PriceStep in Preise um.
Für diskretionäres Eingreifen deaktivieren Sie die automatischen Gewinnziele und verwenden nur den Bollinger-Ausstieg.
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 FibonacciTimeZonesStrategy : 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 FibonacciTimeZonesStrategy()
{
_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 fibonacci_time_zones_strategy(Strategy):
def __init__(self):
super(fibonacci_time_zones_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(fibonacci_time_zones_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(fibonacci_time_zones_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 fibonacci_time_zones_strategy()