Ver en GitHub

Parabolic SAR con Confirmación de MACD

Esta estrategia combina el indicador Parabolic SAR con la confirmación del MACD. Se abre una posición cuando el precio cruza el SAR en una dirección respaldada por el MACD, con el objetivo de capturar reversiones de tendencia.

Detalles

  • Criterios de entrada: El precio cruza el SAR y la línea MACD está en el mismo lado que su línea de señal.
  • Largo/Corto: Ambas direcciones.
  • Criterios de salida: Cruce opuesto de precio/SAR o MACD.
  • Stops: No.
  • Valores predeterminados:
    • SarStart = 0.02m
    • SarIncrement = 0.02m
    • SarMax = 0.2m
    • MacdFast = 12
    • MacdSlow = 26
    • MacdSignal = 9
    • CandleType = TimeSpan.FromMinutes(5)
  • Filtros:
    • Categoría: Tendencia
    • Dirección: Ambos
    • Indicadores: Parabolic SAR, MACD
    • Stops: No
    • Complejidad: Intermedio
    • Marco temporal: Intradía
    • Estacionalidad: No
    • Redes neuronales: No
    • Divergencia: No
    • Nivel de riesgo: Medio
using System;

using Ecng.Common;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// EMA crossover with MACD confirmation.
/// </summary>
public class ParabolicSarMacdTrendZoneStrategy : Strategy
{
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<DataType> _candleType;

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

	public ParabolicSarMacdTrendZoneStrategy()
	{
		_fastLength = Param(nameof(FastLength), 14).SetGreaterThanZero();
		_slowLength = Param(nameof(SlowLength), 40).SetGreaterThanZero();
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame());
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var fast = new ExponentialMovingAverage { Length = FastLength };
		var slow = new ExponentialMovingAverage { Length = SlowLength };
		var macd = new MovingAverageConvergenceDivergenceSignal();

		var prevF = 0m;
		var prevS = 0m;
		var init = false;
		var lastSignal = DateTimeOffset.MinValue;
		var cooldown = TimeSpan.FromMinutes(360);

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(fast, slow, macd, (candle, fv, sv, macdVal) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!fv.IsFormed || !sv.IsFormed || !macdVal.IsFormed)
					return;

				var f = fv.ToDecimal();
				var s = sv.ToDecimal();
				var macdTyped = (MovingAverageConvergenceDivergenceSignalValue)macdVal;
				var macdLine = macdTyped.Macd;
				var signalLine = macdTyped.Signal;

				if (!init)
				{
					prevF = f;
					prevS = s;
					init = true;
					return;
				}

				if (candle.OpenTime - lastSignal >= cooldown)
				{
					if (prevF <= prevS && f > s && macdLine > signalLine && Position <= 0)
					{
						BuyMarket();
						lastSignal = candle.OpenTime;
					}
					else if (prevF >= prevS && f < s && macdLine < signalLine && 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);
		}
	}
}