Die HPCS Inter5-Strategie ist ein Single-Shot-Momentum-Skript, das vom MetaTrader 4-Experten _HPCS_Inter5_MT4_EA_V01_WE konvertiert wurde. Wenn die Strategie startet, prüft sie die letzten abgeschlossenen Kerzen und sendet einen Marktkaufauftrag, wenn der Schlusskurs von vor fünf Balken höher ist als der letzte Schlusskurs. Optionale schützende Stop-Loss- und Take-Profit-Distanzen emulieren das Pip-basierte Verhalten des ursprünglichen EA.
Handelslogik
Abonnieren Sie die konfigurierte Kerzenserie und behalten Sie die letzten sechs abgeschlossenen Abschlüsse bei.
Nachdem der Puffer gefüllt ist, vergleichen Sie den Schlusskurs von vor fünf Balken mit dem letzten Schlusskurs (Close[5] > Close[1] in MetaTrader-Begriffen).
Wenn die Bedingung erfüllt ist und noch kein Handel getätigt wurde, senden Sie eine Marktkauforder mit dem konfigurierten Volumen.
Schutzbefehle werden einmalig beim Start bis StartProtection aktiviert, wobei eine Pip-Umrechnung im MetaTrader-Stil verwendet wird: Instrumente mit 3 oder 5 Dezimalstellen multiplizieren PriceStep mit 10, um die Pip-Größe zu bestimmen, andernfalls wird die Rohgröße PriceStep verwendet.
Die Strategie eröffnet keine zusätzlichen Trades und ignoriert jedes nachfolgende Signal, sobald die erste Position besetzt ist.
Parameter
Name
Standard
Beschreibung
Candle Type
Zeitrahmen von 1 Minute
Kerzentyp, der zur Erfassung der Schlusskurse verwendet wird. Stellen Sie den Zeitrahmen ein, der Ihrem gewünschten Signalintervall entspricht.
Stop Loss (pips)
10
Abstand für den schützenden Stop-Loss in MetaTrader Pips. Ein Wert von 0 deaktiviert den Stopp.
Take Profit (pips)
10
Abstand für den schützenden Take-Profit in MetaTrader Pips. Ein Wert von 0 deaktiviert den Take-Profit.
Trade Volume
1
Volumen der Market-Order, die bei Auslösung der Eintrittsbedingung übermittelt wird.
Implementierungshinweise
Die Strategie erfordert einen konfigurierten Security.PriceStep (oder Security.Step), um Pip-Abstände umzuwandeln. Fehlt diese Information, bleiben die Schutzoffsets inaktiv, das Einfahrsignal funktioniert jedoch weiterhin.
Nur fertige Kerzen (CandleStates.Finished) werden verarbeitet, um dem MetaTrader-Verhalten zu entsprechen, das auf Close[1] und älteren Werten basiert.
Der interne Puffer speichert genau sechs Schließungen, ohne die Indikatorhistorie zu verwenden, wobei der minimalistische Charakter der Quelle EA berücksichtigt wird.
IsFormedAndOnlineAndAllowTrading() wird vor dem Senden der Bestellung überprüft, um sicherzustellen, dass die Umgebung zur Ausführung bereit ist.
Nutzungstipps
Weisen Sie ein Forex-Instrument mit den richtigen Preis- und Volumeneinstellungen zu.
Passen Sie Candle Type an den Zeitrahmen an, den Sie analysieren möchten.
Lassen Sie den Stop-Loss oder Take-Profit bei Null, wenn Sie Exits lieber manuell verwalten möchten.
Starten Sie die Strategie immer dann neu, wenn Sie die Eintrittsbedingung neu bewerten möchten, da sie nur einmal pro Sitzung ausgelöst wird.
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;
using StockSharp.Algo;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Single-shot momentum strategy converted from the "_HPCS_Inter5" MetaTrader script.
/// Places one market buy when the close price from five bars ago exceeds the most recent close.
/// </summary>
public class HpcsInter5Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _stopLossPips;
private readonly StrategyParam<int> _takeProfitPips;
private readonly StrategyParam<decimal> _tradeVolume;
private readonly decimal?[] _recentCloses = new decimal?[6];
private decimal _pipSize;
private bool _wasLongSignal;
private bool _hasSignal;
/// <summary>
/// Candle type used to evaluate the closing prices.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Stop-loss distance expressed in MetaTrader-style pips.
/// </summary>
public int StopLossPips
{
get => _stopLossPips.Value;
set => _stopLossPips.Value = value;
}
/// <summary>
/// Take-profit distance expressed in MetaTrader-style pips.
/// </summary>
public int TakeProfitPips
{
get => _takeProfitPips.Value;
set => _takeProfitPips.Value = value;
}
/// <summary>
/// Trade volume submitted with the market entry.
/// </summary>
public decimal TradeVolume
{
get => _tradeVolume.Value;
set => _tradeVolume.Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="HpcsInter5Strategy"/> class.
/// </summary>
public HpcsInter5Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(120).TimeFrame())
.SetDisplay("Candle Type", "Candle type used for the close comparison", "General");
_stopLossPips = Param(nameof(StopLossPips), 20)
.SetDisplay("Stop Loss (pips)", "Stop-loss distance expressed in pips", "Risk Management");
_takeProfitPips = Param(nameof(TakeProfitPips), 20)
.SetDisplay("Take Profit (pips)", "Take-profit distance expressed in pips", "Risk Management");
_tradeVolume = Param(nameof(TradeVolume), 1m)
.SetGreaterThanZero()
.SetDisplay("Trade Volume", "Volume submitted with the market entry", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
Array.Clear(_recentCloses, 0, _recentCloses.Length);
_pipSize = 0m;
_wasLongSignal = false;
_hasSignal = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
if (Security is null)
throw new InvalidOperationException("Security must be assigned before starting the strategy.");
base.OnStarted2(time);
InitializePipSize();
Volume = TradeVolume;
_wasLongSignal = false;
_hasSignal = false;
var stopLoss = StopLossPips > 0 && _pipSize > 0m
? new Unit(StopLossPips * _pipSize, UnitTypes.Absolute)
: null;
var takeProfit = TakeProfitPips > 0 && _pipSize > 0m
? new Unit(TakeProfitPips * _pipSize, UnitTypes.Absolute)
: null;
if (stopLoss != null || takeProfit != null)
StartProtection(stopLoss: stopLoss, takeProfit: takeProfit);
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
ShiftCloses(candle.ClosePrice);
if (_recentCloses[1] is not decimal lastClose || _recentCloses[5] is not decimal olderClose)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var threshold = lastClose * 0.005m;
var longSignal = olderClose - lastClose > threshold;
var shortSignal = lastClose - olderClose > threshold;
var crossedLong = longSignal && (!_hasSignal || !_wasLongSignal);
var crossedShort = shortSignal && (!_hasSignal || _wasLongSignal);
if (crossedLong && Position <= 0)
{
BuyMarket();
}
else if (crossedShort && Position >= 0)
{
SellMarket();
}
if (longSignal || shortSignal)
{
_wasLongSignal = longSignal;
_hasSignal = true;
}
}
private void ShiftCloses(decimal close)
{
for (var i = _recentCloses.Length - 1; i > 0; i--)
_recentCloses[i] = _recentCloses[i - 1];
_recentCloses[0] = close;
}
private void InitializePipSize()
{
var step = Security.PriceStep ?? 0.01m;
if (step <= 0m)
step = 0.01m;
var pipFactor = Security.Decimals is 3 or 5 ? 10m : 1m;
_pipSize = step * pipFactor;
}
}
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, Unit, UnitTypes
from StockSharp.Algo.Strategies import Strategy
class hpcs_inter5_strategy(Strategy):
"""
HPCS Inter5: momentum strategy comparing close from 5 bars ago
vs current close. Buys when older close exceeds recent by threshold.
Sells on reverse. Uses StartProtection for SL/TP.
"""
def __init__(self):
super(hpcs_inter5_strategy, self).__init__()
self._stop_loss_pips = self.Param("StopLossPips", 20) \
.SetDisplay("Stop Loss (pips)", "Stop-loss distance in pips", "Risk Management")
self._take_profit_pips = self.Param("TakeProfitPips", 20) \
.SetDisplay("Take Profit (pips)", "Take-profit distance in pips", "Risk Management")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(120))) \
.SetDisplay("Candle Type", "Candle type for close comparison", "General")
self._recent_closes = [None] * 6
self._pip_size = 0.0
self._was_long_signal = False
self._has_signal = False
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(hpcs_inter5_strategy, self).OnReseted()
self._recent_closes = [None] * 6
self._pip_size = 0.0
self._was_long_signal = False
self._has_signal = False
def OnStarted2(self, time):
super(hpcs_inter5_strategy, self).OnStarted2(time)
step = 0.01
if self.Security is not None and self.Security.PriceStep is not None:
step = float(self.Security.PriceStep)
if step <= 0:
step = 0.01
decimals = 0
if self.Security is not None and self.Security.Decimals is not None:
decimals = int(self.Security.Decimals)
pip_factor = 10.0 if decimals in (3, 5) else 1.0
self._pip_size = step * pip_factor
sl_pips = self._stop_loss_pips.Value
tp_pips = self._take_profit_pips.Value
sl = None
tp = None
if sl_pips > 0 and self._pip_size > 0:
sl = Unit(sl_pips * self._pip_size, UnitTypes.Absolute)
if tp_pips > 0 and self._pip_size > 0:
tp = Unit(tp_pips * self._pip_size, UnitTypes.Absolute)
if sl is not None or tp is not None:
self.StartProtection(tp, sl)
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self._process_candle).Start()
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
for i in range(len(self._recent_closes) - 1, 0, -1):
self._recent_closes[i] = self._recent_closes[i - 1]
self._recent_closes[0] = close
last_close = self._recent_closes[1]
older_close = self._recent_closes[5]
if last_close is None or older_close is None:
return
threshold = last_close * 0.005
long_signal = older_close - last_close > threshold
short_signal = last_close - older_close > threshold
crossed_long = long_signal and (not self._has_signal or not self._was_long_signal)
crossed_short = short_signal and (not self._has_signal or self._was_long_signal)
if crossed_long and self.Position <= 0:
self.BuyMarket()
elif crossed_short and self.Position >= 0:
self.SellMarket()
if long_signal or short_signal:
self._was_long_signal = long_signal
self._has_signal = True
def CreateClone(self):
return hpcs_inter5_strategy()