Ver no GitHub

Estratégia BuySell

Esta estratégia emula o especialista BuySell do MetaTrader. Combina uma média móvel com o Average True Range (ATR) para detectar reversões de tendência. Quando a média móvel vira para cima, o sistema considera o mercado altista; quando vira para baixo, considera o mercado baixista. Uma operação é aberta apenas se a vela anterior estava no estado oposto, confirmando uma reversão. Os níveis opcionais de stop-loss e take-profit são expressos em pontos de preço.

Detalhes

  • Lógica de entrada
    • Comprado: a média móvel passa de descendente para ascendente e a vela anterior era baixista.
    • Vendido: a média móvel passa de ascendente para descendente e a vela anterior era altista.
  • Lógica de saída
    • Comprado: a média móvel vira para baixo ou o stop-loss / take-profit é acionado.
    • Vendido: a média móvel vira para cima ou o stop-loss / take-profit é acionado.
  • Indicadores: Média Móvel Simples (SMA) e ATR.
  • Stops: Stop-loss e take-profit em pontos.
  • Permissões: flags separadas permitem ou proíbem abrir/fechar posições compradas e vendidas.
  • Período padrão: velas de 4 horas.

Parâmetros

Nome Padrão Descrição
MaPeriod 14 Período da média móvel.
AtrPeriod 60 Período do ATR.
StopLoss 1000 Stop-loss em pontos de preço.
TakeProfit 2000 Take-profit em pontos de preço.
AllowLongEntry true Permissão para abrir posições compradas.
AllowShortEntry true Permissão para abrir posições vendidas.
AllowLongExit true Permissão para fechar posições compradas.
AllowShortExit true Permissão para fechar posições vendidas.
CandleType H4 Período utilizado para os cálculos.

Uso

  1. Adicione a estratégia à sua solução StockSharp.
  2. Configure os parâmetros conforme necessário.
  3. Execute a estratégia no modo ao vivo ou de backtesting. As operações são executadas usando ordens BuyMarket e SellMarket.

A abordagem é adequada para mercados onde as reversões de tendência são acompanhadas por mudanças de volatilidade capturadas pelo ATR.

using System;
using System.Collections.Generic;

using Ecng.Common;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Buy/Sell strategy based on EMA crossover.
/// </summary>
public class BuySellStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevFast;
	private decimal _prevSlow;
	private bool _hasPrev;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public BuySellStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast EMA period", "Indicator");
		_slowPeriod = Param(nameof(SlowPeriod), 28)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow EMA period", "Indicator");
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle type", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
		=> [(Security, CandleType)];

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFast = 0;
		_prevSlow = 0;
		_hasPrev = false;
	}

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

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };

		SubscribeCandles(CandleType)
			.Bind(fast, slow, ProcessCandle)
			.Start();
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal)
	{
		if (candle.State != CandleStates.Finished) return;

		if (!_hasPrev)
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			_hasPrev = true;
			return;
		}

		var crossUp = _prevFast <= _prevSlow && fastVal > slowVal;
		var crossDown = _prevFast >= _prevSlow && fastVal < slowVal;

		if (crossUp && Position <= 0)
		{
			if (Position < 0) BuyMarket();
			BuyMarket();
		}
		else if (crossDown && Position >= 0)
		{
			if (Position > 0) SellMarket();
			SellMarket();
		}

		_prevFast = fastVal;
		_prevSlow = slowVal;
	}
}