Ver en GitHub

Estrategia de Linear Regression Channel (Fibo)

Descripción general

Esta estrategia es la conversión a StockSharp del asesor experto de MetaTrader "linear regression channel". Opera en la dirección de la tendencia lineal de mayor temporalidad confirmada por un conjunto de medias móviles ponderadas, lecturas de Momentum y un filtro MACD mensual. Las reglas de gestión monetaria replican el comportamiento original con objetivos de beneficio flotantes, seguimiento de ganancias acumuladas, protección de punto de equilibrio y un stop de capital.

Lógica de trading

  1. Temporalidad principal – tipo de vela configurable (por defecto 15 minutos). Todos los cálculos de señales se ejecutan en esta temporalidad.
  2. Filtro de tendencia – una LWMA rápida y una lenta calculadas sobre el precio típico. Las señales largas requieren que la LWMA rápida esté por encima de la lenta; las señales cortas requieren lo contrario.
  3. Confirmación de Momentum – el indicador de Momentum se evalúa en una temporalidad superior que refleja el mapeo original de MetaTrader (M1→M15, M5→M30, M15→H1, M30→H4, H1→D1, H4→W1, D1→MN1). Los últimos tres valores de Momentum se convierten a la distancia absoluta desde el nivel 100. Una configuración larga necesita que cualquiera de las tres distancias supere el umbral alcista, mientras que una configuración corta necesita que cualquiera de las tres supere el umbral bajista.
  4. Sesgo MACD mensual – las velas mensuales impulsan un filtro MACD(12,26,9). Las operaciones largas solo se permiten cuando la línea principal del MACD está por encima de su línea de señal; las operaciones cortas requieren la relación contraria.
  5. Condición de entrada – cuando todos los filtros se alinean y el trading está permitido, la estrategia abre una orden de mercado en la dirección correspondiente. La posición actual se cierra y se invierte cuando se produce una señal opuesta.

Gestión de riesgos y operaciones

  • Stop-loss / take-profit fijo – las distancias se definen en puntos del instrumento y se aplican a cada entrada. Si el máximo/mínimo de la vela perfora estos niveles, se cierra la posición.
  • Stop de seguimiento – opcional; se activa una vez que la posición gana una cantidad configurable de puntos y sigue el mejor precio con el offset especificado.
  • Punto de equilibrio – opcional; después de que el precio avanza la distancia del disparador, el nivel de stop se mueve al precio de entrada más/menos un offset para asegurar ganancias.
  • Take-profit de beneficio flotante – objetivo monetario opcional. Cuando el beneficio flotante neto (expresado en moneda de cuenta) supera el umbral, se cierran todas las posiciones.
  • Take-profit basado en porcentaje – objetivo opcional basado en el capital inicial en el momento en que inicia la estrategia.
  • Seguimiento monetario – una vez que el beneficio flotante alcanza el disparador, la estrategia registra el beneficio máximo. Si el beneficio retrocede la cantidad de stop especificada, se cierra la posición.
  • Stop de capital – protección contra drawdown opcional. Mientras la posición está perdiendo, si la pérdida flotante supera un porcentaje del pico de capital observado, la estrategia liquida la posición.

Parámetros

Nombre Descripción
Candle Type Temporalidad principal para la generación de señales.
Fast LWMA / Slow LWMA Períodos para las medias móviles ponderadas linealmente rápida y lenta.
Momentum Length Longitud de retrospectiva del Momentum en la temporalidad superior.
Momentum Buy Threshold / Momentum Sell Threshold Distancia absoluta mínima desde 100 requerida para confirmación de Momentum alcista/bajista.
Take Profit (points) / Stop Loss (points) Distancias de protección expresadas en puntos del instrumento.
Use Trailing, Trailing Activation, Trailing Offset Configuración del stop de seguimiento.
Use Break-even, Break-even Trigger, Break-even Offset Parámetros de lógica de punto de equilibrio.
Max Trades Número máximo de entradas secuenciales permitidas durante la ejecución.
Order Volume Volumen base para órdenes de mercado.
Use Money TP, Money Take Profit Take-profit monetario flotante.
Use Percent TP, Percent Take Profit Take-profit calculado como porcentaje del capital inicial.
Enable Money Trailing, Money Trailing Trigger, Money Trailing Stop Seguimiento del beneficio flotante.
Use Equity Stop, Equity Risk % Protección de stop-loss basada en capital.

Notas

  • La estrategia mantiene solo una posición neta (larga o corta) y se invierte cuando llega una señal opuesta.
  • Las suscripciones de Momentum y MACD agregan automáticamente las temporalidades superiores necesarias al feed de datos a través de GetWorkingSecurities().
  • Todos los comentarios dentro del código están en inglés según las directrices del repositorio.
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;

public class LinearRegressionChannelFibStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _stopLossPoints;
	private readonly StrategyParam<int> _takeProfitPoints;

	private ExponentialMovingAverage _fast;
	private ExponentialMovingAverage _slow;

	private decimal _prevFast;
	private decimal _prevSlow;
	private decimal _entryPrice;
	private int _cooldown;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int StopLossPoints { get => _stopLossPoints.Value; set => _stopLossPoints.Value = value; }
	public int TakeProfitPoints { get => _takeProfitPoints.Value; set => _takeProfitPoints.Value = value; }

	public LinearRegressionChannelFibStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 14).SetGreaterThanZero().SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 50).SetGreaterThanZero().SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_stopLossPoints = Param(nameof(StopLossPoints), 200).SetNotNegative().SetDisplay("Stop Loss", "Stop-loss in price steps", "Risk");
		_takeProfitPoints = Param(nameof(TakeProfitPoints), 400).SetNotNegative().SetDisplay("Take Profit", "Take-profit in price steps", "Risk");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		yield return (Security, TimeSpan.FromMinutes(5).TimeFrame());
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_fast = null; _slow = null;
		_prevFast = 0; _prevSlow = 0; _entryPrice = 0; _cooldown = 0;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_fast = new ExponentialMovingAverage { Length = FastPeriod };
		_slow = new ExponentialMovingAverage { Length = SlowPeriod };
		var subscription = SubscribeCandles(TimeSpan.FromMinutes(5).TimeFrame());
		subscription.Bind(_fast, _slow, ProcessCandle);
		subscription.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!_fast.IsFormed || !_slow.IsFormed) { _prevFast = fastValue; _prevSlow = slowValue; return; }
		if (_cooldown > 0) { _cooldown--; _prevFast = fastValue; _prevSlow = slowValue; return; }

		var close = candle.ClosePrice;
		var step = Security?.PriceStep ?? 1m;

		if (Position > 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close <= _entryPrice - StopLossPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close >= _entryPrice + TakeProfitPoints * step) { SellMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}
		else if (Position < 0 && _entryPrice > 0)
		{
			if (StopLossPoints > 0 && close >= _entryPrice + StopLossPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
			if (TakeProfitPoints > 0 && close <= _entryPrice - TakeProfitPoints * step) { BuyMarket(); _entryPrice = 0; _cooldown = 100; _prevFast = fastValue; _prevSlow = slowValue; return; }
		}

		if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
		{ if (Position < 0) BuyMarket(); BuyMarket(); _entryPrice = close; _cooldown = 100; }
		else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
		{ if (Position > 0) SellMarket(); SellMarket(); _entryPrice = close; _cooldown = 100; }

		_prevFast = fastValue; _prevSlow = slowValue;
	}
}