Esta estratégia calcula a média dos últimos valores de RSI para gerar sinais de trading. Calcula um Índice de Força Relativa (RSI) padrão sobre um período configurável e depois aplica uma média móvel simples ao próprio RSI. As operações são abertas quando o RSI médio cruza limites predefinidos e fechadas quando o limiar oposto é atingido.
Lógica de trading
Cálculo do RSI
O indicador usa RsiPeriod para calcular o RSI baseado nos preços de fechamento das velas.
Média do RSI
Os últimos AveragePeriod valores de RSI são suavizados por uma média móvel simples.
Regras de entrada
Se BuyEnabled for true e nenhuma posição estiver aberta, uma ordem de compra é enviada quando o RSI médio excede BuyThreshold (padrão 55).
Se SellEnabled for true e nenhuma posição estiver aberta, uma ordem de venda é enviada quando o RSI médio cai abaixo de SellThreshold (padrão 45).
Regras de saída
Quando CloseBySignal for true, posições abertas são fechadas em sinais opostos:
Posições compradas fecham quando o RSI médio cai abaixo de CloseBuyThreshold (padrão 47).
Posições vendidas fecham quando o RSI médio sobe acima de CloseSellThreshold (padrão 52).
Parâmetros
BuyEnabled – habilitar ou desabilitar entradas compradas.
SellEnabled – habilitar ou desabilitar entradas vendidas.
CloseBySignal – permitir saídas em sinais RSI opostos.
RsiPeriod – comprimento do cálculo do RSI.
AveragePeriod – número de valores de RSI usados para a média.
BuyThreshold – valor do RSI médio acima do qual uma posição comprada é aberta.
SellThreshold – valor do RSI médio abaixo do qual uma posição vendida é aberta.
CloseBuyThreshold – valor do RSI médio abaixo do qual uma posição comprada é fechada.
CloseSellThreshold – valor do RSI médio acima do qual uma posição vendida é fechada.
CandleType – tipo de vela para assinaturas.
Notas
Esta estratégia demonstra como valores de indicadores podem ser combinados por vinculação na API de alto nível do StockSharp. Funções de trailing stop e gerenciamento de dinheiro da versão MQL original são omitidas por simplicidade.
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Strategy that trades based on averaged RSI values.
/// Uses RSI smoothed by SMA to generate signals.
/// </summary>
public class AutoTradeWithRsiStrategy : Strategy
{
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _averagePeriod;
private readonly StrategyParam<decimal> _buyThreshold;
private readonly StrategyParam<decimal> _sellThreshold;
private readonly StrategyParam<DataType> _candleType;
private ExponentialMovingAverage _rsiAvg;
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public int AveragePeriod { get => _averagePeriod.Value; set => _averagePeriod.Value = value; }
public decimal BuyThreshold { get => _buyThreshold.Value; set => _buyThreshold.Value = value; }
public decimal SellThreshold { get => _sellThreshold.Value; set => _sellThreshold.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public AutoTradeWithRsiStrategy()
{
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI calculation period", "Indicator");
_averagePeriod = Param(nameof(AveragePeriod), 21)
.SetGreaterThanZero()
.SetDisplay("Average Period", "SMA period to smooth RSI", "Indicator");
_buyThreshold = Param(nameof(BuyThreshold), 55m)
.SetDisplay("Buy Threshold", "Averaged RSI above which to buy", "Rules");
_sellThreshold = Param(nameof(SellThreshold), 45m)
.SetDisplay("Sell Threshold", "Averaged RSI below which to sell", "Rules");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle data type", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_rsiAvg = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
_rsiAvg = new ExponentialMovingAverage { Length = AveragePeriod };
Indicators.Add(_rsiAvg);
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(rsi, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
var area2 = CreateChartArea();
if (area2 != null)
DrawIndicator(area2, rsi);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!rsiValue.IsFormed)
return;
var avgResult = _rsiAvg.Process(rsiValue);
if (!avgResult.IsFormed)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var avgRsi = avgResult.GetValue<decimal>();
if (avgRsi > BuyThreshold && Position <= 0)
BuyMarket();
else if (avgRsi < SellThreshold && Position >= 0)
SellMarket();
}
}
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, ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class auto_trade_with_rsi_strategy(Strategy):
def __init__(self):
super(auto_trade_with_rsi_strategy, self).__init__()
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI calculation period", "Indicator")
self._average_period = self.Param("AveragePeriod", 21) \
.SetDisplay("Average Period", "SMA period to smooth RSI", "Indicator")
self._buy_threshold = self.Param("BuyThreshold", 55.0) \
.SetDisplay("Buy Threshold", "Averaged RSI above which to buy", "Rules")
self._sell_threshold = self.Param("SellThreshold", 45.0) \
.SetDisplay("Sell Threshold", "Averaged RSI below which to sell", "Rules")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle data type", "General")
self._rsi_avg = None
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def average_period(self):
return self._average_period.Value
@property
def buy_threshold(self):
return self._buy_threshold.Value
@property
def sell_threshold(self):
return self._sell_threshold.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(auto_trade_with_rsi_strategy, self).OnReseted()
self._rsi_avg = None
def OnStarted2(self, time):
super(auto_trade_with_rsi_strategy, self).OnStarted2(time)
rsi = RelativeStrengthIndex()
rsi.Length = self.rsi_period
self._rsi_avg = ExponentialMovingAverage()
self._rsi_avg.Length = self.average_period
self.Indicators.Add(self._rsi_avg)
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(rsi, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def process_candle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
if not rsi_value.IsFormed:
return
avg_result = self._rsi_avg.Process(rsi_value)
if not avg_result.IsFormed:
return
avg_rsi = float(avg_result)
if avg_rsi > float(self.buy_threshold) and self.Position <= 0:
self.BuyMarket()
elif avg_rsi < float(self.sell_threshold) and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return auto_trade_with_rsi_strategy()