Gaussian Detrended Reversion es una estrategia de reversión a la media que utiliza un oscilador de precio detendenciado suavizado con una Media Móvil Arnaud Legoux (ALMA). Las posiciones largas se abren cuando el oscilador suavizado cruza por encima de su versión retardada mientras está por debajo de cero; los cortos se abren en cruces descendentes por encima de cero. Las posiciones se cierran en cruces opuestos o cuando el oscilador cruza la línea cero.
Detalles
Datos: Velas de precio.
Criterios de entrada:
Largo: El DPO suavizado por ALMA cruza por encima de su línea de retardo y está por debajo de cero.
Corto: El DPO suavizado por ALMA cruza por debajo de su línea de retardo y está por encima de cero.
Criterios de salida: Cruce de retardo opuesto o cruce de la línea cero.
Stops: Ninguno.
Valores predeterminados:
PriceLength = 52
SmoothingLength = 52
LagLength = 26
Filtros:
Categoría: Reversión a la media
Dirección: Largo/Corto
Indicadores: EMA, ALMA
Complejidad: Bajo
Nivel de riesgo: Medio
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;
public class GaussianDetrendedReversionStrategy : Strategy
{
private readonly StrategyParam<int> _fastEmaPeriod;
private readonly StrategyParam<int> _slowEmaPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFastEma;
private decimal _prevSlowEma;
public int FastEmaPeriod { get => _fastEmaPeriod.Value; set => _fastEmaPeriod.Value = value; }
public int SlowEmaPeriod { get => _slowEmaPeriod.Value; set => _slowEmaPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public GaussianDetrendedReversionStrategy()
{
_fastEmaPeriod = Param(nameof(FastEmaPeriod), 120)
.SetGreaterThanZero()
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowEmaPeriod = Param(nameof(SlowEmaPeriod), 450)
.SetGreaterThanZero()
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
protected override void OnReseted()
{
base.OnReseted();
_prevFastEma = 0m;
_prevSlowEma = 0m;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fastEma = new ExponentialMovingAverage { Length = FastEmaPeriod };
var slowEma = new ExponentialMovingAverage { Length = SlowEmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(fastEma, slowEma, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastEma);
DrawIndicator(area, slowEma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fastEmaValue, decimal slowEmaValue)
{
if (candle.State != CandleStates.Finished) return;
if (_prevFastEma == 0m || _prevSlowEma == 0m)
{
_prevFastEma = fastEmaValue;
_prevSlowEma = slowEmaValue;
return;
}
if (_prevFastEma <= _prevSlowEma && fastEmaValue > slowEmaValue && Position <= 0)
BuyMarket();
else if (_prevFastEma >= _prevSlowEma && fastEmaValue < slowEmaValue && Position >= 0)
SellMarket();
_prevFastEma = fastEmaValue;
_prevSlowEma = slowEmaValue;
}
}
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 gaussian_detrended_reversion_strategy(Strategy):
"""
GaussianDetrendedReversion: EMA crossover strategy.
Buys when fast EMA crosses above slow EMA, sells on reverse.
"""
def __init__(self):
super(gaussian_detrended_reversion_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 120) .SetDisplay("Fast EMA", "Fast EMA period", "Indicator")
self._slow_period = self.Param("SlowPeriod", 450) .SetDisplay("Slow EMA", "Slow EMA period", "Indicator")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(1))) .SetDisplay("Candle Type", "Time frame for candles", "General")
self._prev_fast = 0.0
self._prev_slow = 0.0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(gaussian_detrended_reversion_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
def OnStarted2(self, time):
super(gaussian_detrended_reversion_strategy, self).OnStarted2(time)
fast = ExponentialMovingAverage()
fast.Length = self._fast_period.Value
slow = ExponentialMovingAverage()
slow.Length = self._slow_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast, slow, self._process_candle).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 _process_candle(self, candle, fast_val, slow_val):
if candle.State != CandleStates.Finished:
return
fast_v = float(fast_val)
slow_v = float(slow_val)
if self._prev_fast <= self._prev_slow and fast_val > slow_val and self.Position <= 0:
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and fast_val < slow_val and self.Position >= 0:
self.SellMarket()
self._prev_fast = fast_val
self._prev_slow = slow_val
def CreateClone(self):
return gaussian_detrended_reversion_strategy()