using RSI and Bollinger Bands
using RSI and Bollinger Bands
18 Dec 2023, 12:28
can someone tell my why i not able to get open positions using this code when i am using 1 year of data when i am doing backtesting
……………………………………………………..
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
namespace RSI_and_BollingerBands_Retracement
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class RSIAndBollingerBandsRetracement : Robot
{
[Parameter("Periods", DefaultValue = 20, Group = "Bollinger Bands")]
public int BbPeriods { get; set; }
[Parameter("Standard Deviation", DefaultValue = 2, Group = "Bollinger Bands")]
public double BbStdDev { get; set; }
[Parameter("MA Type", DefaultValue = MovingAverageType.Simple, Group = "Bollinger Bands")]
public MovingAverageType BbMaType { get; set; }
[Parameter("Source", Group = "Bollinger Bands")]
public DataSeries BbSource { get; set; }
[Parameter("RSI Periods", DefaultValue = 14, Group = "RSI")]
public int RsiPeriods { get; set; }
[Parameter("RSI Source", Group = "RSI")]
public DataSeries RsiSource { get; set; }
[Parameter("Overbought Level", DefaultValue = 70, Group = "RSI")]
public int RsiOverboughtLevel { get; set; }
[Parameter("Oversold Level", DefaultValue = 30, Group = "RSI")]
public int RsiOversoldLevel { get; set; }
[Parameter("Volume", DefaultValue = 10000, Group = "Trade")]
public int Volume { get; set; }
[Parameter("Robot Label", DefaultValue = "RSI and BB", Group = "Orders management")]
public string RobotLabel { get; set; }
private BollingerBands BollingerBands;
private RelativeStrengthIndex Rsi;
protected override void OnStart()
{
BollingerBands = Indicators.BollingerBands(BbSource, BbPeriods, BbStdDev, BbMaType);
Rsi = Indicators.RelativeStrengthIndex(RsiSource, RsiPeriods);
}
private bool IsDivergence(DataSeries prices, int bbPeriods, DataSeries rsiValues)
{
// Calculate Bollinger Bands for the specified period
var bollingerBands = Indicators.BollingerBands(prices, bbPeriods, BbStdDev, BbMaType);// Get the last two Bollinger Bands top values
var bbTop1 = bollingerBands.Top[bollingerBands.Top.Count - 2];
var bbTop2 = bollingerBands.Top[bollingerBands.Top.Count - 1];
var rsi1 = rsiValues[rsiValues.Count - 2];
var rsi2 = rsiValues[rsiValues.Count - 1];
// Check for bearish divergence
if (rsi1 > rsi2 && bbTop1 < bbTop2)
{
return true;
}
// Check for bullish divergence
if (rsi1 < rsi2 && bbTop1 > bbTop2)
{
return true;
}
return false;
}
protected override void OnBar()
{
var i = Bars.Count - 1;
var prevBbTop = BollingerBands.Top[i - 2];
var prevBbBottom = BollingerBands.Bottom[i - 2];
var prevRsi = Rsi.Result[i - 2];
if (double.IsNaN(prevBbTop) || double.IsNaN(prevBbBottom) || double.IsNaN(prevRsi))
return;
var prevClose = Bars.ClosePrices[i - 2];
var prevHighOverBbTop = prevClose > prevBbTop;
var prevLowBelowBbBottom = prevClose < prevBbBottom;
if (prevHighOverBbTop && prevLowBelowBbBottom)
return;
var isClosedCandleUp = Bars.ClosePrices[i - 1] > Bars.OpenPrices[i - 1];
var bbTop = BollingerBands.Top.LastValue;
var bbBottom = BollingerBands.Bottom.LastValue;
var bbMain = BollingerBands.Main.LastValue;
// Check for divergence
var isDivergence = IsDivergence(Bars.ClosePrices, BbPeriods, Rsi.Result);
if (isDivergence)
return;
if (prevHighOverBbTop && Bars.HighPrices.Last(1) > bbTop && Bars.HighPrices.Last(2) < bbTop &&
prevRsi > RsiOverboughtLevel && IsDivergence(Bars.ClosePrices, BbPeriods, Rsi.Result))
{
var stopLossPips = (bbTop - bbMain) / Symbol.PipSize;
OpenPosition(TradeType.Sell, stopLossPips);
}
else if (prevLowBelowBbBottom && Bars.LowPrices.Last(1) < bbBottom && Bars.LowPrices.Last(2) > bbBottom &&
prevRsi < RsiOversoldLevel && IsDivergence(Bars.ClosePrices, BbPeriods, Rsi.Result))
{
var stopLossPips = (bbMain - bbBottom) / Symbol.PipSize;
OpenPosition(TradeType.Buy, stopLossPips);
}
}
private void OpenPosition(TradeType side, double stopLossPips)
{
if (Positions.Any(p => p.SymbolName == SymbolName && p.Label == RobotLabel))
return;
ExecuteMarketOrder(side, SymbolName, Volume, RobotLabel, stopLossPips, null);
}
protected override void OnTick()
{
var openedPosition = Positions.FirstOrDefault(p => p.SymbolName == SymbolName && p.Label == RobotLabel);
if (openedPosition == null)
return;
if (openedPosition.TradeType == TradeType.Sell && Bid <= BollingerBands.Bottom.LastValue)
{
ClosePosition(openedPosition);
}
else if (openedPosition.TradeType == TradeType.Buy && Bid >= BollingerBands.Top.LastValue)
{
ClosePosition(openedPosition);
}
}
}
}