Esta estratégia é um port StockSharp do consultor especialista MetaTrader Exp_XPeriodCandleSystem_Tm_Plus. O robô original baseia-se no indicador personalizado XPeriod Candle System, que suaviza dados de candles e colore as barras de acordo com rompimentos das Bandas de Bollinger. A versão traduzida reproduz este comportamento aplicando suavização exponencial às séries OHLC, mapeando os mesmos modos de preço aplicado e conduzindo operações a partir dos estados de cor resultantes. Uma saída baseada em tempo e ordens de proteção configuráveis complementam a lógica de rompimento.
Lógica de negociação
Candles suavizados – Médias móveis exponenciais com comprimento configurável constroem valores sintéticos de abertura, máxima, mínima e fechamento que aproximam o indicador fonte.
Preço aplicado – O usuário pode selecionar qualquer uma das doze fórmulas de preço (fechamento, abertura, mediana, variações de seguidor de tendência, Demark, etc.) antes de alimentar os dados nas Bandas de Bollinger.
Análise de bandas – Um indicador de Bandas de Bollinger (comprimento e desvio configuráveis) processa a série de preços suavizados. Bandas finalizadas são necessárias antes que os sinais sejam avaliados.
Estados de cor –
Barra altista acima da banda superior → cor 0 (rompimento para cima).
Barra baixista abaixo da banda inferior → cor 4 (rompimento para baixo).
Outras barras altistas → cor 1; outras barras baixistas → cor 3.
Um deslocamento de rompimento configurável (convertido para unidades de preço usando o tamanho de tick do símbolo quando possível) evita falsos gatilhos.
Entradas – A estratégia analisa a vela definida por SignalBar e sua predecessora:
Abrir comprado quando a barra anterior foi um rompimento altista (0) e a barra de sinal não é.
Abrir vendido quando a barra anterior foi um rompimento baixista (4) e a barra de sinal não é.
Saídas –
Fechar comprados quando a barra de referência é baixista (> 2).
Fechar vendidos quando a barra de referência é altista (< 2).
Um temporizador de manutenção opcional (TimeTrade e HoldingMinutes) fecha posições após os minutos especificados.
Risco – StartProtection implanta distâncias absolutas opcionais de take-profit e stop-loss para cada operação.
Parâmetros
Parâmetro
Descrição
Valor padrão
OrderVolume
Tamanho base de ordem utilizado para entradas de mercado.
0.1
BuyPosOpen / SellPosOpen
Habilitar/desabilitar entradas compradas ou vendidas.
true
BuyPosClose / SellPosClose
Permitir saídas de posições compradas ou vendidas.
true
TimeTrade
Ativa o filtro de saída baseado em tempo.
true
HoldingMinutes
Tempo máximo de manutenção antes que o filtro de tempo feche uma posição.
960
CandleType
Tipo de dados de candle (período) solicitado do mercado.
4 horas
Period
Comprimento das médias móveis exponenciais de suavização.
5
BollingerLength
Número de barras suavizadas dentro da janela de cálculo de Bollinger.
20
BandsDeviation
Multiplicador da largura de banda.
1.001
AppliedPriceMode
Transformação de preço usada antes do indicador Bollinger (fechamento, abertura, mediana, seguidor de tendência, Demark, etc.).
Close
SignalBar
Índice da barra usada para avaliação de sinais (1 = última barra fechada).
1
StopLoss / TakeProfit
Distâncias absolutas (em unidades de preço) usadas pelo motor de proteção.
1000 / 2000
Deviation
Deslocamento de rompimento extra adicionado acima/abaixo das Bandas de Bollinger.
10
Notas de uso
O passo de suavização usa médias móveis exponenciais para replicar o cálculo proprietário do XPeriod. Períodos menores mantêm os candles sintéticos mais próximos dos preços de mercado, enquanto períodos maiores enfatizam a estrutura de tendência.
SignalBar deve permanecer dentro do histórico armazenado (até 14 posições após a barra atual). Valores maiores que o histórico disponível ignorarão automaticamente o trading.
O deslocamento de rompimento é multiplicado por PriceStep quando o ativo expõe um tamanho de tick. Isso mantém o comportamento similar à versão MetaTrader onde Deviation é definido em pontos.
StopLoss e TakeProfit são especificados em unidades absolutas de preço. Defina-os como zero para desabilitar as ordens de proteção mantendo a infraestrutura de gestão ativa.
Nenhuma tradução Python foi fornecida ainda; esta pasta contém apenas a implementação em C#.
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// XPeriod candle system with Bollinger Bands breakout.
/// Buys on close above upper band with bullish candle, sells on close below lower band with bearish candle.
/// </summary>
public class XPeriodCandleSystemTmPlusStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _bbPeriod;
private readonly StrategyParam<decimal> _bbWidth;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int BbPeriod
{
get => _bbPeriod.Value;
set => _bbPeriod.Value = value;
}
public decimal BbWidth
{
get => _bbWidth.Value;
set => _bbWidth.Value = value;
}
public XPeriodCandleSystemTmPlusStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_bbPeriod = Param(nameof(BbPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("BB Period", "Bollinger Bands period", "Indicators");
_bbWidth = Param(nameof(BbWidth), 2m)
.SetGreaterThanZero()
.SetDisplay("BB Width", "Bollinger Bands width", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var bb = new BollingerBands { Length = BbPeriod, Width = BbWidth };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(bb, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, bb);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue value)
{
if (candle.State != CandleStates.Finished)
return;
var bb = (BollingerBandsValue)value;
if (bb.UpBand is not decimal upper ||
bb.LowBand is not decimal lower ||
bb.MovingAverage is not decimal middle)
return;
var close = candle.ClosePrice;
var isBullish = candle.ClosePrice > candle.OpenPrice;
var isBearish = candle.ClosePrice < candle.OpenPrice;
// Buy: close above upper band with bullish candle
if (close > upper && isBullish && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// Sell: close below lower band with bearish candle
else if (close < lower && isBearish && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
// Exit long at middle band
else if (Position > 0 && close < middle)
{
SellMarket();
}
// Exit short at middle band
else if (Position < 0 && close > middle)
{
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 StockSharp.Algo.Indicators import BollingerBands
from StockSharp.Algo.Strategies import Strategy
class x_period_candle_system_tm_plus_strategy(Strategy):
def __init__(self):
super(x_period_candle_system_tm_plus_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._bb_period = self.Param("BbPeriod", 20) \
.SetDisplay("BB Period", "Bollinger Bands period", "Indicators")
self._bb_width = self.Param("BbWidth", 2.0) \
.SetDisplay("BB Width", "Bollinger Bands width", "Indicators")
@property
def CandleType(self):
return self._candle_type.Value
@property
def BbPeriod(self):
return self._bb_period.Value
@property
def BbWidth(self):
return self._bb_width.Value
def OnStarted2(self, time):
super(x_period_candle_system_tm_plus_strategy, self).OnStarted2(time)
bb = BollingerBands()
bb.Length = self.BbPeriod
bb.Width = self.BbWidth
subscription = self.SubscribeCandles(self.CandleType)
subscription.BindEx(bb, 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, bb_value):
if candle.State != CandleStates.Finished:
return
upper = bb_value.UpBand
lower = bb_value.LowBand
middle = bb_value.MovingAverage
if upper is None or lower is None or middle is None:
return
upper = float(upper)
lower = float(lower)
middle = float(middle)
close = float(candle.ClosePrice)
is_bullish = float(candle.ClosePrice) > float(candle.OpenPrice)
is_bearish = float(candle.ClosePrice) < float(candle.OpenPrice)
# Buy: close above upper band with bullish candle
if close > upper and is_bullish and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
# Sell: close below lower band with bearish candle
elif close < lower and is_bearish and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
# Exit long at middle band
elif self.Position > 0 and close < middle:
self.SellMarket()
# Exit short at middle band
elif self.Position < 0 and close > middle:
self.BuyMarket()
def CreateClone(self):
return x_period_candle_system_tm_plus_strategy()