Original strategy from https://relaxedtrader.com/rsi-trading-strategy/
Trading rules:
Author claims:
From converted script tested on SPY on daily timeframe with max allowed period, since 1993:
Using a different share size calculation:
Trading rules:
- Use two RSI values:
- 4 day RSI (RSI 1)
- 9 day RSI (RSI 2)
- Wait for RSI 1 and RSI 2 to go below 40
- When RSI 1reaches 70
- BUY
- When RSI 2reaches 70
- SELL
Code:
# SPY RSI Swing Trading Strategy
# Free for use. Header credits must be included when any form of the code included in this package is used.
# v1.0 - barbaros - converted for b4signals.com
input RiskManagement = yes;
input PercentRisk = 100;
input Portfolio = 100000;
input var1 = 39;
input var2 = 4;
input var3 = 9;
input var4 = 5;
input RSI_High_Value = 70;
input RSI_Low_Value = 40;
input targetWinRate = 1;
input targetWinLoss = .50;
def atr = Average(AbsValue(close - close[1]), var1);
def RSI_1 = RSI(var2);
def RSI_2 = RSI(var3);
def SharesToTrade = if RiskManagement then RoundDown((PercentRisk * 0.01) * Portfolio) else 1;
def buyCond = close > Average(close, 200) and RSI_1 > RSI_High_Value and lowest(RSI_1, var4) < RSI_Low_Value and lowest(RSI_2, var4) < RSI_Low_Value;
def sellCond = RSI_2 >= RSI_High_Value;
def direction = if BarNumber() == 1 then 0
else if direction[1] == 0 and buyCond and SharesToTrade > 0 then 1
else if direction[1] == 1 and sellCond then 0
else direction[1];
AddOrder(OrderType.BUY_TO_OPEN, direction crosses above 0, tradeSize = SharesToTrade, name = "LONG");
AddOrder(OrderType.SELL_TO_CLOSE, direction crosses below 1, name = "EXIT");
#Global Scripts
def FPL = FloatingPL();
def entry = EntryPrice();
def portfolioSize = if !isNaN(FPL) then FPL + Portfolio else Portfolio;
script incrementValue {
input condition = yes;
input increment = 1;
input startingValue = 0;
def _value = CompoundValue(1,
if condition
then _value[1] + increment
else _value[1], startingValue);
plot incrementValue = _value;
}
;
# Entry Calculations. Note: Only parses on a Strategy Chart
def bn = if !IsNaN(close) and !IsNaN(close[1]) and !IsNaN(close[-1]) then BarNumber() else bn[1];
def entryPrice = if !IsNaN(entry)
then entry
else entryPrice[1];
def hasEntry = !IsNaN(entry);
def isNewEntry = entryPrice != entryPrice[1];
#is active trade
def highFPL = HighestAll(FPL);
def lowFPL = LowestAll(FPL);
def fplreturn = (FPL - FPL[1]) / FPL[1];
def cumsum = Sum(fplreturn);
def highBarNumber = CompoundValue(1, if FPL == highFPL
then bn
else highBarNumber[1], 0);
def lowBarNumber = CompoundValue(1, if FPL == lowFPL
then bn
else lowBarNumber[1], 0);
#Win/Loss ratios
def entryBarsTemp = if hasEntry
then bn
else Double.NaN;
def entryBarNum = if hasEntry and isNewEntry
then bn
else entryBarNum[1];
def isEntryBar = entryBarNum != entryBarNum[1];
def entryBarPL = if isEntryBar
then FPL
else entryBarPL[1];
def exitBarsTemp = if !hasEntry
and bn > entryBarsTemp[1]
then bn
else Double.NaN;
def exitBarNum = if !hasEntry and !IsNaN(exitBarsTemp[1])
then bn
else exitBarNum[1];
def isExitBar = exitBarNum != exitBarNum[1];
def exitBarPL = if isExitBar
then FPL
else exitBarPL[1];
def entryReturn = if isExitBar then exitBarPL - exitBarPL[1] else entryReturn[1];
def isWin = if isExitBar and entryReturn >= 0 then 1 else 0;
def isLoss = if isExitBar and entryReturn < 0 then 1 else 0;
def entryReturnWin = if isWin then entryReturn else entryReturnWin[1];
def entryReturnLoss = if isLoss then entryReturn else entryReturnLoss[1];
def entryFPLWins = if isWin then entryReturn else 0;
def entryFPLLosses = if isLoss then entryReturn else 0;
def entryFPLAll = if isLoss or isWin then entryReturn else 0;
#Counts
def entryCount = incrementValue(entryFPLAll);
def winCount = incrementValue(isWin);
def lossCount = incrementValue(isLoss);
def highestReturn = if entryReturnWin[1] > highestReturn[1]
then entryReturnWin[1]
else highestReturn[1];
def lowestReturn = if entryReturnLoss[1] < lowestReturn[1]
then entryReturnLoss[1]
else lowestReturn[1];
def winRate = winCount / lossCount;
def winLossRatio = winCount / (winCount + lossCount); # winCount / entryCount;
def avgReturn = TotalSum(entryFPLAll) / entryCount;
def avgWin = TotalSum(entryFPLWins) / winCount;
def avgLoss = TotalSum(entryFPLLosses) / lossCount;
#Labels
AddLabel(yes,
text = "Total Trades: " + entryCount + " ",
color = Color.WHITE
);
AddLabel(yes,
text = "WinCount: " + winCount +
" | LossCount: " + lossCount +
" | WinRate: " + Round(winRate, 2) + " ",
color = if winRate >= targetWinRate
then Color.CYAN
else Color.MAGENTA
);
AddLabel(yes,
text = "W/L: " + AsPercent(winLossRatio) + " ",
color = if winLossRatio > targetWinLoss
then Color.CYAN
else Color.MAGENTA
);
AddLabel(yes,
text = "AvgReturn: " + AsDollars(avgReturn) +
" | AvgWin: " + AsDollars(avgWin) +
" | AvgLoss: " + AsDollars(avgLoss) + " ",
color = if avgReturn >= 0
then Color.CYAN
else Color.MAGENTA
);
AddLabel(yes,
text = "Total Profit: " + AsDollars(FPL) + " ",
color = if FPL > 0
then Color.CYAN
else Color.MAGENTA
);
AddLabel(yes,
text = "Final Portfolio: " + AsDollars(portfolioSize) + " (" + AsPercent(portfolioSize / Portfolio) + ") ",
color = if portfolioSize > Portfolio
then Color.CYAN
else Color.MAGENTA
);
Author claims:

From converted script tested on SPY on daily timeframe with max allowed period, since 1993:

Using a different share size calculation:

Code:
# SPY RSI Swing Trading Strategy
# Free for use. Header credits must be included when any form of the code included in this package is used.
# v1.0 - barbaros - converted for b4signals.com
# v1.1 - barbaros - realistic share size calculation
input useMoneyManagement = yes;
input initialBalance = 100000;
input var1 = 39;
input var2 = 4;
input var3 = 9;
input var4 = 5;
input RSI_High_Value = 70;
input RSI_Low_Value = 40;
input targetWinRate = 1;
input targetWinLoss = .50;
def atr = Average(AbsValue(close - close[1]), var1);
def RSI_1 = RSI(var2);
def RSI_2 = RSI(var3);
#def SharesToTrade = if RiskManagement then RoundDown((PercentRisk * 0.01) * Portfolio) else 1;
def FPL = FloatingPL();
def entry = EntryPrice();
def portfolioSize = if !isNaN(FPL) then FPL + initialBalance else initialBalance;
def SharesToTrade = if useMoneyManagement then RoundDown(portfolioSize / (atr * close), 0) else 1;
def buyCond = close > Average(close, 200) and RSI_1 > RSI_High_Value and lowest(RSI_1, var4) < RSI_Low_Value and lowest(RSI_2, var4) < RSI_Low_Value;
def sellCond = RSI_2 >= RSI_High_Value;
def direction = if BarNumber() == 1 then 0
else if direction[1] == 0 and buyCond and SharesToTrade > 0 then 1
else if direction[1] == 1 and sellCond then 0
else direction[1];
AddOrder(OrderType.BUY_TO_OPEN, direction crosses above 0, tradeSize = SharesToTrade, name = "LONG");
AddOrder(OrderType.SELL_TO_CLOSE, direction crosses below 1, name = "EXIT");
#Global Scripts
script incrementValue {
input condition = yes;
input increment = 1;
input startingValue = 0;
def _value = CompoundValue(1,
if condition
then _value[1] + increment
else _value[1], startingValue);
plot incrementValue = _value;
};
# Entry Calculations. Note: Only parses on a Strategy Chart
def bn = if !IsNaN(close) and !IsNaN(close[1]) and !IsNaN(close[-1]) then BarNumber() else bn[1];
def entryPrice = if !IsNaN(entry)
then entry
else entryPrice[1];
def hasEntry = !IsNaN(entry);
def isNewEntry = entryPrice != entryPrice[1];
#is active trade
def highFPL = HighestAll(FPL);
def lowFPL = LowestAll(FPL);
def fplreturn = (FPL - FPL[1]) / FPL[1];
def cumsum = Sum(fplreturn);
def highBarNumber = CompoundValue(1, if FPL == highFPL
then bn
else highBarNumber[1], 0);
def lowBarNumber = CompoundValue(1, if FPL == lowFPL
then bn
else lowBarNumber[1], 0);
#Win/Loss ratios
def entryBarsTemp = if hasEntry
then bn
else Double.NaN;
def entryBarNum = if hasEntry and isNewEntry
then bn
else entryBarNum[1];
def isEntryBar = entryBarNum != entryBarNum[1];
def entryBarPL = if isEntryBar
then FPL
else entryBarPL[1];
def exitBarsTemp = if !hasEntry
and bn > entryBarsTemp[1]
then bn
else Double.NaN;
def exitBarNum = if !hasEntry and !IsNaN(exitBarsTemp[1])
then bn
else exitBarNum[1];
def isExitBar = exitBarNum != exitBarNum[1];
def exitBarPL = if isExitBar
then FPL
else exitBarPL[1];
def entryReturn = if isExitBar then exitBarPL - exitBarPL[1] else entryReturn[1];
def isWin = if isExitBar and entryReturn >= 0 then 1 else 0;
def isLoss = if isExitBar and entryReturn < 0 then 1 else 0;
def entryReturnWin = if isWin then entryReturn else entryReturnWin[1];
def entryReturnLoss = if isLoss then entryReturn else entryReturnLoss[1];
def entryFPLWins = if isWin then entryReturn else 0;
def entryFPLLosses = if isLoss then entryReturn else 0;
def entryFPLAll = if isLoss or isWin then entryReturn else 0;
#Counts
def entryCount = incrementValue(entryFPLAll);
def winCount = incrementValue(isWin);
def lossCount = incrementValue(isLoss);
def highestReturn = if entryReturnWin[1] > highestReturn[1]
then entryReturnWin[1]
else highestReturn[1];
def lowestReturn = if entryReturnLoss[1] < lowestReturn[1]
then entryReturnLoss[1]
else lowestReturn[1];
def winRate = winCount / lossCount;
def winLossRatio = winCount / (winCount + lossCount); # winCount / entryCount;
def avgReturn = TotalSum(entryFPLAll) / entryCount;
def avgWin = TotalSum(entryFPLWins) / winCount;
def avgLoss = TotalSum(entryFPLLosses) / lossCount;
#Labels
AddLabel(yes,
text = "Total Trades: " + entryCount + " ",
color = Color.WHITE
);
AddLabel(yes,
text = "WinCount: " + winCount +
" | LossCount: " + lossCount +
" | WinRate: " + Round(winRate, 2) + " ",
color = if winRate >= targetWinRate
then Color.CYAN
else Color.MAGENTA
);
AddLabel(yes,
text = "W/L: " + AsPercent(winLossRatio) + " ",
color = if winLossRatio > targetWinLoss
then Color.CYAN
else Color.MAGENTA
);
AddLabel(yes,
text = "AvgReturn: " + AsDollars(avgReturn) +
" | AvgWin: " + AsDollars(avgWin) +
" | AvgLoss: " + AsDollars(avgLoss) + " ",
color = if avgReturn >= 0
then Color.CYAN
else Color.MAGENTA
);
AddLabel(yes,
text = "Total Profit: " + AsDollars(FPL) + " ",
color = if FPL > 0
then Color.CYAN
else Color.MAGENTA
);
AddLabel(yes,
text = "Final Portfolio: " + AsDollars(portfolioSize) + " (" + AsPercent(portfolioSize / initialBalance) + ") ",
color = if portfolioSize > initialBalance
then Color.CYAN
else Color.MAGENTA
);