Стратегия RGT RSI Bollinger
Стратегия объединяет индикатор RSI и полосы Боллинджера для поиска возврата к среднему. Длинная позиция открывается, когда RSI указывает на перепроданность, а цена находится ниже нижней полосы. Короткая позиция открывается, когда RSI показывает перекупленность и цена выше верхней полосы. Сразу после входа выставляется стоп-лосс, который позже начинает сопровождаться при достижении минимальной прибыли.
Трейлинг-стоп фиксирует прибыль, следуя за ценой на фиксированном расстоянии при благоприятном движении. Позиции закрываются при срабатывании трейлинг-стопа.
Детали
- Условия входа: RSI ниже
RsiLowи цена ниже нижней полосы для покупок; RSI вышеRsiHighи цена выше верхней полосы для продаж. - Длинные/короткие: В обе стороны.
- Условия выхода: Срабатывание трейлинг-стопа.
- Стопы: Начальный стоп-лосс и трейлинг-стоп.
- Значения по умолчанию:
RsiPeriod= 8RsiHigh= 90RsiLow= 10StopLossPips= 70TrailingStopPips= 35MinProfitPips= 30Volume= 1CandleType= TimeSpan.FromMinutes(5)
- Фильтры:
- Категория: Возврат к среднему
- Направление: В обе стороны
- Индикаторы: RSI, полосы Боллинджера
- Стопы: Да
- Сложность: Новичок
- Таймфрейм: Внутридневной
- Сезонность: Нет
- Нейросети: Нет
- Дивергенция: Нет
- Уровень риска: Средний
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>
/// RSI with Bollinger Bands strategy.
/// </summary>
public class RgtRsiBollingerStrategy : Strategy
{
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _rsiHigh;
private readonly StrategyParam<int> _rsiLow;
private readonly StrategyParam<decimal> _stopLoss;
private readonly StrategyParam<decimal> _trailingStop;
private readonly StrategyParam<decimal> _minProfit;
private readonly StrategyParam<DataType> _candleType;
private decimal _entryPrice;
private decimal _stopPrice;
private bool _isLong;
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public int RsiHigh { get => _rsiHigh.Value; set => _rsiHigh.Value = value; }
public int RsiLow { get => _rsiLow.Value; set => _rsiLow.Value = value; }
public decimal StopLoss { get => _stopLoss.Value; set => _stopLoss.Value = value; }
public decimal TrailingStop { get => _trailingStop.Value; set => _trailingStop.Value = value; }
public decimal MinProfit { get => _minProfit.Value; set => _minProfit.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public RgtRsiBollingerStrategy()
{
_rsiPeriod = Param(nameof(RsiPeriod), 8)
.SetDisplay("RSI Period", "RSI calculation period", "Indicator");
_rsiHigh = Param(nameof(RsiHigh), 55)
.SetDisplay("RSI High", "Overbought RSI level", "Indicator");
_rsiLow = Param(nameof(RsiLow), 45)
.SetDisplay("RSI Low", "Oversold RSI level", "Indicator");
_stopLoss = Param(nameof(StopLoss), 500m)
.SetGreaterThanZero()
.SetDisplay("Stop Loss", "Stop loss in price units", "Risk");
_trailingStop = Param(nameof(TrailingStop), 300m)
.SetGreaterThanZero()
.SetDisplay("Trailing Stop", "Trailing stop distance", "Risk");
_minProfit = Param(nameof(MinProfit), 200m)
.SetGreaterThanZero()
.SetDisplay("Min Profit", "Minimum profit before trailing", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_entryPrice = 0;
_stopPrice = 0;
_isLong = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var bb = new BollingerBands { Length = 20, Width = 2m };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(new IIndicator[] { rsi, bb }, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue[] values)
{
if (candle.State != CandleStates.Finished)
return;
if (values[0].IsEmpty || values[1].IsEmpty)
return;
var rsiValue = values[0].GetValue<decimal>();
var bbVal = (BollingerBandsValue)values[1];
if (bbVal.UpBand is not decimal upper ||
bbVal.LowBand is not decimal lower)
return;
if (Position == 0)
{
if (rsiValue < RsiLow && candle.ClosePrice < lower)
{
BuyMarket();
_entryPrice = candle.ClosePrice;
_stopPrice = _entryPrice - StopLoss;
_isLong = true;
}
else if (rsiValue > RsiHigh && candle.ClosePrice > upper)
{
SellMarket();
_entryPrice = candle.ClosePrice;
_stopPrice = _entryPrice + StopLoss;
_isLong = false;
}
}
else if (_isLong && Position > 0)
{
var profit = candle.ClosePrice - _entryPrice;
if (profit > MinProfit)
{
var newStop = candle.ClosePrice - TrailingStop;
if (newStop > _stopPrice)
_stopPrice = newStop;
}
if (candle.ClosePrice <= _stopPrice)
SellMarket();
}
else if (!_isLong && Position < 0)
{
var profit = _entryPrice - candle.ClosePrice;
if (profit > MinProfit)
{
var newStop = candle.ClosePrice + TrailingStop;
if (newStop < _stopPrice)
_stopPrice = newStop;
}
if (candle.ClosePrice >= _stopPrice)
BuyMarket();
}
}
}
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 System import Array
from StockSharp.Algo.Indicators import BollingerBands, RelativeStrengthIndex, IIndicator, IndicatorHelper
from StockSharp.Algo.Strategies import Strategy
class rgt_rsi_bollinger_strategy(Strategy):
def __init__(self):
super(rgt_rsi_bollinger_strategy, self).__init__()
self._rsi_period = self.Param("RsiPeriod", 8) \
.SetDisplay("RSI Period", "RSI calculation period", "Indicator")
self._rsi_high = self.Param("RsiHigh", 55) \
.SetDisplay("RSI High", "Overbought RSI level", "Indicator")
self._rsi_low = self.Param("RsiLow", 45) \
.SetDisplay("RSI Low", "Oversold RSI level", "Indicator")
self._stop_loss = self.Param("StopLoss", 500.0) \
.SetDisplay("Stop Loss", "Stop loss in price units", "Risk")
self._trailing_stop = self.Param("TrailingStop", 300.0) \
.SetDisplay("Trailing Stop", "Trailing stop distance", "Risk")
self._min_profit = self.Param("MinProfit", 200.0) \
.SetDisplay("Min Profit", "Minimum profit before trailing", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._entry_price = 0.0
self._stop_price = 0.0
self._is_long = False
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def rsi_high(self):
return self._rsi_high.Value
@property
def rsi_low(self):
return self._rsi_low.Value
@property
def stop_loss(self):
return self._stop_loss.Value
@property
def trailing_stop(self):
return self._trailing_stop.Value
@property
def min_profit(self):
return self._min_profit.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(rgt_rsi_bollinger_strategy, self).OnReseted()
self._entry_price = 0.0
self._stop_price = 0.0
self._is_long = False
def OnStarted2(self, time):
super(rgt_rsi_bollinger_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = self.rsi_period
bb = BollingerBands()
bb.Length = 20
bb.Width = 2.0
indicators = Array[IIndicator]([rsi, bb])
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(indicators, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, bb)
self.DrawOwnTrades(area)
def on_process(self, candle, values):
if candle.State != CandleStates.Finished:
return
if values[0].IsEmpty or values[1].IsEmpty:
return
rsi_val = IndicatorHelper.ToDecimal(values[0])
bb_val = values[1]
up = bb_val.UpBand
lo = bb_val.LowBand
if up is None or lo is None:
return
close = candle.ClosePrice
if self.Position == 0:
if rsi_val < self.rsi_low and close < lo:
self.BuyMarket()
self._entry_price = close
self._stop_price = self._entry_price - self.stop_loss
self._is_long = True
elif rsi_val > self.rsi_high and close > up:
self.SellMarket()
self._entry_price = close
self._stop_price = self._entry_price + self.stop_loss
self._is_long = False
elif self._is_long and self.Position > 0:
profit = close - self._entry_price
if profit > self.min_profit:
new_stop = close - self.trailing_stop
if new_stop > self._stop_price:
self._stop_price = new_stop
if close <= self._stop_price:
self.SellMarket()
elif not self._is_long and self.Position < 0:
profit = self._entry_price - close
if profit > self.min_profit:
new_stop = close + self.trailing_stop
if new_stop < self._stop_price:
self._stop_price = new_stop
if close >= self._stop_price:
self.BuyMarket()
def CreateClone(self):
return rgt_rsi_bollinger_strategy()