Diese Strategie repliziert die Logik des ursprünglichen Expert Advisors „CHO Smoothed EA“. Es beobachtet die Überkreuzungen des Chaikin-Oszillators bei abgeschlossenen Kerzen und glättet den Oszillator mit einem konfigurierbaren gleitenden Durchschnitt. Optionale Filter beschränken den Handel auf eine bestimmte Sitzung, schränken die Handelsrichtung ein und validieren Signale mit Nulllinienbestätigung. Wenn ein Signal akzeptiert wird, sendet die Strategie eine Marktorder und verwaltet die Position mithilfe fester Distanzen in Punkten für Stop-Loss, Take-Profit und Trailing-Schutz.
Handelslogik
Die Werte des Chaikin-Oszillators werden für jede fertige Kerze mit konfigurierbaren schnellen und langsamen Perioden berechnet.
Ein gleitender Durchschnitt des Oszillators erzeugt die Signallinie. Der Zeitraum und die Art des gleitenden Durchschnitts können angepasst werden.
Lange Einträge treten auf, wenn der Oszillator die geglättete Linie überschreitet. Kurze Einträge erfolgen an der gegenüberliegenden Kreuzung. Signale können umgekehrt werden, um entgegen der ursprünglichen Richtung zu handeln.
Wenn der Nullpegelfilter aktiviert ist, müssen beide Oszillatorwerte für Long-Trades unter Null und für Short-Trades über Null liegen.
Die Strategie kann entgegengesetzte Positionen automatisch schließen, bevor ein neuer Handel eingegangen wird, oder Signale ignorieren, bis die aktuelle Position flach ist. Es kann auch ein Einzelpositionsmodus erzwungen werden.
Der Handel kann auf ein tägliches Zeitfenster beschränkt werden. Windows, die Mitternacht überschreiten, werden unterstützt.
Nach einem Einstieg speichert die Strategie den Einstiegspreis, wandelt die konfigurierten Punktabstände in Preisversätze um und überwacht Kerzen auf Stop-Loss-, Take-Profit- und Trailing-Stop-Ereignisse.
Risikomanagement
Stop-Loss- und Take-Profit-Level werden aus dem Einstiegspreis unter Verwendung von Punktabständen multipliziert mit dem Preisschritt des Instruments berechnet.
Der Trailing-Stop wird aktiviert, nachdem der Preis um den konfigurierten Trailing-Schritt ansteigt, und folgt dann mit der Trailing-Distanz.
Wenn ein Schutzniveau erreicht wird, wird die Position sofort mit einer Marktorder geschlossen und alle Risikoniveaus werden zurückgesetzt.
Parameter
Kerzentyp – Zeitrahmen, der zum Erstellen der Kerzen für die Indikatorberechnungen verwendet wird.
Schnelle Periode / Langsame Periode – Schnelle und langsame Perioden des Chaikin-Oszillators.
Signal-MA-Periode / Signal-MA-Typ – Glättungseinstellungen für den gleitenden Durchschnitt, die auf den Oszillator angewendet werden.
Nullwert verwenden – Vor dem Handel müssen beide Oszillatorwerte auf der richtigen Seite von Null liegen.
Handelsmodus – nur Long, nur Short oder beide Richtungen zulassen.
Umgekehrte Signale – Long- und Short-Einträge tauschen.
Gegenüberliegende Positionen schließen – bestehende entgegengesetzte Positionen schließen, bevor ein neuer Handel eröffnet wird.
Nur eine Position – Einträge verhindern, wenn eine Position bereits offen ist.
Zeitsteuerung / Startzeit / Endzeit verwenden – aktivieren und konfigurieren Sie das tägliche Handelsfenster.
Stop Loss (Pkte) – Abstand in Punkten für den Schutzstopp.
Take Profit (Pkte) – Abstand in Punkten für Gewinnziele.
Trailing Stop (Punkte) – Trailing Stop-Distanz in Punkten.
Trailing Step (Punkte) – minimale günstige Bewegung (in Punkten) vor der Bewegung des Trailing Stops.
Zusätzliche Hinweise
Legen Sie die Eigenschaft Volume der Strategie fest, bevor Sie sie starten, um die Handelsgröße zu steuern.
Da die Strategie Marktaufträge ausgibt, stellen Sie eine ausreichende Liquidität sicher und berücksichtigen Sie Slippage in Live-Umgebungen.
Wenn die Start- und Endzeiten des Handelsfensters gleich sind, bleibt die Strategie inaktiv und entspricht dem ursprünglichen Verhalten des Expert Advisors.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Trades CCI oscillator zero-line crossovers with signal MA smoothing.
/// Originally based on Chaikin Oscillator concept, adapted to use CCI.
/// </summary>
public class ChoSmoothedEaStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<int> _maPeriod;
private CommodityChannelIndex _cci;
private readonly Queue<decimal> _cciHistory = new();
private decimal? _prevCci;
private decimal? _prevSignal;
/// <summary>
/// Initializes a new instance of the <see cref="ChoSmoothedEaStrategy"/> class.
/// </summary>
public ChoSmoothedEaStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for signal calculations", "General");
_cciPeriod = Param(nameof(CciPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("CCI Period", "Period for CCI oscillator", "Indicator");
_maPeriod = Param(nameof(MaPeriod), 9)
.SetGreaterThanZero()
.SetDisplay("Signal MA Period", "Period of smoothing moving average on CCI", "Indicator");
}
/// <summary>
/// Candle type used for calculations.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// CCI oscillator period.
/// </summary>
public int CciPeriod
{
get => _cciPeriod.Value;
set => _cciPeriod.Value = value;
}
/// <summary>
/// Period of the smoothing moving average.
/// </summary>
public int MaPeriod
{
get => _maPeriod.Value;
set => _maPeriod.Value = value;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevCci = null;
_prevSignal = null;
_cciHistory.Clear();
_cci = new CommodityChannelIndex { Length = CciPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_cci, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal cciValue)
{
if (candle.State != CandleStates.Finished)
return;
_cciHistory.Enqueue(cciValue);
while (_cciHistory.Count > MaPeriod)
_cciHistory.Dequeue();
if (!_cci.IsFormed)
return;
if (_cciHistory.Count < MaPeriod)
{
_prevCci = cciValue;
return;
}
// Calculate signal line (SMA of CCI)
var sum = 0m;
var history = _cciHistory.ToArray();
foreach (var v in history)
sum += v;
var signalValue = sum / history.Length;
if (_prevCci is null || _prevSignal is null)
{
_prevCci = cciValue;
_prevSignal = signalValue;
return;
}
var crossUp = _prevCci <= _prevSignal && cciValue > signalValue;
var crossDown = _prevCci >= _prevSignal && cciValue < signalValue;
var volume = Volume;
if (volume <= 0)
volume = 1;
var minSpread = 25m;
if (crossUp && Math.Abs(cciValue - signalValue) >= minSpread)
{
if (Position <= 0)
BuyMarket(Position < 0 ? Math.Abs(Position) + volume : volume);
}
else if (crossDown && Math.Abs(cciValue - signalValue) >= minSpread)
{
if (Position >= 0)
SellMarket(Position > 0 ? Math.Abs(Position) + volume : volume);
}
_prevCci = cciValue;
_prevSignal = signalValue;
}
/// <inheritdoc />
protected override void OnReseted()
{
_prevCci = null;
_prevSignal = null;
_cci = null;
_cciHistory.Clear();
base.OnReseted();
}
}