Die Strategie rekonstruiert den Dual-Timeframe-Experten "Exp_ColorX2MA_X2" für StockSharp. Sie schichtet zwei ColorX2MA-Filter: eine Trendkarte für den höheren Zeitrahmen und einen Einstiegsauslöser für den niedrigeren Zeitrahmen. Beide ColorX2MA-Werte werden durch Kaskadierung zweier konfigurierbarer gleitender Durchschnitte aufgebaut und anschließend entsprechend der aktuellen Steigung eingefärbt. Handelsentscheidungen werden getroffen, wenn sich die Farbe des niedrigeren Zeitrahmens in Richtung des Trends des höheren Zeitrahmens ändert.
Die Implementierung unterstützt die ursprünglichen Optionen für angewandte Preise und die gängigsten Glättungsmodi (SMA, EMA, SMMA, LWMA, Jurik). Wenn der Jurik-Indikator eine Phase-Eigenschaft bereitstellt, wird diese mit dem konfigurierten Phasenwert aktualisiert.
Handelsregeln
Long-Einstieg
Die ColorX2MA-Farbe des höheren Zeitrahmens ist bullisch (trend direction > 0).
Die ColorX2MA-Farbe des niedrigeren Zeitrahmens wechselte von bullisch im vorherigen Balken zu neutral oder bärisch im letzten abgeschlossenen Balken (Clr[1] == 1 und Clr[0] != 1).
Long-Handel ist aktiviert.
Short-Einstieg
Die ColorX2MA-Farbe des höheren Zeitrahmens ist bärisch (trend direction < 0).
Die ColorX2MA-Farbe des niedrigeren Zeitrahmens wechselte von bärisch im vorherigen Balken zu neutral oder bullisch im letzten abgeschlossenen Balken (Clr[1] == 2 und Clr[0] != 2).
Short-Handel ist aktiviert.
Long-Ausstieg
Wenn eine bärische Farbe im niedrigeren Zeitrahmen erscheint (Clr[1] == 2) und die sekundäre Long-Schließerlaubnis aktiviert ist, oder der Trend des höheren Zeitrahmens bärisch wird, während die primäre Long-Schließerlaubnis aktiviert ist.
Short-Ausstieg
Wenn eine bullische Farbe im niedrigeren Zeitrahmen erscheint (Clr[1] == 1) und die sekundäre Short-Schließerlaubnis aktiviert ist, oder der Trend des höheren Zeitrahmens bullisch wird, während die primäre Short-Schließerlaubnis aktiviert ist.
Stops
Optionale Stop-Loss- und Take-Profit-Abstände werden in Punkten angegeben (multipliziert mit dem Preisschritt des Instruments). Sie werden bei jeder abgeschlossenen Signalkerze ausgewertet, indem die Kerzenextreme mit dem durchschnittlichen Positionspreis verglichen werden.
Standardwerte
Trend-Zeitrahmen: 6-Stunden-Kerzen.
Signal-Zeitrahmen: 30-Minuten-Kerzen.
Trend-Glättung: SMA(12) in Jurik(5, Phase 15).
Signal-Glättung: SMA(12) in Jurik(5, Phase 15).
Angewandter Preis: Schlusskurs.
Signalversatz: 1 Balken in beiden Zeitrahmen.
Erlaubnisse: Long-/Short-Einstiege und -Ausstiege sind aktiviert.
Stop-Loss: 1000 Punkte (umgerechnet mit dem Preisschritt).
Take-Profit: 2000 Punkte (umgerechnet mit dem Preisschritt).
Filter und Hinweise
Richtung: handelt Long und Short, gesteuert über Erlaubnisflags.
Zeitrahmen: dualer Zeitrahmen (Trend auf HTF, Einstiege auf LTF).
Indikatoren: zweistufiges ColorX2MA mit konfigurierbaren Glättungsmethoden.
Glättungsunterstützung: Sma, Ema, Smma, Lwma, Jurik. Andere Modi der Originalbibliothek sind nicht implementiert.
Angewandte Preise: alle 12 ursprünglichen Formeln einschließlich TrendFollow- und Demark-Preisen.
Stops: optionaler Stop-Loss und Take-Profit mit festem Abstand.
Komplexität: mittel, da zwei Zeitrahmen und Farb-Puffer synchronisiert werden.
Geeignet für: Trendfolge-Setups auf FX, Indizes oder Krypto, bei denen der ColorX2MA-Indikator bevorzugt wird.
Verwendungshinweise
Den höheren Zeitrahmen deutlich größer als den Signal-Zeitrahmen halten, um häufige Whipsaws zu vermeiden.
Den Signalversatz-Parameter (SignalSignalBar) enger setzen, um schneller zu reagieren, oder erhöhen, um mehr zu glätten.
Wenn das Instrument kein PriceStep bereitstellt, werden die Stop-/Take-Abstände direkt in Preiseinheiten interpretiert.
Jurik-Glättung erfordert ein lizenziertes StockSharp-Indikatorpaket; wenn nicht verfügbar, läuft die Strategie weiterhin mit den anderen Glättungsoptionen.
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;
/// <summary>
/// ColorX2MA X2 strategy (simplified). Uses dual EMA smoothing to detect trend color transitions.
/// Buys when the smoothed MA turns up, sells when it turns down.
/// </summary>
public class ExpColorX2MaX2Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int FastLength
{
get => _fastLength.Value;
set => _fastLength.Value = value;
}
public int SlowLength
{
get => _slowLength.Value;
set => _slowLength.Value = value;
}
public ExpColorX2MaX2Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candles", "General");
_fastLength = Param(nameof(FastLength), 12)
.SetGreaterThanZero()
.SetDisplay("Fast Length", "Fast EMA period", "Indicators");
_slowLength = Param(nameof(SlowLength), 26)
.SetGreaterThanZero()
.SetDisplay("Slow Length", "Slow EMA period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fastEma = new ExponentialMovingAverage { Length = FastLength };
var slowEma = new ExponentialMovingAverage { Length = SlowLength };
decimal prevFast = 0, prevSlow = 0;
var hasPrev = false;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastEma, slowEma, (ICandleMessage candle, decimal fastValue, decimal slowValue) =>
{
if (candle.State != CandleStates.Finished)
return;
if (!hasPrev)
{
prevFast = fastValue;
prevSlow = slowValue;
hasPrev = true;
return;
}
if (!IsFormedAndOnlineAndAllowTrading())
{
prevFast = fastValue;
prevSlow = slowValue;
return;
}
// Fast crosses above slow
if (prevFast <= prevSlow && fastValue > slowValue && Position <= 0)
BuyMarket();
// Fast crosses below slow
else if (prevFast >= prevSlow && fastValue < slowValue && Position >= 0)
SellMarket();
prevFast = fastValue;
prevSlow = slowValue;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastEma);
DrawIndicator(area, slowEma);
DrawOwnTrades(area);
}
}
}
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 exp_color_x2_ma_x2_strategy(Strategy):
def __init__(self):
super(exp_color_x2_ma_x2_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Candles", "General")
self._fast_length = self.Param("FastLength", 12) \
.SetDisplay("Fast Length", "Fast EMA period", "Indicators")
self._slow_length = self.Param("SlowLength", 26) \
.SetDisplay("Slow Length", "Slow EMA period", "Indicators")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastLength(self):
return self._fast_length.Value
@property
def SlowLength(self):
return self._slow_length.Value
def OnReseted(self):
super(exp_color_x2_ma_x2_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(exp_color_x2_ma_x2_strategy, self).OnStarted2(time)
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
fast_ema = ExponentialMovingAverage()
fast_ema.Length = self.FastLength
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self.SlowLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast_ema, slow_ema, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_ema)
self.DrawIndicator(area, slow_ema)
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 not self._has_prev:
self._prev_fast = fv
self._prev_slow = sv
self._has_prev = True
return
if self._prev_fast <= self._prev_slow and fv > sv and self.Position <= 0:
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and fv < sv and self.Position >= 0:
self.SellMarket()
self._prev_fast = fv
self._prev_slow = sv
def CreateClone(self):
return exp_color_x2_ma_x2_strategy()