Die One Two Three Strategie handelt Ausbrüche des Chaikin-Oszillators nach einer ausgedehnten Phase flacher Akkumulation. Sie emuliert den originalen MetaTrader 5-Experten, indem sie eine Akkumulations-/Distributions-Linie mit zwei EMAs kombiniert, validiert, dass der Marktdruck mehrere Bars lang neutral geblieben ist, und dann bei einem starken Anstieg des Chaikin-Momentums einsteigt. Der StockSharp-Port hält Lot-Sizing, Stop-Management und Trailing-Logik durch Strategieparameter konfigurierbar.
Konzept
Den Chaikin-Oszillator als Differenz zwischen einem schnellen und einem langsamen exponentiellen gleitenden Durchschnitt berechnen, der auf die Akkumulations-/Distributions-Linie aus den eingehenden Kerzen angewendet wird.
Die letzten BarsCount Oszillatorwerte verfolgen und Bars klassifizieren, bei denen der absolute Chaikin-Wert innerhalb von FlatLevel bleibt.
Handel nur erlauben, wenn mehr als FlatPercent Prozent dieser gespeicherten Werte innerhalb des Flat-Bereichs geblieben sind, was auf eine ruhige Akkumulation hinweist.
Wenn eine neue Kerze abschließt, in die Richtung des Chaikin-Impulses einsteigen, wenn seine Größe OpenLevel überschreitet.
Einstiegsregeln
Long: Der Chaikin-Oszillator auf der gerade geschlossenen Kerze ist größer oder gleich OpenLevel und die aktuelle Nettoposition ist nicht positiv.
Short: Der Chaikin-Oszillator auf der gerade geschlossenen Kerze ist kleiner oder gleich dem negativen OpenLevel und die aktuelle Nettoposition ist nicht negativ.
Aufträge werden zum Markt ausgegeben. Wenn die Strategie eine Gegenposition hält, wird die Auftragsgröße erhöht, um das bestehende Exposure zu glätten, bevor der neue Trade eröffnet wird.
Ausstiegsregeln
Ein fester Stop-Loss (StopLossPips) und Take-Profit (TakeProfitPips) werden in Preisabweichungen übersetzt, indem der Sicherheitspreisschritt verwendet wird (1 Pip = 1 Preisschritt), und unmittelbar nach dem Einstieg angewendet.
Ein optionaler Trailing Stop passt den Schutz-Stop an, sobald der Preis mindestens TrailingStopPips + TrailingStepPips zugunsten des Trades läuft. Der neue Stop wird genau TrailingStopPips vom aktuellen Schlusskurs entfernt platziert, während der Step-Buffer ein vorzeitiges Anziehen verhindert.
Wenn innerhalb des abgeschlossenen Kerzenbereichs entweder der Stop oder das Ziel berührt wird, wird die Position zum Markt geschlossen.
Risiko- und Geldmanagement
OrderVolume kontrolliert die Menge, die mit jeder Marktorder gesendet wird. Die Strategie addiert oder subtrahiert beim Richtungswechsel automatisch die aktuelle Positionsgröße, sodass Umkehrungen in einem einzigen Trade erfolgen.
Das Setzen eines pip-basierten Parameters auf null deaktiviert diese Komponente (zum Beispiel hält ein Take-Profit von null Trades offen, bis der Stop oder das Gegensignal auftritt).
Parameter
OrderVolume – Basis-Volumen für Einstiege.
StopLossPips – Abstand in Pips zwischen Einstiegspreis und Schutz-Stop.
TakeProfitPips – Abstand in Pips zwischen Einstiegspreis und Gewinnziel.
TrailingStopPips – Abstand in Pips, der zwischen Preis und Trailing Stop gehalten wird. Auf null setzen, um Trailing zu deaktivieren.
TrailingStepPips – Minimaler Pip-Gewinn über den Trailing-Abstand hinaus, bevor der Stop erneut bewegt wird.
FastLength – Periode des schnellen EMA im Chaikin-Oszillator.
SlowLength – Periode des langsamen EMA im Chaikin-Oszillator.
FlatLevel – Absoluter Chaikin-Wert, der noch als flaches Marktverhalten zählt.
OpenLevel – Chaikin-Größe, die erforderlich ist, um einen neuen Trade auszulösen, sobald die Flat-Bedingung erfüllt ist.
BarsCount – Anzahl der jüngsten Chaikin-Werte, die bei der Berechnung des Flat-Verhältnisses ausgewertet werden.
FlatPercent – Mindestprozentsatz der gespeicherten Werte, die innerhalb des Flat-Bereichs bleiben müssen, um den Handel zu erlauben.
CandleType – Kerzendatentyp oder Zeitrahmen, der die Indikatorberechnungen speist.
Hinweise
Die Trailing-Logik spiegelt den MetaTrader-Experten wider: Wenn TrailingStopPips ungleich null ist, halten Sie TrailingStepPips positiv, um einen stagnierenden Stop zu vermeiden.
Da StockSharp-Strategien mit dem Sicherheitspreisschritt arbeiten, gehen die pip-basierten Abstände davon aus, dass ein Pip einem Preisschritt entspricht; passen Sie die Parameterwerte entsprechend für Instrumente mit unterschiedlichen Tick-Größen an.
Die Strategie verarbeitet nur abgeschlossene Kerzen und versucht nicht, intrabar zu reagieren, was dem ursprünglichen Experten entspricht, der bei neuen Bar-Eröffnungen ausführt.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class OneTwoThreeStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal? _prevFast, _prevSlow;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public OneTwoThreeStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 5).SetGreaterThanZero().SetDisplay("Fast EMA", "Fast period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 13).SetGreaterThanZero().SetDisplay("Slow EMA", "Slow period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = null;
_prevSlow = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = null; _prevSlow = null;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fast, slow, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!IsFormedAndOnlineAndAllowTrading()) { _prevFast = fast; _prevSlow = slow; return; }
if (_prevFast == null || _prevSlow == null) { _prevFast = fast; _prevSlow = slow; return; }
var prevAbove = _prevFast.Value > _prevSlow.Value;
var currAbove = fast > slow;
_prevFast = fast; _prevSlow = slow;
if (!prevAbove && currAbove && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
else if (prevAbove && !currAbove && 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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class one_two_three_strategy(Strategy):
def __init__(self):
super(one_two_three_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 5) \
.SetDisplay("Fast EMA", "Fast period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 13) \
.SetDisplay("Slow EMA", "Slow period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
def OnReseted(self):
super(one_two_three_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(one_two_three_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast = ExponentialMovingAverage()
fast.Length = self.FastPeriod
slow = ExponentialMovingAverage()
slow.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, slow, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if self._prev_fast is None or self._prev_slow is None:
self._prev_fast = fv
self._prev_slow = sv
return
prev_above = self._prev_fast > self._prev_slow
curr_above = fv > sv
self._prev_fast = fv
self._prev_slow = sv
if not prev_above and curr_above and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif prev_above and not curr_above and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return one_two_three_strategy()