Diese Strategie ist ein Port des MQL5-Experten Exp_ColorX2MA_Digit.
Der ursprüngliche Algorithmus färbt einen doppelt geglätteten gleitenden Durchschnitt je nach seiner Neigung in verschiedenen Farben ein und verwendet diese Farben zur Erzeugung von Handelssignalen.
In dieser C#-Version wird das Verhalten durch zwei einfache gleitende Durchschnitte angenähert und auf deren Kreuzungen gehandelt.
Handelslogik
Ein schneller gleitender Durchschnitt glättet die Preisreihe.
Ein langsamer gleitender Durchschnitt glättet das Ergebnis des schnellen.
Wenn der schnelle Durchschnitt den langsamen von unten nach oben kreuzt, eröffnet die Strategie eine Long-Position und schließt eine vorhandene Short-Position.
Wenn der schnelle Durchschnitt den langsamen von oben nach unten kreuzt, eröffnet die Strategie eine Short-Position und schließt eine vorhandene Long-Position.
Signale werden nur nach dem Schließen der Kerze verarbeitet.
Parameter
FastLength – Länge der ersten Glättung (Standard 12).
SlowLength – Länge der zweiten Glättung (Standard 5).
CandleType – Zeitrahmen der für Berechnungen verwendeten Kerzen.
Die Strategie verwendet ausschließlich die High-Level-API: SubscribeCandles mit Bind zur Versorgung der Indikatoren und BuyMarket/SellMarket zur Positionsverwaltung. Kommentare im Code sind auf Englisch für einfachere Wartung.
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>
/// Trend following strategy based on two sequential moving averages.
/// Trades on crossovers of fast and slow SMAs.
/// </summary>
public class ColorX2MaDigitStrategy : Strategy
{
private readonly StrategyParam<int> _fastLength;
private readonly StrategyParam<int> _slowLength;
private readonly StrategyParam<DataType> _candleType;
private decimal? _prevFast;
private decimal? _prevSlow;
public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ColorX2MaDigitStrategy()
{
_fastLength = Param(nameof(FastLength), 8)
.SetGreaterThanZero()
.SetDisplay("Fast MA Length", "Length of the first smoothing", "Parameters");
_slowLength = Param(nameof(SlowLength), 21)
.SetGreaterThanZero()
.SetDisplay("Slow MA Length", "Length of the second smoothing", "Parameters");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for strategy", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = null;
_prevSlow = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = null;
_prevSlow = null;
var fastMa = new ExponentialMovingAverage { Length = FastLength };
var slowMa = new ExponentialMovingAverage { Length = SlowLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastMa, slowMa, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastMa);
DrawIndicator(area, slowMa);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fastMa, decimal slowMa)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (_prevFast is null || _prevSlow is null)
{
_prevFast = fastMa;
_prevSlow = slowMa;
return;
}
var wasAbove = _prevFast > _prevSlow;
var isAbove = fastMa > slowMa;
// Fast MA crossed above slow MA -> buy
if (!wasAbove && isAbove && Position <= 0)
BuyMarket();
// Fast MA crossed below slow MA -> sell
else if (wasAbove && !isAbove && Position >= 0)
SellMarket();
_prevFast = fastMa;
_prevSlow = slowMa;
}
}
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 color_x2_ma_digit_strategy(Strategy):
def __init__(self):
super(color_x2_ma_digit_strategy, self).__init__()
self._fast_length = self.Param("FastLength", 8) \
.SetDisplay("Fast MA Length", "Length of the first smoothing", "Parameters")
self._slow_length = self.Param("SlowLength", 21) \
.SetDisplay("Slow MA Length", "Length of the second smoothing", "Parameters")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe for strategy", "General")
self._prev_fast = None
self._prev_slow = None
@property
def fast_length(self):
return self._fast_length.Value
@property
def slow_length(self):
return self._slow_length.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(color_x2_ma_digit_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(color_x2_ma_digit_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast_ma = ExponentialMovingAverage()
fast_ma.Length = self.fast_length
slow_ma = ExponentialMovingAverage()
slow_ma.Length = self.slow_length
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast_ma, slow_ma, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_ma)
self.DrawIndicator(area, slow_ma)
self.DrawOwnTrades(area)
def process_candle(self, candle, fast_ma, slow_ma):
if candle.State != CandleStates.Finished:
return
fast_ma = float(fast_ma)
slow_ma = float(slow_ma)
if self._prev_fast is None or self._prev_slow is None:
self._prev_fast = fast_ma
self._prev_slow = slow_ma
return
was_above = self._prev_fast > self._prev_slow
is_above = fast_ma > slow_ma
if not was_above and is_above and self.Position <= 0:
self.BuyMarket()
elif was_above and not is_above and self.Position >= 0:
self.SellMarket()
self._prev_fast = fast_ma
self._prev_slow = slow_ma
def CreateClone(self):
return color_x2_ma_digit_strategy()