Ver en GitHub

Fibonacci Estrategia de entradas potenciales

Descripción general

Esta estrategia reproduce el comportamiento del asesor experto EA_PUB_FibonacciPotentialEntries original. Coloca dos órdenes límite en los niveles de retroceso del 50 % y 61 % Fibonacci y gestiona su ciclo de vida utilizando el nivel alto StockSharp API.

Lógica de trading

  1. Colocación inicial

    • Tan pronto como las cotizaciones de oferta/demanda estén disponibles, la estrategia calcula el diferencial actual y envía dos órdenes límite:
      • Orden #1: colocada en el nivel del 50% con un stop protector por debajo (o por encima para cortos) del nivel del 61%.
      • Orden #2: colocada en el nivel del 61% con un tope protector colocado a medio camino hacia el nivel del 100%.
    • Los volúmenes están dimensionados para que la primera operación arriesgue el 0,7% de la cartera y la segunda operación arriesgue la parte restante del parámetro RiskPercent.
  2. Manejo de objetivos

    • Cuando el precio alcanza el nivel TargetPrice, la estrategia cierra la mitad de cada posición ocupada utilizando órdenes de mercado.
    • Después de una salida parcial, el volumen restante está protegido hasta el punto de equilibrio (precio de entrada). Si el mercado vuelve a ese nivel el resto de la posición se cierra automáticamente.
  3. Dirección

    • IsBullish = true crea límites de compra (plantilla alcista original).
    • IsBullish = false refleja el comportamiento con límites de venta y controles de parada/objetivo invertidos.

Parámetros

Nombre Descripción
PriceOn50Level Nivel de precio para la primera orden límite.
PriceOn61Level Nivel de precio para la segunda orden límite.
PriceOn100Level Nivel de referencia utilizado para calcular la segunda parada comercial.
TargetPrice Objetivo de beneficio compartido para ambas posiciones.
RiskPercent Porcentaje total del capital de la cartera arriesgado en ambas entradas.
IsBullish Elige entre configuraciones largas y cortas.

Notas de conversión

  • Solo se utilizan ayudantes de alto nivel (SubscribeLevel1, BuyLimit, SellLimit, BuyMarket, SellMarket), exactamente como lo exigen las pautas del repositorio.
  • Las salidas parciales y los ajustes de punto de equilibrio se reproducen con órdenes de mercado, coincidiendo con el comportamiento del robot MQL sin depender de llamadas de modificación de órdenes de bajo nivel.
  • Los volúmenes de posición están normalizados al paso de volumen del instrumento para mantenerse consistentes con las convenciones StockSharp.
namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Fibonacci Potential Entries strategy: Two-candle reversal with RSI filter.
/// Uses price swing highs/lows as fibonacci reference points.
/// </summary>
public class FibonacciPotentialEntriesStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private decimal _highestHigh;
	private decimal _lowestLow;
	private decimal _prevClose;
	private int _barCount;
	private int _candlesSinceTrade;
	private bool _hasPrevClose;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public FibonacciPotentialEntriesStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_rsiPeriod = Param(nameof(RsiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("RSI Period", "RSI period", "Indicators");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_highestHigh = 0;
		_lowestLow = decimal.MaxValue;
		_prevClose = 0;
		_barCount = 0;
		_candlesSinceTrade = SignalCooldownCandles;
		_hasPrevClose = false;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_highestHigh = 0;
		_lowestLow = decimal.MaxValue;
		_prevClose = 0;
		_barCount = 0;
		_candlesSinceTrade = SignalCooldownCandles;
		_hasPrevClose = false;
		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(rsi, ProcessCandle).Start();
	}

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

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		if (candle.HighPrice > _highestHigh) _highestHigh = candle.HighPrice;
		if (candle.LowPrice < _lowestLow) _lowestLow = candle.LowPrice;
		_barCount++;

		if (_barCount < 20) return;

		var range = _highestHigh - _lowestLow;
		if (range <= 0) return;

		var fib382 = _highestHigh - range * 0.382m;
		var fib618 = _highestHigh - range * 0.618m;
		var close = candle.ClosePrice;
		var crossedIntoBuyZone = _hasPrevClose && _prevClose > fib618 && close <= fib618;
		var crossedIntoSellZone = _hasPrevClose && _prevClose < fib382 && close >= fib382;

		if (crossedIntoBuyZone && rsiValue < 40 && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
		{
			BuyMarket();
			_candlesSinceTrade = 0;
		}
		else if (crossedIntoSellZone && rsiValue > 60 && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
		{
			SellMarket();
			_candlesSinceTrade = 0;
		}

		_prevClose = close;
		_hasPrevClose = true;
	}
}