Ver en GitHub

Estrategia de regresión de múltiples marcos temporales

Una estrategia de múltiples marcos temporales que combina canales de regresión lineal en velas M1, M5 y H1. La pendiente de regresión del canal H1 define la tendencia dominante, mientras que los canales M5 y M1 proporcionan ubicaciones de entrada precisas cerca del soporte y la resistencia.

Lógica comercial

  • Fuentes de datos: nueve períodos de tiempo de velas estándar (M1, M5, M15, M30, H1, H4, D1, W1, MN1).
  • Indicadores: cada feed es procesado por un canal de regresión lineal de longitud configurable. El canal proporciona una línea central y bandas superior/inferior simétricas basadas en la desviación máxima de los cierres recientes.
  • Filtro de tendencias: la estrategia sólo considera operaciones cortas cuando la pendiente del canal H1 es negativa y operaciones largas cuando es positiva.
  • Entrada:
    • Corto: los últimos máximos M5 y M1 perforan sus bandas superiores del canal, mientras que la pendiente H1 es negativa.
    • Largo: los últimos mínimos de M5 y M1 alcanzan sus bandas de canal inferiores, mientras que la pendiente H1 es positiva.
  • Manejo de órdenes: las entradas se ejecutan con órdenes de mercado utilizando el volumen configurado. Los objetivos de limitación de pérdidas y toma de ganancias se derivan del ancho medio y la línea central del canal M5, respectivamente.
  • Salida: las posiciones se cierran en las velas M1 cuando el precio alcanza el stop protector o el objetivo de la línea central.
  • Gestión de posiciones: como máximo hay una posición de mercado abierta en cualquier momento.

Parámetros

Nombre Descripción
EnableTrading Permite que la estrategia realice pedidos cuando está habilitada.
BarsToCount Número de barras utilizadas en cada canal de regresión (50 por defecto).
Volume Volumen de órdenes de mercado en lotes.

Notas

  • Las ventanas de regresión más largas proporcionan pendientes del canal más suaves pero reacciones más lentas.
  • La visualización de pendiente de marcos de tiempo múltiples es útil para monitorear la alineación en intervalos más altos, aunque solo las entradas de pendiente H1.
  • Los niveles de protección se recalculan cada vez que se forma una nueva vela M5; La recalibración frecuente mantiene el riesgo estrechamente vinculado a la geometría actual del canal.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Linear regression channel strategy.
/// Uses LinearReg as the center line with Highest/Lowest to form a channel.
/// Sells at upper channel, buys at lower channel, with trend filter from regression slope.
/// </summary>
public class MultiTimeFrameRegressionStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _regressionLength;
	private readonly StrategyParam<int> _channelLength;

	private decimal _prevLrValue;
	private bool _hasPrev;

	public MultiTimeFrameRegressionStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for analysis.", "General");

		_regressionLength = Param(nameof(RegressionLength), 20)
			.SetDisplay("Regression Length", "Period for linear regression.", "Indicators");

		_channelLength = Param(nameof(ChannelLength), 20)
			.SetDisplay("Channel Length", "Period for highest/lowest channel.", "Indicators");
	}

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

	public int RegressionLength
	{
		get => _regressionLength.Value;
		set => _regressionLength.Value = value;
	}

	public int ChannelLength
	{
		get => _channelLength.Value;
		set => _channelLength.Value = value;
	}

	/// <inheritdoc />
	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevLrValue = 0;
		_hasPrev = false;
	}

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

		_prevLrValue = 0;
		_hasPrev = false;

		var lr = new LinearReg { Length = RegressionLength };
		var highest = new Highest { Length = ChannelLength };
		var lowest = new Lowest { Length = ChannelLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(lr, highest, lowest, ProcessCandle)
			.Start();

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

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

		var close = candle.ClosePrice;

		// Determine slope direction from regression
		var slope = _hasPrev ? lrValue - _prevLrValue : 0m;

		// Channel boundaries
		var channelMid = (highestValue + lowestValue) / 2m;
		var channelWidth = highestValue - lowestValue;

		if (channelWidth <= 0)
		{
			_prevLrValue = lrValue;
			_hasPrev = true;
			return;
		}

		// Upper/lower thresholds
		var upperThreshold = channelMid + channelWidth * 0.4m;
		var lowerThreshold = channelMid - channelWidth * 0.4m;

		// Exit conditions
		if (Position > 0 && (close >= upperThreshold || slope < 0))
		{
			SellMarket();
		}
		else if (Position < 0 && (close <= lowerThreshold || slope > 0))
		{
			BuyMarket();
		}

		// Entry conditions
		if (Position == 0)
		{
			if (close <= lowerThreshold && slope >= 0)
			{
				// Price near lower channel with flat/rising regression
				BuyMarket();
			}
			else if (close >= upperThreshold && slope <= 0)
			{
				// Price near upper channel with flat/falling regression
				SellMarket();
			}
		}

		_prevLrValue = lrValue;
		_hasPrev = true;
	}
}