Esta estrategia opera basándose en el cruce de los indicadores Bulls Power y Bears Power en un marco temporal de cuatro horas. Bulls Power mide la presión compradora por encima de un precio promedio, mientras que Bears Power muestra la presión vendedora por debajo de él. Cuando la fuerza compradora supera la fuerza vendedora, el sistema abre una posición larga. Cuando la fuerza vendedora se vuelve dominante, abre una posición corta.
Las pruebas en datos históricos de criptomonedas muestran que los cruces claros suelen preceder a reversiones a corto plazo. La estrategia está diseñada para estar siempre larga o corta, revirtiendo la posición cada vez que los indicadores se cruzan en la dirección opuesta.
Detalles
Criterios de entrada:
Largo: El valor de Bulls Power cruza por encima de Bears Power.
Corto: El valor de Bears Power cruza por encima de Bulls Power.
Largo/Corto: Ambas direcciones.
Criterios de salida: Cruce opuesto que invierte la posición.
Stops: Ninguno. Las posiciones se revierten en lugar de cerrarse por stop.
Filtros:
Marco temporal: velas de 4 horas por defecto.
Indicadores: Bulls Power, Bears Power.
Dirección: Reversión basada en cambio de momentum.
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>
/// EMA crossover with RSI filter strategy.
/// </summary>
public class BullsBearsPowerCrossStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public BullsBearsPowerCrossStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 13)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 26)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow EMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle type", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
SubscribeCandles(CandleType)
.Bind(fast, slow, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev)
{
_prevFast = fastVal;
_prevSlow = slowVal;
_hasPrev = true;
return;
}
var crossUp = _prevFast <= _prevSlow && fastVal > slowVal;
var crossDown = _prevFast >= _prevSlow && fastVal < slowVal;
if (crossUp && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (crossDown && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevFast = fastVal;
_prevSlow = slowVal;
}
}