Ver no GitHub

Estratégia BandOsMa

Visão geral

A Estratégia BandOsMa converte o consultor especialista MetaTrader 5 "BandOsMA" em uma estratégia StockSharp. Ele avalia o histograma MACD (OsMA) usando Bollinger bandas construídas diretamente nos valores do histograma. Os rompimentos acima ou abaixo das bandas criam sinais de entrada, enquanto uma média móvel adicional do histograma gerencia as saídas de sinal.

A estratégia opera em um único símbolo e prazo selecionado pelo usuário. Os valores dos indicadores são calculados em velas finalizadas usando assinaturas de velas de alto nível de StockSharp.

Lógica de negociação

  1. Indicadores
    • MovingAverageConvergenceDivergenceSignal fornece o histograma MACD (OsMA).
    • BollingerBands é aplicado à sequência OsMA para detectar desvios extremos.
    • Uma média móvel configurável suaviza o histograma e atua como um filtro de saída.
  2. Entrada
    • Um sinal longo aparece quando o OsMA atual fecha abaixo da banda inferior enquanto a barra anterior permanece acima dela.
    • Um sinal curto aparece quando o OsMA atual fecha acima da banda superior enquanto a barra anterior permanece abaixo dela.
  3. Sair
    • Os sinais são apagados quando o histograma cruza a média móvel na direção oposta.
    • Quando uma posição aberta não corresponde mais ao sinal ativo, a posição é fechada imediatamente.
    • Um stop loss baseado em pip é anexado a cada posição. A parada também atua como uma parada móvel com a mesma distância e um passo final igual a StopLossPoints / 50 (espelhando a classe auxiliar MetaTrader).

Gerenciamento de posição

  • Stop Loss e Trailing: A distância de stop é expressa em MetaTrader pontos e convertida em unidades de preço usando o PriceStep do instrumento. A mesma distância é usada para o trailing stop, que avança quando o preço de fechamento melhora pelo menos um trailing step.
  • Uma posição por vez: Apenas uma posição líquida é mantida. Os sinais opostos fecham a posição atual antes de considerar uma nova entrada.

Parâmetros

Grupo Nome Descrição Padrão
Geral CandleType Prazo para assinatura de velas e cálculo de indicadores. H1
Risco LotSize Volume de negociação em lotes. 0.01
Risco StopLossPoints Distância de stop-loss expressa em MetaTrader pontos (também usada para trailing). 1000
Indicadores MacdFastPeriod Comprimento EMA rápido em MACD. 12
Indicadores MacdSlowPeriod Comprimento EMA lento em MACD. 26
Indicadores MacdSignalPeriod Comprimento do sinal EMA em MACD. 9
Indicadores PriceType Preço aplicado para entrada MACD (Close, Open, High, Low, Median, Typical, Weighted). Typical
Indicadores BollingerPeriod Período de Bollinger bandas na sequência OsMA. 26
Indicadores BollingerShift Shift aplicado a Bollinger buffers (não negativo). 0
Indicadores BollingerDeviation Multiplicador de desvio padrão para Bollinger bandas. 2
Indicadores MovingAveragePeriod Comprimento da média móvel aplicada ao OsMA. 10
Indicadores MovingAverageShift Shift aplicado ao buffer de média móvel (não negativo). 0
Indicadores MovingAverageMethod Tipo de média móvel (Simple, Exponential, Smoothed, LinearWeighted). Simple

Notas de implementação

  • O processamento de velas usa WhenCandlesFinished para garantir que apenas as barras finais conduzam a lógica.
  • Os valores dos indicadores são armazenados em buffers de histórico para emular mudanças de buffer no estilo MetaTrader. Mudanças negativas não são suportadas; use valores zero ou positivos como nos padrões originais do especialista.
  • As paradas finais dependem do fechamento de velas, em vez de atualizações passo a passo. Ajuste a distância do pip se for necessário um rastreamento preciso no nível do tick.

Uso

  1. Selecione o símbolo e o período desejados em StockSharp.
  2. Configure os parâmetros, especialmente CandleType, LotSize e períodos do indicador.
  3. Inicie a estratégia; ele assinará velas, calculará os indicadores e executará negociações de acordo com a lógica descrita.
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>
/// Strategy combining the MACD histogram (OsMA) with Bollinger Bands to trade reversals.
/// When OsMA crosses below lower Bollinger band, buy signal is generated.
/// When OsMA crosses above upper Bollinger band, sell signal is generated.
/// </summary>
public class BandOsMaStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _macdFastPeriod;
	private readonly StrategyParam<int> _macdSlowPeriod;
	private readonly StrategyParam<int> _macdSignalPeriod;
	private readonly StrategyParam<int> _bollingerPeriod;
	private readonly StrategyParam<decimal> _bollingerDeviation;

	private decimal _prevOsma;
	private decimal _prevUpper;
	private decimal _prevLower;
	private bool _hasPrev;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int MacdFastPeriod
	{
		get => _macdFastPeriod.Value;
		set => _macdFastPeriod.Value = value;
	}

	public int MacdSlowPeriod
	{
		get => _macdSlowPeriod.Value;
		set => _macdSlowPeriod.Value = value;
	}

	public int MacdSignalPeriod
	{
		get => _macdSignalPeriod.Value;
		set => _macdSignalPeriod.Value = value;
	}

	public int BollingerPeriod
	{
		get => _bollingerPeriod.Value;
		set => _bollingerPeriod.Value = value;
	}

	public decimal BollingerDeviation
	{
		get => _bollingerDeviation.Value;
		set => _bollingerDeviation.Value = value;
	}

	public BandOsMaStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
			.SetDisplay("Candle Type", "Primary timeframe", "General");

		_macdFastPeriod = Param(nameof(MacdFastPeriod), 20)
			.SetDisplay("MACD Fast", "Fast EMA length", "Indicators");

		_macdSlowPeriod = Param(nameof(MacdSlowPeriod), 50)
			.SetDisplay("MACD Slow", "Slow EMA length", "Indicators");

		_macdSignalPeriod = Param(nameof(MacdSignalPeriod), 12)
			.SetDisplay("MACD Signal", "Signal EMA length", "Indicators");

		_bollingerPeriod = Param(nameof(BollingerPeriod), 14)
			.SetDisplay("Bollinger Period", "OsMA Bollinger Bands period", "Indicators");

		_bollingerDeviation = Param(nameof(BollingerDeviation), 2m)
			.SetDisplay("Bollinger Deviation", "Bollinger Bands deviation", "Indicators");
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var macd = new MovingAverageConvergenceDivergenceSignal
		{
			Macd =
			{
				ShortMa = { Length = MacdFastPeriod },
				LongMa = { Length = MacdSlowPeriod }
			},
			SignalMa = { Length = MacdSignalPeriod }
		};

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(macd, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, macd);
			DrawOwnTrades(area);
		}
	}

	private BollingerBands _bollinger;

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		var val = (IMovingAverageConvergenceDivergenceSignalValue)macdValue;
		if (val.Macd is not decimal macdLine || val.Signal is not decimal signalLine)
			return;

		var osma = macdLine - signalLine;

		_bollinger ??= new BollingerBands
		{
			Length = BollingerPeriod,
			Width = BollingerDeviation
		};

		var bbResult = (BollingerBandsValue)_bollinger.Process(new DecimalIndicatorValue(_bollinger, osma, candle.CloseTime));
		if (bbResult.UpBand is not decimal upper || bbResult.LowBand is not decimal lower)
		{
			return;
		}

		if (_hasPrev)
		{
			// Buy: OsMA crosses below lower band (reversal up expected)
			if (_prevOsma > _prevLower && osma <= lower && Position <= 0)
			{
				BuyMarket(Position < 0 ? Math.Abs(Position) + 1 : 1);
			}
			// Sell: OsMA crosses above upper band (reversal down expected)
			else if (_prevOsma < _prevUpper && osma >= upper && Position >= 0)
			{
				SellMarket(Position > 0 ? Math.Abs(Position) + 1 : 1);
			}
		}

		_prevOsma = osma;
		_prevUpper = upper;
		_prevLower = lower;
		_hasPrev = true;
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		_prevOsma = 0;
		_prevUpper = 0;
		_prevLower = 0;
		_hasPrev = false;
		_bollinger = null;

		base.OnReseted();
	}
}