Открыть на GitHub

Стратегия RPM5 BullsBearsEyes

Общее описание

RPM5 BullsBearsEyes — порт советника MetaTrader 4 Rpm5_mt4v1 на платформу StockSharp. Оригинальный алгоритм комбинировал индикаторы Bulls Power и Bears Power в собственный осциллятор BullsBearsEyes и удерживал единственную позицию по направлению преобладающей силы. Перенос повторяет ту же логику с использованием высокоуровневого API StockSharp, сохраняя исходные параметры рисков, правила трейлинга и пороги сигналов.

Восстановление индикатора

  • На выбранном таймфрейме рассчитываются стандартные индикаторы Bulls Power и Bears Power.
  • Их сумма проходит через тот же четырёхступенчатый IIR-фильтр, что применялся в MT4. Параметр Gamma управляет скоростью реакции осциллятора.
  • Фильтр выдаёт значение в диапазоне от 0 до 1. Значения выше порога свидетельствуют о доминировании покупателей, ниже — продавцов. Точные 0 или 1 появляются при полном исчерпании одной из сторон, как и в оригинале.

Правила торговли

  1. Стратегия подписывается на выбранные свечи (по умолчанию 5 минут) и обрабатывает только закрытые бары.
  2. При отсутствии позиции оценивается отношение BullsBearsEyes:
    • Покупка — текущее значение строго выше Threshold (0.5 по умолчанию).
    • Продажа — текущее значение строго ниже Threshold.
    • Одновременно поддерживается не более одной позиции, противоположные сигналы игнорируются до полного закрытия текущей сделки.
  3. После входа позиция удерживается до срабатывания стоп-лосса, тейк-профита либо трейлинг-стопа.

Управление рисками

  • Стоп-лосс и тейк-профит вычисляются из исходных 25 и 150 пунктов. При открытии позиции значения пересчитываются в цену с использованием PriceStep инструмента.
  • Трейлинг по ATR: на каждой закрытой свече оценивается средний истинный диапазон (AtrPeriod, по умолчанию 5). Дистанция трейлинга равна одному пункту плюс AtrMultiplier × ATR. Как только цена проходит это расстояние, стоп подтягивается вслед за рынком — аналогично вызовам OrderModify в MQL4.
  • Проверка защитных уровней выполняется до поиска новых сигналов, поэтому выходы имеют приоритет над повторными входами.

Параметры

Имя Значение по умолчанию Описание
Bulls/Bears Period 13 Период усреднения индикаторов Bulls Power и Bears Power.
Gamma 0.5 Коэффициент сглаживания четырёхступенчатого фильтра BullsBearsEyes.
Threshold 0.5 Граница между «бычьей» (> порога) и «медвежьей» (< порога) зонами.
ATR Period 5 Период ATR, используемый для трейлинг-стопа.
ATR Multiplier 1.5 Множитель ATR при расчёте дистанции трейлинга.
Stop Loss (pips) 25 Расстояние стоп-лосса (в пунктах, пересчитывается в цену).
Take Profit (pips) 150 Расстояние тейк-профита (в пунктах, пересчитывается в цену).
Trade Volume 1 Объём рыночного ордера для новых сделок.
Candle Type Свечи 5 минут Таймфрейм, который обрабатывает стратегия.

Примечания

  • Графические объекты дневного канала из MT4 не переносятся, поскольку носили исключительно декоративный характер.
  • Все комментарии в коде написаны на английском языке.
  • Тестовые сценарии в репозитории не изменялись; при необходимости запустите стандартные проверки решения.
using System;
using System.Collections.Generic;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// RPM5 Bulls Bears Eyes strategy using Bull/Bear power with EMA filter.
/// Buy when bull power is positive and bear power crosses above threshold.
/// Sell when bear power is negative and bull power crosses below threshold.
/// </summary>
public class Rpm5BullsBearsEyesStrategy : Strategy
{
	private readonly StrategyParam<int> _emaPeriod;
	private readonly StrategyParam<int> _powerPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevBull;
	private decimal _prevBear;
	private bool _hasPrev;

	public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
	public int PowerPeriod { get => _powerPeriod.Value; set => _powerPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public Rpm5BullsBearsEyesStrategy()
	{
		_emaPeriod = Param(nameof(EmaPeriod), 13)
			.SetDisplay("EMA Period", "EMA trend period", "Indicators");

		_powerPeriod = Param(nameof(PowerPeriod), 13)
			.SetDisplay("Power Period", "Bulls/Bears power period", "Indicators");

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

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevBull = 0m;
		_prevBear = 0m;
		_hasPrev = false;
	}

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

		_hasPrev = false;

		var ema = new ExponentialMovingAverage { Length = EmaPeriod };
		var bulls = new BullPower { Length = PowerPeriod };
		var bears = new BearPower { Length = PowerPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(ema, bulls, bears, ProcessCandle)
			.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal emaValue, decimal bullValue, decimal bearValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!_hasPrev)
		{
			_prevBull = bullValue;
			_prevBear = bearValue;
			_hasPrev = true;
			return;
		}

		// Long: price above EMA, bull power positive, bear power crossing from negative to less negative
		var longSignal = candle.ClosePrice > emaValue && bullValue > 0 && _prevBear < 0 && bearValue > _prevBear;
		// Short: price below EMA, bear power negative, bull power crossing from positive to less positive
		var shortSignal = candle.ClosePrice < emaValue && bearValue < 0 && _prevBull > 0 && bullValue < _prevBull;

		if (Position <= 0 && longSignal)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		else if (Position >= 0 && shortSignal)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevBull = bullValue;
		_prevBear = bearValue;
	}
}