Ver no GitHub

Estratégia PA Oscilador

Esta estratégia é uma portagem do especialista MQL5 Exp_PA_Oscillator.mq5. Aplica duas médias móveis exponenciais (EMAs) aos preços de fechamento das velas e analisa a derivada de sua diferença.

Lógica

  1. Calcular EMAs rápida e lenta.
  2. Calcular a diferença entre elas e rastrear sua mudança em relação ao valor anterior.
  3. Determinar um código de cor para a derivada:
    • 0 – a derivada é positiva e o MACD está subindo.
    • 1 – a derivada é zero.
    • 2 – a derivada é negativa e o MACD está caindo.
  4. Usar as cores das duas últimas velas concluídas para gerar sinais:
    • Duas barras atrás a cor era 0 e a barra anterior mudou de 0 → abrir posição comprada e fechar posição vendida.
    • Duas barras atrás a cor era 2 e a barra anterior mudou de 2 → abrir posição vendida e fechar posição comprada.

Parâmetros

Nome Descrição
FastLength Comprimento do EMA rápido.
SlowLength Comprimento do EMA lento.
BuyPosOpen Habilitar abertura de posições compradas.
SellPosOpen Habilitar abertura de posições vendidas.
BuyPosClose Habilitar fechamento de posições compradas.
SellPosClose Habilitar fechamento de posições vendidas.
CandleType Período de velas utilizado para os cálculos.

Notas

  • Apenas velas concluídas são processadas.
  • Ordens a mercado são usadas para entradas e saídas.
  • Esta implementação foca na clareza e fins educacionais, não na rentabilidade.
using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Strategy based on the PA Oscillator indicator.
/// It trades when the derivative of the difference between fast and slow EMAs changes sign.
/// </summary>
public class PaOscillatorStrategy : Strategy
{
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<DataType> _candleType;

	private decimal? _prevMacd;
	private int? _prevColor;
	private int? _prevPrevColor;

	/// <summary>
	/// Length of the fast EMA.
	/// </summary>
	public int FastLength
	{
		get => _fastLength.Value;
		set => _fastLength.Value = value;
	}

	/// <summary>
	/// Length of the slow EMA.
	/// </summary>
	public int SlowLength
	{
		get => _slowLength.Value;
		set => _slowLength.Value = value;
	}

	/// <summary>
	/// Candle type for calculations.
	/// </summary>
	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	/// <summary>
	/// Initializes a new instance of the strategy.
	/// </summary>
	public PaOscillatorStrategy()
	{
		_fastLength = Param(nameof(FastLength), 12)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA Length", "Fast EMA period", "Indicators");

		_slowLength = Param(nameof(SlowLength), 26)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA Length", "Slow EMA period", "Indicators");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for strategy", "General");
	}

	/// <inheritdoc />
	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevMacd = null;
		_prevColor = null;
		_prevPrevColor = null;
	}

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

		var fastEma = new ExponentialMovingAverage { Length = FastLength };
		var slowEma = new ExponentialMovingAverage { Length = SlowLength };

		var subscription = SubscribeCandles(CandleType);

		subscription
			.Bind(fastEma, slowEma, ProcessCandle)
			.Start();

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

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

		var macd = fast - slow;

		if (_prevMacd is null)
		{
			_prevMacd = macd;
			_prevColor = 1;
			_prevPrevColor = 1;
			return;
		}

		var osc = macd - _prevMacd.Value;
		var color = osc > 0 ? 0 : osc < 0 ? 2 : 1;

		if (_prevPrevColor == 0 && _prevColor > 0)
		{
			if (Position < 0)
				BuyMarket();
			if (Position <= 0)
				BuyMarket();
		}
		else if (_prevPrevColor == 2 && _prevColor < 2)
		{
			if (Position > 0)
				SellMarket();
			if (Position >= 0)
				SellMarket();
		}

		_prevMacd = macd;
		_prevPrevColor = _prevColor;
		_prevColor = color;
	}
}