Los indicadores Ichimoku proporcionan un sistema completo de seguimiento de tendencia. Este enfoque se centra en el cruce de la Tenkan-sen sobre la Kijun-sen mientras el precio opera en relación con la nube Kumo. Un cruce alcista por encima de la nube señala la continuación alcista de la tendencia, mientras que un cruce bajista por debajo de la nube sugiere debilidad.
Las pruebas indican una rentabilidad anual media de aproximadamente el 142%. Funciona mejor en el mercado de acciones.
Durante la operación, la estrategia calcula los componentes Ichimoku en cada barra. Cuando la Tenkan sube por encima de la Kijun y el precio está por encima de la nube, se inicia una operación larga con un stop cerca de la Kijun. Un cruce en la dirección opuesta por debajo de la nube activa una operación corta con una colocación similar del stop.
El sistema permanece en la operación hasta que se alcanza el stop o el cruce se revierte, con el objetivo de capturar movimientos sostenidos que siguen la dirección de la nube.
Detalles
Criterios de entrada: Cruce Tenkan/Kijun con precio relativo a la nube Kumo.
Largo/Corto: Ambos.
Criterios de salida: Stop-loss o cruce opuesto.
Stops: Sí, al nivel de Kijun.
Valores predeterminados:
TenkanPeriod = 9
KijunPeriod = 26
SenkouSpanBPeriod = 52
CandleType = 30 minute
Filtros:
Categoría: Seguimiento de tendencia
Dirección: Ambos
Indicadores: Ichimoku
Stops: Sí
Complejidad: Intermedio
Marco temporal: Swing
Estacionalidad: No
Redes neuronales: No
Divergencia: No
Nivel de riesgo: Medio
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()