Ichimoku 転換線/基準線クロスストラテジー
Ichimokuインジケーターは完全なトレンドフォローシステムを提供します。このアプローチは、価格が雲(Kumo)に対してどこで取引されているかを見ながら、転換線(Tenkan-sen)が基準線(Kijun-sen)を交差する点に焦点を当てます。雲の上でのブルッシュなクロスはトレンド継続の上昇を示し、雲の下でのベアリッシュなクロスは弱さを示唆します。
テストでは年平均リターン約142%を示しています。株式市場で最も優れたパフォーマンスを発揮します。
稼働中、戦略は各バーでIchimokuのコンポーネントを計算します。転換線が基準線を上抜け、価格が雲の上にある場合、基準線近くにストップを置いたロングトレードが開始されます。雲の下での逆方向のクロスが同様のストップ配置でショートを引き起こします。
システムはストップが当たるかクロスが反転するまでトレードを保持し、雲の方向に沿った持続的な動きを捉えることを目指します。
詳細
- エントリー条件: 雲(Kumo)に対する価格の位置を伴う転換線/基準線クロス。
- ロング/ショート: 両方。
- エグジット条件: ストップロスまたは逆方向のクロス。
- ストップ: はい、基準線レベル。
- デフォルト値:
TenkanPeriod= 9KijunPeriod= 26SenkouSpanBPeriod= 52CandleType= 30 minute
- フィルター:
- カテゴリ: トレンドフォロー
- 方向: 両方
- インジケーター: Ichimoku
- ストップ: はい
- 複雑さ: 中級
- 時間軸: スイング
- 季節性: いいえ
- ニューラルネットワーク: いいえ
- ダイバージェンス: いいえ
- リスクレベル: 中
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>
/// Ichimoku Tenkan/Kijun Cross strategy.
/// Tenkan-sen crossing above Kijun-sen while the close is above the cloud opens a long position, the opposite cross below the
/// cloud a short one. The stop is the Kijun-sen at entry; an opposite cross closes the position, reversing it when the close
/// is on the other side of the cloud.
/// </summary>
public class IchimokuTenkanKijunStrategy : Strategy
{
private readonly StrategyParam<int> _tenkanPeriod;
private readonly StrategyParam<int> _kijunPeriod;
private readonly StrategyParam<int> _senkouSpanBPeriod;
private readonly StrategyParam<DataType> _candleType;
private bool? _prevTenkanAbove;
private decimal _stopPrice;
/// <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 B period.
/// </summary>
public int SenkouSpanBPeriod
{
get => _senkouSpanBPeriod.Value;
set => _senkouSpanBPeriod.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public IchimokuTenkanKijunStrategy()
{
_tenkanPeriod = Param(nameof(TenkanPeriod), 9)
.SetGreaterThanZero()
.SetDisplay("Tenkan Period", "Period for Tenkan-sen", "Ichimoku");
_kijunPeriod = Param(nameof(KijunPeriod), 26)
.SetGreaterThanZero()
.SetDisplay("Kijun Period", "Period for Kijun-sen", "Ichimoku");
_senkouSpanBPeriod = Param(nameof(SenkouSpanBPeriod), 52)
.SetGreaterThanZero()
.SetDisplay("Senkou Span B Period", "Period for Senkou Span B", "Ichimoku");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).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 OnReseted()
{
base.OnReseted();
_prevTenkanAbove = null;
_stopPrice = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevTenkanAbove = null;
_stopPrice = default;
var ichimoku = new Ichimoku
{
Tenkan = { Length = TenkanPeriod },
Kijun = { Length = KijunPeriod },
SenkouB = { Length = SenkouSpanBPeriod }
};
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(ichimoku, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ichimoku);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue ichimokuIv)
{
if (candle.State != CandleStates.Finished)
return;
if (ichimokuIv is not IIchimokuValue { Tenkan: decimal tenkan, Kijun: decimal kijun, SenkouA: decimal senkouA, SenkouB: decimal senkouB })
return;
// Equal lines are no cross; the previous side holds.
var wasAbove = _prevTenkanAbove;
if (tenkan != kijun)
_prevTenkanAbove = tenkan > kijun;
if (wasAbove is not bool previous || !IsFormedAndOnlineAndAllowTrading())
return;
var bullishCross = !previous && tenkan > kijun;
var bearishCross = previous && tenkan < kijun;
var close = candle.ClosePrice;
var upperKumo = Math.Max(senkouA, senkouB);
var lowerKumo = Math.Min(senkouA, senkouB);
if (Position > 0)
{
if (bearishCross && close < lowerKumo)
{
SellMarket(Volume + Position);
_stopPrice = kijun;
}
else if (bearishCross || close <= _stopPrice)
{
SellMarket(Position);
}
}
else if (Position < 0)
{
if (bullishCross && close > upperKumo)
{
BuyMarket(Volume - Position);
_stopPrice = kijun;
}
else if (bullishCross || close >= _stopPrice)
{
BuyMarket(-Position);
}
}
else if (bullishCross && close > upperKumo)
{
BuyMarket(Volume);
_stopPrice = kijun;
}
else if (bearishCross && close < lowerKumo)
{
SellMarket(Volume);
_stopPrice = kijun;
}
}
}
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, Decimal
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import Ichimoku
from StockSharp.Algo.Strategies import Strategy
class ichimoku_tenkan_kijun_strategy(Strategy):
"""
Ichimoku Tenkan/Kijun Cross strategy.
Tenkan-sen crossing above Kijun-sen while the close is above the cloud opens a long position, the opposite cross below the
cloud a short one. The stop is the Kijun-sen at entry; an opposite cross closes the position, reversing it when the close
is on the other side of the cloud.
"""
def __init__(self):
super(ichimoku_tenkan_kijun_strategy, self).__init__()
self._tenkan_period = self.Param("TenkanPeriod", 9).SetGreaterThanZero().SetDisplay("Tenkan Period", "Period for Tenkan-sen", "Ichimoku")
self._kijun_period = self.Param("KijunPeriod", 26).SetGreaterThanZero().SetDisplay("Kijun Period", "Period for Kijun-sen", "Ichimoku")
self._senkou_span_b_period = self.Param("SenkouSpanBPeriod", 52).SetGreaterThanZero().SetDisplay("Senkou Span B Period", "Period for Senkou Span B", "Ichimoku")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._prev_tenkan_above = None
self._stop_price = Decimal(0)
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(ichimoku_tenkan_kijun_strategy, self).OnReseted()
self._prev_tenkan_above = None
self._stop_price = Decimal(0)
def OnStarted2(self, time):
super(ichimoku_tenkan_kijun_strategy, self).OnStarted2(time)
self._prev_tenkan_above = None
self._stop_price = Decimal(0)
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
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(ichimoku, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, ichimoku)
self.DrawOwnTrades(area)
def _process_candle(self, candle, ichimoku_iv):
if candle.State != CandleStates.Finished:
return
tenkan = ichimoku_iv.Tenkan
kijun = ichimoku_iv.Kijun
senkou_a = ichimoku_iv.SenkouA
senkou_b = ichimoku_iv.SenkouB
if tenkan is None or kijun is None or senkou_a is None or senkou_b is None:
return
# Equal lines are no cross; the previous side holds.
was_above = self._prev_tenkan_above
if tenkan != kijun:
self._prev_tenkan_above = tenkan > kijun
if was_above is None or not self.IsFormedAndOnlineAndAllowTrading():
return
bullish_cross = not was_above and tenkan > kijun
bearish_cross = was_above and tenkan < kijun
close = candle.ClosePrice
upper_kumo = Math.Max(senkou_a, senkou_b)
lower_kumo = Math.Min(senkou_a, senkou_b)
if self.Position > 0:
if bearish_cross and close < lower_kumo:
self.SellMarket(self.Volume + self.Position)
self._stop_price = kijun
elif bearish_cross or close <= self._stop_price:
self.SellMarket(self.Position)
elif self.Position < 0:
if bullish_cross and close > upper_kumo:
self.BuyMarket(self.Volume - self.Position)
self._stop_price = kijun
elif bullish_cross or close >= self._stop_price:
self.BuyMarket(-self.Position)
elif bullish_cross and close > upper_kumo:
self.BuyMarket(self.Volume)
self._stop_price = kijun
elif bearish_cross and close < lower_kumo:
self.SellMarket(self.Volume)
self._stop_price = kijun
def CreateClone(self):
return ichimoku_tenkan_kijun_strategy()