Auf GitHub ansehen

EMA SAR Power Strategy

This intraday strategy combines fast and slow exponential moving averages with Parabolic SAR and Bulls/Bears Power indicators. It trades only during active market hours and requires sufficient free margin before entering any position.

The system goes short when the fast EMA is below the slow EMA, Parabolic SAR sits above the candle high, and Bears Power is rising while remaining negative. It goes long when the fast EMA is above the slow EMA, Parabolic SAR is below the candle low, and Bulls Power is falling but still positive. Each trade places a wide stop-loss and a closer take-profit.

Dynamic Margin Filter

Before trading, the strategy checks the portfolio's free margin. Depending on its value, the required minimum margin increases stepwise: 600 → 1000 → 1300 → 1500 → 1800 → 2000 → 2500. Trading is skipped whenever the free margin falls below the current threshold.

Details

  • Entry Criteria:
    • Short: EMA3 < EMA34 && SAR > High && BearsPower < 0 && BearsPower > BearsPower[1].
    • Long: EMA3 > EMA34 && SAR < Low && BullsPower > 0 && BullsPower < BullsPower[1].
  • Long/Short: Both sides.
  • Stop/Target: Stop-loss at 2000 points, take-profit at 400 points.
  • Time Filter: Trades only between 09:00 and 16:59 broker time.
  • Indicators:
    • Exponential Moving Averages (3, 34) on median price.
    • Parabolic SAR (0.02 step, 0.2 maximum).
    • Bulls Power (13) and Bears Power (13).
  • Default Volume: 30 contracts.
  • Timeframe: 15-minute candles.
  • Filters:
    • Category: Trend following
    • Direction: Both
    • Indicators: Multiple
    • Stops: Yes
    • Complexity: Moderate
    • Timeframe: Intraday
    • Seasonality: No
    • Neural networks: No
    • Divergence: No
    • Risk level: High
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>
/// EMA crossover strategy with Parabolic SAR confirmation.
/// Buys when fast EMA above slow EMA and SAR below price.
/// Sells when fast EMA below slow EMA and SAR above price.
/// </summary>
public class EmaSarPowerStrategy : Strategy
{
	private readonly StrategyParam<int> _fastLength;
	private readonly StrategyParam<int> _slowLength;
	private readonly StrategyParam<DataType> _candleType;

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

	public int FastLength { get => _fastLength.Value; set => _fastLength.Value = value; }
	public int SlowLength { get => _slowLength.Value; set => _slowLength.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public EmaSarPowerStrategy()
	{
		_fastLength = Param(nameof(FastLength), 3)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

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

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles", "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 fastEma = new ExponentialMovingAverage { Length = FastLength };
		var slowEma = new ExponentialMovingAverage { Length = SlowLength };
		var sar = new ParabolicSar();

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fastEma, slowEma, sar, 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, decimal sar)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!_hasPrev)
		{
			_prevFast = fast;
			_prevSlow = slow;
			_hasPrev = true;
			return;
		}

		// Buy: EMA crossover up + SAR below price
		if (_prevFast <= _prevSlow && fast > slow && sar < candle.LowPrice)
		{
			if (Position <= 0)
				BuyMarket();
		}
		// Sell: EMA crossover down + SAR above price
		else if (_prevFast >= _prevSlow && fast < slow && sar > candle.HighPrice)
		{
			if (Position >= 0)
				SellMarket();
		}

		_prevFast = fast;
		_prevSlow = slow;
	}
}