Diese Strategie implementiert den Experten MetaTrader „AH HM CCI“ in StockSharp erneut. Es achtet auf Hammer und hängenden Kerzenleuchter
Muster und erfordert eine Bestätigung durch den Commodity Channel Index (CCI), bevor ein Handel abgeschlossen wird. Die zusätzlichen Bestätigungsfilter
erkennt schwache Muster und hilft dabei, Einträge an der durch CCI signalisierten Momentumverschiebung auszurichten.
Die Logik läuft nur auf abgeschlossenen Kerzen und verwendet einen kurzen einfachen gleitenden Durchschnitt (SMA), um den vorherrschenden Trend zu definieren. Der Vorherige
Kerze muss ein Hammer in einem Abwärtstrend mit überverkauftem CCI zum Kaufen oder ein hängender Mann in einem Aufwärtstrend mit überkauftem CCI zum Verkauf sein. Ausgänge
werden verwaltet, wenn CCI konfigurierbare Auslöseschwellen überschreitet, wodurch die abstimmungsbasierte Exit-Logik des ursprünglichen Experten repliziert wird.
Handelslogik
Trendfilter – Der Mittelpunkt der vorherigen Kerze muss unter (für Long-Positionen) oder über (für Short-Positionen) einem berechneten Wert von SMA liegen
Schlusskurse. Dies ahmt die Trendprüfung des gleitenden Durchschnitts des ursprünglichen Assistenten nach.
Mustererkennung – Die Strategie wertet den vorherigen Balken aus und prüft:
Körper vollständig im oberen Drittel des Kerzenbereichs.
Lücke zwischen dem Öffnen/Schließen der vorherigen Kerze und der Kerze davor.
Richtungskontext (Hammer für einen Abwärtstrend, hängender Mann für einen Aufwärtstrend).
CCI-Bestätigung – Der CCI des vorherigen Balkens muss unter dem Long-Schwellenwert oder über dem Short-Schwellenwert liegen. Die Standardwerte
entsprechen der Vorlage MetaTrader (40 für Long-Positionen und 60 für Short-Positionen).
Positionsausstiege – Bestehende Positionen werden geschlossen, wenn CCI entweder die untere oder obere Ausstiegsschwelle überschreitet. Überquerung von
unten schließt Longs; Überqueren von oben schließt Shorts.
Parameter
Name
Beschreibung
Standard
CandleType
Kerzentyp und Zeitrahmen, die zur Mustererkennung verwendet werden.
TimeSpan.FromMinutes(15)
CciPeriod
Anzahl der vom Commodity Channel Index verwendeten Balken.
11
MaPeriod
Anzahl der Balken im Trendfilter SMA.
5
LongConfirmationThreshold
Maximal zulässiger CCI-Wert für ein Hammersignal.
40
ShortConfirmationThreshold
Zulässiger Mindestwert CCI für ein Hängender-Mann-Signal.
60
ExitUpperThreshold
CCI-Ebene, die nach einem Aufwärtsübergang Ausstiege auslöst.
70
ExitLowerThreshold
Sekundäre Ausstiegsebene für Frühsignale.
30
Alle Parameter stehen zur Optimierung zur Verfügung. Die Schwellenwerte akzeptieren negative Werte, sodass Sie die Strategie an andere anpassen können
Märkte oder Lärmpegel durch Anziehen oder Lösen der Filter anpassen.
Orderverwaltung
Bei Eingaben werden Marktaufträge mit einer Größe von Volume + |Position| verwendet, um sicherzustellen, dass Umkehrungen in einem einzigen Trade ausgeführt werden.
Ausgänge verlassen sich ausschließlich auf die CCI-Kreuze, um in der Nähe des MetaTrader-Experten zu bleiben. Fügen Sie bei Bedarf StartProtection Anrufe hinzu
explizite Stop-Loss- oder Take-Profit-Level.
Nutzungstipps
Wenden Sie die Strategie auf liquide Instrumente an, bei denen Candlestick-Gaps und -Tails informativ sind.
Experimentieren Sie mit längeren CciPeriod- und MaPeriod-Werten, um Störungen beim Handel mit höheren Zeitrahmen auszugleichen.
Eine Senkung von LongConfirmationThreshold oder eine Erhöhung von ShortConfirmationThreshold verringert die Anzahl der Trades, verbessert sich jedoch
Selektivität.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Hammer/Hanging Man + CCI strategy.
/// Buys on hammer with negative CCI, sells on hanging man with positive CCI.
/// </summary>
public class HammerHangingManCciStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<decimal> _cciLevel;
private readonly StrategyParam<int> _signalCooldownCandles;
private int _candlesSinceTrade;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
public decimal CciLevel { get => _cciLevel.Value; set => _cciLevel.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public HammerHangingManCciStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("CCI Period", "CCI period", "Indicators");
_cciLevel = Param(nameof(CciLevel), 100m)
.SetDisplay("CCI Level", "CCI threshold", "Signals");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_candlesSinceTrade = SignalCooldownCandles;
var cci = new CommodityChannelIndex { Length = CciPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(cci, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal cciValue)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);
var range = candle.HighPrice - candle.LowPrice;
if (range <= 0 || body <= 0) return;
var upperShadow = candle.HighPrice - Math.Max(candle.OpenPrice, candle.ClosePrice);
var lowerShadow = Math.Min(candle.OpenPrice, candle.ClosePrice) - candle.LowPrice;
var isHammer = lowerShadow > body * 2.5m && upperShadow < body * 0.5m;
var isHangingMan = upperShadow > body * 2.5m && lowerShadow < body * 0.5m;
if (isHammer && cciValue < -CciLevel && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (isHangingMan && cciValue > CciLevel && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
}
}
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 CommodityChannelIndex
from StockSharp.Algo.Strategies import Strategy
class hammer_hanging_man_cci_strategy(Strategy):
def __init__(self):
super(hammer_hanging_man_cci_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._cci_period = self.Param("CciPeriod", 14)
self._cci_level = self.Param("CciLevel", 100.0)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 6)
self._candles_since_trade = 6
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def CciPeriod(self):
return self._cci_period.Value
@CciPeriod.setter
def CciPeriod(self, value):
self._cci_period.Value = value
@property
def CciLevel(self):
return self._cci_level.Value
@CciLevel.setter
def CciLevel(self, value):
self._cci_level.Value = value
@property
def SignalCooldownCandles(self):
return self._signal_cooldown_candles.Value
@SignalCooldownCandles.setter
def SignalCooldownCandles(self, value):
self._signal_cooldown_candles.Value = value
def OnReseted(self):
super(hammer_hanging_man_cci_strategy, self).OnReseted()
self._candles_since_trade = self.SignalCooldownCandles
def OnStarted2(self, time):
super(hammer_hanging_man_cci_strategy, self).OnStarted2(time)
self._candles_since_trade = self.SignalCooldownCandles
cci = CommodityChannelIndex()
cci.Length = self.CciPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(cci, self._process_candle).Start()
def _process_candle(self, candle, cci_value):
if candle.State != CandleStates.Finished:
return
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
cci_val = float(cci_value)
body = abs(float(candle.ClosePrice) - float(candle.OpenPrice))
rng = float(candle.HighPrice) - float(candle.LowPrice)
if rng <= 0 or body <= 0:
return
upper_shadow = float(candle.HighPrice) - max(float(candle.OpenPrice), float(candle.ClosePrice))
lower_shadow = min(float(candle.OpenPrice), float(candle.ClosePrice)) - float(candle.LowPrice)
is_hammer = lower_shadow > body * 2.5 and upper_shadow < body * 0.5
is_hanging_man = upper_shadow > body * 2.5 and lower_shadow < body * 0.5
if is_hammer and cci_val < -self.CciLevel and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif is_hanging_man and cci_val > self.CciLevel and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
def CreateClone(self):
return hammer_hanging_man_cci_strategy()