Strategie Williams R Ichimoku
Dieses Setup kombiniert die Momentum-Extreme von Williams %R mit der Trendstruktur, die durch die Ichimoku Cloud definiert wird. Die Idee ist, starken Bewegungen nur dann beizutreten, wenn der Preis auf der günstigen Seite der Cloud liegt und die kurzfristigen Linien die Richtung bestätigen.
Tests zeigen eine durchschnittliche Jahresrendite von etwa 73%. Sie funktioniert am besten auf dem Kryptomarkt.
Eine Long-Gelegenheit entsteht, wenn der Oszillator unter WilliamsROversold fällt, während der Preis über der Cloud liegt und Tenkan-sen über Kijun-sen liegt. Ein Short-Signal entsteht, wenn %R über WilliamsROverbought steigt, der Preis unter der Cloud liegt und Tenkan-sen unter Kijun-sen. Die Position bleibt offen, bis der Preis die entgegengesetzte Seite der Cloud überkreuzt.
Da die Methode auf mehrere Bestätigungen wartet, eignet sie sich für Trader, die klare Trendfilter gegenüber schnellen Umkehrungen bevorzugen. Die gegenüberliegende Seite der Cloud dient als dynamischer Stop, sodass sich das Risiko mit dem zugrunde liegenden Trend anpasst.
Details
- Einstiegskriterien:
- Long: %R < WilliamsROversold && price above Ichimoku cloud and Tenkan-sen > Kijun-sen
- Short: %R > WilliamsROverbought && price below Ichimoku cloud and Tenkan-sen < Kijun-sen
- Long/Short: Beide Seiten.
- Ausstiegskriterien:
- Long: Ausstieg, wenn der Preis unter die Cloud fällt
- Short: Ausstieg, wenn der Preis über die Cloud steigt
- Stops: Ja.
- Standardwerte:
WilliamsRPeriod = 14
WilliamsROversold = -80
WilliamsROverbought = -20
TenkanPeriod = 9
KijunPeriod = 26
SenkouSpanBPeriod = 52
CandleType = TimeSpan.FromMinutes(15)
-80 und -20 sind die Standardwerte der Williams-%R-Schwellen, die die Regeln nennen. Ein Long schließt, wenn der Kurs unter der Wolke schließt, ein Short, wenn er darüber schließt. Ein Einstiegssignal gegen eine offene Position dreht sie.
- Filter:
- Kategorie: Gemischt
- Richtung: Beide
- Indikatoren: Williams R Ichimoku
- 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>
/// Williams R Ichimoku strategy.
/// Williams %R below WilliamsROversold with a close above the cloud and Tenkan-sen above Kijun-sen goes long, %R above WilliamsROverbought
/// with a close below the cloud and Tenkan-sen below Kijun-sen goes short, reversing an opposite position. The cloud is the trailing stop: a long closes
/// when price closes below the cloud and a short when it closes above it.
/// </summary>
public class WilliamsIchimokuStrategy : Strategy
{
private readonly StrategyParam<int> _tenkanPeriod;
private readonly StrategyParam<int> _kijunPeriod;
private readonly StrategyParam<int> _senkouSpanBPeriod;
private readonly StrategyParam<int> _williamsRPeriod;
private readonly StrategyParam<decimal> _williamsROversold;
private readonly StrategyParam<decimal> _williamsROverbought;
private readonly StrategyParam<DataType> _candleType;
/// <summary>
/// Period of Tenkan-sen.
/// </summary>
public int TenkanPeriod
{
get => _tenkanPeriod.Value;
set => _tenkanPeriod.Value = value;
}
/// <summary>
/// Period of Kijun-sen.
/// </summary>
public int KijunPeriod
{
get => _kijunPeriod.Value;
set => _kijunPeriod.Value = value;
}
/// <summary>
/// Period of Senkou Span B.
/// </summary>
public int SenkouSpanBPeriod
{
get => _senkouSpanBPeriod.Value;
set => _senkouSpanBPeriod.Value = value;
}
/// <summary>
/// Period of Williams %R.
/// </summary>
public int WilliamsRPeriod
{
get => _williamsRPeriod.Value;
set => _williamsRPeriod.Value = value;
}
/// <summary>
/// Williams %R level for longs.
/// </summary>
public decimal WilliamsROversold
{
get => _williamsROversold.Value;
set => _williamsROversold.Value = value;
}
/// <summary>
/// Williams %R level for shorts.
/// </summary>
public decimal WilliamsROverbought
{
get => _williamsROverbought.Value;
set => _williamsROverbought.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public WilliamsIchimokuStrategy()
{
_tenkanPeriod = Param(nameof(TenkanPeriod), 9)
.SetGreaterThanZero()
.SetDisplay("Tenkan Period", "Period of Tenkan-sen", "Ichimoku");
_kijunPeriod = Param(nameof(KijunPeriod), 26)
.SetGreaterThanZero()
.SetDisplay("Kijun Period", "Period of Kijun-sen", "Ichimoku");
_senkouSpanBPeriod = Param(nameof(SenkouSpanBPeriod), 52)
.SetGreaterThanZero()
.SetDisplay("Senkou Span B Period", "Period of Senkou Span B", "Ichimoku");
_williamsRPeriod = Param(nameof(WilliamsRPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("Williams %R Period", "Period of Williams %R", "Williams %R");
_williamsROversold = Param(nameof(WilliamsROversold), -80m)
.SetDisplay("Williams %R Oversold", "Williams %R level for longs", "Williams %R");
_williamsROverbought = Param(nameof(WilliamsROverbought), -20m)
.SetDisplay("Williams %R Overbought", "Williams %R level for shorts", "Williams %R");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(15).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var ichimoku = new Ichimoku
{
Tenkan = { Length = TenkanPeriod },
Kijun = { Length = KijunPeriod },
SenkouB = { Length = SenkouSpanBPeriod }
};
var williams = new WilliamsR { Length = WilliamsRPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(williams, ichimoku, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ichimoku);
DrawOwnTrades(area);
var oscillators = CreateChartArea();
if (oscillators != null)
{
DrawIndicator(oscillators, williams);
}
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue williamsValue, IIndicatorValue ichimokuValue)
{
if (candle.State != CandleStates.Finished)
return;
if (ichimokuValue is not IIchimokuValue { Tenkan: decimal tenkan, Kijun: decimal kijun, SenkouA: decimal senkouA, SenkouB: decimal senkouB })
return;
if (!williamsValue.IsFormed)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var close = candle.ClosePrice;
var cloudTop = Math.Max(senkouA, senkouB);
var cloudBottom = Math.Min(senkouA, senkouB);
var williams = williamsValue.GetValue<decimal>();
if (williams < WilliamsROversold && close > cloudTop && tenkan > kijun && Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
else if (williams > WilliamsROverbought && close < cloudBottom && tenkan < kijun && Position >= 0)
SellMarket(Volume + Math.Abs(Position));
else if (Position > 0 && close < cloudBottom)
SellMarket(Position);
else if (Position < 0 && close > cloudTop)
BuyMarket(-Position);
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import WilliamsR, Ichimoku
from StockSharp.Algo.Strategies import Strategy
class williams_ichimoku_strategy(Strategy):
"""
Williams R Ichimoku strategy.
Williams %R below WilliamsROversold with a close above the cloud and Tenkan-sen above Kijun-sen goes long, %R above WilliamsROverbought
with a close below the cloud and Tenkan-sen below Kijun-sen goes short, reversing an opposite position. The cloud is the trailing stop: a long closes
when price closes below the cloud and a short when it closes above it.
"""
def __init__(self):
super(williams_ichimoku_strategy, self).__init__()
self._tenkan_period = self.Param("TenkanPeriod", 9).SetGreaterThanZero().SetDisplay("Tenkan Period", "Period of Tenkan-sen", "Ichimoku")
self._kijun_period = self.Param("KijunPeriod", 26).SetGreaterThanZero().SetDisplay("Kijun Period", "Period of Kijun-sen", "Ichimoku")
self._senkou_span_b_period = self.Param("SenkouSpanBPeriod", 52).SetGreaterThanZero().SetDisplay("Senkou Span B Period", "Period of Senkou Span B", "Ichimoku")
self._williams_r_period = self.Param("WilliamsRPeriod", 14).SetGreaterThanZero().SetDisplay("Williams %R Period", "Period of Williams %R", "Williams %R")
self._williams_r_oversold = self.Param("WilliamsROversold", -80.0).SetDisplay("Williams %R Oversold", "Williams %R level for longs", "Williams %R")
self._williams_r_overbought = self.Param("WilliamsROverbought", -20.0).SetDisplay("Williams %R Overbought", "Williams %R level for shorts", "Williams %R")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(15))).SetDisplay("Candle Type", "Type of candles to use", "General")
@property
def candle_type(self):
return self._candle_type.Value
def OnStarted2(self, time):
super(williams_ichimoku_strategy, self).OnStarted2(time)
ichimoku = Ichimoku()
ichimoku.Tenkan.Length = self._tenkan_period.Value
ichimoku.Kijun.Length = self._kijun_period.Value
ichimoku.SenkouB.Length = self._senkou_span_b_period.Value
williams = WilliamsR()
williams.Length = self._williams_r_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(williams, ichimoku, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ichimoku)
self.DrawOwnTrades(area)
oscillators = self.CreateChartArea()
if oscillators is not None:
self.DrawIndicator(oscillators, williams)
def _process_candle(self, candle, williams_value, ichimoku_value):
if candle.State != CandleStates.Finished:
return
tenkan = ichimoku_value.Tenkan
kijun = ichimoku_value.Kijun
senkou_a = ichimoku_value.SenkouA
senkou_b = ichimoku_value.SenkouB
if tenkan is None or kijun is None or senkou_a is None or senkou_b is None:
return
if not williams_value.IsFormed:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
close = candle.ClosePrice
cloud_top = senkou_a if senkou_a > senkou_b else senkou_b
cloud_bottom = senkou_b if senkou_a > senkou_b else senkou_a
williams = williams_value.GetValue[Decimal](None)
if williams < Decimal(self._williams_r_oversold.Value) and close > cloud_top and tenkan > kijun and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
elif williams > Decimal(self._williams_r_overbought.Value) and close < cloud_bottom and tenkan < kijun and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
elif self.Position > 0 and close < cloud_bottom:
self.SellMarket(self.Position)
elif self.Position < 0 and close > cloud_top:
self.BuyMarket(-self.Position)
def CreateClone(self):
return williams_ichimoku_strategy()