Главная
/
Примеры стратегий
Открыть на GitHub
Стратегия AbcWsCci
Описание
AbcWsCci сочетает свечные модели «Три белых солдата» и «Три чёрные вороны» с индикатором Commodity Channel Index (CCI) . Стратегия анализирует только закрытые свечи, оценивает размер их тел относительно скользящего среднего и открывает позиции, когда формируются три последовательные сильные свечи, подтверждённые экстремальными значениями CCI. Выход из позиции происходит при выходе CCI из зоны экстремумов, что указывает на ослабление импульса.
Логика работы
Ведётся скользящее среднее величины тел свечей, чтобы определить минимальный размер «длинной» свечи.
Определяется модель «Три белых солдата» (три подряд сильных бычьих свечи с растущими серединами).
Определяется модель «Три чёрные вороны» (три подряд сильных медвежьих свечи с понижающимися серединами).
Для входа в лонг требуется формирование «солдат» и значение CCI ниже -50 .
Для входа в шорт требуется формирование «ворон» и значение CCI выше 50 .
Выход из лонга осуществляется при возвращении CCI из области ниже -80 или выше 80 .
Выход из шорта осуществляется при симметричном пересечении уровней 80 и -80 .
Параметры
Имя
Описание
Значение по умолчанию
CciPeriod
Период расчёта индикатора CCI.
37
BodyAveragePeriod
Количество свечей в среднем значении тела.
13
CandleType
Таймфрейм свечей для анализа.
1 час
Используемые индикаторы
CCI — подтверждение входов и определение момента выхода.
Простое скользящее среднее тел свечей — фильтр, исключающий слабые свечи из паттерна.
Управление позицией
Открыть лонг , если выполнены условия «солдат» и CCI < -50, а текущая позиция не длинная.
Открыть шорт , если выполнены условия «ворон» и CCI > 50, а текущая позиция не короткая.
Закрыть лонг , если CCI выходит из диапазона -80/80.
Закрыть шорт , если CCI выходит из диапазона +80/-80.
Дополнительные рекомендации
Стратегия работает по завершённым свечам, поэтому не использует неполные данные.
Эффективнее на инструментах с выраженными импульсами.
Рекомендуется дополнить систему внешним риск-менеджментом (стоп-лоссы, динамический объём).
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// ABC WS CCI strategy: 3 white soldiers / 3 black crows pattern with CCI confirmation.
/// Buys after 3 bullish candles with CCI below 100, sells after 3 bearish candles with CCI above -100.
/// </summary>
public class AbcWsCciStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _cciPeriod;
private readonly StrategyParam<int> _signalCooldownCandles;
private int _bullCount;
private int _bearCount;
private int _candlesSinceTrade;
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public AbcWsCciStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_cciPeriod = Param(nameof(CciPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("CCI Period", "CCI period for confirmation", "Indicators");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_bullCount = 0;
_bearCount = 0;
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_bullCount = 0;
_bearCount = 0;
_candlesSinceTrade = SignalCooldownCandles;
var cci = new CommodityChannelIndex { Length = CciPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(cci, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal cci)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
if (candle.ClosePrice > candle.OpenPrice)
{
_bullCount++;
_bearCount = 0;
}
else if (candle.ClosePrice < candle.OpenPrice)
{
_bearCount++;
_bullCount = 0;
}
else
{
_bullCount = 0;
_bearCount = 0;
}
// Exit on CCI reversal
if (Position > 0 && cci > 200 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
else if (Position < 0 && cci < -200 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
// Entry on 3 soldiers/crows pattern
if (_bullCount >= 3 && cci < 100 && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_bullCount = 0;
_candlesSinceTrade = 0;
}
else if (_bearCount >= 3 && cci > -100 && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_bearCount = 0;
_candlesSinceTrade = 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 CommodityChannelIndex
from StockSharp.Algo.Strategies import Strategy
class abc_ws_cci_strategy(Strategy):
def __init__(self):
super(abc_ws_cci_strategy, self).__init__()
self._cci_period = self.Param("CciPeriod", 14) \
.SetDisplay("CCI Period", "CCI period for confirmation", "Indicators")
self._signal_cooldown = self.Param("SignalCooldownCandles", 6) \
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading")
self._cci = None
self._bull_count = 0
self._bear_count = 0
self._candles_since_trade = 0
@property
def cci_period(self):
return self._cci_period.Value
@property
def signal_cooldown(self):
return self._signal_cooldown.Value
def OnReseted(self):
super(abc_ws_cci_strategy, self).OnReseted()
self._cci = None
self._bull_count = 0
self._bear_count = 0
self._candles_since_trade = self.signal_cooldown
def OnStarted2(self, time):
super(abc_ws_cci_strategy, self).OnStarted2(time)
self._cci = CommodityChannelIndex()
self._cci.Length = self.cci_period
self._bull_count = 0
self._bear_count = 0
self._candles_since_trade = self.signal_cooldown
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(60)))
subscription.Bind(self._cci, self._process_candle)
subscription.Start()
def _process_candle(self, candle, cci_value):
if candle.State != CandleStates.Finished:
return
if not self._cci.IsFormed:
return
cci_val = float(cci_value)
if self._candles_since_trade < self.signal_cooldown:
self._candles_since_trade += 1
close = float(candle.ClosePrice)
open_p = float(candle.OpenPrice)
if close > open_p:
self._bull_count += 1
self._bear_count = 0
elif close < open_p:
self._bear_count += 1
self._bull_count = 0
else:
self._bull_count = 0
self._bear_count = 0
if self.Position > 0 and cci_val > 200.0 and self._candles_since_trade >= self.signal_cooldown:
self.SellMarket()
self._candles_since_trade = 0
elif self.Position < 0 and cci_val < -200.0 and self._candles_since_trade >= self.signal_cooldown:
self.BuyMarket()
self._candles_since_trade = 0
if self._bull_count >= 3 and cci_val < 100.0 and self.Position <= 0 and self._candles_since_trade >= self.signal_cooldown:
self.BuyMarket()
self._bull_count = 0
self._candles_since_trade = 0
elif self._bear_count >= 3 and cci_val > -100.0 and self.Position >= 0 and self._candles_since_trade >= self.signal_cooldown:
self.SellMarket()
self._bear_count = 0
self._candles_since_trade = 0
def CreateClone(self):
return abc_ws_cci_strategy()