CBC_WS_RSI — реализация на StockSharp высокого уровня оригинального советника MQL5. Стратегия объединяет свечные модели «Три белых солдата» и «Три черные вороны» с подтверждением по RSI. Вход выполняется только тогда, когда много-свечная разворотная конфигурация совпадает с направлением импульса. Обработка ведётся исключительно по сформированным свечам, а все подписки реализованы через SubscribeCandles().Bind(...) без ручной работы с буферами индикаторов.
Логика торговли
Условия для покупки
Обнаружена фигура «Три белых солдата»:
Три подряд бычьи свечи с закрытием выше открытия.
Каждое закрытие выше закрытия предыдущей свечи.
Вторая и третья свечи открываются внутри тела предыдущей.
RSI текущей свечи не превышает уровня подтверждения лонга (по умолчанию 40).
При отсутствии позиции выполняется покупка Volume по рынку. При наличии короткой позиции она закрывается и только затем открывается длинная.
Условия для продажи
Обнаружена фигура «Три черные вороны»:
Три подряд медвежьи свечи с закрытием ниже открытия.
Каждое закрытие ниже закрытия предыдущей свечи.
Вторая и третья свечи открываются внутри тела предыдущей.
RSI текущей свечи не ниже уровня подтверждения шорта (по умолчанию 60).
При отсутствии позиции выполняется продажа Volume по рынку. При наличии длинной позиции она закрывается и только затем открывается короткая.
Правила выхода
Закрытие лонга: RSI пересекает сверху вниз верхний (70) или нижний (30) уровни выхода.
Закрытие шорта: RSI пересекает снизу вверх нижний (30) или верхний (70) уровни выхода.
Защита позиций: Параметры стоп-лосса и тейк-профита задаются в процентах. Если значения больше нуля, защита активируется через StartProtection.
Стратегия отслеживает два последних значения RSI и фиксирует позицию при первом же пересечении критических уровней, что позволяет быстро реагировать на изменение импульса.
Параметры
Имя
Описание
Значение по умолчанию
CandleType
Тип и таймфрейм свечей для подписки.
Свечи 1 часа
RsiPeriod
Период расчёта RSI.
37
LongConfirmationLevel
Максимальный RSI для входа в лонг.
40
ShortConfirmationLevel
Минимальный RSI для входа в шорт.
60
LowerExitLevel
Нижний уровень RSI для закрытия позиций.
30
UpperExitLevel
Верхний уровень RSI для закрытия позиций.
70
StopLossPercent
Стоп-лосс в процентах (0 отключает).
1
TakeProfitPercent
Тейк-профит в процентах (0 отключает).
2
Все числовые параметры помечены SetCanOptimize(true) и могут участвовать в оптимизации.
Визуализация
При наличии области графика стратегия отображает:
выбранную свечную серию;
линию RSI;
совершённые сделки, что помогает оценить точность распознавания моделей.
Рекомендации по использованию
Перед запуском установите желаемый объём Volume.
Стратегия подходит для любых инструментов с данными OHLC.
Свечи с нулевым телом игнорируются, что уменьшает влияние дожи.
Подтверждение RSI снижает количество ложных сигналов при слабых разворотах.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// CBC WS RSI strategy: 3 Black Crows / 3 White Soldiers with RSI confirmation.
/// Buys after 3 bullish candles with RSI below 60, sells after 3 bearish with RSI above 40.
/// </summary>
public class CbcWsRsiStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
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 RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public CbcWsRsiStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI 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 rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsi)
{
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 RSI extremes
if (Position > 0 && rsi > 75 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_candlesSinceTrade = 0;
}
else if (Position < 0 && rsi < 25 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
// Entry on pattern
if (_bullCount >= 3 && rsi < 60 && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_bullCount = 0;
_candlesSinceTrade = 0;
}
else if (_bearCount >= 3 && rsi > 40 && 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 RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class cbc_ws_rsi_strategy(Strategy):
def __init__(self):
super(cbc_ws_rsi_strategy, self).__init__()
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI period for confirmation", "Indicators")
self._signal_cooldown = self.Param("SignalCooldownCandles", 6) \
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading")
self._rsi = None
self._bull_count = 0
self._bear_count = 0
self._candles_since_trade = 0
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def signal_cooldown(self):
return self._signal_cooldown.Value
def OnReseted(self):
super(cbc_ws_rsi_strategy, self).OnReseted()
self._rsi = None
self._bull_count = 0
self._bear_count = 0
self._candles_since_trade = self.signal_cooldown
def OnStarted2(self, time):
super(cbc_ws_rsi_strategy, self).OnStarted2(time)
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.rsi_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._rsi, self._process_candle)
subscription.Start()
def _process_candle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
if not self._rsi.IsFormed:
return
rsi_val = float(rsi_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 rsi_val > 75.0 and self._candles_since_trade >= self.signal_cooldown:
self.SellMarket()
self._candles_since_trade = 0
elif self.Position < 0 and rsi_val < 25.0 and self._candles_since_trade >= self.signal_cooldown:
self.BuyMarket()
self._candles_since_trade = 0
if self._bull_count >= 3 and rsi_val < 60.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 rsi_val > 40.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 cbc_ws_rsi_strategy()