Ver no GitHub

Fibonacci Estratégia de entradas potenciais

Visão geral

Esta estratégia reproduz o comportamento do consultor especialista EA_PUB_FibonacciPotentialEntries original. Ele coloca dois pedidos de limite nos níveis de retração Fibonacci de 50% e 61% e gerencia seu ciclo de vida usando o StockSharp API de alto nível.

Lógica de negociação

  1. Colocação inicial

    • Assim que as cotações de compra/venda estiverem disponíveis, a estratégia calcula o spread atual e envia duas ordens de limite:
      • Ordem nº 1: colocada no nível de 50% com um stop de proteção abaixo (ou acima para posições vendidas) do nível de 61%.
      • Ordem #2: colocada no nível 61% com um stop de proteção colocado a meio caminho do nível 100%.
    • Os volumes são dimensionados de modo que a primeira negociação arrisque 0,7% da carteira e a segunda negociação arrisque a parte restante do parâmetro RiskPercent.
  2. Manuseio de alvo

    • Quando o preço atinge o nível TargetPrice a estratégia fecha metade de cada posição preenchida usando ordens de mercado.
    • Após a saída parcial, o volume restante fica protegido no ponto de equilíbrio (preço de entrada). Se o mercado retornar a esse nível, o restante da posição será fechado automaticamente.
  3. Direção

    • IsBullish = true cria limites de compra (modelo otimista original).
    • IsBullish = false reflete o comportamento com limites de venda e verificações de stop/target invertidas.

Parâmetros

Nome Descrição
PriceOn50Level Nível de preço para o primeiro pedido com limite.
PriceOn61Level Nível de preço para o segundo pedido com limite.
PriceOn100Level Nível de referência utilizado para calcular o segundo stop comercial.
TargetPrice Meta de lucro compartilhada para ambas as posições.
RiskPercent Percentagem total do capital da carteira arriscada em ambas as entradas.
IsBullish Escolhe entre configurações longas e curtas.

Notas de conversão

  • Somente auxiliares de alto nível (SubscribeLevel1, BuyLimit, SellLimit, BuyMarket, SellMarket) são usados, exatamente conforme exigido pelas diretrizes do repositório.
  • Saídas parciais e ajustes de ponto de equilíbrio são reproduzidos com ordens de mercado, correspondendo ao comportamento do robô MQL sem depender de chamadas de modificação de ordem de baixo nível.
  • Os volumes de posição são normalizados para a etapa de volume do instrumento para permanecerem consistentes com as convenções 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;
	}
}