La estrategia Hpcs Inter7 es un sistema de ruptura de Bollinger bandas convertido del MetaTrader asesor experto de 4 _HPCS_Inter7_MT4_EA_V01_We.mq4. El algoritmo monitorea las bandas Bollinger estándar calculadas en la serie de velas seleccionada. Cuando el precio cruza fuera de las bandas, lo interpreta como una ruptura de impulso y abre una posición en la dirección de la ruptura. Para cada nueva entrada, la estrategia coloca inmediatamente los objetivos de parada de pérdidas y toma de ganancias a una distancia fija del precio de entrada para replicar el comportamiento original del asesor experto.
Lógica de trading
Entrada corta: Cuando la vela anterior cerró por encima de la banda inferior y la última vela cerrada termina por debajo de la banda inferior, la estrategia abre una venta de mercado. Esto recrea la condición original Close[0] < LowerBand[0] && Close[1] > LowerBand[1].
Entrada larga: Cuando la vela anterior cerró por debajo de la banda superior y la última vela cerrada termina por encima de la banda superior, la estrategia abre una compra de mercado. Esto replica Close[0] > UpperBand[0] && Close[1] < UpperBand[1] de la implementación MQL.
Operación única por vela: El algoritmo recuerda la hora de apertura de la vela que generó la última orden. Se ignora una nueva señal en la misma vela para evitar operaciones duplicadas, reflejando la variable de protección gdt_Candle de MQL4.
Órdenes de protección: Inmediatamente después de que se abre una nueva posición, la estrategia llama a SetStopLoss y SetTakeProfit usando la distancia configurada. Ambos se colocan simétricamente alrededor del precio de entrada, por lo que la posición siempre tiene objetivos de riesgo y recompensa predefinidos.
Parámetros
Nombre
Descripción
Predeterminado
Optimizable
BollingerLength
Número de velas utilizadas para construir las Bollinger Bandas.
20
si
BollingerDeviation
Multiplicador de desviación estándar para el ancho de bandas Bollinger.
2
si
CandleType
Serie de velas utilizadas para los cálculos (el valor predeterminado es un período de tiempo de 1 minuto).
velas de 1 minuto
No
ProtectionDistancePoints
Distancia de parada de pérdidas y toma de ganancias expresada en pasos de precio.
10
si
Notas adicionales
La estrategia utiliza el nivel alto StockSharp API (SubscribeCandles().Bind(...)) y no almacena matrices de historial personalizadas.
StartProtection() se activa al inicio para que la plataforma administre automáticamente las órdenes de protección realizadas por SetStopLoss y SetTakeProfit.
El tamaño de la posición está controlado por la propiedad base Strategy.Volume, al igual que el asesor experto original que negoció un volumen fijo de un lote.
La estrategia fue diseñada para instrumentos FX donde se implementó el EA original, pero se puede usar en cualquier valor que proporcione señales de banda Bollinger significativas y un 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;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class hpcs_inter7_strategy(Strategy):
def __init__(self):
super(hpcs_inter7_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._bollinger_length = self.Param("BollingerLength", 20)
self._band_percent = self.Param("BandPercent", 0.01)
self._prev_close = 0.0
self._prev_lower = 0.0
self._prev_upper = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def BollingerLength(self):
return self._bollinger_length.Value
@BollingerLength.setter
def BollingerLength(self, value):
self._bollinger_length.Value = value
@property
def BandPercent(self):
return self._band_percent.Value
@BandPercent.setter
def BandPercent(self, value):
self._band_percent.Value = value
def OnReseted(self):
super(hpcs_inter7_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_lower = 0.0
self._prev_upper = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(hpcs_inter7_strategy, self).OnStarted2(time)
self._prev_close = 0.0
self._prev_lower = 0.0
self._prev_upper = 0.0
self._has_prev = False
ema = ExponentialMovingAverage()
ema.Length = self.BollingerLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(ema, self._process_candle).Start()
def _process_candle(self, candle, middle_value):
if candle.State != CandleStates.Finished:
return
middle = float(middle_value)
band_pct = float(self.BandPercent)
upper = middle * (1.0 + band_pct)
lower = middle * (1.0 - band_pct)
close = float(candle.ClosePrice)
if self._has_prev:
# Downward cross through lower band - short
if self._prev_close > self._prev_lower and close < lower and self.Position >= 0:
self.SellMarket()
# Upward cross through upper band - long
elif self._prev_close < self._prev_upper and close > upper and self.Position <= 0:
self.BuyMarket()
self._prev_close = close
self._prev_lower = lower
self._prev_upper = upper
self._has_prev = True
def CreateClone(self):
return hpcs_inter7_strategy()