Verwendet einen doppelt geglätteten exponentiellen gleitenden Durchschnitt, bekannt als XMA der 3. Generation, um lokale Hochs und Tiefs zu identifizieren. Eine Long-Position wird eröffnet, wenn der XMA von einem lokalen Tief nach oben dreht. Shorts werden initiiert, wenn der XMA von einem lokalen Hoch umkehrt. Positionen werden bei entgegengesetzten Signalen umgekehrt, und es wird kein expliziter Stop oder Take Profit verwendet.
Details
Einstiegskriterien: Der XMA bildet ein lokales Minimum oder Maximum und kehrt um.
Long/Short: Beide Richtungen.
Ausstiegskriterien: Entgegengesetztes Signal.
Stops: Keine.
Standardwerte:
MaLength = 50
CandleType = TimeSpan.FromHours(4)
Filter:
Kategorie: Trend
Richtung: Beide
Indikatoren: EMA
Stops: Nein
Komplexität: Grundlegend
Zeitrahmen: Intraday (4H)
Saisonalität: Nein
Neuronale Netze: Nein
Divergenz: Nein
Risikolevel: Mittel
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>
/// 3rd Generation XMA reversal strategy using double-smoothed EMA turning points.
/// </summary>
public class ThirdGenerationXmaReversalStrategy : Strategy
{
private readonly StrategyParam<int> _maLength;
private readonly StrategyParam<DataType> _candleType;
private decimal _prev1;
private decimal _prev2;
private int _barCount;
public int MaLength { get => _maLength.Value; set => _maLength.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ThirdGenerationXmaReversalStrategy()
{
_maLength = Param(nameof(MaLength), 50)
.SetDisplay("MA Length", "Base length for the moving average", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prev1 = 0;
_prev2 = 0;
_barCount = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ema1 = new ExponentialMovingAverage { Length = MaLength };
var ema2 = new ExponentialMovingAverage { Length = MaLength / 2 > 0 ? MaLength / 2 : 10 };
SubscribeCandles(CandleType).Bind(ema1, ema2, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal ema1Value, decimal ema2Value)
{
if (candle.State != CandleStates.Finished) return;
// XMA = 2*ema1 - ema2 (third generation concept)
var xma = 2m * ema1Value - ema2Value;
_barCount++;
if (_barCount >= 3)
{
// Local minimum => buy
if (_prev1 < _prev2 && xma > _prev1 && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
// Local maximum => sell
else if (_prev1 > _prev2 && xma < _prev1 && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
}
_prev2 = _prev1;
_prev1 = xma;
}
}
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 third_generation_xma_reversal_strategy(Strategy):
def __init__(self):
super(third_generation_xma_reversal_strategy, self).__init__()
self._ma_length = self.Param("MaLength", 50) \
.SetDisplay("MA Length", "Base length for the moving average", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev1 = 0.0
self._prev2 = 0.0
self._bar_count = 0
@property
def ma_length(self):
return self._ma_length.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(third_generation_xma_reversal_strategy, self).OnReseted()
self._prev1 = 0.0
self._prev2 = 0.0
self._bar_count = 0
def OnStarted2(self, time):
super(third_generation_xma_reversal_strategy, self).OnStarted2(time)
ema1 = ExponentialMovingAverage()
ema1.Length = self.ma_length
ema2 = ExponentialMovingAverage()
half = int(self.ma_length / 2)
ema2.Length = half if half > 0 else 10
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema1, ema2, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle, ema1_value, ema2_value):
if candle.State != CandleStates.Finished:
return
# XMA = 2*ema1 - ema2 (third generation concept)
xma = 2 * ema1_value - ema2_value
self._bar_count += 1
if self._bar_count >= 3:
# Local minimum => buy
if self._prev1 < self._prev2 and xma > self._prev1 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Local maximum => sell
elif self._prev1 > self._prev2 and xma < self._prev1 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev2 = self._prev1
self._prev1 = xma
def CreateClone(self):
return third_generation_xma_reversal_strategy()