Strategie zur Erschöpfung des Firebird MA-Umschlags
Die Strategie repliziert den Umschlagumkehrexperten von Firebird v0.60. Es misst einen einfachen gleitenden Durchschnitt und verrechnet ihn um einen Prozentsatz, um obere und untere Hüllkurven zu bilden. Wenn der Preis das obere Band durchbricht, verkauft die Strategie, und wenn das untere Band durchbricht, kauft sie. Zusätzliche Positionen werden nur dann gemittelt, wenn sich der Preis um mindestens einen konfigurierbaren Pip-Schritt über den vorherigen Eintrag hinaus bewegt. Der gesamte Stop-Loss wird auf alle Einträge aufgeteilt, wodurch verhindert wird, dass außer Kontrolle geratene Trends wiederholt in die gleiche Richtung eintreten.
Einzelheiten
Eintrittskriterien:
Berechnen Sie einen SMA entweder für Kerzeneröffnungen oder den Hoch-/Tief-Mittelpunkt.
Oberer Umschlag = SMA × (1 + Prozent/100); unterer Umschlag = SMA × (1 − Prozent/100).
Steigen Sie Short ein, wenn der Schlusskurs über dem oberen Band liegt (es sei denn, ein aktueller Stopp hat Shorts gesperrt), steigen Sie Long ein, wenn der Schlusskurs unterhalb des unteren Bandes liegt (es sei denn, Long-Positionen sind gesperrt).
Average-in-Trades sind zulässig, sobald sich der Preis um PipStep Pips (optional skaliert nach Stärke) über die letzte Füllung hinaus bewegt.
Lang/Kurz: Lang und kurz.
Ausstiegskriterien:
Geteilter Take-Profit zum durchschnittlichen Einstiegspreis ± TakeProfit Pips.
Gemeinsamer Stop-Loss zum durchschnittlichen Einstiegspreis ∓ StopLoss / position count Pips.
Sperrflag verhindert Wiedereinfahrt in die gleiche Richtung, bis nach einem Stopp ein Gegensignal ausgelöst wird.
Stops: Ja, aggregierter Stop-Loss und Take-Profit.
Standardwerte:
MaLength = 10
Percent = 0,3
TradeOnFriday = wahr
UseHighLow = false (Öffnet verwenden)
PipStep = 30
IncreasementPower = 0
TakeProfit = 30
StopLoss = 200
TradeVolume = 1
Filter:
Kategorie: Mean-Reversion
Richtung: Beide
Indikatoren: SMA Umschläge
Stoppt: Ja
Komplexität: Mittel
Zeitrahmen: Beliebig
Saisonalität: Optionaler Freitagsfilter
Neuronale Netze: Nein
Divergenz: Nein
Risikostufe: Hoch aufgrund der Mittelwertbildung
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Firebird MA Envelope Exhaustion strategy - Bollinger Bands mean reversion.
/// Buys when close drops below lower band (exhaustion).
/// Sells when close rises above upper band (exhaustion).
/// Exits at the middle band.
/// </summary>
public class FirebirdMaEnvelopeExhaustionStrategy : Strategy
{
private readonly StrategyParam<int> _bbPeriod;
private readonly StrategyParam<decimal> _bbWidth;
private readonly StrategyParam<DataType> _candleType;
public int BbPeriod { get => _bbPeriod.Value; set => _bbPeriod.Value = value; }
public decimal BbWidth { get => _bbWidth.Value; set => _bbWidth.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public FirebirdMaEnvelopeExhaustionStrategy()
{
_bbPeriod = Param(nameof(BbPeriod), 10)
.SetDisplay("BB Period", "Bollinger Bands period", "Indicators");
_bbWidth = Param(nameof(BbWidth), 2m)
.SetDisplay("BB Width", "Bollinger Bands width", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
protected override void OnReseted() { base.OnReseted(); }
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var bb = new BollingerBands { Length = BbPeriod, Width = BbWidth };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(bb, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue value)
{
if (candle.State != CandleStates.Finished)
return;
if (!value.IsFinal || value.IsEmpty)
return;
var bbVal = value as BollingerBandsValue;
if (bbVal == null)
return;
var upper = bbVal.UpBand;
var lower = bbVal.LowBand;
var middle = bbVal.MovingAverage;
if (upper == null || lower == null || middle == null)
return;
var close = candle.ClosePrice;
// Close below lower band = exhaustion, buy
if (close < lower.Value && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// Close above upper band = exhaustion, sell
else if (close > upper.Value && 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 BollingerBands
from StockSharp.Algo.Strategies import Strategy
class firebird_ma_envelope_exhaustion_strategy(Strategy):
def __init__(self):
super(firebird_ma_envelope_exhaustion_strategy, self).__init__()
self._bb_period = self.Param("BbPeriod", 10).SetDisplay("BB Period", "Bollinger Bands period", "Indicators")
self._bb_width = self.Param("BbWidth", 2.0).SetDisplay("BB Width", "Bollinger Bands width", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))).SetDisplay("Candle Type", "Candle timeframe", "General")
@property
def bb_period(self): return self._bb_period.Value
@property
def bb_width(self): return self._bb_width.Value
@property
def candle_type(self): return self._candle_type.Value
def OnReseted(self):
super(firebird_ma_envelope_exhaustion_strategy, self).OnReseted()
def OnStarted2(self, time):
super(firebird_ma_envelope_exhaustion_strategy, self).OnStarted2(time)
bb = BollingerBands()
bb.Length = self.bb_period
bb.Width = self.bb_width
subscription = self.SubscribeCandles(self.candle_type)
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 or bb_value.IsEmpty:
return
if bb_value.UpBand is None or bb_value.LowBand is None or bb_value.MovingAverage is None:
return
upper = float(bb_value.UpBand)
lower = float(bb_value.LowBand)
close = float(candle.ClosePrice)
if close < lower and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif close > upper and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return firebird_ma_envelope_exhaustion_strategy()