Ver en GitHub

Estrategia WE TRUST Channel

Descripción general

La Estrategia WE TRUST Channel es un port de StockSharp de alto nivel del asesor experto de MetaTrader 5 "WE TRUST". El sistema opera pullbacks hacia una media móvil ponderada lineal que está rodeada por bandas de desviación estándar. Cuando el precio cierra fuera de las bandas, la estrategia anticipa una reversión a la media y abre una posición de mercado de vuelta hacia el centro del canal. La inversión de señales, el cierre opcional de trades opuestos y los parámetros de gestión monetaria basados en pips reflejan el experto original.

Lógica de trading

  1. Suscribirse al tipo de vela configurado (velas por hora por defecto) y calcular dos indicadores en la fuente de precio seleccionada:
    • Una media móvil ponderada lineal (LWMA) con período y desplazamiento configurables.
    • Una envolvente de desviación estándar con su propio período y desplazamiento.
  2. Convertir los offsets basados en pips en distancias de precio absolutas usando el PriceStep del instrumento. Las cotizaciones de cinco y tres dígitos multiplican el paso por 10 para emular la definición de pip de MetaTrader.
  3. Calcular los límites superior e inferior del canal: LWMA ± StdDev ± ChannelIndentPips (convertidos en unidades de precio).
  4. Evaluar solo velas finalizadas. Cuando el precio de la vela elegida cierra por debajo del canal inferior, la estrategia genera una señal de compra. Cuando cierra por encima del canal superior, genera una señal de venta.
  5. Opcionalmente invertir las señales cuando ReverseSignals está habilitado. Opcionalmente aplanar una posición opuesta antes de actuar sobre una nueva señal cuando CloseOpposite está habilitado.
  6. Enviar órdenes de mercado con el volumen configurado cuando la posición actual está plana o alineada con la dirección de la señal.

Gestión de riesgos

  • StopLossPips y TakeProfitPips traducen distancias en pips a órdenes protectoras absolutas a través de StartProtection. Establecerlos en 0 para deshabilitar el nivel respectivo.
  • TrailingStopPips y TrailingStepPips controlan un trailing stop basado en pips que sigue los trades rentables. Ambos parámetros se convierten en distancias de precio usando la misma lógica de tamaño de pip.
  • Todas las salidas se realizan con órdenes de mercado para permanecer cercanas a la implementación de MQL5.

Parámetros

Parámetro Descripción Predeterminado
OrderVolume Volumen del trade enviado con cada orden de mercado. 0.1
StopLossPips Distancia de stop-loss expresada en pips (0 deshabilita el stop). 40
TakeProfitPips Distancia de take-profit expresada en pips (0 deshabilita el objetivo). 60
TrailingStopPips Distancia de trailing stop en pips. 10
TrailingStepPips Paso de trailing en pips entre ajustes de stop. 10
MaPeriod Período de la media móvil ponderada lineal. 60
MaShift Número de barras que la media móvil se desplaza hacia adelante. 0
StdDevPeriod Período del cálculo de desviación estándar. 50
StdDevShift Número de barras que el valor de desviación se desplaza. 0
SignalBarOffset Número de barras completadas hacia atrás al evaluar señales. 1
ChannelIndentPips Buffer adicional añadido fuera de las bandas de desviación. 1
ReverseSignals Invertir la lógica de compra/venta del rompimiento del canal. false
CloseOpposite Cerrar una posición opuesta antes de entrar en un nuevo trade. false
AppliedPrice Componente de precio de la vela alimentado en ambos indicadores. Weighted
CandleType Tipo de datos de vela solicitado al conector. marco temporal de 1 hora

Notas

  • La estrategia depende de metadatos válidos de PriceStep. Si el exchange no lo proporciona, el código recurre a Security.Step y finalmente a 1.
  • Solo la implementación en C# está incluida en este directorio. El port de Python se omite intencionalmente según las instrucciones.
  • La lógica procesa solo velas finalizadas y no intenta acumular datos de barra parciales.
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 WeTrustChannelStrategy : 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 WeTrustChannelStrategy()
	{
		_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;
	}
}