Auf GitHub ansehen

PSAR Trader Ticks Ticks

Strategy based on Parabolic SAR indicator. PSAR Trader Ticks follows the dots of the Parabolic SAR indicator and reacts when price crosses from one side to the other. It opens a long position when price moves above the SAR and a short position when price moves below it. Trading can be restricted to a specific time range, and existing positions can optionally be closed when an opposite signal appears. The strategy also applies take-profit and stop-loss levels measured in ticks.

Details

  • Entry Criteria: Price crossing the Parabolic SAR indicator.
  • Long/Short: Both directions.
  • Exit Criteria: Opposite signal (optional), stop-loss or take-profit.
  • Stops: Take-profit and stop-loss in ticks.
  • Default Values:
    • Step = 0.001m
    • Maximum = 0.2m
    • TakeProfitTicks = 50
    • StopLossTicks = 50
    • StartHour = 0
    • EndHour = 23
    • CloseOnOpposite = true
    • CandleType = TimeSpan.FromMinutes(5)
  • Filters:
    • Category: Trend
    • Direction: Both
    • Indicators: Parabolic SAR
    • Stops: Take-profit, Stop-loss
    • Complexity: Basic
    • Timeframe: Intraday (5m)
    • Seasonality: No
    • Neural Networks: No
    • Divergence: No
    • Risk Level: Medium
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>
/// PSAR Trader strategy - opens long when price crosses above SAR
/// and short when price crosses below SAR.
/// </summary>
public class PsarTraderTicksStrategy : Strategy
{
	private readonly StrategyParam<decimal> _step;
	private readonly StrategyParam<decimal> _maximum;
	private readonly StrategyParam<DataType> _candleType;

	private decimal _prevSar;
	private decimal _prevPrice;
	private bool _hasPrev;

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

	public PsarTraderTicksStrategy()
	{
		_step = Param(nameof(Step), 0.001m)
			.SetDisplay("SAR Step", "Acceleration factor step", "Indicators");
		_maximum = Param(nameof(Maximum), 0.2m)
			.SetDisplay("SAR Maximum", "Maximum acceleration factor", "Indicators");
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles to use", "General");
	}

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

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevSar = 0;
		_prevPrice = 0;
		_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 sarValue)
	{
		if (candle.State != CandleStates.Finished) return;

		if (!_hasPrev)
		{
			_prevSar = sarValue;
			_prevPrice = candle.ClosePrice;
			_hasPrev = true;
			return;
		}

		var prevAbove = _prevPrice > _prevSar;
		var currAbove = candle.ClosePrice > sarValue;

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

		_prevSar = sarValue;
		_prevPrice = candle.ClosePrice;
	}
}