Strategie konvertiert vom MetaTrader-Experten Exp_AverageChangeCandle. Sie recreiert die ursprüngliche Logik in StockSharp, indem sie Kerzen-Ratios relativ zu einem dynamischen Basis-gleitenden Durchschnitt glättet und auf bullische/bärische Farbübergänge reagiert.
Kernidee
Einen Basis-gleitenden Durchschnitt (MaMethod1, Length1) über den ausgewählten angewandten Preis berechnen.
Den aktuellen Kerzen-Eröffnungs- und Schlusskurs als Ratios zur Basis ausdrücken und sie zur Potenz Power erheben.
Die transformierten Eröffnungs- und Schlusswerte mit einem sekundären gleitenden Durchschnitt (MaMethod2, Length2) glätten.
Die Kerzenfarbe klassifizieren: bullisch wenn geglätteter Schluss > geglättete Eröffnung, bärisch wenn geglätteter Schluss < geglättete Eröffnung.
Handelssignale generieren, wenn sich die Farbe nach der konfigurierten SignalBar-Verzögerung ändert.
Nur abgeschlossene Kerzen werden verarbeitet. Die Strategie öffnet Marktpositionen in Richtung der neuen Farbe und schließt optional die entgegengesetzte Seite.
Parameter
Parameter
Standard
Beschreibung
OrderVolume
1
Volumen beim Öffnen einer neuen Position.
MaMethod1
Lwma
Glättung des Basis-Ratios (Teilmenge von SMA/EMA/SMMA/LWMA/JJMA/AMA). Nicht unterstützte Typen fallen auf EMA zurück.
Length1
12
Zeitraum des Basis-gleitenden Durchschnitts.
Phase1
15
Jurik-Phasenparameter für die Basis (aus Kompatibilitätsgründen beibehalten).
PriceSource
Median
Angewandter Preis vor der Basis-Berechnung.
MaMethod2
Jjma
Glättung der transformierten Ratios.
Length2
5
Zeitraum des Signal-gleitenden Durchschnitts.
Phase2
100
Jurik-Phasenparameter für die Signalglättung.
Power
5
Exponent beim Erheben der Eröffnungs-/Schlusskurs-Ratios.
SignalBar
1
Anzahl der geschlossenen Balken vor einer Reaktion auf eine Farbänderung.
BuyOpenEnabled
true
Long-Positionen öffnen erlauben.
SellOpenEnabled
true
Short-Positionen öffnen erlauben.
BuyCloseEnabled
true
Longs schließen wenn ein bärisches Signal erscheint.
SellCloseEnabled
true
Shorts schließen wenn ein bullisches Signal erscheint.
StopLossPoints
0
Absoluter Stop-Loss-Abstand. 0 deaktiviert den Stop.
TakeProfitPoints
0
Absoluter Take-Profit-Abstand. 0 deaktiviert das Ziel.
CandleType
H4-Zeitrahmen
Kerzenserie, die von der Strategie verarbeitet wird.
Handelsregeln
Bullischer Übergang (color ändert sich auf 2): aktive Shorts schließen (wenn erlaubt) und eine Long-Position öffnen wenn Position <= 0 und BuyOpenEnabled wahr ist.
Bärischer Übergang (color ändert sich auf 0): aktive Longs schließen (wenn erlaubt) und eine Short-Position öffnen wenn Position >= 0 und SellOpenEnabled wahr ist.
Farbe 1 (neutral) löst keine Trades aus.
Signale werden anhand der Balken ausgewertet, die SignalBar Schritte hinter der zuletzt abgeschlossenen Kerze liegen, um das ursprüngliche MetaTrader-Timing nachzuahmen.
Risikomanagement
StopLossPoints und TakeProfitPoints konfigurieren StartProtection mit absoluten Abständen. Wenn einer der Werte null ist, wird der jeweilige Schutz deaktiviert.
Hinweise
Nur die in StockSharp verfügbaren Glättungsmethoden werden direkt implementiert. JurX, ParMA, T3 und VIDYA aus dem Originalcode werden als funktionaler Fallback zu EMA zugeordnet.
Phasenparameter werden aus Kompatibilitätsgründen beibehalten, betreffen aber nur Jurik/Kaufman-basierte Durchschnitte.
Die Strategie verwendet Marktaufträge, genau wie der ursprüngliche Expertenberater. Die Slippage-Verwaltung der MQL-Version wird nicht reproduziert, da StockSharp die Ausführung über Konnektoren handhabt.
namespace StockSharp.Samples.Strategies;
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Average Change Candle strategy (simplified).
/// Compares smoothed open vs close ratios to detect bullish/bearish candle patterns.
/// Uses EMA of open and close to determine trend direction.
/// </summary>
public class AverageChangeCandleStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaPeriod;
private decimal _prevSmoothedOpen;
private decimal _prevSmoothedClose;
private bool _initialized;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int EmaPeriod
{
get => _emaPeriod.Value;
set => _emaPeriod.Value = value;
}
public AverageChangeCandleStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Source candles", "General");
_emaPeriod = Param(nameof(EmaPeriod), 12)
.SetGreaterThanZero()
.SetDisplay("EMA Period", "EMA smoothing period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevSmoothedOpen = 0m;
_prevSmoothedClose = 0m;
_initialized = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevSmoothedOpen = 0;
_prevSmoothedClose = 0;
_initialized = false;
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ema, (ICandleMessage candle, decimal emaValue) =>
{
if (candle.State != CandleStates.Finished)
return;
// Simple exponential smoothing of open and close
var alpha = 2m / (EmaPeriod + 1m);
if (!_initialized)
{
_prevSmoothedOpen = candle.OpenPrice;
_prevSmoothedClose = candle.ClosePrice;
_initialized = true;
return;
}
var smoothedOpen = alpha * candle.OpenPrice + (1m - alpha) * _prevSmoothedOpen;
var smoothedClose = alpha * candle.ClosePrice + (1m - alpha) * _prevSmoothedClose;
var prevBullish = _prevSmoothedClose > _prevSmoothedOpen;
var currBullish = smoothedClose > smoothedOpen;
if (!IsFormedAndOnlineAndAllowTrading())
{
_prevSmoothedOpen = smoothedOpen;
_prevSmoothedClose = smoothedClose;
return;
}
// Buy on transition to bullish smoothed candle
if (currBullish && !prevBullish && candle.ClosePrice > emaValue && Position <= 0)
{
BuyMarket();
}
// Sell on transition to bearish smoothed candle
else if (!currBullish && prevBullish && candle.ClosePrice < emaValue && Position >= 0)
{
SellMarket();
}
_prevSmoothedOpen = smoothedOpen;
_prevSmoothedClose = smoothedClose;
})
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
}
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 average_change_candle_strategy(Strategy):
def __init__(self):
super(average_change_candle_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Source candles", "General")
self._ema_period = self.Param("EmaPeriod", 12) \
.SetDisplay("EMA Period", "EMA smoothing period", "Indicators")
self._prev_smoothed_open = 0.0
self._prev_smoothed_close = 0.0
self._initialized = False
@property
def CandleType(self):
return self._candle_type.Value
@property
def EmaPeriod(self):
return self._ema_period.Value
def OnReseted(self):
super(average_change_candle_strategy, self).OnReseted()
self._prev_smoothed_open = 0.0
self._prev_smoothed_close = 0.0
self._initialized = False
def OnStarted2(self, time):
super(average_change_candle_strategy, self).OnStarted2(time)
self._prev_smoothed_open = 0.0
self._prev_smoothed_close = 0.0
self._initialized = False
ema = ExponentialMovingAverage()
ema.Length = self.EmaPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription \
.Bind(ema, self._on_process) \
.Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ema)
self.DrawOwnTrades(area)
def _on_process(self, candle, ema_value):
if candle.State != CandleStates.Finished:
return
ev = float(ema_value)
o = float(candle.OpenPrice)
c = float(candle.ClosePrice)
alpha = 2.0 / (self.EmaPeriod + 1.0)
if not self._initialized:
self._prev_smoothed_open = o
self._prev_smoothed_close = c
self._initialized = True
return
smoothed_open = alpha * o + (1.0 - alpha) * self._prev_smoothed_open
smoothed_close = alpha * c + (1.0 - alpha) * self._prev_smoothed_close
prev_bullish = self._prev_smoothed_close > self._prev_smoothed_open
curr_bullish = smoothed_close > smoothed_open
if curr_bullish and not prev_bullish and c > ev and self.Position <= 0:
self.BuyMarket()
elif not curr_bullish and prev_bullish and c < ev and self.Position >= 0:
self.SellMarket()
self._prev_smoothed_open = smoothed_open
self._prev_smoothed_close = smoothed_close
def CreateClone(self):
return average_change_candle_strategy()