Ver en GitHub

Estrategia de Umbral de Oscilador Adaptativo

El Umbral de Oscilador Adaptativo utiliza el RSI con un umbral dinámico basado en el Umbral Adaptativo de Bufi (BAT). Compra cuando el RSI cae por debajo de un nivel fijo o un umbral adaptativo.

Detalles

  • Criterios de entrada: El RSI cae por debajo del umbral fijo o adaptativo
  • Largo/Corto: Largo
  • Criterios de salida: Salida por barras fijas o stop-loss en dólares
  • Stops: Stop-loss en dólares
  • Valores predeterminados:
    • UseAdaptiveThreshold = true
    • RsiLength = 2
    • BuyLevel = 14
    • AdaptiveLength = 8
    • AdaptiveCoefficient = 6
    • ExitBars = 28
    • DollarStopLoss = 1600
  • Filtros:
    • Categoría: Oscilador
    • Dirección: Largo
    • Indicadores: RSI, StandardDeviation, LinearRegression
    • Stops: Dólar
    • Complejidad: Básico
    • Marco temporal: Cualquiera
    • Estacionalidad: No
    • Redes neuronales: No
    • Divergencia: No
    • Nivel de riesgo: Medio
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>
/// Adaptive Oscillator Threshold strategy using EMA crossover.
/// </summary>
public class AdaptiveOscillatorThresholdStrategy : Strategy
{
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<DataType> _candleType;

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

	public AdaptiveOscillatorThresholdStrategy()
	{
		_slowLength = Param(nameof(SlowLength), 40)
			.SetGreaterThanZero()
			.SetDisplay("Slow Length", "Slow EMA period", "General");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		var fast = new ExponentialMovingAverage { Length = 14 };
		var slow = new ExponentialMovingAverage { Length = SlowLength };
		var prevF = 0m; var prevS = 0m; var init = false;
		var lastSignal = DateTimeOffset.MinValue;
		var cooldown = TimeSpan.FromMinutes(360);
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fast, slow, (candle, f, s) =>
		{
			if (candle.State != CandleStates.Finished) return;
			if (!fast.IsFormed || !slow.IsFormed) return;
			if (!init) { prevF = f; prevS = s; init = true; return; }
			if (candle.OpenTime - lastSignal >= cooldown)
			{
				if (prevF <= prevS && f > s && Position <= 0) { BuyMarket(); lastSignal = candle.OpenTime; }
				else if (prevF >= prevS && f < s && Position >= 0) { SellMarket(); lastSignal = candle.OpenTime; }
			}
			prevF = f; prevS = s;
		}).Start();
		var area = CreateChartArea();
		if (area != null) { DrawCandles(area, subscription); DrawIndicator(area, fast); DrawIndicator(area, slow); DrawOwnTrades(area); }
	}
}