Die Hpcs Inter7-Strategie ist ein Bollinger-Band-Breakout-System, das aus dem MetaTrader 4-Expertenberater _HPCS_Inter7_MT4_EA_V01_We.mq4 umgewandelt wurde. Der Algorithmus überwacht Standard-Bollinger-Bänder, die für die ausgewählte Kerzenserie berechnet wurden. Wenn der Preis die Bänder überschreitet, interpretiert er dies als Momentum-Ausbruch und eröffnet eine Position in Richtung des Ausbruchs. Bei jedem neuen Einstieg platziert die Strategie sofort sowohl Stop-Loss- als auch Take-Profit-Ziele in einem festen Abstand zum Einstiegspreis, um das ursprüngliche Verhalten des Expert Advisors nachzubilden.
Handelslogik
Short-Einstieg: Wenn die vorherige Kerze oberhalb des unteren Bandes schloss und die zuletzt geschlossene Kerze unterhalb des unteren Bandes endete, eröffnet die Strategie einen Marktverkauf. Dadurch wird der ursprüngliche Zustand Close[0] < LowerBand[0] && Close[1] > LowerBand[1] wiederhergestellt.
Long-Einstieg: Wenn die vorherige Kerze unterhalb des oberen Bandes schloss und die letzte geschlossene Kerze oberhalb des oberen Bandes endete, eröffnet die Strategie einen Marktkauf. Dadurch wird Close[0] > UpperBand[0] && Close[1] < UpperBand[1] aus der MQL-Implementierung repliziert.
Einzelhandel pro Kerze: Der Algorithmus merkt sich die Öffnungszeit der Kerze, die den letzten Auftrag generiert hat. Ein neues Signal auf derselben Kerze wird ignoriert, um doppelte Trades zu vermeiden, was die Guard-Variable gdt_Candle von MQL4 widerspiegelt.
Schutzanordnungen: Unmittelbar nachdem eine neue Position eröffnet wurde, ruft die Strategie SetStopLoss und SetTakeProfit unter Verwendung der konfigurierten Distanz auf. Beide sind symmetrisch um den Einstiegspreis platziert, sodass die Position immer vordefinierte Risiko- und Ertragsziele aufweist.
Parameter
Name
Beschreibung
Standard
Optimierbar
BollingerLength
Anzahl der Kerzen, die zum Aufbau der Bollinger-Bänder verwendet werden.
20
Ja
BollingerDeviation
Standardabweichungsmultiplikator für die Bandbreite Bollinger.
2
Ja
CandleType
Für Berechnungen verwendete Kerzenserie (standardmäßig 1 Minute Zeitrahmen).
1-Minuten-Kerzen
Nein
ProtectionDistancePoints
Stop-Loss- und Take-Profit-Distanz, ausgedrückt in Preisschritten.
10
Ja
Zusätzliche Hinweise
Die Strategie verwendet die StockSharp-Hochebene API (SubscribeCandles().Bind(...)) und speichert keine benutzerdefinierten Verlaufsarrays.
StartProtection() wird beim Start aktiviert, sodass die Plattform automatisch Schutzanordnungen verwaltet, die von SetStopLoss und SetTakeProfit aufgegeben wurden.
Die Positionsgröße wird durch die Basiseigenschaft Strategy.Volume gesteuert, genau wie beim ursprünglichen Expert Advisor, der ein festes Volumen von einem Lot handelte.
Die Strategie wurde für FX-Instrumente entwickelt, bei denen der ursprüngliche EA eingesetzt wurde, sie kann jedoch auf jedes Wertpapier angewendet werden, das aussagekräftige Bollinger-Bandsignale und einen gültigen PriceStep-Wert liefert.
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()