Ver en GitHub

Estrategia de Seguimiento de Tendencia con Parabolic Compra Venta

Combina Parabolic SAR con cruces de medias móviles. Las entradas largas ocurren cuando el precio está por encima de una SMA de tendencia larga, la EMA rápida cruza por encima de la EMA lenta y el SAR es alcista. Las entradas cortas usan las condiciones opuestas. El stop loss se coloca en la SMA de tendencia y el take profit usa una ratio riesgo/recompensa.

Detalles

  • Entrada:
    • Largo: precio > SMA de tendencia, EMA rápida cruza por encima de EMA lenta, SAR alcista
    • Corto: precio < SMA de tendencia, EMA rápida cruza por debajo de EMA lenta, SAR bajista
  • Salida:
    • stop en SMA de tendencia
    • take profit = riesgo/recompensa * distancia desde entrada hasta SMA de tendencia
  • Indicadores: Parabolic SAR, SMA, EMA
  • Marco temporal: configurable
  • Tipo: Seguimiento de tendencia
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 Parabolic Buy Sell strategy using EMA crossover.
/// </summary>
public class TrendFollowingParabolicBuySellStrategy : Strategy
{
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<DataType> _candleType;

	public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public TrendFollowingParabolicBuySellStrategy()
	{
		_slowLength = Param(nameof(SlowLength), 40)
			.SetGreaterThanZero()
			.SetDisplay("Slow Length", "Slow EMA period", "General");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		var fast = new ExponentialMovingAverage { Length = 14 };
		var slow = new ExponentialMovingAverage { Length = SlowLength };
		var prevF = 0m; var prevS = 0m; var init = false;
		var lastSignal = DateTimeOffset.MinValue;
		var cooldown = TimeSpan.FromMinutes(360);
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, (candle, f, s) =>
		{
			if (candle.State != CandleStates.Finished) return;
			if (!fast.IsFormed || !slow.IsFormed) return;
			if (!init) { prevF = f; prevS = s; init = true; return; }
			if (candle.OpenTime - lastSignal >= cooldown)
			{
				if (prevF <= prevS && f > s && Position <= 0) { BuyMarket(); lastSignal = candle.OpenTime; }
				else if (prevF >= prevS && f < s && Position >= 0) { SellMarket(); lastSignal = candle.OpenTime; }
			}
			prevF = f; prevS = s;
		}).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
	}
}