Ver no GitHub

Estratégia SpectrAnalysis WPR

Esta estratégia foi convertida a partir do expert MQL5 Exp_i-SpectrAnalysis_WPR. Ela analisa a direção do indicador Williams %R e abre ou fecha posições de acordo com as viradas do indicador.

Lógica

  1. Subscrever às velas do período selecionado.
  2. Calcular Williams %R com o período configurado.
  3. Manter os últimos dois valores do indicador para detectar a direção ascendente ou descendente.
  4. Quando o indicador vira para cima e entradas compradas são permitidas:
    • Fechar posições vendidas se habilitado.
    • Abrir uma nova posição comprada.
  5. Quando o indicador vira para baixo e entradas vendidas são permitidas:
    • Fechar posições compradas se habilitado.
    • Abrir uma nova posição vendida.

Apenas velas concluídas são processadas. A estratégia não utiliza consultas históricas complexas e depende de ligações de API de alto nível.

Parâmetros

Nome Descrição Padrão
Candle Type Período das velas usadas para cálculos 4h
WPR Period Período do indicador Williams %R 13
Allow Long Entry Permitir abrir posições compradas true
Allow Short Entry Permitir abrir posições vendidas true
Allow Long Exit Permitir fechar posições compradas true
Allow Short Exit Permitir fechar posições vendidas true

Notas

A versão MQL original aplicava análise espectral à saída do Williams %R. Esta conversão em C# usa o indicador Williams %R padrão e replica a lógica de sinais rastreando os valores recentes do indicador.

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>
/// Strategy based on Williams %R trend direction.
/// </summary>
public class SpectrAnalysisWprStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _wprPeriod;
	private readonly StrategyParam<bool> _buyPosOpen;
	private readonly StrategyParam<bool> _sellPosOpen;
	private readonly StrategyParam<bool> _buyPosClose;
	private readonly StrategyParam<bool> _sellPosClose;

	private decimal? _prev;
	private decimal? _prev2;

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

	/// <summary>
	/// Williams %R period.
	/// </summary>
	public int WprPeriod
	{
		get => _wprPeriod.Value;
		set => _wprPeriod.Value = value;
	}

	/// <summary>
	/// Allow opening long positions.
	/// </summary>
	public bool BuyPosOpen
	{
		get => _buyPosOpen.Value;
		set => _buyPosOpen.Value = value;
	}

	/// <summary>
	/// Allow opening short positions.
	/// </summary>
	public bool SellPosOpen
	{
		get => _sellPosOpen.Value;
		set => _sellPosOpen.Value = value;
	}

	/// <summary>
	/// Allow closing long positions.
	/// </summary>
	public bool BuyPosClose
	{
		get => _buyPosClose.Value;
		set => _buyPosClose.Value = value;
	}

	/// <summary>
	/// Allow closing short positions.
	/// </summary>
	public bool SellPosClose
	{
		get => _sellPosClose.Value;
		set => _sellPosClose.Value = value;
	}

	/// <summary>
	/// Initializes a new instance of the strategy.
	/// </summary>
	public SpectrAnalysisWprStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Timeframe for indicator", "General");
		_wprPeriod = Param(nameof(WprPeriod), 13)
			.SetGreaterThanZero()
			.SetDisplay("WPR Period", "Williams %R period", "Indicator");
		_buyPosOpen = Param(nameof(BuyPosOpen), true)
			.SetDisplay("Allow Long Entry", "Enable long position opening", "Trading");
		_sellPosOpen = Param(nameof(SellPosOpen), true)
			.SetDisplay("Allow Short Entry", "Enable short position opening", "Trading");
		_buyPosClose = Param(nameof(BuyPosClose), true)
			.SetDisplay("Allow Long Exit", "Enable closing of long positions", "Trading");
		_sellPosClose = Param(nameof(SellPosClose), true)
			.SetDisplay("Allow Short Exit", "Enable closing of short positions", "Trading");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prev = null;
		_prev2 = null;
	}

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

		_prev = null;
		_prev2 = null;

		var wpr = new WilliamsR { Length = WprPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(wpr, ProcessCandle).Start();

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

	private void ProcessCandle(ICandleMessage candle, decimal wprValue)
	{
		if (candle.State != CandleStates.Finished || !IsFormedAndOnlineAndAllowTrading())
			return;

		if (_prev is null || _prev2 is null)
		{
			_prev2 = _prev;
			_prev = wprValue;
			return;
		}

		// Upward direction detected (WPR was falling, now turning up)
		if (_prev < _prev2 && wprValue >= _prev)
		{
			if (BuyPosOpen && Position <= 0)
				BuyMarket(Position < 0 ? Volume + Math.Abs(Position) : Volume);
			else if (SellPosClose && Position < 0)
				BuyMarket(Math.Abs(Position));
		}
		// Downward direction detected (WPR was rising, now turning down)
		else if (_prev > _prev2 && wprValue <= _prev)
		{
			if (SellPosOpen && Position >= 0)
				SellMarket(Position > 0 ? Volume + Position : Volume);
			else if (BuyPosClose && Position > 0)
				SellMarket(Position);
		}

		_prev2 = _prev;
		_prev = wprValue;
	}
}