Esta estratégia converte o expert advisor original iRSISign do MQL5 para a API de alto nível do StockSharp. Combina o Índice de Força Relativa (RSI) com o Average True Range (ATR) para gerar sinais de entrada e saída.
O sistema escuta velas finalizadas de um período definido pelo usuário. Quando o RSI cruza acima do limiar inferior, sinaliza uma possível reversão de alta e abre uma posição comprada ou fecha uma posição vendida existente. Por outro lado, quando o RSI cai abaixo do limiar superior, entra em uma posição vendida ou fecha uma posição comprada ativa. O ATR é calculado mas usado apenas como contexto adicional, espelhando o indicador original que exibia setas de sinal deslocadas por ATR.
Detalhes
Critérios de entrada:
Comprado: O valor anterior do RSI estava abaixo de DownLevel e o RSI atual cruza acima.
Vendido: O valor anterior do RSI estava acima de UpLevel e o RSI atual cruza abaixo.
Comprado/Vendido: Ambas as direções são permitidas e podem ser habilitadas independentemente.
Critérios de saída:
O sinal oposto fecha a posição atual se o sinalizador de fechamento correspondente estiver ativo.
Stops: Não implementados. Gestão de risco pode ser adicionada externamente se necessário.
Valores padrão:
RsiPeriod = 14
AtrPeriod = 14
UpLevel = 70
DownLevel = 30
CandleType = velas de 1 hora
Filtros:
Categoria: Momentum
Direção: Ambos
Indicadores: RSI, ATR
Stops: Não
Complexidade: Básico
Período: Flexível
Sazonalidade: Não
Redes neurais: Não
Divergência: Não
Nível de risco: Médio
Parâmetros
Nome
Descrição
RsiPeriod
Comprimento do RSI.
AtrPeriod
Comprimento do ATR.
UpLevel
Limiar superior do RSI que gera sinais de venda.
DownLevel
Limiar inferior do RSI que gera sinais de compra.
CandleType
Período das velas usado para cálculos.
BuyOpen
Habilitar abertura de posições compradas.
SellOpen
Habilitar abertura de posições vendidas.
BuyClose
Permitir fechamento de posições compradas com sinal oposto.
SellClose
Permitir fechamento de posições vendidas com sinal oposto.
A estratégia é destinada como exemplo educacional demonstrando como traduzir a lógica simples do MQL5 para o framework de estratégias de alto nível do StockSharp.
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 based signal strategy.
/// Opens long when RSI crosses above the down level.
/// Opens short when RSI crosses below the up level.
/// </summary>
public class RsiSignStrategy : Strategy
{
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<decimal> _upLevel;
private readonly StrategyParam<decimal> _downLevel;
private readonly StrategyParam<DataType> _candleType;
private decimal? _previousRsi;
public int RsiPeriod { get => _rsiPeriod.Value; set => _rsiPeriod.Value = value; }
public decimal UpLevel { get => _upLevel.Value; set => _upLevel.Value = value; }
public decimal DownLevel { get => _downLevel.Value; set => _downLevel.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public RsiSignStrategy()
{
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "Length of RSI indicator", "Indicator");
_upLevel = Param(nameof(UpLevel), 70m)
.SetDisplay("RSI Upper Level", "Sell when RSI falls below this value", "Indicator");
_downLevel = Param(nameof(DownLevel), 30m)
.SetDisplay("RSI Lower Level", "Buy when RSI rises above this value", "Indicator");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe used for indicator calculations", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_previousRsi = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_previousRsi = null;
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(rsi, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, rsi);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var prevRsi = _previousRsi;
_previousRsi = rsiValue;
if (prevRsi is null)
return;
// RSI crosses above lower level -> buy signal
if (prevRsi <= DownLevel && rsiValue > DownLevel && Position <= 0)
BuyMarket();
// RSI crosses below upper level -> sell signal
else if (prevRsi >= UpLevel && rsiValue < UpLevel && 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
from StockSharp.Algo.Strategies import Strategy
class rsi_sign_strategy(Strategy):
def __init__(self):
super(rsi_sign_strategy, self).__init__()
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "Length of RSI indicator", "Indicator")
self._up_level = self.Param("UpLevel", 70.0) \
.SetDisplay("RSI Upper Level", "Sell when RSI falls below this value", "Indicator")
self._down_level = self.Param("DownLevel", 30.0) \
.SetDisplay("RSI Lower Level", "Buy when RSI rises above this value", "Indicator")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe used for indicator calculations", "General")
self._previous_rsi = None
@property
def rsi_period(self):
return self._rsi_period.Value
@property
def up_level(self):
return self._up_level.Value
@property
def down_level(self):
return self._down_level.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(rsi_sign_strategy, self).OnReseted()
self._previous_rsi = None
def OnStarted2(self, time):
super(rsi_sign_strategy, self).OnStarted2(time)
self._previous_rsi = None
rsi = RelativeStrengthIndex()
rsi.Length = self.rsi_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(rsi, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, rsi)
self.DrawOwnTrades(area)
def process_candle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
rsi_value = float(rsi_value)
prev_rsi = self._previous_rsi
self._previous_rsi = rsi_value
if prev_rsi is None:
return
down_lvl = float(self.down_level)
up_lvl = float(self.up_level)
if prev_rsi <= down_lvl and rsi_value > down_lvl and self.Position <= 0:
self.BuyMarket()
elif prev_rsi >= up_lvl and rsi_value < up_lvl and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return rsi_sign_strategy()