Diese Strategie ist eine direkte Portierung des MetaTrader-Expertenberaters ichimok2005, der auf den StockSharp-Experten API zugeschnitten ist. Es konzentriert sich auf die Identifizierung entscheidender Ausbrüche über oder unter der Senkou Span B-Linie Ichimoku und bestätigt die Dynamik durch aufeinanderfolgende Kerzenkörper.
Handelslogik
Lange Einrichtung
Bewerten Sie die letzten Shift + 2 abgeschlossenen Kerzen (der Standardwert für Shift ist 1, sodass der Algorithmus die vorherigen drei Balken berücksichtigt).
Fordern Sie Folgendes:
Die älteste Referenzkerze (Shift + 2) öffnete sich unterhalb von Senkou Span B.
Die mittlere Referenzkerze (Shift + 1) öffnete über Senkou Span B und schloss darüber.
Die letzte Referenzkerze (Shift) öffnete und schloss über Senkou Span B.
Die letzten beiden Referenzkerzen sind bullisch (Schlusskurs ist höher als Eröffnungspreis).
Stellen Sie sicher, dass der Ichimoku Chinkou Span nicht in der Wolke gefangen ist, wenn Senkou Span A unter Senkou Span B liegt. Dies imitiert den ursprünglichen Expert Advisor-Filter, der überlastete Marktphasen vermeidet.
Wenn die Strategie derzeit eine Short-Position hält, wird diese geschlossen. Andernfalls wird ein neuer Long-Trade eröffnet, sofern das vorherige Signal nicht bereits Long war.
Kurze Einrichtung
Spiegeln Sie die Long-Bedingungen in die entgegengesetzte Richtung:
Kerze Shift + 2 muss sich über Senkou Span B öffnen.
Kerze Shift + 1 muss unterhalb von Senkou Span B öffnen und schließen.
Kerze Shift muss unterhalb von Senkou Span B öffnen und schließen.
Die letzten beiden Referenzkerzen sind bärisch (Schlusskurs ist niedriger als Eröffnungspreis).
Die Chinkou-Spanne muss außerhalb der Wolke bleiben, wenn Senkou-Spanne A unter Senkou-Spanne B liegt.
Schließen Sie alle vorhandenen Long-Positionen und eröffnen Sie dann eine neue Short-Position, wenn das vorherige Signal nicht Short war.
Positionen werden mit den Schutzanordnungen von StockSharp verwaltet. Stop-Loss und Take-Profit werden in Preisschritten gemessen und mithilfe des PriceStep des Instruments in absolute Abstände umgerechnet. Schutzaufträge werden bei Marktaustritten registriert, um das MetaTrader-Verhalten bei der Verwendung von Marktstopps zu reproduzieren.
Positionsgrößen
Der ursprüngliche Advisor unterstützte zwei Größenmodi:
Festes Volumen (UseMoneyManagement = false): Trades werden mit dem Parameter OrderVolume ausgeführt (Standard 0,1 Lots).
Geldmanagement (UseMoneyManagement = true): Die Strategie verwendet den aktuellen Wert des Portfolios und den Prozentsatz MaximumRisk, um die Auftragsgröße abzuleiten. Das Ergebnis wird an der Losstufe des Wertpapiers festgehalten und fällt nie unter eine einzelne Stufe.
Parameter
Parameter
Beschreibung
Standard
StopLossPoints
Stop-Loss-Distanz in Preisschritten.
30
TakeProfitPoints
Take-Profit-Distanz in Preisschritten.
60
Shift
Anzahl der Balken, die bei der Validierung der Breakout-Struktur als Offset verwendet werden.
1
OrderVolume
Handelsgröße behoben, wenn die Geldverwaltung deaktiviert ist.
0,1
MaximumRisk
Portfolio-Prozentsatz, der zur Größenbestimmung von Aufträgen verwendet wird, wenn die Geldverwaltung aktiviert ist.
10
UseMoneyManagement
Ermöglicht eine risikobasierte Positionsgrößenbestimmung.
falsch
TenkanPeriod
Tenkan-sen-Periode des Ichimoku-Indikators.
9
KijunPeriod
Kijun-Sen-Periode des Ichimoku-Indikators.
26
SenkouBPeriod
Senkou Span B-Periode des Ichimoku-Indikators.
52
CandleType
Zeitrahmen für alle Berechnungen (standardmäßig stündliche Kerzen).
1 Stunde
Notizen
Es werden nur abgeschlossene Kerzen verarbeitet, wodurch garantiert wird, dass die Ichimoku-Werte endgültig sind.
Die Strategie verfolgt die zuletzt ausgeführte Richtung (_lastSignal), um die Wiederholung identischer Befehle bei aufeinanderfolgenden Signalen zu vermeiden, was dem Expertenverhalten von MetaTrader entspricht.
Wenn das Instrument PriceStep nicht veröffentlicht, werden die Stop-Loss- und Take-Profit-Abstände als absolute Preiswerte behandelt.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class Ichimoku2005Strategy : Strategy
{
private readonly StrategyParam<int> _channelPeriod;
private readonly StrategyParam<int> _cooldownCandles;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevClose;
private decimal _prevMid;
private bool _hasPrev;
private int _cooldownRemaining;
public int ChannelPeriod { get => _channelPeriod.Value; set => _channelPeriod.Value = value; }
public int CooldownCandles { get => _cooldownCandles.Value; set => _cooldownCandles.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public Ichimoku2005Strategy()
{
_channelPeriod = Param(nameof(ChannelPeriod), 52).SetDisplay("Channel Period", "Channel lookback", "Indicators");
_cooldownCandles = Param(nameof(CooldownCandles), 150).SetDisplay("Cooldown", "Candles between signals", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = default;
_prevMid = default;
_hasPrev = default;
_cooldownRemaining = default;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = 0;
_prevMid = 0;
_hasPrev = false;
_cooldownRemaining = 0;
var highest = new Highest { Length = ChannelPeriod };
var lowest = new Lowest { Length = ChannelPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(highest, lowest, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal highest, decimal lowest)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
var mid = (highest + lowest) / 2;
if (!_hasPrev) { _prevClose = close; _prevMid = mid; _hasPrev = true; return; }
if (_cooldownRemaining > 0)
{
_cooldownRemaining--;
_prevClose = close;
_prevMid = mid;
return;
}
if (_prevClose <= _prevMid && close > mid && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
_cooldownRemaining = CooldownCandles;
}
else if (_prevClose >= _prevMid && close < mid && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
_cooldownRemaining = CooldownCandles;
}
_prevClose = close;
_prevMid = mid;
}
}
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 Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class ichimoku_2005_strategy(Strategy):
def __init__(self):
super(ichimoku_2005_strategy, self).__init__()
self._channel_period = self.Param("ChannelPeriod", 52) \
.SetDisplay("Channel Period", "Channel lookback", "Indicators")
self._cooldown_candles = self.Param("CooldownCandles", 150) \
.SetDisplay("Cooldown", "Candles between signals", "General")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_close = 0.0
self._prev_mid = 0.0
self._has_prev = False
self._cooldown_remaining = 0
@property
def channel_period(self):
return self._channel_period.Value
@property
def cooldown_candles(self):
return self._cooldown_candles.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(ichimoku_2005_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_mid = 0.0
self._has_prev = False
self._cooldown_remaining = 0
def OnStarted2(self, time):
super(ichimoku_2005_strategy, self).OnStarted2(time)
self._prev_close = 0.0
self._prev_mid = 0.0
self._has_prev = False
self._cooldown_remaining = 0
highest = Highest()
highest.Length = self.channel_period
lowest = Lowest()
lowest.Length = self.channel_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(highest, lowest, self.process_candle).Start()
def process_candle(self, candle, highest, lowest):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
mid = (float(highest) + float(lowest)) / 2.0
if not self._has_prev:
self._prev_close = close
self._prev_mid = mid
self._has_prev = True
return
if self._cooldown_remaining > 0:
self._cooldown_remaining -= 1
self._prev_close = close
self._prev_mid = mid
return
if self._prev_close <= self._prev_mid and close > mid and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
self._cooldown_remaining = self.cooldown_candles
elif self._prev_close >= self._prev_mid and close < mid and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._cooldown_remaining = self.cooldown_candles
self._prev_close = close
self._prev_mid = mid
def CreateClone(self):
return ichimoku_2005_strategy()