Пробой облака Ichimoku
Стратегия основана на пробое облака Ichimoku (Kumo).
Тестирование показывает среднегодичную доходность около 70%. Стратегию лучше запускать на фондовом рынке.
Метод опирается на сигналы индикатора Ichimoku. Когда цена пробивает облако вверх и Tenkan-sen пересекает Kijun-sen, открывается длинная позиция. Пробой ниже облака запускает короткую позицию. Сделка удерживается, пока цена не вернётся обратно через облако.
Облако обозначает ключевые уровни поддержки и сопротивления, поэтому система ждёт уверенного закрытия свечи за его пределами. Комбинирование нескольких компонентов Ichimoku помогает избегать сделок с низкой вероятностью успеха во флэтовом рынке.
Подробности
- Критерии входа: сигналы на основе Ichimoku.
- Длинные/короткие: оба направления.
- Критерии выхода: противоположный сигнал.
- Стопы: нет.
- Параметры по умолчанию:
TenkanPeriod= 9KijunPeriod= 26SenkouSpanPeriod= 52CandleType= TimeSpan.FromMinutes(15)
- Фильтры:
- Категория: Пробой
- Направление: Оба
- Индикаторы: Ichimoku
- Стопы: Нет
- Сложность: Базовая
- Таймфрейм: Внутридневной (15м)
- Сезонность: Нет
- Нейронные сети: Нет
- Дивергенция: Нет
- Уровень риска: Средний
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 based on Ichimoku Kumo (cloud) breakout.
/// Trades on Tenkan/Kijun crosses with cloud confirmation.
/// </summary>
public class IchimokuKumoBreakoutStrategy : Strategy
{
private readonly StrategyParam<int> _tenkanPeriod;
private readonly StrategyParam<int> _kijunPeriod;
private readonly StrategyParam<int> _senkouSpanPeriod;
private readonly StrategyParam<DataType> _candleType;
private bool _prevTenkanAboveKijun;
private bool _hasPrevValues;
private int _candlesSinceLastTrade;
/// <summary>
/// Period for Tenkan-sen line.
/// </summary>
public int TenkanPeriod
{
get => _tenkanPeriod.Value;
set => _tenkanPeriod.Value = value;
}
/// <summary>
/// Period for Kijun-sen line.
/// </summary>
public int KijunPeriod
{
get => _kijunPeriod.Value;
set => _kijunPeriod.Value = value;
}
/// <summary>
/// Period for Senkou Span B.
/// </summary>
public int SenkouSpanPeriod
{
get => _senkouSpanPeriod.Value;
set => _senkouSpanPeriod.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Initialize the Ichimoku Kumo Breakout strategy.
/// </summary>
public IchimokuKumoBreakoutStrategy()
{
_tenkanPeriod = Param(nameof(TenkanPeriod), 9)
.SetDisplay("Tenkan-sen Period", "Period for Tenkan-sen line", "Indicators")
.SetOptimize(7, 13, 2);
_kijunPeriod = Param(nameof(KijunPeriod), 26)
.SetDisplay("Kijun-sen Period", "Period for Kijun-sen line", "Indicators")
.SetOptimize(20, 30, 2);
_senkouSpanPeriod = Param(nameof(SenkouSpanPeriod), 52)
.SetDisplay("Senkou Span B Period", "Period for Senkou Span B", "Indicators")
.SetOptimize(40, 60, 4);
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).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();
_prevTenkanAboveKijun = default;
_hasPrevValues = default;
_candlesSinceLastTrade = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var tenkan = new Highest { Length = TenkanPeriod };
var tenkanLow = new Lowest { Length = TenkanPeriod };
var kijun = new Highest { Length = KijunPeriod };
var kijunLow = new Lowest { Length = KijunPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(tenkan, tenkanLow, kijun, kijunLow, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal tenkanHigh, decimal tenkanLow, decimal kijunHigh, decimal kijunLow)
{
if (candle.State != CandleStates.Finished)
return;
var tenkan = (tenkanHigh + tenkanLow) / 2m;
var kijun = (kijunHigh + kijunLow) / 2m;
if (tenkan == 0 || kijun == 0)
return;
var tenkanAboveKijun = tenkan > kijun;
_candlesSinceLastTrade++;
if (!_hasPrevValues)
{
_hasPrevValues = true;
_prevTenkanAboveKijun = tenkanAboveKijun;
return;
}
// Detect cross
var isCross = tenkanAboveKijun != _prevTenkanAboveKijun;
_prevTenkanAboveKijun = tenkanAboveKijun;
if (!isCross)
return;
// Cooldown to avoid too many trades
if (_candlesSinceLastTrade < 4)
return;
if (tenkanAboveKijun && Position <= 0)
{
BuyMarket();
_candlesSinceLastTrade = 0;
}
else if (!tenkanAboveKijun && Position >= 0)
{
SellMarket();
_candlesSinceLastTrade = 0;
}
}
}
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 Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class ichimoku_kumo_breakout_strategy(Strategy):
"""
Ichimoku Kumo breakout. Tenkan/Kijun cross with cloud confirmation.
"""
def __init__(self):
super(ichimoku_kumo_breakout_strategy, self).__init__()
self._tenkan_period = self.Param("TenkanPeriod", 9).SetDisplay("Tenkan Period", "Tenkan-sen period", "Indicators")
self._kijun_period = self.Param("KijunPeriod", 26).SetDisplay("Kijun Period", "Kijun-sen period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Timeframe", "General")
self._prev_tenkan_above = False
self._has_prev = False
self._candles_since_trade = 0
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(ichimoku_kumo_breakout_strategy, self).OnReseted()
self._prev_tenkan_above = False
self._has_prev = False
self._candles_since_trade = 0
def OnStarted2(self, time):
super(ichimoku_kumo_breakout_strategy, self).OnStarted2(time)
tenkan_h = Highest()
tenkan_h.Length = self._tenkan_period.Value
tenkan_l = Lowest()
tenkan_l.Length = self._tenkan_period.Value
kijun_h = Highest()
kijun_h.Length = self._kijun_period.Value
kijun_l = Lowest()
kijun_l.Length = self._kijun_period.Value
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(tenkan_h, tenkan_l, kijun_h, kijun_l, self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def _process_candle(self, candle, th, tl, kh, kl):
if candle.State != CandleStates.Finished:
return
tenkan = (float(th) + float(tl)) / 2.0
kijun = (float(kh) + float(kl)) / 2.0
if tenkan == 0 or kijun == 0:
return
tenkan_above = tenkan > kijun
self._candles_since_trade += 1
if not self._has_prev:
self._has_prev = True
self._prev_tenkan_above = tenkan_above
return
is_cross = tenkan_above != self._prev_tenkan_above
self._prev_tenkan_above = tenkan_above
if not is_cross:
return
if self._candles_since_trade < 4:
return
if tenkan_above and self.Position <= 0:
self.BuyMarket()
self._candles_since_trade = 0
elif not tenkan_above and self.Position >= 0:
self.SellMarket()
self._candles_since_trade = 0
def CreateClone(self):
return ichimoku_kumo_breakout_strategy()