declare lower;
def na = Double.NaN;
script normalizer {
input data = close;
input Min = 0;
input Max = 100;
input length = 50;
def hhData = Highest(data, length);
def llData = Lowest(data, length);
plot resized = (((Max - Min) * (data - llData)) /
(hhData - llData)) + Min;
}
### Relative Strength Index (RSI) ###
input length = 14;
input price = close;
def averageType = AverageType.WILDERS;
def NetChgAvg = MovingAverage(averageType, price - price[1], length);
def TotChgAvg = MovingAverage(averageType, AbsValue(price - price[1]), length);
def ChgRatio = if TotChgAvg != 0 then NetChgAvg / TotChgAvg else 0;
def RSI = 50 * (ChgRatio + 1);
plot x = normalizer(RSI);
x.SetDefaultColor(Color.GREEN);
x.SetLineWeight(3);
### True Strength Index (TSI) ###
input longLength = 25;
input shortLength = 13;
input averageType2 = AverageType.EXPONENTIAL;
def diff = close - close[1];
def doubleSmoothedAbsDiff = MovingAverage(averageType2, MovingAverage(averageType2, AbsValue(diff), longLength), shortLength);
def TSI;
TSI = if doubleSmoothedAbsDiff == 0 then 0
else 100 * (MovingAverage(averageType2, MovingAverage(averageType2, diff, longLength), shortLength)) / doubleSmoothedAbsDiff;
plot y = normalizer(TSI);
y.SetDefaultColor(Color.RED);
y.SetLineWeight(3);
def RSICrossAbove = x > y and y < y[1];
def RSICrossBelow = x < y and y > y[1];
AddLabel(yes, "RSI crossed above TSI" , if RSICrossAbove then Color.LIGHT_GREEN else Color.BLACK);
AddLabel(yes, "RSI crossed below TSI" , if RSICrossBelow then Color.PINK else Color.BLACK);
Alert(RSICrossAbove, "RSI crossed above TSI" , Alert.BAR, Sound.Chimes);
Alert(RSICrossBelow, "RSI crossed below TSI" , Alert.BAR, Sound.Chimes);
AddCloud(x, y, Color.GREEN, Color.RED);
# Arrow Snippet courtesy of @lucprokop and @Pensar
# Source: https://usethinkscript.com/threads/offset-plotted-arrows-for-thinkorswim.9195/post-84956
# check if RSI has crossed TSI
def x1u = (x crosses above y);
def x1d = (x crosses below y);
input arrow_size = 4;
input arrow_vertical_factor = 10;
def vert = (ticksize() * arrow_vertical_factor * arrow_size);
# calc vertical placement for arrows
def arrow1up = if !x1u then na else low - 20 * ATR(length = 20, averageType = averageType.SIMPLE);
def arrow1dwn = if !x1d then na else high - 5 * ATR(length = 20, averageType = averageType.SIMPLE);
# plot arrows for crossings
plot pma1xup = if RSICrossAbove then arrow1up else na;
pma1xup.SetPaintingStrategy(PaintingStrategy.ARROW_up);
pma1xup.SetDefaultColor(Color.YELLOW);
pma1xup.hidebubble();
pma1xup.setlineweight(arrow_size);
plot pma1xdwn = if RSICrossBelow then arrow1dwn else na;
pma1xdwn.SetPaintingStrategy(PaintingStrategy.ARROW_DOWN);
pma1xdwn.SetDefaultColor(Color.YELLOW);
pma1xdwn.hidebubble();
pma1xdwn.setlineweight(arrow_size);