Esta estrategia construye un oscilador OSMA de Momentum de cero rezago personalizado utilizando cinco cálculos de Momentum.
Cuando el valor del oscilador de hace dos barras está por debajo del valor de hace tres barras, la tendencia se considera alcista.
En este caso, las posiciones cortas se cierran y se puede abrir una nueva posición larga si el valor más reciente está por encima del valor de hace dos barras.
Cuando el valor de hace dos barras está por encima del valor de hace tres barras, la tendencia es bajista, las posiciones largas se cierran y se puede abrir una corta si el último valor está por debajo del valor de hace dos barras.
Parámetros
Smoothing1 – primer factor de suavizado para la tendencia lenta.
Smoothing2 – segundo factor de suavizado para la línea OSMA.
Factor1-5 – pesos aplicados a cada componente de Momentum.
MomentumPeriod1-5 – períodos para los indicadores de Momentum.
CandleType – marco temporal de velas para los cálculos.
BuyOpen – permitir abrir posiciones largas.
SellOpen – permitir abrir posiciones cortas.
BuyClose – permitir cerrar posiciones largas.
SellClose – permitir cerrar posiciones cortas.
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 the zero-lag momentum OSMA indicator.
/// Uses weighted momentum composite with EMA smoothing for trend detection.
/// </summary>
public class ColorZerolagMomentumOsmaStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevOsma;
private decimal _prevPrevOsma;
private int _count;
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 ColorZerolagMomentumOsmaStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 8)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA period", "General");
_slowPeriod = Param(nameof(SlowPeriod), 21)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow EMA period", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle Type", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevOsma = 0;
_prevPrevOsma = 0;
_count = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
SubscribeCandles(CandleType)
.Bind(fast, slow, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished)
return;
var osma = fastValue - slowValue;
_count++;
if (_count < 3)
{
_prevPrevOsma = _prevOsma;
_prevOsma = osma;
return;
}
// Buy when OSMA turns up (was decreasing, now increasing)
var turnUp = _prevOsma < _prevPrevOsma && osma > _prevOsma;
// Sell when OSMA turns down (was increasing, now decreasing)
var turnDown = _prevOsma > _prevPrevOsma && osma < _prevOsma;
if (turnUp && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (turnDown && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevPrevOsma = _prevOsma;
_prevOsma = osma;
}
}