Nifty 50 5mint Strategy
The Nifty 50 5mint Strategy trades breakouts on the Nifty 50 index using DEMA, VWAP and Bollinger Bands confirmation.
Details
- Entry Criteria:
- Long: close above previous high, close above upper Bollinger band and DEMA above VWAP.
- Short: close below previous low, close below lower Bollinger band and DEMA below VWAP.
- Long/Short: both.
- Exit Criteria: stop-loss.
- Stops: yes, fixed points.
- Default Values:
DemaPeriod = 6BollingerLength = 20BollingerStdDev = 2LookbackPeriod = 5StopLossPoints = 25CandleType = TimeSpan.FromMinutes(5).TimeFrame()
- Filters:
- Category: Breakout
- Direction: Both
- Indicators: DEMA, VWAP, Bollinger Bands
- Stops: Yes
- 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>
/// Nifty 50 5-minute breakout strategy.
/// A long opens when the close breaks above the highest high of the previous LookbackPeriod candles and above the upper Bollinger band
/// while DEMA is above the session VWAP; a short uses the lowest low, the lower band and DEMA below VWAP. An opposite signal reverses
/// the position, and a fixed stop of StopLossPoints price steps closes it otherwise.
/// </summary>
public class Nifty505mintStrategy : Strategy
{
private readonly StrategyParam<int> _demaPeriod;
private readonly StrategyParam<int> _bollingerLength;
private readonly StrategyParam<decimal> _bollingerStdDev;
private readonly StrategyParam<int> _lookbackPeriod;
private readonly StrategyParam<decimal> _stopLossPoints;
private readonly StrategyParam<DataType> _candleType;
private Highest _highest;
private Lowest _lowest;
private decimal? _prevHighest;
private decimal? _prevLowest;
private DateTime _vwapDate;
private decimal _vwapPriceVolume;
private decimal _vwapVolume;
/// <summary>
/// DEMA period.
/// </summary>
public int DemaPeriod
{
get => _demaPeriod.Value;
set => _demaPeriod.Value = value;
}
/// <summary>
/// Bollinger Bands period.
/// </summary>
public int BollingerLength
{
get => _bollingerLength.Value;
set => _bollingerLength.Value = value;
}
/// <summary>
/// Bollinger Bands standard deviation multiplier.
/// </summary>
public decimal BollingerStdDev
{
get => _bollingerStdDev.Value;
set => _bollingerStdDev.Value = value;
}
/// <summary>
/// Previous candles whose high or low has to be broken.
/// </summary>
public int LookbackPeriod
{
get => _lookbackPeriod.Value;
set => _lookbackPeriod.Value = value;
}
/// <summary>
/// Stop loss distance in price steps.
/// </summary>
public decimal StopLossPoints
{
get => _stopLossPoints.Value;
set => _stopLossPoints.Value = value;
}
/// <summary>
/// Candle type.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Constructor.
/// </summary>
public Nifty505mintStrategy()
{
_demaPeriod = Param(nameof(DemaPeriod), 6)
.SetGreaterThanZero()
.SetDisplay("DEMA Period", "DEMA period", "Indicators");
_bollingerLength = Param(nameof(BollingerLength), 20)
.SetGreaterThanZero()
.SetDisplay("Bollinger Length", "Bollinger Bands period", "Indicators");
_bollingerStdDev = Param(nameof(BollingerStdDev), 2m)
.SetGreaterThanZero()
.SetDisplay("Bollinger StdDev", "Bollinger Bands standard deviation multiplier", "Indicators");
_lookbackPeriod = Param(nameof(LookbackPeriod), 5)
.SetGreaterThanZero()
.SetDisplay("Lookback Period", "Previous candles whose high or low has to be broken", "Signals");
_stopLossPoints = Param(nameof(StopLossPoints), 25m)
.SetNotNegative()
.SetDisplay("Stop Loss Points", "Stop loss distance in price steps", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
ResetState();
}
private void ResetState()
{
_highest = null;
_lowest = null;
_prevHighest = null;
_prevLowest = null;
_vwapDate = default;
_vwapPriceVolume = 0m;
_vwapVolume = 0m;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
ResetState();
_highest = new Highest { Length = LookbackPeriod };
_lowest = new Lowest { Length = LookbackPeriod };
var dema = new DoubleExponentialMovingAverage { Length = DemaPeriod };
var bollinger = new BollingerBands { Length = BollingerLength, Width = BollingerStdDev };
var subscription = SubscribeCandles(CandleType);
subscription
.BindEx(dema, bollinger, ProcessCandle)
.Start();
var step = Security?.PriceStep ?? 1m;
StartProtection(new Unit(), StopLossPoints > 0 ? new Unit(StopLossPoints * step, UnitTypes.Absolute) : new Unit(), useMarketOrders: true);
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, dema);
DrawIndicator(area, bollinger);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, IIndicatorValue demaValue, IIndicatorValue bollingerValue)
{
if (candle.State != CandleStates.Finished)
return;
// Session VWAP restarts every UTC day.
var date = candle.OpenTime.Date;
if (date != _vwapDate)
{
_vwapDate = date;
_vwapPriceVolume = 0m;
_vwapVolume = 0m;
}
var typical = (candle.HighPrice + candle.LowPrice + candle.ClosePrice) / 3m;
_vwapPriceVolume += typical * candle.TotalVolume;
_vwapVolume += candle.TotalVolume;
// The breakout levels are measured on the candles before this one.
var prevHighest = _prevHighest;
var prevLowest = _prevLowest;
var highestValue = _highest.Process(candle.HighPrice, candle.ServerTime, true);
var lowestValue = _lowest.Process(candle.LowPrice, candle.ServerTime, true);
if (_highest.IsFormed && _lowest.IsFormed)
{
_prevHighest = highestValue.ToDecimal();
_prevLowest = lowestValue.ToDecimal();
}
if (!demaValue.IsFormed || !bollingerValue.IsFormed || prevHighest is not decimal lastHigh || prevLowest is not decimal lastLow)
return;
if (bollingerValue is not IBollingerBandsValue { UpBand: decimal upper, LowBand: decimal lower })
return;
if (!IsFormedAndOnlineAndAllowTrading() || _vwapVolume <= 0)
return;
var close = candle.ClosePrice;
var dema = demaValue.GetValue<decimal>();
var vwap = _vwapPriceVolume / _vwapVolume;
if (close > lastHigh && close > upper && dema > vwap && Position <= 0)
BuyMarket(Volume + Math.Abs(Position));
else if (close < lastLow && close < lower && dema < vwap && Position >= 0)
SellMarket(Volume + Math.Abs(Position));
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Decimal
from StockSharp.Messages import DataType, CandleStates, Unit, UnitTypes
from StockSharp.Algo.Indicators import DoubleExponentialMovingAverage, BollingerBands, Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
from indicator_extensions import *
class nifty_50_5mint_strategy(Strategy):
"""
Nifty 50 5-minute breakout strategy.
A long opens when the close breaks above the highest high of the previous LookbackPeriod candles and above the upper Bollinger band
while DEMA is above the session VWAP; a short uses the lowest low, the lower band and DEMA below VWAP. An opposite signal reverses
the position, and a fixed stop of StopLossPoints price steps closes it otherwise.
"""
def __init__(self):
super(nifty_50_5mint_strategy, self).__init__()
self._dema_period = self.Param("DemaPeriod", 6).SetGreaterThanZero().SetDisplay("DEMA Period", "DEMA period", "Indicators")
self._bollinger_length = self.Param("BollingerLength", 20).SetGreaterThanZero().SetDisplay("Bollinger Length", "Bollinger Bands period", "Indicators")
self._bollinger_std_dev = self.Param("BollingerStdDev", 2.0).SetGreaterThanZero().SetDisplay("Bollinger StdDev", "Bollinger Bands standard deviation multiplier", "Indicators")
self._lookback_period = self.Param("LookbackPeriod", 5).SetGreaterThanZero().SetDisplay("Lookback Period", "Previous candles whose high or low has to be broken", "Signals")
self._stop_loss_points = self.Param("StopLossPoints", 25.0).SetNotNegative().SetDisplay("Stop Loss Points", "Stop loss distance in price steps", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Type of candles to use", "General")
self._reset_state()
@property
def candle_type(self):
return self._candle_type.Value
def _reset_state(self):
self._highest = None
self._lowest = None
self._prev_highest = None
self._prev_lowest = None
self._vwap_date = None
self._vwap_price_volume = 0.0
self._vwap_volume = 0.0
def OnReseted(self):
super(nifty_50_5mint_strategy, self).OnReseted()
self._reset_state()
def OnStarted2(self, time):
super(nifty_50_5mint_strategy, self).OnStarted2(time)
self._reset_state()
self._highest = Highest()
self._highest.Length = self._lookback_period.Value
self._lowest = Lowest()
self._lowest.Length = self._lookback_period.Value
dema = DoubleExponentialMovingAverage()
dema.Length = self._dema_period.Value
bollinger = BollingerBands()
bollinger.Length = self._bollinger_length.Value
bollinger.Width = Decimal(self._bollinger_std_dev.Value)
subscription = self.SubscribeCandles(self.candle_type)
subscription.BindEx(dema, bollinger, self._process_candle).Start()
step = self.Security.PriceStep if self.Security is not None and self.Security.PriceStep is not None else Decimal(1)
stop_points = float(self._stop_loss_points.Value)
stop = Unit(Decimal(stop_points) * step, UnitTypes.Absolute) if stop_points > 0 else Unit()
self.StartProtection(Unit(), stop, useMarketOrders=True)
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, dema)
self.DrawIndicator(area, bollinger)
self.DrawOwnTrades(area)
def _process_candle(self, candle, dema_value, bollinger_value):
if candle.State != CandleStates.Finished:
return
# Session VWAP restarts every UTC day.
date = candle.OpenTime.Date
if self._vwap_date is None or date != self._vwap_date:
self._vwap_date = date
self._vwap_price_volume = 0.0
self._vwap_volume = 0.0
volume = float(candle.TotalVolume)
typical = (float(candle.HighPrice) + float(candle.LowPrice) + float(candle.ClosePrice)) / 3.0
self._vwap_price_volume += typical * volume
self._vwap_volume += volume
# The breakout levels are measured on the candles before this one.
last_high = self._prev_highest
last_low = self._prev_lowest
highest_value = process_value(self._highest, candle.HighPrice, candle.ServerTime, True)
lowest_value = process_value(self._lowest, candle.LowPrice, candle.ServerTime, True)
if self._highest.IsFormed and self._lowest.IsFormed:
self._prev_highest = float(to_decimal(highest_value))
self._prev_lowest = float(to_decimal(lowest_value))
if not dema_value.IsFormed or not bollinger_value.IsFormed or last_high is None or last_low is None:
return
if bollinger_value.UpBand is None or bollinger_value.LowBand is None:
return
if not self.IsFormedAndOnlineAndAllowTrading() or self._vwap_volume <= 0:
return
close = float(candle.ClosePrice)
upper = float(bollinger_value.UpBand)
lower = float(bollinger_value.LowBand)
dema = float(dema_value.GetValue[Decimal](None))
vwap = self._vwap_price_volume / self._vwap_volume
if close > last_high and close > upper and dema > vwap and self.Position <= 0:
self.BuyMarket(self.Volume + abs(self.Position))
elif close < last_low and close < lower and dema < vwap and self.Position >= 0:
self.SellMarket(self.Volume + abs(self.Position))
def CreateClone(self):
return nifty_50_5mint_strategy()