Ichimoku RSI Strategie
Ichimoku RSI verwendet Ichimoku-Cloud-Niveaus zur Definition der Trendrichtung, während der RSI kurzfristige Rücksetzer identifiziert. Trades werden mit der Cloud ausgerichtet, mit Einstieg wenn der RSI in einem Aufwärtstrend aus der überverkauften Zone zurückkehrt oder in einem Abwärtstrend aus der überkauften Zone fällt.
Tests zeigen eine durchschnittliche jährliche Rendite von etwa 142%. Die Strategie funktioniert am besten auf dem Aktienmarkt.
Durch die Kombination eines breiten Trendfilters mit einem Momentum-Oszillator zielt die Strategie darauf ab, nach kurzen Pausen in starke Bewegungen einzusteigen.
Stops werden jenseits der Cloud-Grenze gesetzt, um gegen tiefere Korrekturen zu schützen.
Details
- Einstiegskriterien: Indikatorsignal
- Long/Short: Beide
- Ausstiegskriterien: Stop-Loss oder entgegengesetztes Signal
- Stops: Ja, prozentbasiert
- Standardwerte:
CandleType= 15 minuteStopLoss= 2%
- Filter:
- Kategorie: Trendfolge
- Richtung: Beide
- Indikatoren: Ichimoku, RSI
- Stops: Ja
- Komplexität: Mittel
- Zeitrahmen: Intraday
- Saisonalität: Nein
- Neuronale Netze: Nein
- Divergenz: Nein
- Risikolevel: Mittel
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>
/// Strategy combining Ichimoku Tenkan/Kijun crossover and RSI indicators.
/// Enters on Tenkan/Kijun crossover with RSI confirmation.
/// Uses manual Tenkan(9)/Kijun(26) calculation to avoid Ichimoku composite indicator issues.
/// </summary>
public class IchimokuRsiStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _rsiOversold;
private readonly StrategyParam<decimal> _rsiOverbought;
private readonly StrategyParam<int> _cooldownBars;
private decimal _rsiValue;
private int _cooldown;
private readonly List<decimal> _highs = new();
private readonly List<decimal> _lows = new();
private const int TenkanPeriod = 9;
private const int KijunPeriod = 26;
/// <summary>
/// Data type for candles.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Period for RSI calculation.
/// </summary>
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
/// <summary>
/// RSI oversold level.
/// </summary>
public decimal RsiOversold
{
get => _rsiOversold.Value;
set => _rsiOversold.Value = value;
}
/// <summary>
/// RSI overbought level.
/// </summary>
public decimal RsiOverbought
{
get => _rsiOverbought.Value;
set => _rsiOverbought.Value = value;
}
/// <summary>
/// Cooldown bars between trades.
/// </summary>
public int CooldownBars
{
get => _cooldownBars.Value;
set => _cooldownBars.Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="IchimokuRsiStrategy"/>.
/// </summary>
public IchimokuRsiStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetRange(5, 30)
.SetDisplay("RSI Period", "Period for RSI calculation", "RSI Settings");
_rsiOversold = Param(nameof(RsiOversold), 30m)
.SetDisplay("RSI Oversold", "RSI oversold level", "RSI Settings");
_rsiOverbought = Param(nameof(RsiOverbought), 70m)
.SetDisplay("RSI Overbought", "RSI overbought level", "RSI Settings");
_cooldownBars = Param(nameof(CooldownBars), 100)
.SetDisplay("Cooldown Bars", "Bars between trades", "General")
.SetRange(5, 500);
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_rsiValue = 50;
_cooldown = 0;
_highs.Clear();
_lows.Clear();
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(rsi, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
var rsiArea = CreateChartArea();
if (rsiArea != null)
DrawIndicator(rsiArea, rsi);
}
}
private static decimal GetHighest(List<decimal> values, int period)
{
var start = Math.Max(0, values.Count - period);
var max = decimal.MinValue;
for (var i = start; i < values.Count; i++)
if (values[i] > max) max = values[i];
return max;
}
private static decimal GetLowest(List<decimal> values, int period)
{
var start = Math.Max(0, values.Count - period);
var min = decimal.MaxValue;
for (var i = start; i < values.Count; i++)
if (values[i] < min) min = values[i];
return min;
}
private void ProcessCandle(ICandleMessage candle, decimal rsiVal)
{
_rsiValue = rsiVal;
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
// Track highs and lows
_highs.Add(candle.HighPrice);
_lows.Add(candle.LowPrice);
// Keep buffer manageable
if (_highs.Count > KijunPeriod * 2)
{
_highs.RemoveRange(0, _highs.Count - KijunPeriod * 2);
_lows.RemoveRange(0, _lows.Count - KijunPeriod * 2);
}
// Need at least KijunPeriod bars for full calculation
if (_highs.Count < KijunPeriod)
return;
// Tenkan-sen = (highest high over 9 periods + lowest low over 9 periods) / 2
var tenkan = (GetHighest(_highs, TenkanPeriod) + GetLowest(_lows, TenkanPeriod)) / 2;
// Kijun-sen = (highest high over 26 periods + lowest low over 26 periods) / 2
var kijun = (GetHighest(_highs, KijunPeriod) + GetLowest(_lows, KijunPeriod)) / 2;
if (_cooldown > 0)
{
_cooldown--;
return;
}
// Buy: tenkan > kijun (bullish) + RSI not overbought
if (tenkan > kijun && _rsiValue < RsiOverbought && Position == 0)
{
BuyMarket();
_cooldown = CooldownBars;
}
// Sell: tenkan < kijun (bearish) + RSI not oversold
else if (tenkan < kijun && _rsiValue > RsiOversold && Position == 0)
{
SellMarket();
_cooldown = CooldownBars;
}
// Exit long if tenkan crosses below kijun
if (Position > 0 && tenkan < kijun)
{
SellMarket();
_cooldown = CooldownBars;
}
// Exit short if tenkan crosses above kijun
else if (Position < 0 && tenkan > kijun)
{
BuyMarket();
_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
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class ichimoku_rsi_strategy(Strategy):
"""
Ichimoku RSI strategy.
Combines manual Tenkan/Kijun calculation with RSI confirmation.
Enters on Tenkan/Kijun crossover with RSI filter.
"""
TENKAN_PERIOD = 9
KIJUN_PERIOD = 26
def __init__(self):
super(ichimoku_rsi_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._rsi_period = self.Param("RsiPeriod", 14).SetDisplay("RSI Period", "Period for RSI calculation", "RSI Settings")
self._rsi_oversold = self.Param("RsiOversold", 30.0).SetDisplay("RSI Oversold", "RSI oversold level", "RSI Settings")
self._rsi_overbought = self.Param("RsiOverbought", 70.0).SetDisplay("RSI Overbought", "RSI overbought level", "RSI Settings")
self._cooldown_bars = self.Param("CooldownBars", 100).SetDisplay("Cooldown Bars", "Bars between trades", "General")
self._rsi_value = 50.0
self._cooldown = 0
self._highs = []
self._lows = []
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(ichimoku_rsi_strategy, self).OnReseted()
self._rsi_value = 50.0
self._cooldown = 0
self._highs = []
self._lows = []
def OnStarted2(self, time):
super(ichimoku_rsi_strategy, self).OnStarted2(time)
self._rsi_value = 50.0
self._cooldown = 0
self._highs = []
self._lows = []
rsi = RelativeStrengthIndex()
rsi.Length = self._rsi_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(rsi, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
rsi_area = self.CreateChartArea()
if rsi_area is not None:
self.DrawIndicator(rsi_area, rsi)
@staticmethod
def _get_highest(values, period):
start = max(0, len(values) - period)
return max(values[start:])
@staticmethod
def _get_lowest(values, period):
start = max(0, len(values) - period)
return min(values[start:])
def _process_candle(self, candle, rsi_val):
self._rsi_value = float(rsi_val)
if candle.State != CandleStates.Finished:
return
# Track highs and lows
self._highs.append(float(candle.HighPrice))
self._lows.append(float(candle.LowPrice))
# Keep buffer manageable
max_len = self.KIJUN_PERIOD * 2
if len(self._highs) > max_len:
self._highs = self._highs[-max_len:]
self._lows = self._lows[-max_len:]
# Need at least KijunPeriod bars
if len(self._highs) < self.KIJUN_PERIOD:
return
# Tenkan-sen = (highest high over 9 + lowest low over 9) / 2
tenkan = (self._get_highest(self._highs, self.TENKAN_PERIOD) + self._get_lowest(self._lows, self.TENKAN_PERIOD)) / 2.0
# Kijun-sen = (highest high over 26 + lowest low over 26) / 2
kijun = (self._get_highest(self._highs, self.KIJUN_PERIOD) + self._get_lowest(self._lows, self.KIJUN_PERIOD)) / 2.0
cd = self._cooldown_bars.Value
overbought = float(self._rsi_overbought.Value)
oversold = float(self._rsi_oversold.Value)
if self._cooldown > 0:
self._cooldown -= 1
return
# Buy: tenkan > kijun (bullish) + RSI not overbought
if tenkan > kijun and self._rsi_value < overbought and self.Position == 0:
self.BuyMarket()
self._cooldown = cd
# Sell: tenkan < kijun (bearish) + RSI not oversold
elif tenkan < kijun and self._rsi_value > oversold and self.Position == 0:
self.SellMarket()
self._cooldown = cd
# Exit long if tenkan crosses below kijun
if self.Position > 0 and tenkan < kijun:
self.SellMarket()
self._cooldown = cd
# Exit short if tenkan crosses above kijun
elif self.Position < 0 and tenkan > kijun:
self.BuyMarket()
self._cooldown = cd
def CreateClone(self):
return ichimoku_rsi_strategy()