Esta estrategia compara dos medias móviles simples (SMA) y opera basándose en la divergencia entre ellas.
Utiliza la diferencia entre la SMA rápida y la SMA lenta de la vela anterior como medida de divergencia. Si esta divergencia es positiva pero dentro de un rango especificado, la estrategia abre una posición larga. Si la divergencia es negativa y dentro del rango espejado, abre una posición corta. El riesgo se gestiona mediante niveles opcionales de stop-loss y take-profit.
Detalles
Criterios de entrada:
Largo: SMA rápida anterior - SMA lenta anterior >= DvBuySell y <= DvStayOut.
Corto: SMA rápida anterior - SMA lenta anterior <= -DvBuySell y >= -DvStayOut.
Criterios de salida: Las posiciones se cierran mediante stop-loss o take-profit si están configurados.
Stops: Soportados a través de StartProtection con desplazamientos de precio absolutos.
Valores predeterminados:
FastPeriod = 7
SlowPeriod = 88
DvBuySell = 0.0011
DvStayOut = 0.0079
Filtros:
Categoría: Seguimiento de tendencia
Dirección: Ambos
Indicadores: SMA
Stops: Opcional
Complejidad: Básico
Marco temporal: Corto plazo
Estacionalidad: No
Redes neuronales: No
Divergencia: Sí
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;
/// <summary>
/// Strategy based on divergence between fast and slow EMA.
/// </summary>
public class DivergenceTraderStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public DivergenceTraderStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 12)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA length", "Parameters");
_slowPeriod = Param(nameof(SlowPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow EMA length", "Parameters");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fastEma = new ExponentialMovingAverage { Length = FastPeriod };
var slowEma = new ExponentialMovingAverage { Length = SlowPeriod };
SubscribeCandles(CandleType)
.Bind(fastEma, slowEma, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev)
{
_prevFast = fastValue;
_prevSlow = slowValue;
_hasPrev = true;
return;
}
var crossUp = _prevFast <= _prevSlow && fastValue > slowValue;
var crossDown = _prevFast >= _prevSlow && fastValue < slowValue;
if (crossUp && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (crossDown && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevFast = fastValue;
_prevSlow = slowValue;
}
}