Ver en GitHub

Estrategia BullBear Volumen Percentil TP

Esta estrategia utiliza Bull/Bear Power normalizado mediante un Z-Score. Las posiciones largas se abren cuando el Z-Score cruza por encima del umbral, mientras que las posiciones cortas se abren cuando cruza por debajo del umbral negativo. Los niveles de toma de ganancias se basan en multiplicadores de ATR ajustados por volumen y percentiles de precio.

Detalles

  • Criterios de entrada:
    • Largo: Z-Score cruza por encima de ZThreshold.
    • Corto: Z-Score cruza por debajo de -ZThreshold.
  • Largo/Corto: Ambos.
  • Criterios de salida: Z-Score cruza de vuelta a través de cero o alcanza niveles de toma de ganancias.
  • Stops: Toma de ganancias mediante multiplicadores de ATR.
  • Valores predeterminados:
    • Longitud EMA 21, longitud Z-Score 252, umbral 1.618.
    • Período ATR 20, multiplicadores 1.618 / 2.382 / 3.618.
    • Período MA de volumen 100, período de percentil 100.
  • Filtros:
    • Categoría: Momentum
    • Dirección: Ambos
    • Indicadores: EMA, ATR
    • Stops: Sí
    • Complejidad: Medio
    • Marco temporal: Medio plazo
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>
/// Bull/Bear Power strategy using EMA crossover for trend detection.
/// Enters long on golden cross, short on death cross.
/// </summary>
public class BullBearVolumePercentileTpStrategy : 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 BullBearVolumePercentileTpStrategy()
	{
		_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;
	}
}