Ver en GitHub

Estrategia de Relleno de Brechas

La estrategia de Relleno de Brechas aprovecha las brechas de precio entre velas consecutivas de 15 minutos. Cuando una nueva vela abre por encima del máximo de la vela anterior en más de un umbral configurable, la estrategia vende y coloca un límite de compra en el máximo anterior, esperando que la brecha se cierre. Cuando una vela abre por debajo del mínimo anterior en más del umbral, compra y coloca un límite de venta en el mínimo anterior. El umbral se calcula como MinGapSize pasos de precio más el diferencial actual entre la mejor oferta y demanda.

Detalles

  • Criterios de entrada: La brecha entre la apertura actual y el máximo/mínimo anterior supera MinGapSize más el diferencial.
  • Largo/Corto: Ambas direcciones.
  • Criterios de salida: Orden limitada en el extremo de la vela anterior.
  • Stops: No.
  • Valores predeterminados:
    • MinGapSize = 1
    • Volume = 0.1
    • CandleType = 15 minutos
  • Filtros:
    • Categoría: Brecha
    • Dirección: Ambos
    • Indicadores: Ninguno
    • Stops: No
    • Complejidad: Básico
    • Marco temporal: Intradía (15m)
    • Estacionalidad: No
    • Redes neuronales: No
    • Divergencia: No
    • Nivel de riesgo: Medio
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>
/// Gap fill strategy using Highest/Lowest channel breakout.
/// </summary>
public class GapFillStrategy : Strategy
{
	private readonly StrategyParam<int> _channelPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevHigh;
	private decimal _prevLow;
	private bool _hasPrev;

	public int ChannelPeriod { get => _channelPeriod.Value; set => _channelPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public GapFillStrategy()
	{
		_channelPeriod = Param(nameof(ChannelPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("Channel Period", "Highest/Lowest period", "Parameters");
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "Data");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevHigh = 0;
		_prevLow = 0;
		_hasPrev = false;
	}

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

		var highest = new Highest { Length = ChannelPeriod };
		var lowest = new Lowest { Length = ChannelPeriod };

		SubscribeCandles(CandleType)
			.Bind(highest, lowest, ProcessCandle)
			.Start();
	}

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

		if (!_hasPrev)
		{
			_prevHigh = highVal;
			_prevLow = lowVal;
			_hasPrev = true;
			return;
		}

		if (candle.ClosePrice > _prevHigh && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (candle.ClosePrice < _prevLow && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevHigh = highVal;
		_prevLow = lowVal;
	}
}