Ver en GitHub

Estrategia Fisher Org v1

Esta estrategia utiliza el indicador Fisher Transform para capturar reversiones de tendencia. Se abre una posición larga cuando el indicador forma un mínimo local, mientras que se abre una posición corta cuando aparece un máximo local. Las señales opuestas cierran cualquier posición existente.

Reglas

  • Largo: Fisher[t-2] > Fisher[t-1] y Fisher[t-1] <= Fisher[t]
  • Corto: Fisher[t-2] < Fisher[t-1] y Fisher[t-1] >= Fisher[t]

Parámetros

  • Fisher Length – período del Fisher Transform (por defecto 7)
  • Candle Type – marco temporal de las velas utilizadas para los cálculos

Indicadores

  • Fisher Transform
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>
/// Fisher Org v1 strategy.
/// Detects local minima and maxima of the Fisher Transform indicator.
/// Buys on local minima and sells on local maxima.
/// </summary>
public class FisherOrgV1Strategy : Strategy
{
	private readonly StrategyParam<int> _length;
	private readonly StrategyParam<DataType> _candleType;

	private EhlersFisherTransform _fisher;
	private decimal _prev;
	private decimal _prevPrev;
	private int _valueCount;

	/// <summary>
	/// Fisher transform period length.
	/// </summary>
	public int Length
	{
		get => _length.Value;
		set => _length.Value = value;
	}

	/// <summary>
	/// The type of candles to use for strategy calculation.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Initializes a new instance of <see cref="FisherOrgV1Strategy"/>.
	/// </summary>
	public FisherOrgV1Strategy()
	{
		_length = Param(nameof(Length), 7)
			.SetGreaterThanZero()
			.SetDisplay("Fisher Length", "Period for Fisher Transform", "General")
			
			.SetOptimize(5, 20, 1);

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles to use", "General");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prev = 0m;
		_prevPrev = 0m;
		_valueCount = 0;
	}

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

		_fisher = new EhlersFisherTransform
		{
			Length = Length
		};

		var subscription = SubscribeCandles(CandleType);
		subscription.BindEx(_fisher, ProcessCandle).Start();

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		if (fisherVal is not IEhlersFisherTransformValue typed || typed.MainLine is not decimal fisherValue)
			return;

		if (_valueCount < 2)
		{
			if (_valueCount == 0)
				_prev = fisherValue;
			else
			{
				_prevPrev = _prev;
				_prev = fisherValue;
			}

			_valueCount++;
			return;
		}

		var isLongSignal = _prevPrev > _prev && _prev <= fisherValue;
		var isShortSignal = _prevPrev < _prev && _prev >= fisherValue;

		if (isLongSignal && Position <= 0)
			BuyMarket();

		if (isShortSignal && Position >= 0)
			SellMarket();

		_prevPrev = _prev;
		_prev = fisherValue;
	}
}