Ver en GitHub

Estrategia SilverTrend V3 JTPO

Descripción general

SilverTrend V3 es una estrategia de seguimiento de tendencias traducida de la implementación original MetaTrader 4. Evalúa el indicador SilverTrend junto con el filtro estadístico J_TPO para identificar nuevos cambios direccionales. La estrategia opera con un solo instrumento a la vez y aplica una regla fija los viernes por la noche para evitar mantener el riesgo durante el fin de semana.

Lógica de trading

  1. Procesamiento de indicadores
    • La estrategia mantiene un búfer continuo de velas recientes y recalcula la dirección de SilverTrend en cada barra completa.
    • SilverTrend utiliza una ventana de 9 barras y un factor de riesgo de 3 para determinar los límites del canal adaptativo. Si el precio de cierre supera el límite superior, la señal se vuelve alcista; cruzar por debajo del límite inferior convierte la señal a bajista.
    • El cálculo J_TPO (longitud 14) mide la asimetría de la distribución de precios. Solo los valores positivos de J_TPO confirman entradas largas, mientras que se requieren lecturas negativas para entradas cortas.
  2. Condiciones de entrada
    • Se abre una operación larga cuando la señal de SilverTrend cambia de bajista a alcista y J_TPO está por encima de cero.
    • Se abre una operación corta cuando la señal de SilverTrend cambia de alcista a bajista y J_TPO está por debajo de cero.
    • Las nuevas posiciones se bloquean los viernes una vez que la hora del mercado excede el límite configurado.
  3. Gestión de salida
    • Las señales opuestas de SilverTrend cierran las operaciones abiertas inmediatamente.
    • Los niveles opcionales de stop loss inicial y toma de ganancias se colocan a distancias fijas (expresadas en puntos).
    • Un trailing stop opcional sigue el precio una vez que supera el buffer de ganancias configurado.

Parámetros

Nombre Descripción Predeterminado
Volume Tamaño del pedido en lotes. 1
TrailingStopPoints Distancia del trailing stop en puntos de precio. 0 desactiva el seguimiento. 0
TakeProfitPoints Tome la distancia de ganancias en puntos de precio. 0 desactiva la toma de ganancias. 0
InitialStopPoints Distancia inicial de stop loss en puntos de precio. 0 desactiva la parada de protección. 0
FridayCutoffHour Hora (hora de cambio) después de la cual no se permiten nuevas operaciones el viernes. 16
CandleType Tipo de vela o período de tiempo utilizado para el análisis. 1h velas

Notas adicionales

  • Solo hay una posición abierta en cualquier momento, lo que coincide con el comportamiento de operación única del asesor experto original.
  • La implementación utiliza API de alto nivel de StockSharp, por lo que la estrategia se suscribe a velas y realiza lógica solo en barras terminadas.
  • Los stop dinámicos y fijos se gestionan internamente y cerrarán la posición al precio de mercado una vez activados.
using System;

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

namespace StockSharp.Samples.Strategies;

public class SilverTrendV3JtpoStrategy : Strategy
{
	private readonly StrategyParam<int> _rsiPeriod;
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<decimal> _oversold;
	private readonly StrategyParam<decimal> _overbought;
	private readonly StrategyParam<int> _cooldownCandles;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevRsi;
	private bool _hasPrev;
	private int _cooldownRemaining;

	public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public decimal Oversold { get => _oversold.Value; set => _oversold.Value = value; }
	public decimal Overbought { get => _overbought.Value; set => _overbought.Value = value; }
	public int CooldownCandles { get => _cooldownCandles.Value; set => _cooldownCandles.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public SilverTrendV3JtpoStrategy()
	{
		_rsiPeriod = Param(nameof(RsiPeriod), 14).SetDisplay("RSI Period", "RSI lookback", "Indicators");
		_emaPeriod = Param(nameof(EmaPeriod), 20).SetDisplay("EMA Period", "EMA filter", "Indicators");
		_oversold = Param(nameof(Oversold), 25m).SetDisplay("Oversold", "RSI oversold level", "Levels");
		_overbought = Param(nameof(Overbought), 75m).SetDisplay("Overbought", "RSI overbought level", "Levels");
		_cooldownCandles = Param(nameof(CooldownCandles), 50).SetDisplay("Cooldown", "Candles between signals", "General");
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevRsi = default;
		_hasPrev = default;
		_cooldownRemaining = default;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevRsi = 0;
		_hasPrev = false;
		_cooldownRemaining = 0;

		var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(rsi, ema, ProcessCandle).Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal rsi, decimal ema)
	{
		if (candle.State != CandleStates.Finished) return;
		if (!_hasPrev) { _prevRsi = rsi; _hasPrev = true; return; }

		if (_cooldownRemaining > 0)
		{
			_cooldownRemaining--;
			_prevRsi = rsi;
			return;
		}

		var oversold = Oversold;
		var overbought = Overbought;
		var close = candle.ClosePrice;

		if (_prevRsi <= oversold && rsi > oversold && close > ema && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
			_cooldownRemaining = CooldownCandles;
		}
		else if (_prevRsi >= overbought && rsi < overbought && close < ema && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
			_cooldownRemaining = CooldownCandles;
		}
		_prevRsi = rsi;
	}
}