Ver en GitHub

Estrategia de Rompimiento de Liquidez de Bitcoin

Esta estrategia entra en posiciones largas cuando la liquidez y la volatilidad son altas y la tendencia a corto plazo es alcista. La alta liquidez se define como volumen por encima de su media móvil multiplicado por un umbral. La volatilidad se confirma cuando el ATR supera su media móvil.

Detalles

  • Criterios de entrada:
    • Volumen > SMA(volumen) * LiquidityThreshold
    • Cambio de precio (%) > PriceChangeThreshold
    • SMA rápida > SMA lenta
    • RSI < 65
    • ATR > SMA(ATR,10)
  • Largo/Corto: Solo largos.
  • Criterios de salida: SMA rápida cruzando por debajo de la SMA lenta o RSI > 70.
  • Stops: Porcentajes opcionales de stop-loss y toma de ganancias.
  • Valores predeterminados:
    • LiquidityThreshold = 1.3
    • PriceChangeThreshold = 1.5
    • VolatilityPeriod = 14
    • LiquidityPeriod = 20
    • FastMaPeriod = 9
    • SlowMaPeriod = 21
    • RsiPeriod = 14
    • StopLossPercent = 0.5
    • TakeProfitPercent = 7
  • Filtros:
    • Categoría: Ruptura
    • Dirección: Largo
    • Indicadores: SMA, RSI, ATR
    • Stops: Sí
    • Complejidad: Medio
    • Marco temporal: 1h
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>
/// Bitcoin liquidity breakout strategy using EMA crossover.
/// Enters long on golden cross, short on death cross.
/// </summary>
public class BitcoinLiquidityBreakoutStrategy : Strategy
{
	private readonly StrategyParam<int> _fastEmaPeriod;
	private readonly StrategyParam<int> _slowEmaPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFastEma;
	private decimal _prevSlowEma;

	public int FastEmaPeriod { get => _fastEmaPeriod.Value; set => _fastEmaPeriod.Value = value; }
	public int SlowEmaPeriod { get => _slowEmaPeriod.Value; set => _slowEmaPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public BitcoinLiquidityBreakoutStrategy()
	{
		_fastEmaPeriod = Param(nameof(FastEmaPeriod), 120)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowEmaPeriod = Param(nameof(SlowEmaPeriod), 450)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles to use", "General");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFastEma = 0m;
		_prevSlowEma = 0m;
	}

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

		var fastEma = new ExponentialMovingAverage { Length = FastEmaPeriod };
		var slowEma = new ExponentialMovingAverage { Length = SlowEmaPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fastEma, slowEma, ProcessCandle)
			.Start();

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

	private void ProcessCandle(ICandleMessage candle, decimal fastEmaValue, decimal slowEmaValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (_prevFastEma == 0m || _prevSlowEma == 0m)
		{
			_prevFastEma = fastEmaValue;
			_prevSlowEma = slowEmaValue;
			return;
		}

		if (_prevFastEma <= _prevSlowEma && fastEmaValue > slowEmaValue && Position <= 0)
		{
			BuyMarket();
		}
		else if (_prevFastEma >= _prevSlowEma && fastEmaValue < slowEmaValue && Position >= 0)
		{
			SellMarket();
		}

		_prevFastEma = fastEmaValue;
		_prevSlowEma = slowEmaValue;
	}
}