Ver no GitHub

Estratégia PSAR Trader v2

Visão geral

Esta estratégia opera reversões de mercado usando o indicador Parabolic SAR. Uma posição é aberta quando o valor do SAR muda de lado em relação ao preço, sinalizando uma possível mudança de tendência. O algoritmo opera apenas dentro de uma janela de tempo especificada e pode, opcionalmente, fechar uma posição existente quando um sinal oposto aparecer.

Lógica da estratégia

  • Indicador: Parabolic SAR.
  • Compra quando o SAR se move abaixo do fechamento da vela após ter estado acima da vela anterior.
  • Venda quando o SAR se move acima do fechamento da vela após ter estado abaixo da vela anterior.
  • Opera apenas no intervalo StartHourEndHour.
  • Quando CloseOnOppositeSignal está habilitado, uma posição é fechada se um sinal oposto ocorrer antes de abrir uma nova.

Gestão de risco

Ao entrar em uma posição, a estratégia define níveis internos de take-profit e stop-loss. A posição é fechada automaticamente se o preço tocar qualquer um dos níveis.

Parâmetros

Nome Descrição
CandleType Período das velas utilizadas para operar.
Step Passo de aceleração do Parabolic SAR.
Maximum Fator de aceleração máximo do Parabolic SAR.
TakeProfit Meta de lucro em unidades de preço.
StopLoss Stop loss em unidades de preço.
StartHour Hora de início das operações (0–23).
EndHour Hora de encerramento das operações (0–23).
CloseOnOppositeSignal Fechar a posição atual quando um sinal oposto aparecer.

Observações

Este exemplo demonstra o uso básico da API de alto nível com um popular indicador de reversão de tendência. Ajuste os parâmetros e a gestão de risco de acordo com o instrumento operado e as preferências pessoais.

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>
/// Parabolic SAR trader v2 with reversal logic.
/// </summary>
public class PsarTraderV2Strategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<decimal> _step;
	private readonly StrategyParam<decimal> _maximum;

	private decimal _prevSar;
	private bool _prevPriceAboveSar;
	private bool _hasPrev;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public decimal Step { get => _step.Value; set => _step.Value = value; }
	public decimal Maximum { get => _maximum.Value; set => _maximum.Value = value; }

	public PsarTraderV2Strategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Trading timeframe", "General");

		_step = Param(nameof(Step), 0.001m)
			.SetDisplay("PSAR Step", "Acceleration step for PSAR", "Indicators");

		_maximum = Param(nameof(Maximum), 0.2m)
			.SetDisplay("PSAR Maximum", "Maximum acceleration for PSAR", "Indicators");
	}

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

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevSar = 0;
		_prevPriceAboveSar = false;
		_hasPrev = false;
	}

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

		var psar = new ParabolicSar
		{
			AccelerationStep = Step,
			AccelerationMax = Maximum
		};

		SubscribeCandles(CandleType).Bind(psar, ProcessCandle).Start();
	}

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

		var priceAboveSar = candle.ClosePrice > sar;

		if (!_hasPrev)
		{
			_prevSar = sar;
			_prevPriceAboveSar = priceAboveSar;
			_hasPrev = true;
			return;
		}

		if (priceAboveSar != _prevPriceAboveSar)
		{
			if (priceAboveSar && Position <= 0)
			{
				if (Position < 0) BuyMarket();
				BuyMarket();
			}
			else if (!priceAboveSar && Position >= 0)
			{
				if (Position > 0) SellMarket();
				SellMarket();
			}
		}

		_prevSar = sar;
		_prevPriceAboveSar = priceAboveSar;
	}
}