Ver en GitHub

Captura de Tendencia

Estrategia de seguimiento de tendencia que combina el Parabolic SAR con un filtro ADX. Las operaciones largas ocurren cuando el precio cierra por encima del valor SAR mientras el ADX permanece por debajo de un umbral, señalando una tendencia naciente. Las operaciones cortas se abren en la condición opuesta.

Detalles

  • Criterios de entrada: Precio por encima/debajo del Parabolic SAR con ADX por debajo de AdxLevel.
  • Largo/Corto: Ambos direcciones.
  • Criterios de salida: Stop loss, take profit o señal opuesta.
  • Stops: Stop loss fijo, take profit y ajuste de break-even.
  • Valores predeterminados:
    • SarStep = 0.02
    • SarMax = 0.2
    • AdxPeriod = 14
    • AdxLevel = 20
    • StopLoss = 1800 puntos
    • TakeProfit = 500 puntos
    • BreakEven = 50 puntos
    • CandleType = TimeSpan.FromMinutes(1)
  • Filtros:
    • Categoría: Tendencia
    • Dirección: Ambos
    • Indicadores: Parabolic SAR, ADX
    • Stops: Sí
    • Complejidad: Básico
    • Marco temporal: Intradía (1m)
    • Estacionalidad: No
    • Redes neuronales: No
    • Divergencia: No
    • 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>
/// Trend following strategy using Parabolic SAR with EMA confirmation.
/// </summary>
public class TrendCaptureStrategy : Strategy
{
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevClose;
	private decimal _prevEma;
	private decimal _prevSar;
	private bool _hasPrev;

	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public TrendCaptureStrategy()
	{
		_emaPeriod = Param(nameof(EmaPeriod), 20)
			.SetGreaterThanZero()
			.SetDisplay("EMA Period", "EMA period for trend", "Indicators");

		_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();
		_prevClose = 0;
		_prevEma = 0;
		_prevSar = 0;
		_hasPrev = false;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var sar = new ParabolicSar();
		var ema = new ExponentialMovingAverage { Length = EmaPeriod };

		SubscribeCandles(CandleType).Bind(sar, ema, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal sarValue, decimal emaValue)
	{
		if (candle.State != CandleStates.Finished) return;

		var close = candle.ClosePrice;

		if (!_hasPrev)
		{
			_prevClose = close;
			_prevEma = emaValue;
			_prevSar = sarValue;
			_hasPrev = true;
			return;
		}

		var aboveSar = close > sarValue;
		var belowSar = close < sarValue;
		var prevAboveSar = _prevClose > _prevSar;
		var prevBelowSar = _prevClose < _prevSar;

		if (!prevAboveSar && aboveSar && close > emaValue && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (!prevBelowSar && belowSar && close < emaValue && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevClose = close;
		_prevEma = emaValue;
		_prevSar = sarValue;
	}
}