Ver en GitHub

Estrategia de Cruce de Medias Móviles Fibo

Descripción general

Esta estrategia convierte el asesor experto de MetaTrader EA_Fibo_Avg_001a al framework StockSharp. Utiliza dos medias móviles suavizadas. La longitud de la media lenta es la suma del período base y un desplazamiento basado en Fibonacci. Se abre una posición larga cuando la media rápida cruza por encima de la media lenta, mientras que una posición corta se abre en el cruce contrario. Las posiciones se gestionan con stop-loss, take-profit y un trailing stop. La gestión de dinero opcional puede calcular el volumen de la orden a partir del tamaño de la cartera.

Parámetros

  • CandleType – tipo de datos de velas.
  • FiboNumPeriod – longitud adicional añadida a la media móvil lenta.
  • MaPeriod – período base de las medias móviles.
  • TrailingStop – distancia del trailing stop en pasos de precio.
  • TakeProfit – distancia del take-profit en pasos de precio.
  • StopLoss – distancia del stop-loss en pasos de precio.
  • UseMoneyManagement – activar la gestión de dinero simple.
  • PercentMm – porcentaje de la cartera utilizado cuando la gestión de dinero está activada.
  • LotSize – volumen de orden predeterminado cuando la gestión de dinero está desactivada.

Lógica

  1. Suscribirse a velas y calcular dos medias móviles suavizadas.
  2. Cuando la media rápida cruza por encima de la lenta, comprar. Cuando cruza por debajo, vender.
  3. Tras entrar en una posición, establecer niveles de stop-loss, take-profit y trailing.
  4. Actualizar el trailing stop a medida que el precio se mueve a favor y cerrar posiciones cuando se alcanzan los niveles de protección o se produce el cruce opuesto.
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 crossover of two smoothed moving averages with Fibonacci offset.
/// </summary>
public class FiboAvg001aStrategy : Strategy
{
	private readonly StrategyParam<int> _fiboNumPeriod;
	private readonly StrategyParam<int> _maPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

	public int FiboNumPeriod { get => _fiboNumPeriod.Value; set => _fiboNumPeriod.Value = value; }
	public int MaPeriod { get => _maPeriod.Value; set => _maPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public FiboAvg001aStrategy()
	{
		_fiboNumPeriod = Param(nameof(FiboNumPeriod), 11)
			.SetGreaterThanZero()
			.SetDisplay("Fibo Period", "Additional length for slow MA", "Indicators");

		_maPeriod = Param(nameof(MaPeriod), 21)
			.SetGreaterThanZero()
			.SetDisplay("MA Period", "Base moving average period", "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();
		_prevFast = 0;
		_prevSlow = 0;
		_hasPrev = false;
	}

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

		var fastMa = new SmoothedMovingAverage { Length = MaPeriod };
		var slowMa = new SmoothedMovingAverage { Length = MaPeriod + FiboNumPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fastMa, slowMa, ProcessCandle)
			.Start();
	}

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

		if (!_hasPrev)
		{
			_prevFast = fast;
			_prevSlow = slow;
			_hasPrev = true;
			return;
		}

		// Fast crosses above slow -> buy
		if (_prevFast <= _prevSlow && fast > slow)
		{
			if (Position < 0)
				BuyMarket();
			if (Position <= 0)
				BuyMarket();
		}
		// Fast crosses below slow -> sell
		else if (_prevFast >= _prevSlow && fast < slow)
		{
			if (Position > 0)
				SellMarket();
			if (Position >= 0)
				SellMarket();
		}

		_prevFast = fast;
		_prevSlow = slow;
	}
}