//@Name:RSI //@Description:A RSI indicator with editable overbought and oversold levels. Includes signal line. //Author: ShareScript Support //A RSI indicator and its signal calculated using //a simple moving average //The RSI and signal periods can be set below //Modified: Phil Tolhurst, ShareScope Support - 25-07-18 - Added catch for dodgy data and included 'goodData' fix for intraday data to cover more possible issues. // Care has been taken in preparing this code but it is provided without guarantee. // You are welcome to modify and extend it. Please add your name as a modifier if you distribute it. var period = 20; var oBought = 70; var oSold = 30; var sigPeriod = 9; var indCol = Colour.Blue; var indStyle = Pen.Solid; var indWidth = 0; var hCol = Colour.Grey; var hStyle = Pen.Solid; var hWidth = 0; var sigCol = Colour.Red; var sigStyle = Pen.Solid; var sigWidth = 0; //tickbox states var levels = 1; var sigTick = 1; //smoothing types var rsiList = ["Wilder","Exponential","Simple"]; var maList = ["Simple","Exponential","Weighted","Triangular","VariableVHF","VariableCMO","VIDYA"]; var maL2 = ["SMA","EMA","WMA","TMA","VVHF","VCMO","VIDYA"]; var rsiType = 0; var sigType = 0; function init(status) { if (status == Loading || status == Editing) { var store1 = restore(storage.getAt(0), [[levels,0,1],[sigTick,0,1],[indStyle,0,4],[sigStyle,0,4],[hStyle,0,4],[indWidth,0,7],[sigWidth,0,7],[hWidth,0,7],[rsiType,0,3],[sigType,0,6]]); period = storage.getAt(1); oBought = storage.getAt(2); oSold = storage.getAt(3); sigPeriod = storage.getAt(4); indCol = storage.getAt(5); sigCol = storage.getAt(6); hCol = storage.getAt(7); levels = store1[0][0]; sigTick = store1[1][0]; indStyle = store1[2][0]; sigStyle = store1[3][0]; hStyle = store1[4][0]; indWidth = store1[5][0]; sigWidth = store1[6][0]; hWidth = store1[7][0]; rsiType = store1[8][0]; sigType = store1[9][0]; } if (status == Adding || status == Editing) { dlg = new Dialog((status==Adding?"Add":"Edit")+" RSI indicator",270,110); dlg.addOkButton(); dlg.addCancelButton(); dlg.addIntEdit("VAL1",45,5,-1,-1,"RSI:","period",period,2,5000); dlg.addColLinePicker("VAL2",170,5,-1,-1,"","",indCol,indStyle,indWidth); dlg.addDropList("VAL11",105,5,55,-1,rsiList,"","",rsiType); dlg.addIntEdit("VAL3",45,25,-1,-1,"Signal:","period",sigPeriod,2,5000); dlg.addColLinePicker("VAL4",170,25,-1,-1,"","",sigCol,sigStyle,sigWidth); dlg.addDropList("VAL5",105,25,55,-1,maList,"","",sigType); dlg.addTickBox("VAL6",8,26,10,10,"",sigTick); dlg.addTickBox("VAL7",8,50,110,10," Overbought/Oversold levels",levels); dlg.addIntEdit("VAL8",130,70,-1,-1,"Overbought level:","",oBought,0,100); dlg.addIntEdit("VAL9",130,85,-1,-1,"Oversold level:","",oSold,0,100); dlg.addColLinePicker("VAL10",130,50,-1,-1,"","",hCol,hStyle,hWidth); dlg.addGroupBox(4,42,165,60,""); if (dlg.show()==Dialog.Cancel) return false; period = dlg.getValue("VAL1"); rsiType = dlg.getValue("VAL11"); indCol = dlg.getValue("VAL2").colour; indStyle = dlg.getValue("VAL2").pen; indWidth = dlg.getValue("VAL2").width; sigPeriod = dlg.getValue("VAL3"); sigCol = dlg.getValue("VAL4").colour; sigStyle = dlg.getValue("VAL4").pen; sigWidth = dlg.getValue("VAL4").width; sigType = dlg.getValue("VAL5"); sigTick = dlg.getValue("VAL6"); levels = dlg.getValue("VAL7"); oBought = dlg.getValue("VAL8"); oSold = dlg.getValue("VAL9"); hCol = dlg.getValue("VAL10").colour; hStyle = dlg.getValue("VAL10").pen; hWidth = dlg.getValue("VAL10").width; storage.setAt(0, compress([[levels,0,1],[sigTick,0,1],[indStyle,0,4],[sigStyle,0,4],[hStyle,0,4],[indWidth,0,7],[sigWidth,0,7],[hWidth,0,7],[rsiType,0,3],[sigType,0,6]])); storage.setAt(1, period); storage.setAt(2, oBought); storage.setAt(3, oSold); storage.setAt(4, sigPeriod); storage.setAt(5, indCol); storage.setAt(6, sigCol); storage.setAt(7, hCol); } setSeriesColour(0,indCol); setSeriesLineStyle(0,indStyle,indWidth); setSeriesColour(1,sigCol); setSeriesLineStyle(1,sigStyle,sigWidth); setSeriesColour(2,hCol); setSeriesLineStyle(2,hStyle,hWidth); setSeriesColour(3,hCol); setSeriesLineStyle(3,hStyle,hWidth); setTitle(period+" RSI (sig:"+sigPeriod+" "+maL2[sigType]+")"); setRange(Range.MinMax,0,100); } function getGraph(share, data) { if (data == undefined || data.length<2 || data[0].close == undefined) { var output = []; output.length = data.length; return output; } var rsi = new Array(); var rsi1 = new RSI(period,rsiType); var signal = new MA(sigPeriod,sigType) var ma = new Array(); var upperLine = new Array(); var lowerLine = new Array(); var goodData = data[0].close; for (var i=0; i0) { if(data[i].close != undefined) { goodData = data[i].close } } rsi[i] = rsi1.getNext(goodData); upperLine[i] = oBought; lowerLine[i] = oSold; if (sigTick==1)ma[i] = signal.getNext(rsi[i]); else ma[i]=null; } if(levels == 0) return [rsi,ma]; else return [rsi,ma,upperLine,lowerLine]; } function compress(data) { var rangeTot = 1 var output = 0 for (var i = 0;i8388608) print("Too much data for single storage space") return output } function restore(storage, data) { var remainder = storage var rangeTot = 1 for (var i=0;i=0;i--) { if (i