Ichimoku Stochastic Strategy
Strategie basierend auf den Indikatoren Ichimoku Cloud und Stochastic Oscillator. Geht long, wenn der Preis über Kumo (Wolke) liegt, Tenkan > Kijun, und der Stochastic überverkauft ist (< 20). Geht short, wenn der Preis unter Kumo liegt, Tenkan < Kijun, und der Stochastic überkauft ist (> 80).
Tests zeigen eine durchschnittliche jährliche Rendite von etwa 118%. Sie funktioniert am besten auf dem Aktienmarkt.
Ichimoku skizziert den Trend und die Unterstützungsniveaus, während Stochastic den Einstieg bei Rücksetzern timed. Trades öffnen sich, wenn der Oszillator in der vorherrschenden Wolkenrichtung zurücksetzt.
Trader, die strukturierte Indikatoren bevorzugen, finden es praktisch. ATR-Stops decken abrupte Umkehrungen ab.
Details
- Einstiegskriterien:
- Long:
Price > Cloud && StochK < 20 - Short:
Price < Cloud && StochK > 80
- Long:
- Long/Short: Beide
- Ausstiegskriterien:
- Cloud-Ausbruch in entgegengesetzter Richtung
- Stops: Verwendet Ichimoku Cloud-Grenzen
- Standardwerte:
TenkanPeriod= 9KijunPeriod= 26SenkouPeriod= 52StochPeriod= 14StochK= 3StochD= 3CandleType= TimeSpan.FromMinutes(30).TimeFrame()
- Filter:
- Kategorie: Mean Reversion
- Richtung: Beide
- Indikatoren: Ichimoku Cloud, Stochastic Oscillator
- Stops: Ja
- Komplexität: Mittel
- Zeitrahmen: Mittelfristig
- Saisonalität: Nein
- Neuronale Netze: Nein
- Divergenz: Nein
- Risikolevel: Mittel
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;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy based on Ichimoku Cloud and Stochastic Oscillator indicators.
/// Enters long when price is above Kumo (cloud), Tenkan > Kijun, and Stochastic is oversold (< 20)
/// Enters short when price is below Kumo, Tenkan < Kijun, and Stochastic is overbought (> 80)
/// </summary>
public class IchimokuStochasticStrategy : Strategy
{
private readonly StrategyParam<int> _tenkanPeriod;
private readonly StrategyParam<int> _kijunPeriod;
private readonly StrategyParam<int> _senkouPeriod;
private readonly StrategyParam<int> _stochPeriod;
private readonly StrategyParam<int> _stochK;
private readonly StrategyParam<int> _stochD;
private readonly StrategyParam<int> _cooldownBars;
private readonly StrategyParam<DataType> _candleType;
private int _cooldown;
/// <summary>
/// Tenkan-sen period
/// </summary>
public int TenkanPeriod
{
get => _tenkanPeriod.Value;
set => _tenkanPeriod.Value = value;
}
/// <summary>
/// Kijun-sen period
/// </summary>
public int KijunPeriod
{
get => _kijunPeriod.Value;
set => _kijunPeriod.Value = value;
}
/// <summary>
/// Senkou Span period
/// </summary>
public int SenkouPeriod
{
get => _senkouPeriod.Value;
set => _senkouPeriod.Value = value;
}
/// <summary>
/// Stochastic %K period
/// </summary>
public int StochPeriod
{
get => _stochPeriod.Value;
set => _stochPeriod.Value = value;
}
/// <summary>
/// Stochastic %K smoothing period
/// </summary>
public int StochK
{
get => _stochK.Value;
set => _stochK.Value = value;
}
/// <summary>
/// Stochastic %D period
/// </summary>
public int StochD
{
get => _stochD.Value;
set => _stochD.Value = value;
}
/// <summary>
/// Bars to wait between trades.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Candle type for strategy calculation
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor
/// </summary>
public IchimokuStochasticStrategy()
{
_tenkanPeriod = Param(nameof(TenkanPeriod), 9)
.SetGreaterThanZero()
.SetDisplay("Tenkan-sen Period", "Period for Tenkan-sen line", "Ichimoku")
.SetOptimize(7, 12, 1);
_kijunPeriod = Param(nameof(KijunPeriod), 26)
.SetGreaterThanZero()
.SetDisplay("Kijun-sen Period", "Period for Kijun-sen line", "Ichimoku")
.SetOptimize(20, 30, 2);
_senkouPeriod = Param(nameof(SenkouPeriod), 52)
.SetGreaterThanZero()
.SetDisplay("Senkou Span Period", "Period for Senkou Span B line", "Ichimoku")
.SetOptimize(40, 60, 5);
_stochPeriod = Param(nameof(StochPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("Stochastic Period", "Period for Stochastic Oscillator", "Stochastic")
.SetOptimize(10, 20, 2);
_stochK = Param(nameof(StochK), 3)
.SetGreaterThanZero()
.SetDisplay("Stochastic %K", "Smoothing for Stochastic %K line", "Stochastic")
.SetOptimize(1, 5, 1);
_stochD = Param(nameof(StochD), 3)
.SetGreaterThanZero()
.SetDisplay("Stochastic %D", "Period for Stochastic %D line", "Stochastic")
.SetOptimize(1, 5, 1);
_cooldownBars = Param(nameof(CooldownBars), 4)
.SetRange(1, 20)
.SetDisplay("Cooldown Bars", "Bars between trades", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for strategy", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_cooldown = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
// Create indicators
var ichimoku = new Ichimoku
{
Tenkan = { Length = TenkanPeriod },
Kijun = { Length = KijunPeriod },
SenkouB = { Length = SenkouPeriod }
};
var stochastic = new StochasticOscillator
{
K = { Length = StochK },
D = { Length = StochD },
};
// Subscribe to candles and bind indicators
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(ichimoku, stochastic, ProcessCandle)
.Start();
// Setup chart visualization if available
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ichimoku);
// Create a separate area for Stochastic
var stochArea = CreateChartArea();
if (stochArea != null)
{
DrawIndicator(stochArea, stochastic);
}
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue ichimokuValue, IIndicatorValue stochValue)
{
// Skip unfinished candles
if (candle.State != CandleStates.Finished)
return;
// Check if strategy is ready to trade
if (!IsFormedAndOnlineAndAllowTrading())
return;
// Get additional values from Ichimoku
var ichimokuTyped = (IchimokuValue)ichimokuValue;
if (ichimokuTyped.Tenkan is not decimal tenkan)
return;
if (ichimokuTyped.Kijun is not decimal kijun)
return;
if (ichimokuTyped.SenkouA is not decimal senkouA)
return;
if (ichimokuTyped.SenkouB is not decimal senkouB)
return;
// Current price (close of the candle)
var price = candle.ClosePrice;
// Check if price is above/below Kumo cloud
var isAboveKumo = price > Math.Max(senkouA, senkouB);
var isBelowKumo = price < Math.Min(senkouA, senkouB);
// Check Tenkan/Kijun cross (trend direction)
var isBullishCross = tenkan > kijun;
var isBearishCross = tenkan < kijun;
var stochTyped = (StochasticOscillatorValue)stochValue;
// Get Stochastic %K value
if (stochTyped.K is not decimal stochasticK)
return;
if (_cooldown > 0)
{
_cooldown--;
return;
}
// Trading logic
if (isAboveKumo && isBullishCross && stochasticK < 15 && Position <= 0)
{
BuyMarket(Volume + Math.Abs(Position));
_cooldown = CooldownBars;
}
else if (isBelowKumo && isBearishCross && stochasticK > 85 && Position >= 0)
{
SellMarket(Volume + Math.Abs(Position));
_cooldown = CooldownBars;
}
else if (isBearishCross && Position > 0)
{
SellMarket(Position);
_cooldown = CooldownBars;
}
else if (isBullishCross && Position < 0)
{
BuyMarket(Math.Abs(Position));
_cooldown = CooldownBars;
}
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates, Sides
from StockSharp.Algo.Indicators import Ichimoku, StochasticOscillator
from StockSharp.Algo.Strategies import Strategy
from datatype_extensions import *
class ichimoku_stochastic_strategy(Strategy):
"""
Strategy based on Ichimoku Cloud and Stochastic Oscillator indicators.
"""
def __init__(self):
super(ichimoku_stochastic_strategy, self).__init__()
self._tenkan_period = self.Param("TenkanPeriod", 9) \
.SetDisplay("Tenkan-sen Period", "Period for Tenkan-sen line", "Ichimoku")
self._kijun_period = self.Param("KijunPeriod", 26) \
.SetDisplay("Kijun-sen Period", "Period for Kijun-sen line", "Ichimoku")
self._senkou_period = self.Param("SenkouPeriod", 52) \
.SetDisplay("Senkou Span Period", "Period for Senkou Span B line", "Ichimoku")
self._stoch_period = self.Param("StochPeriod", 14) \
.SetDisplay("Stochastic Period", "Period for Stochastic Oscillator", "Stochastic")
self._stoch_k = self.Param("StochK", 3) \
.SetDisplay("Stochastic %K", "Smoothing for Stochastic %K line", "Stochastic")
self._stoch_d = self.Param("StochD", 3) \
.SetDisplay("Stochastic %D", "Period for Stochastic %D line", "Stochastic")
self._cooldown_bars = self.Param("CooldownBars", 4) \
.SetRange(1, 20) \
.SetDisplay("Cooldown Bars", "Bars between trades", "General")
self._candle_type = self.Param("CandleType", tf(30)) \
.SetDisplay("Candle Type", "Timeframe for strategy", "General")
self._cooldown = 0
@property
def CandleType(self):
return self._candle_type.Value
def OnReseted(self):
super(ichimoku_stochastic_strategy, self).OnReseted()
self._cooldown = 0
def OnStarted2(self, time):
super(ichimoku_stochastic_strategy, self).OnStarted2(time)
self._cooldown = 0
ichimoku = Ichimoku()
ichimoku.Tenkan.Length = self._tenkan_period.Value
ichimoku.Kijun.Length = self._kijun_period.Value
ichimoku.SenkouB.Length = self._senkou_period.Value
stochastic = StochasticOscillator()
stochastic.K.Length = self._stoch_k.Value
stochastic.D.Length = self._stoch_d.Value
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(ichimoku, stochastic, self.ProcessCandle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ichimoku)
stoch_area = self.CreateChartArea()
if stoch_area is not None:
self.DrawIndicator(stoch_area, stochastic)
self.DrawOwnTrades(area)
def ProcessCandle(self, candle, ichimoku_value, stoch_value):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
if ichimoku_value.Tenkan is None:
return
tenkan = float(ichimoku_value.Tenkan)
if ichimoku_value.Kijun is None:
return
kijun = float(ichimoku_value.Kijun)
if ichimoku_value.SenkouA is None:
return
senkou_a = float(ichimoku_value.SenkouA)
if ichimoku_value.SenkouB is None:
return
senkou_b = float(ichimoku_value.SenkouB)
price = float(candle.ClosePrice)
is_above_kumo = price > max(senkou_a, senkou_b)
is_below_kumo = price < min(senkou_a, senkou_b)
is_bullish_cross = tenkan > kijun
is_bearish_cross = tenkan < kijun
if stoch_value.K is None:
return
stochastic_k = float(stoch_value.K)
if self._cooldown > 0:
self._cooldown -= 1
return
cooldown = int(self._cooldown_bars.Value)
if is_above_kumo and is_bullish_cross and stochastic_k < 15 and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
self._cooldown = cooldown
elif is_below_kumo and is_bearish_cross and stochastic_k > 85 and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
self._cooldown = cooldown
elif is_bearish_cross and self.Position > 0:
self.SellMarket(self.Position)
self._cooldown = cooldown
elif is_bullish_cross and self.Position < 0:
self.BuyMarket(abs(self.Position))
self._cooldown = cooldown
def CreateClone(self):
return ichimoku_stochastic_strategy()