A estratégia de MA Bollinger RSI transporta os MetaTrader especialistas BolRSIMAs para o StockSharp API de alto nível. O sistema combina um
Bollinger Quebra de banda, um filtro RSI e uma média móvel exponencial de período de tempo mais alto (EMA) para identificar negociações de pullback em
a direção da tendência dominante. O dimensionamento automático do lote é preservado: quando habilitado a estratégia converte o risco configurado
fração do patrimônio do portfólio em volume usando o preço atual, a distância de stop Bollinger e o tamanho do contrato do instrumento.
Lógica de negociação
Assine a série de velas primárias (padrão: 1 hora) e calcule Bollinger bandas e RSI no mesmo período de tempo.
Assine velas diárias e insira seus preços de fechamento em um EMA período de 200 para reproduzir o filtro de período mais alto usado
no original EA.
Gere uma configuração longa quando a última vela fechar abaixo da banda inferior, o valor RSI estiver abaixo do limite de sobrevenda
e o fechamento permanece acima do EMA diário. Uma configuração curta é acionada por um fechamento acima da banda superior, RSI acima do
limite de sobrecompra e preço abaixo do EMA diário.
Abra posições apenas quando nenhuma exposição estiver ativa. Cada novo comércio armazena níveis de stop-loss e take-profit derivados do
valores anteriores de Bollinger: os comprados usam lowerBand - StopLossOffset e têm como alvo a banda intermediária; uso de shorts
upperBand + StopLossOffset e segmentar a banda intermediária também.
Em cada vela finalizada, a estratégia verifica os extremos da vela em relação aos níveis de proteção. Se o baixo/alto tocar o
stop ou target, a posição é fechada imediatamente, emulando as ordens de proteção colocadas pela versão MetaTrader.
Parâmetros
Nome
Padrão
Descrição
CandleType
Velas de 1 hora
Período primário processado por Bollinger Bandas e RSI.
DailyCandleType
Velas de 1 dia
Prazo maior que alimenta o filtro de tendência EMA.
BollingerPeriod
20
Número de velas usadas para construir Bollinger Bandas.
BollingerDeviation
2
Multiplicador de largura de banda.
RsiPeriod
13
RSI comprimento de suavização.
RsiUpperLevel
70
Limite de sobrecompra necessário para negociações curtas.
RsiLowerLevel
30
Limite de sobrevenda necessário para negociações longas.
MaPeriod
200
Duração do prazo superior EMA.
StopLossOffset
0.0238
Buffer extra adicionado fora da banda antes de colocar o stop loss.
UseAutoLot
true
Permite dimensionamento de posição baseado em risco.
RiskPerTrade
0.05
Fração do patrimônio alocado para cada negociação quando o lote automático está ativo.
FixedVolume
0.1
Tamanho do pedido quando o dimensionamento automático do lote está desativado.
Gestão de dinheiro
Quando UseAutoLot é true, o volume é igual a (equity * RiskPerTrade) / (StopLossOffset * price * contractSize) arredondado para o
limites de câmbio. Isso reflete a rotina autolot MetaTrader, que divide o valor do risco pela distância do stop em dinheiro e
o tamanho do contrato.
Se as informações sobre o patrimônio ou o preço não estiverem disponíveis, a estratégia volta para FixedVolume, respeitando ainda o
restrições de volume do instrumento.
Diferenças do especialista MetaTrader
As ordens stop-loss e take-profit são simuladas por meio de máximos e mínimos de velas, em vez de ordens do lado do servidor, correspondendo ao
resultado do EA original sem depender do envio síncrono de pedidos.
O filtro EMA usa assinaturas de velas de StockSharp; não há dependência de chamadas de dados diárias específicas de MetaTrader.
O dimensionamento de risco respeita StockSharp limites de segurança (MinVolume, MaxVolume, VolumeStep) para evitar pedidos rejeitados em exchanges.
Dicas de uso
Ajuste StopLossOffset ao negociar símbolos com diferentes escalas de preços para que a distância reflita os EA originais
Buffer de 2,38% além da banda Bollinger.
Se o instrumento usar um período diário diferente (por exemplo, trocas de criptografia), altere DailyCandleType adequadamente para que o EMA
reflete o filtro de tendência pretendido.
Combine a estratégia com trailing stops externos se preferir saídas dinâmicas assim que a meta da banda intermediária for atingida.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Bollinger + RSI + MA strategy.
/// Buys when price at lower BB and RSI oversold, sells at upper BB and RSI overbought.
/// </summary>
public class BollingerRsiMaStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
private readonly StrategyParam<int> _bbPeriod;
private readonly StrategyParam<decimal> _bandPercent;
private readonly StrategyParam<int> _signalCooldownCandles;
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 BbPeriod { get => _bbPeriod.Value; set => _bbPeriod.Value = value; }
public decimal BandPercent { get => _bandPercent.Value; set => _bandPercent.Value = value; }
public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }
public BollingerRsiMaStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
_bbPeriod = Param(nameof(BbPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("BB Period", "Bollinger Bands period", "Indicators");
_bandPercent = Param(nameof(BandPercent), 0.01m)
.SetGreaterThanZero()
.SetDisplay("Band Percent", "MA percentage band width", "Signals");
_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
.SetGreaterThanZero()
.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_candlesSinceTrade = SignalCooldownCandles;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_candlesSinceTrade = SignalCooldownCandles;
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var ma = new SimpleMovingAverage { Length = BbPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(rsi, ma, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal rsiValue, decimal maValue)
{
if (candle.State != CandleStates.Finished) return;
if (_candlesSinceTrade < SignalCooldownCandles)
_candlesSinceTrade++;
var close = candle.ClosePrice;
var upper = maValue * (1 + BandPercent);
var lower = maValue * (1 - BandPercent);
// Mean reversion: buy at lower band, sell at upper band
if (close < lower && rsiValue < 35 && Position <= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
BuyMarket();
_candlesSinceTrade = 0;
}
else if (close > upper && rsiValue > 65 && Position >= 0 && _candlesSinceTrade >= SignalCooldownCandles)
{
SellMarket();
_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, SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class bollinger_rsi_ma_strategy(Strategy):
def __init__(self):
super(bollinger_rsi_ma_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30)))
self._rsi_period = self.Param("RsiPeriod", 14)
self._bb_period = self.Param("BbPeriod", 20)
self._band_percent = self.Param("BandPercent", 0.01)
self._signal_cooldown_candles = self.Param("SignalCooldownCandles", 6)
self._candles_since_trade = 6
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def RsiPeriod(self):
return self._rsi_period.Value
@RsiPeriod.setter
def RsiPeriod(self, value):
self._rsi_period.Value = value
@property
def BbPeriod(self):
return self._bb_period.Value
@BbPeriod.setter
def BbPeriod(self, value):
self._bb_period.Value = value
@property
def BandPercent(self):
return self._band_percent.Value
@BandPercent.setter
def BandPercent(self, value):
self._band_percent.Value = value
@property
def SignalCooldownCandles(self):
return self._signal_cooldown_candles.Value
@SignalCooldownCandles.setter
def SignalCooldownCandles(self, value):
self._signal_cooldown_candles.Value = value
def OnReseted(self):
super(bollinger_rsi_ma_strategy, self).OnReseted()
self._candles_since_trade = self.SignalCooldownCandles
def OnStarted2(self, time):
super(bollinger_rsi_ma_strategy, self).OnStarted2(time)
self._candles_since_trade = self.SignalCooldownCandles
rsi = RelativeStrengthIndex()
rsi.Length = self.RsiPeriod
ma = SimpleMovingAverage()
ma.Length = self.BbPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(rsi, ma, self._process_candle).Start()
def _process_candle(self, candle, rsi_value, ma_value):
if candle.State != CandleStates.Finished:
return
if self._candles_since_trade < self.SignalCooldownCandles:
self._candles_since_trade += 1
close = float(candle.ClosePrice)
rsi_val = float(rsi_value)
ma_val = float(ma_value)
upper = ma_val * (1.0 + self.BandPercent)
lower = ma_val * (1.0 - self.BandPercent)
if close < lower and rsi_val < 35 and self.Position <= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.BuyMarket()
self._candles_since_trade = 0
elif close > upper and rsi_val > 65 and self.Position >= 0 and self._candles_since_trade >= self.SignalCooldownCandles:
self.SellMarket()
self._candles_since_trade = 0
def CreateClone(self):
return bollinger_rsi_ma_strategy()