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].
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;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage, ParabolicSar
from StockSharp.Algo.Strategies import Strategy
class ema_sar_power_strategy(Strategy):
def __init__(self):
super(ema_sar_power_strategy, self).__init__()
self._fast_length = self.Param("FastLength", 3) \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_length = self.Param("SlowLength", 34) \
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
@property
def fast_length(self):
return self._fast_length.Value
@property
def slow_length(self):
return self._slow_length.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(ema_sar_power_strategy, self).OnReseted()
self._prev_fast = 0.0
self._prev_slow = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(ema_sar_power_strategy, self).OnStarted2(time)
fast_ema = ExponentialMovingAverage()
fast_ema.Length = self.fast_length
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self.slow_length
sar = ParabolicSar()
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast_ema, slow_ema, sar, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast_ema)
self.DrawIndicator(area, slow_ema)
self.DrawOwnTrades(area)
def on_process(self, candle, fast, slow, sar):
if candle.State != CandleStates.Finished:
return
if not self._has_prev:
self._prev_fast = fast
self._prev_slow = slow
self._has_prev = True
return
# Buy: EMA crossover up + SAR below price
if self._prev_fast <= self._prev_slow and fast > slow and sar < candle.LowPrice:
if self.Position <= 0:
self.BuyMarket()
# Sell: EMA crossover down + SAR above price
elif self._prev_fast >= self._prev_slow and fast < slow and sar > candle.HighPrice:
if self.Position >= 0:
self.SellMarket()
self._prev_fast = fast
self._prev_slow = slow
def CreateClone(self):
return ema_sar_power_strategy()