Ver en GitHub

Estrategia Stoch Komposter

Esta estrategia es un port del experto MQL5 Exp_iStochKomposter. Utiliza el Oscilador Estocástico para detectar reversiones de momentum y opera cuando la línea %K cruza umbrales predefinidos.

Cómo Funciona

  • Calcula el Oscilador Estocástico en el marco temporal seleccionado.
  • Genera una señal de compra cuando %K cruza por encima del nivel inferior (por defecto 30).
  • Genera una señal de venta cuando %K cruza por debajo del nivel superior (por defecto 70).
  • En cada señal, la estrategia cierra cualquier posición opuesta y abre una nueva posición en la dirección de la señal usando órdenes de mercado.
  • Se aplican niveles opcionales de stop loss y take profit mediante StartProtection.

Parámetros

Nombre Descripción Predeterminado
KPeriod Período de cálculo de la línea %K 5
DPeriod Período de suavizado de la línea %D 3
UpLevel Umbral de sobrecompra para activar ventas 70
DownLevel Umbral de sobreventa para activar compras 30
StopLoss Stop loss absoluto en unidades de precio 1000
TakeProfit Take profit absoluto en unidades de precio 2000
CandleType Marco temporal para cálculos 1 hora

Notas

  • La estrategia opera solo en velas finalizadas.
  • No calcula los niveles ATR del indicador original; se usaban solo para posicionar flechas en la versión MQL.
  • El tamaño de posición se define mediante la propiedad Volume de la estrategia.
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>
/// Strategy using Stochastic Oscillator crossovers.
/// Opens long when %K crosses above the lower level and opens short when crossing below the upper level.
/// </summary>
public class StochKomposterStrategy : Strategy
{
	private readonly StrategyParam<int> _kPeriod;
	private readonly StrategyParam<int> _dPeriod;
	private readonly StrategyParam<decimal> _upLevel;
	private readonly StrategyParam<decimal> _downLevel;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _prevK;

	public int KPeriod { get => _kPeriod.Value; set => _kPeriod.Value = value; }
	public int DPeriod { get => _dPeriod.Value; set => _dPeriod.Value = value; }
	public decimal UpLevel { get => _upLevel.Value; set => _upLevel.Value = value; }
	public decimal DownLevel { get => _downLevel.Value; set => _downLevel.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public StochKomposterStrategy()
	{
		_kPeriod = Param(nameof(KPeriod), 5)
			.SetGreaterThanZero()
			.SetDisplay("K Period", "Stochastic %K calculation period", "Indicators");

		_dPeriod = Param(nameof(DPeriod), 3)
			.SetGreaterThanZero()
			.SetDisplay("D Period", "Stochastic %D smoothing period", "Indicators");

		_upLevel = Param(nameof(UpLevel), 70m)
			.SetDisplay("Upper Level", "Overbought threshold", "Indicators");

		_downLevel = Param(nameof(DownLevel), 30m)
			.SetDisplay("Lower Level", "Oversold threshold", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for strategy", "General");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevK = null;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_prevK = null;

		var stochastic = new StochasticOscillator
		{
			K = { Length = KPeriod },
			D = { Length = DPeriod },
		};

		var subscription = SubscribeCandles(CandleType);
		subscription.BindEx(stochastic, ProcessCandle).Start();

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

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue stochValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		if (stochValue is not IStochasticOscillatorValue value || value.K is not decimal k)
			return;

		if (_prevK is null)
		{
			_prevK = k;
			return;
		}

		var prev = _prevK.Value;

		// %K crosses above lower level -> buy
		if (prev <= DownLevel && k > DownLevel && Position <= 0)
			BuyMarket();
		// %K crosses below upper level -> sell
		else if (prev >= UpLevel && k < UpLevel && Position >= 0)
			SellMarket();

		_prevK = k;
	}
}