Ver en GitHub

Estrategia de Tendencia Fibo Candles

Esta estrategia utiliza la técnica personalizada Fibo Candles para determinar la dirección de la tendencia. El indicador pinta cada vela en uno de dos colores basándose en una comparación de ratio de Fibonacci entre el cierre actual y el rango máximo/mínimo reciente. Un cambio de color señala una posible reversión. Cuando el color se vuelve alcista, la estrategia cierra cualquier posición corta y abre una larga. Cuando el color se vuelve bajista, cierra cualquier posición larga y abre una corta.

El método se adapta a la volatilidad del mercado mediante un período de lookback y un nivel de Fibonacci seleccionable. Un stop loss y take profit en puntos absolutos protegen cada operación.

Detalles

  • Criterios de entrada:
    • Largo: El color de la vela actual cambia de bajista a alcista.
    • Corto: El color de la vela actual cambia de alcista a bajista.
  • Largo/Corto: Ambos lados.
  • Criterios de salida:
    • Las posiciones existentes se cierran cuando aparece el color opuesto.
  • Stops: Stop loss y take profit fijos en puntos mediante StartProtection.
  • Valores predeterminados:
    • Period = 10 (velas utilizadas para medir el rango máximo/mínimo).
    • Fibo Level = 0.236 (ratio utilizado para la decisión de tendencia).
    • Stop Loss = 1000 puntos.
    • Take Profit = 2000 puntos.
  • Filtros:
    • Categoría: Seguimiento de tendencia
    • Dirección: Ambos
    • Indicadores: Highest, Lowest
    • Stops: Sí
    • Complejidad: Medio
    • Marco temporal: Horario por defecto
    • Estacionalidad: No
    • Redes neuronales: No
    • Divergencia: No
    • Nivel de riesgo: Moderado
using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Strategy based on color changes of the Fibo Candles indicator.
/// The indicator colors candles according to Fibonacci ratios and trend direction.
/// A change from bearish to bullish color triggers a long entry and closes short positions.
/// A change from bullish to bearish color triggers a short entry and closes long positions.
/// </summary>
public class FiboCandlesTrendStrategy : Strategy
{
	public enum FiboLevels
	{
		Level1 = 1,
		Level2,
		Level3,
		Level4,
		Level5
	}

	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _period;
	private readonly StrategyParam<FiboLevels> _fiboLevel;
	private readonly StrategyParam<int> _stopLoss;
	private readonly StrategyParam<int> _takeProfit;

	private Highest _highest;
	private Lowest _lowest;
	private int _trend;
	private int? _previousColor;
	private decimal _levelMultiplier;

	/// <summary>
	/// Type and timeframe of candles used by the strategy.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Lookback period for high and low calculations.
	/// </summary>
	public int Period
	{
		get => _period.Value;
		set => _period.Value = value;
	}

	/// <summary>
	/// Fibonacci level used by the indicator logic.
	/// </summary>
	public FiboLevels Level
	{
		get => _fiboLevel.Value;
		set => _fiboLevel.Value = value;
	}

	/// <summary>
	/// Stop loss in points.
	/// </summary>
	public int StopLoss
	{
		get => _stopLoss.Value;
		set => _stopLoss.Value = value;
	}

	/// <summary>
	/// Take profit in points.
	/// </summary>
	public int TakeProfit
	{
		get => _takeProfit.Value;
		set => _takeProfit.Value = value;
	}

	/// <summary>
	/// Initializes a new instance of <see cref="FiboCandlesTrendStrategy"/>.
	/// </summary>
	public FiboCandlesTrendStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Type and timeframe of candles", "General");

		_period = Param(nameof(Period), 10)
			.SetGreaterThanZero()
			.SetDisplay("Period", "Lookback period for high/low", "FiboCandles")
			
			.SetOptimize(5, 30, 5);

		_fiboLevel = Param(nameof(Level), FiboLevels.Level1)
			.SetDisplay("Fibo Level", "Fibonacci ratio level", "FiboCandles");

		_stopLoss = Param(nameof(StopLoss), 1000)
			.SetGreaterThanZero()
			.SetDisplay("Stop Loss", "Stop loss in points", "Risk")
			
			.SetOptimize(500, 2000, 500);

		_takeProfit = Param(nameof(TakeProfit), 2000)
			.SetGreaterThanZero()
			.SetDisplay("Take Profit", "Take profit in points", "Risk")
			
			.SetOptimize(1000, 4000, 500);
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_highest = null;
		_lowest = null;
		_trend = 0;
		_previousColor = null;
		_levelMultiplier = 0m;
	}

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

		_highest = new Highest { Length = Period };
		_lowest = new Lowest { Length = Period };
		_levelMultiplier = GetLevelMultiplier(Level);

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(_highest, _lowest, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawOwnTrades(area);
		}
	}

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

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		if (!_highest.IsFormed || !_lowest.IsFormed)
			return;

		var range = highest - lowest;
		var trend = _trend;
		var open = candle.OpenPrice;
		var close = candle.ClosePrice;

		if (open > close)
		{
			if (!(trend < 0 && range * _levelMultiplier < close - lowest))
				trend = 1;
			else
				trend = -1;
		}
		else
		{
			if (!(trend > 0 && range * _levelMultiplier < highest - close))
				trend = -1;
			else
				trend = 1;
		}

		var color = trend == 1 ? 1 : 0;

		if (_previousColor.HasValue)
		{
			if (color == 1 && _previousColor.Value == 0)
			{
				BuyMarket();
			}
			else if (color == 0 && _previousColor.Value == 1)
			{
				SellMarket();
			}
		}

		_previousColor = color;
		_trend = trend;
	}

	private static decimal GetLevelMultiplier(FiboLevels level)
	{
		return level switch
		{
			FiboLevels.Level1 => 0.236m,
			FiboLevels.Level2 => 0.382m,
			FiboLevels.Level3 => 0.500m,
			FiboLevels.Level4 => 0.618m,
			FiboLevels.Level5 => 0.762m,
			_ => 0.236m
		};
	}
}