StockSharp porta do consultor especialista RUBBERBANDS 1.6 MetaTrader. O sistema original mantém um par protegido de bilhetes de compra e venda, reinjeta o lado fechado após cada lucro e ativa uma rede de segurança quando a perda corrente excede os limites de caixa predefinidos. A conversão mantém o ciclo alternado, mas adapta a mecânica ao modelo de posição líquida de StockSharp calculando a média na direção da exposição atual em vez de manter ordens de hedge independentes.
Lógica de negociação
Início do ciclo: No início de cada minuto, ou quando Enter Now é alternado, a estratégia abre uma posição de mercado usando BaseVolume. O próximo ciclo alterna a direção (comprar, depois vender, depois comprar novamente, etc.).
Meta de lucro base: o lucro líquido não realizado em execução é comparado com TargetProfitPerLot * BaseVolume. Quando alcançada, a posição é liquidada e o próximo ciclo muda de direção.
Controle de sessão:UseSessionTakeProfit e UseSessionStopLoss observam o lucro acumulado realizado mais o lucro não realizado medido em dinheiro por lote base. Atingir qualquer um dos limites aciona uma liquidação completa e zera os contadores.
Modo de segurança: Quando ativado e a perda não realizada exceder SafetyStartPerLot * BaseVolume, o algoritmo entra no modo de segurança e começa a calcular a média na direção atual enviando pedidos adicionais de tamanho SafetyVolume. Cada perda extra de SafetyStepPerLot por lote de segurança programa outra ordem média.
Saídas de segurança: Enquanto estiver no modo de segurança, a posição é achatada quando o ganho não realizado atinge SafetyProfitPerLot * |Position| ou quando a métrica do nível da sessão ultrapassa SafetyModeTakeProfitPerLot * BaseVolume.
Condições de Entrada
Entradas longas
Nenhuma exposição aberta e o minuto acabou de passar ou Enter Now é verdade.
A estratégia atualmente espera abrir uma posição longa (ciclos alternados).
O interruptor de parada manual está desativado.
Entradas curtas
Igual às condições longas, mas a direção do próximo ciclo é curta.
Gerenciamento de saída
Alvo base atingido: Feche toda a posição e inverta a direção do ciclo.
Sessão TP/SL: Feche a posição, limpe os contadores de lucro realizado e permaneça estável até o gatilho do próximo minuto.
Lucro de segurança: Feche a posição quando a meta de PnL líquido for atingida enquanto o modo de segurança estiver ativo.
Média de segurança: Ordens de segurança adicionais são anexadas quando a perda não realizada cresce em incrementos de SafetyStepPerLot.
Fechamento manual: A configuração Close Now fecha a posição na próxima vela e zera o acumulador de lucro realizado.
Parâmetros
Parâmetro
Descrição
BaseVolume
Tamanho da ordem de mercado para a etapa primária.
TargetProfitPerLot
Meta de lucro (dinheiro por lote) para o comércio base.
UseSessionTakeProfit / SessionTakeProfitPerLot
Habilite e configure o lucro em toda a sessão.
UseSessionStopLoss / SessionStopLossPerLot
Habilite e configure o stop loss em toda a sessão.
UseSafetyMode
Alterne a lógica de média de segurança.
SafetyStartPerLot
Perda por lote base que ativa o modo de segurança.
SafetyVolume
Volume de cada ordem de média de segurança.
SafetyStepPerLot
Perda adicional por lote de segurança necessária para enfileirar outra ordem de segurança.
SafetyProfitPerLot
Meta de lucro aplicada no modo de segurança.
SafetyModeTakeProfitPerLot
Meta de lucro no nível da sessão enquanto o modo de segurança está ativo.
Ajudantes de restauração de estado para reinicializações.
QuiesceNow, Enter Now, Stop Trading, Close Now
Chaves manuais que espelham as variáveis externas EA originais.
CandleType
Período de tempo da série de velas que aciona o loop (padrão 1 minuto).
Notas práticas
StockSharp mantém uma única posição líquida por instrumento. Em vez de manter bilhetes de compra e venda simultâneos, a conversão é calculada para a posição existente quando o modo de segurança está ativo. Isto preserva os limites baseados em dinheiro, ao mesmo tempo que está em conformidade com o modelo de compensação.
Os limites de lucros e perdas são expressos na moeda da conta por lote, refletindo as entradas externas MetaTrader. Ajuste-os para corresponder ao valor do tick do instrumento.
As opções manuais (Stop Trading, Close Now, Enter Now, Quiesce) podem ser alteradas instantaneamente na interface do usuário para controlar a estratégia sem editar o código.
StartProtection() é invocado no início para reutilizar a estrutura de proteção StockSharp padrão para controles de risco.
Certifique-se de que os metadados do instrumento (VolumeStep, VolumeMin, VolumeMax) estejam configurados para que os volumes solicitados passem na validação de troca; o auxiliar os alinha automaticamente com a etapa válida mais próxima.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Rubberbands Safety Net: Mean reversion with Bollinger-style bands.
/// Buys at lower band, sells at upper band with ATR stops.
/// </summary>
public class RubberbandsSafetyNetStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _smaLength;
private readonly StrategyParam<int> _atrLength;
private readonly StrategyParam<decimal> _bandMult;
private decimal _entryPrice;
public RubberbandsSafetyNetStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(8).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_smaLength = Param(nameof(SmaLength), 20)
.SetDisplay("SMA Length", "SMA center band period.", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period for bands and stops.", "Indicators");
_bandMult = Param(nameof(BandMult), 2.0m)
.SetDisplay("Band Mult", "ATR multiplier for bands.", "Signals");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int SmaLength
{
get => _smaLength.Value;
set => _smaLength.Value = value;
}
public int AtrLength
{
get => _atrLength.Value;
set => _atrLength.Value = value;
}
public decimal BandMult
{
get => _bandMult.Value;
set => _bandMult.Value = value;
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_entryPrice = 0;
var sma = new SimpleMovingAverage { Length = SmaLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(sma, atr, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal smaVal, decimal atrVal)
{
if (candle.State != CandleStates.Finished)
return;
if (atrVal <= 0)
return;
var close = candle.ClosePrice;
var upper = smaVal + atrVal * BandMult;
var lower = smaVal - atrVal * BandMult;
if (Position > 0)
{
if (close >= smaVal || close <= _entryPrice - atrVal * 3m)
{
SellMarket();
_entryPrice = 0;
}
}
else if (Position < 0)
{
if (close <= smaVal || close >= _entryPrice + atrVal * 3m)
{
BuyMarket();
_entryPrice = 0;
}
}
if (Position == 0)
{
if (close <= lower)
{
_entryPrice = close;
BuyMarket();
}
else if (close >= upper)
{
_entryPrice = close;
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.Strategies import Strategy
from StockSharp.Algo.Indicators import SimpleMovingAverage, AverageTrueRange
class rubberbands_safety_net_strategy(Strategy):
def __init__(self):
super(rubberbands_safety_net_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(8))) \
.SetDisplay("Candle Type", "Timeframe.", "General")
self._sma_length = self.Param("SmaLength", 20) \
.SetDisplay("SMA Length", "SMA center band period.", "Indicators")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period for bands and stops.", "Indicators")
self._band_mult = self.Param("BandMult", 2.0) \
.SetDisplay("Band Mult", "ATR multiplier for bands.", "Signals")
self._entry_price = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@property
def SmaLength(self):
return self._sma_length.Value
@property
def AtrLength(self):
return self._atr_length.Value
@property
def BandMult(self):
return self._band_mult.Value
def OnStarted2(self, time):
super(rubberbands_safety_net_strategy, self).OnStarted2(time)
self._entry_price = 0.0
self._sma = SimpleMovingAverage()
self._sma.Length = self.SmaLength
self._atr = AverageTrueRange()
self._atr.Length = self.AtrLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._sma, self._atr, self.ProcessCandle).Start()
def ProcessCandle(self, candle, sma_val, atr_val):
if candle.State != CandleStates.Finished:
return
sv = float(sma_val)
av = float(atr_val)
if av <= 0:
return
close = float(candle.ClosePrice)
bm = float(self.BandMult)
upper = sv + av * bm
lower = sv - av * bm
if self.Position > 0:
if close >= sv or close <= self._entry_price - av * 3.0:
self.SellMarket()
self._entry_price = 0.0
elif self.Position < 0:
if close <= sv or close >= self._entry_price + av * 3.0:
self.BuyMarket()
self._entry_price = 0.0
if self.Position == 0:
if close <= lower:
self._entry_price = close
self.BuyMarket()
elif close >= upper:
self._entry_price = close
self.SellMarket()
def OnReseted(self):
super(rubberbands_safety_net_strategy, self).OnReseted()
self._entry_price = 0.0
def CreateClone(self):
return rubberbands_safety_net_strategy()