Ver no GitHub

Estratégia Hpcs Inter7

Visão geral

A estratégia Hpcs Inter7 é um sistema de breakout de bandas Bollinger convertido do MetaTrader 4 consultor especialista _HPCS_Inter7_MT4_EA_V01_We.mq4. O algoritmo monitora bandas Bollinger padrão calculadas na série de velas selecionada. Quando o preço ultrapassa as bandas, ele interpreta isso como um rompimento de impulso e abre uma posição na direção do rompimento. Para cada nova entrada, a estratégia coloca imediatamente as metas de stop loss e takeprofit a uma distância fixa do preço de entrada para replicar o comportamento original do consultor especialista.

Lógica de negociação

  • Entrada curta: Quando a vela anterior fechou acima da banda inferior e a última vela fechada terminou abaixo da banda inferior, a estratégia abre uma venda no mercado. Isso recria a condição original Close[0] < LowerBand[0] && Close[1] > LowerBand[1].
  • Entrada longa: Quando a vela anterior fechou abaixo da banda superior e a última vela fechada terminou acima da banda superior, a estratégia abre uma compra no mercado. Isso replica Close[0] > UpperBand[0] && Close[1] < UpperBand[1] da implementação MQL.
  • Negociação única por vela: O algoritmo lembra o horário de abertura da vela que gerou a última ordem. Um novo sinal na mesma vela é ignorado para evitar negociações duplicadas, espelhando a variável de guarda gdt_Candle de MQL4.
  • Ordens de proteção: Imediatamente após a abertura de uma nova posição, a estratégia chama SetStopLoss e SetTakeProfit usando a distância configurada. Ambos são colocados simetricamente em torno do preço de entrada para que a posição tenha sempre metas de risco e recompensa predefinidas.

Parâmetros

Nome Descrição Padrão Otimizável
BollingerLength Número de velas usadas para construir as bandas Bollinger. 20 Sim
BollingerDeviation Multiplicador de desvio padrão para a largura das bandas Bollinger. 2 Sim
CandleType Série de velas usada para cálculos (o padrão é o período de 1 minuto). Velas de 1 minuto Não
ProtectionDistancePoints Distância Stop Loss e Take Profit expressa em etapas de preço. 10 Sim

Notas adicionais

  • A estratégia usa o StockSharp API de alto nível (SubscribeCandles().Bind(...)) e não armazena matrizes de histórico personalizadas.
  • StartProtection() é ativado no início para que a plataforma gerencie automaticamente as ordens de proteção feitas por SetStopLoss e SetTakeProfit.
  • O tamanho da posição é controlado pela propriedade base Strategy.Volume, assim como o consultor especialista original que negociou um volume fixo de um lote.
  • A estratégia foi projetada para instrumentos FX onde o EA original foi implantado, mas pode ser usada em qualquer segurança que forneça sinais de banda Bollinger significativos e um valor PriceStep válido.
using System;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Strategy converted from _HPCS_Inter7_MT4_EA_V01_We.mq4.
/// Sells when price crosses below the lower Bollinger band and buys when price crosses above the upper band.
/// </summary>
public class HpcsInter7Strategy : Strategy
{
	private readonly StrategyParam<int> _bollingerLength;
	private readonly StrategyParam<decimal> _bollingerDeviation;
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<decimal> _bandPercent;

	private decimal? _prevClose;
	private decimal? _prevLower;
	private decimal? _prevUpper;

	/// <summary>
	/// Initializes a new instance of the <see cref="HpcsInter7Strategy"/> class.
	/// </summary>
	public HpcsInter7Strategy()
	{
		_bollingerLength = Param(nameof(BollingerLength), 20)
			.SetGreaterThanZero()
			.SetDisplay("Bollinger Length", "Number of candles included in the Bollinger Bands calculation", "Indicators");

		_bollingerDeviation = Param(nameof(BollingerDeviation), 2m)
			.SetGreaterThanZero()
			.SetDisplay("Bollinger Deviation", "Standard deviation multiplier for the Bollinger Bands", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Time frame used for Bollinger Bands", "General");

		_bandPercent = Param(nameof(BandPercent), 0.01m)
			.SetGreaterThanZero()
			.SetDisplay("Band Percent", "MA percentage band width", "Indicators");
	}

	/// <summary>
	/// Bollinger Bands length.
	/// </summary>
	public int BollingerLength
	{
		get => _bollingerLength.Value;
		set => _bollingerLength.Value = value;
	}

	/// <summary>
	/// Bollinger Bands deviation multiplier.
	/// </summary>
	public decimal BollingerDeviation
	{
		get => _bollingerDeviation.Value;
		set => _bollingerDeviation.Value = value;
	}

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

	public decimal BandPercent
	{
		get => _bandPercent.Value;
		set => _bandPercent.Value = value;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevClose = null;
		_prevLower = null;
		_prevUpper = null;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevClose = null;
		_prevLower = null;
		_prevUpper = null;

		var bollinger = new ExponentialMovingAverage { Length = BollingerLength };

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

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
			return;

		var upper = middle * (1 + BandPercent);
		var lower = middle * (1 - BandPercent);

		if (_prevClose.HasValue && _prevLower.HasValue && _prevUpper.HasValue)
		{
			// Downward cross through the lower band - open short
			if (_prevClose.Value > _prevLower.Value && candle.ClosePrice < lower && Position >= 0)
			{
				SellMarket();
			}
			// Upward cross through the upper band - open long
			else if (_prevClose.Value < _prevUpper.Value && candle.ClosePrice > upper && Position <= 0)
			{
				BuyMarket();
			}
		}

		_prevClose = candle.ClosePrice;
		_prevLower = lower;
		_prevUpper = upper;
	}
}