Ver no GitHub

Estratégia Treine-se

Esta estratégia é uma versão StockSharp do consultor especialista MetaTrader 4 TrainYourself-V1_1-1. Ele recria a lógica de construção e breakout do canal enquanto substitui os botões gráficos do script MT4 por chamadas de método explícitas. O algoritmo reconstrói continuamente um canal de preços no estilo Donchian e dispara uma negociação assim que o preço escapa do canal após a primeira consolidação dentro dele.

Lógica de negociação

  1. Construção do canal

    • Um indicador DonchianChannels com períodos ChannelLength é avaliado em cada vela finalizada do CandleType selecionado.
    • As bandas superior e inferior brutas são expandidas com um buffer extra semelhante a MetaTrader: BufferPoints multiplicado pelo instrumento PriceStep. Isso reproduz o script original que inicialmente colocou as linhas de tendência a 50 pontos da oferta/venda atual antes de deslizá-las sobre máximos e mínimos recentes.
    • Os valores UpperBand/LowerBand resultantes são expostos como propriedades somente leitura para que possam ser exibidos em painéis personalizados.
  2. Condição de armamento

    • O mecanismo de breakout permanece desarmado enquanto uma posição está aberta ou quando EnableTrendTrade é falso.
    • Quando não há posição, o preço deve fechar dentro do canal com uma margem adicional de ActivationPoints * PriceStep de ambos os limites. Só então _isArmed se torna true, imitando o MetaTrader sinalizador q=1 que foi definido quando o preço voltou para o canal.
  3. Execução de breakout

    • Uma vez armado, um fechamento igual ou superior a UpperBand coloca uma ordem de compra de mercado (se AllowBuyOpen estiver ativado). Um fechamento igual ou inferior a LowerBand coloca uma ordem de venda a mercado (respeitando AllowSellOpen).
    • Depois que uma ordem é colocada, a estratégia se desarma até que o preço entre novamente no canal sem qualquer posição aberta.
  4. Gerenciamento de riscos

    • StartProtection configura ordens de proteção automáticas. As distâncias são calculadas multiplicando TakeProfitPoints e StopLossPoints pelo PriceStep atual. Se o corretor não relatar uma etapa, um substituto de 0.0001 será usado, correspondendo ao comportamento de MetaTrader Point.
  5. Controles manuais

    • Os rótulos MT4 (BUY_TRIANGLE, SELL_TRIANGLE, CLOSE_ORDER) são substituídos por três métodos públicos: TriggerManualBuy(), TriggerManualSell() e ClosePositionManually(). Eles respeitam AllowBuyOpen/AllowSellOpen, verificam o status da conexão via IsFormedAndOnlineAndAllowTrading() e também desarmam a lógica de breakout para que as negociações manuais não acionem imediatamente entradas automatizadas.

Parâmetros

Parâmetro Padrão Descrição
CandleType 30m período de tempo Assinatura de vela primária usada para todos os cálculos.
ChannelLength 20 Número de velas analisadas pelo canal Donchian.
BufferPoints 50 MetaTrader pontos extras adicionados no último fechamento antes de finalizar o canal.
ActivationPoints 2 Margem (em pontos) que o preço deve manter longe das bordas do canal antes que um rompimento possa ser armado.
StopLossPoints 100 Distância stop-loss em pontos; convertido em preço absoluto multiplicando por PriceStep.
TakeProfitPoints 100 Distância de take-profit em pontos; convertido em preço absoluto usando PriceStep.
EnableTrendTrade true Permite negociação de breakout automática. Quando false apenas os métodos auxiliares manuais podem abrir/fechar posições.
Volume 1 Tamanho do pedido para negociações automáticas e manuais.

Notas de uso

  • O consultor especialista original exigia arrastar ícones no gráfico para (re)construir linhas de tendência. Em StockSharp o canal é reconstruído automaticamente a cada vela, portanto nenhuma atualização manual é necessária.
  • Como a estratégia expõe UpperBand, LowerBand e IsArmed, os painéis ou widgets de IU podem replicar o feedback visual original sem depender de objetos gráficos.
  • Os níveis de stop-loss e take-profit são opcionais. Defina os parâmetros correspondentes como 0 para desativar as ordens de proteção, espelhando o comportamento MetaTrader onde as rotinas de modificação foram ignoradas quando o valor externo era zero.
  • As entradas manuais respeitam o mesmo parâmetro Volume e beneficiam automaticamente das distâncias de proteção configuradas.
  • Para redefinir o estado de rompimento manualmente, chame ClosePositionManually() (que também limpa IsArmed) ou espere que o preço entre novamente no canal para que a condição de armar seja satisfeita novamente.
using System;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

/// <summary>
/// TrainYourself: Donchian channel breakout strategy.
/// Uses Highest/Lowest as channel, arms after price is inside channel,
/// then trades breakouts.
/// </summary>
public class TrainYourselfStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _channelLength;
	private readonly StrategyParam<int> _atrLength;

	private decimal _prevHighest;
	private decimal _prevLowest;
	private bool _isArmed;
	private decimal _entryPrice;

	public TrainYourselfStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe.", "General");

		_channelLength = Param(nameof(ChannelLength), 20)
			.SetDisplay("Channel Length", "Highest/Lowest period.", "Channel");

		_atrLength = Param(nameof(AtrLength), 14)
			.SetDisplay("ATR Length", "ATR for stop distance.", "Indicators");
	}

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

	public int ChannelLength
	{
		get => _channelLength.Value;
		set => _channelLength.Value = value;
	}

	public int AtrLength
	{
		get => _atrLength.Value;
		set => _atrLength.Value = value;
	}

	/// <inheritdoc />
	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevHighest = 0;
		_prevLowest = 0;
		_isArmed = false;
		_entryPrice = 0;
	}

		protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_prevHighest = 0;
		_prevLowest = 0;
		_isArmed = false;
		_entryPrice = 0;

		var highest = new Highest { Length = ChannelLength };
		var lowest = new Lowest { Length = ChannelLength };
		var atr = new AverageTrueRange { Length = AtrLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(highest, lowest, atr, ProcessCandle)
			.Start();

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

	private void ProcessCandle(ICandleMessage candle, decimal highVal, decimal lowVal, decimal atrVal)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (_prevHighest == 0 || _prevLowest == 0 || atrVal <= 0)
		{
			_prevHighest = highVal;
			_prevLowest = lowVal;
			return;
		}

		var close = candle.ClosePrice;
		var upper = _prevHighest;
		var lower = _prevLowest;

		// Manage position: exit on channel re-entry
		if (Position > 0)
		{
			if (close < (upper + lower) / 2m)
			{
				SellMarket();
				_entryPrice = 0;
				_isArmed = false;
			}
		}
		else if (Position < 0)
		{
			if (close > (upper + lower) / 2m)
			{
				BuyMarket();
				_entryPrice = 0;
				_isArmed = false;
			}
		}

		// Arm when price is inside channel
		if (Position == 0)
		{
			if (!_isArmed)
			{
				var margin = atrVal * 0.2m;
				if (close > lower + margin && close < upper - margin)
					_isArmed = true;
			}
			else
			{
				// Breakout entry
				if (close > upper)
				{
					_entryPrice = close;
					BuyMarket();
					_isArmed = false;
				}
				else if (close < lower)
				{
					_entryPrice = close;
					SellMarket();
					_isArmed = false;
				}
			}
		}

		_prevHighest = highVal;
		_prevLowest = lowVal;
	}
}