Ver no GitHub

Estratégia RobotPower M5

Esta estratégia combina os indicadores Bulls Power e Bears Power em um gráfico de 5 minutos. Abre posições quando o momentum combinado de touros e ursos cruza zero e gerencia saídas com alvos fixos e um trailing stop.

Como funciona

  • Indicadores: Bulls Power e Bears Power com um período compartilhado BullBearPeriod.
  • Período: velas de 5 minutos por padrão (CandleType).

Regras de entrada

  • Entrada comprada: Quando BullsPower + BearsPower > 0 e nenhuma posição está aberta, comprar a mercado.
  • Entrada vendida: Quando BullsPower + BearsPower < 0 e nenhuma posição está aberta, vender a mercado.

Regras de saída

  • Take Profit: Fechar a posição quando o preço se mover TakeProfit unidades na direção da operação.
  • Stop Loss: Fechar a posição se o preço se mover contra a posição por StopLoss unidades.
  • Trailing Stop: Após a entrada, o stop loss segue o preço por TrailingStep uma vez que o preço avança mais que o dobro dessa distância.

Parâmetros

  • BullBearPeriod – período para os cálculos de Bulls Power e Bears Power.
  • TrailingStep – tamanho do passo ao ajustar o trailing stop.
  • TakeProfit – distância da entrada até o nível de take profit.
  • StopLoss – distância da entrada até o nível de stop loss.
  • CandleType – período dos candles para cálculo de sinais.

Tamanho da posição

Usa a propriedade Volume da estratégia para o tamanho da ordem.

Notas

Projetada para fins educacionais e serve como exemplo de conversão de uma estratégia MQL para a API do StockSharp.

using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Bulls and Bears Power crossover strategy with trailing stop.
/// Buys when Bulls Power plus Bears Power is positive and sells when negative.
/// Applies fixed take profit and stop loss with trailing adjustment.
/// </summary>
public class RobotPowerM5Strategy : Strategy
{
	private readonly StrategyParam<int> _bullBearPeriod;
	private readonly StrategyParam<decimal> _trailingStep;
	private readonly StrategyParam<decimal> _takeProfit;
	private readonly StrategyParam<decimal> _stopLoss;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _stopPrice;
	private decimal _takePrice;

	/// <summary>
	/// Period for Bulls Power and Bears Power.
	/// </summary>
	public int BullBearPeriod
	{
		get => _bullBearPeriod.Value;
		set => _bullBearPeriod.Value = value;
	}

	/// <summary>
	/// Trailing step distance.
	/// </summary>
	public decimal TrailingStep
	{
		get => _trailingStep.Value;
		set => _trailingStep.Value = value;
	}

	/// <summary>
	/// Take profit distance in price units.
	/// </summary>
	public decimal TakeProfit
	{
		get => _takeProfit.Value;
		set => _takeProfit.Value = value;
	}

	/// <summary>
	/// Stop loss distance in price units.
	/// </summary>
	public decimal StopLoss
	{
		get => _stopLoss.Value;
		set => _stopLoss.Value = value;
	}

	/// <summary>
	/// Candle type used for calculations.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Initializes a new instance of <see cref="RobotPowerM5Strategy"/>.
	/// </summary>
	public RobotPowerM5Strategy()
	{
		_bullBearPeriod = Param(nameof(BullBearPeriod), 5)
			.SetGreaterThanZero()
			.SetDisplay("Bull/Bear Period", "Bulls and Bears Power period", "Indicators");

		_trailingStep = Param(nameof(TrailingStep), 10m)
			.SetGreaterThanZero()
			.SetDisplay("Trailing Step", "Trailing stop step size", "Risk");

		_takeProfit = Param(nameof(TakeProfit), 150m)
			.SetGreaterThanZero()
			.SetDisplay("Take Profit", "Take profit distance", "Risk");

		_stopLoss = Param(nameof(StopLoss), 105m)
			.SetGreaterThanZero()
			.SetDisplay("Stop Loss", "Stop loss distance", "Risk");

		_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();
		_stopPrice = 0m;
		_takePrice = 0m;
	}

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

		_stopPrice = 0m;
		_takePrice = 0m;

		var bulls = new BullPower { Length = BullBearPeriod };
		var bears = new BearPower { Length = BullBearPeriod };

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

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

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

		var sum = bullsValue + bearsValue;

		if (Position == 0)
		{
			if (sum > 0)
			{
				BuyMarket();
				_stopPrice = candle.ClosePrice - StopLoss;
				_takePrice = candle.ClosePrice + TakeProfit;
			}
			else if (sum < 0)
			{
				SellMarket();
				_stopPrice = candle.ClosePrice + StopLoss;
				_takePrice = candle.ClosePrice - TakeProfit;
			}
			return;
		}

		if (Position > 0)
		{
			if (candle.LowPrice <= _stopPrice || candle.HighPrice >= _takePrice)
			{
				SellMarket();
				_stopPrice = 0m;
				_takePrice = 0m;
				return;
			}

			if (candle.ClosePrice - _stopPrice > 2 * TrailingStep)
				_stopPrice = candle.ClosePrice - TrailingStep;
		}
		else if (Position < 0)
		{
			if (candle.HighPrice >= _stopPrice || candle.LowPrice <= _takePrice)
			{
				BuyMarket();
				_stopPrice = 0m;
				_takePrice = 0m;
				return;
			}

			if (_stopPrice - candle.ClosePrice > 2 * TrailingStep)
				_stopPrice = candle.ClosePrice + TrailingStep;
		}
	}
}