/*[[ Name := Inverse Fisher Transform of RSI Programmer := Paul Y. Shimada, PaulYShimada@Yahoo.com Revision := 2004.07.15. Fixes by Minko Vassilev mvp@bulgaria.com Reference := Adapted from Ehler, John F., May 2004, "The Inverse Fisher Transform," Technical Analysis of Stocks and Commodities, p39-42,96-98. Link := www.MesaSoftware.com Separate Window := Yes First Color := Chartreuse First Draw Type := Line First Symbol := 217 Use Second Data := Yes Second Color := DimGray Second Draw Type := Line Second Symbol := 218 ]]*/ Inputs: HiTrigger(0.5), // default=0.5 LoTrigger(-0.5), // default=-0.5 RsiBars(5), // default=5 WmaBars(9), // default=9 info(0), // default=0 ; Variables: // Generic shift(0), loopbegin(0), is_First(True), prevbars(0), count(0), ; Variables: // Specific Name("InvFisher RSI"), Value2(0), IFish(0), // For manual calc. RSI SumUp(0), SumDn(0), AvgUp(0), AvgDn(0), Delta(0), RSI(0), // For calc. WMA WmaNumerator(0), WmaDenominator(0), LastTime(0), PrevAvgUp(0), PrevAvgDn(0), cntdown(0), ; Arrays: // For calc. generic WMA (weighted moving average) Value1[40](0), ; SetLoopCount(0); //-------------------------------------------------------- // Usage if info Then Begin Alert("See Terminal>Journal Tab for usage of \n",Name); Print("|___________________"); Print("|* ",Name," *"); Print("| ","Sell: cross under HiTrigger (or under LoTrigger if no prior cross under HiTrigger)"); Print("| ","Buy: cross over LoTrigger (or over HiTrigger if no prior cross over LoTrigger)"); Print("|* ",Name," *"); Print("|```````````````````"); End; //-------------------------------------------------------- // Check Inputs If 0>HiTrigger or HiTrigger>1 Then Begin Alert("Input Error: must be 0< HiTrigger <1, Cannot=",HiTrigger); Exit; End; If -1>LoTrigger or LoTrigger>0 Then Begin Alert("Input Error: must be -1< LoTrigger <0, Cannot=",Lotrigger); Exit; End; If 0>RsiBars or RsiBars>50 Then Begin Alert("Input Error: must be 0< RsiBars <50, Cannot=",RsiBars); Exit; End; //-------------------------------------------------------- // Check for additional bars loading or total reloadng. If Bars1 Then is_First=True; prevbars=Bars; //-------------------------------------------------------- // Pre-Loop setup // loopbegin prevents counting of previously plotted bars excluding current Bars if is_First Then Begin loopBegin=Bars-1-1;// BarIndexNumber=Shift=Bars-1...0 // Compute the initial AvgUp & AvgDn for RSI For shift=loopBegin DownTo loopBegin-RsiBars Begin Delta=C[shift]-C[shift+1]; SumUp=SumUp+max(0,Delta); SumDn=SumDn-min(0,Delta); End; AvgUp=SumUp/RsiBars; AvgDn=SumDn/RsiBars; loopBegin=loopBegin-RsiBars; End; //-------------------------------------------------------- // loop from loopbegin to current bar (shift=0) if not is_First Then { if (Time[0]<>LastTime) Then { PrevAvgUp = AvgUp; PrevAvgDn = AvgDn; AvgUp = 0; AvgDn = 0; For count=WmaBars-1 Downto 1 Begin Value1[count]=Value1[count-1]; End; LastTime = Time[0]; } } Else { cntdown = 1; } For shift=loopbegin Downto cntdown Begin // Calc RSI manually Delta=Close[shift]-Close[shift+1]; if is_First Then { AvgUp=((RsiBars-1)*AvgUp+Max(0,Delta))/RsiBars; AvgDn=((RsiBars-1)*AvgDn-Min(0,Delta))/RsiBars; } Else { AvgUp=((RsiBars-1)*PrevAvgUp+Max(0,Delta))/RsiBars; AvgDn=((RsiBars-1)*PrevAvgDn-Min(0,Delta))/RsiBars; } RSI=100-100/(1+AvgUp/AvgDn); // Then scale RSI to between -5 and +5 /* Do not use iRSI fctn because it's too slow Value1=0.1*(iRSI(RsiBars,shift)-50); */ Value1[0]=0.1*(RSI-50); // Use weighted moving average to smooth Value1. // Ehler suggests could also use EMA, which would be simpler coding at the expense of Alpha. WmaNumerator=0; WmaDenominator=0; For count=WmaBars DownTo 1 Begin WmaNumerator=WmaNumerator+count*Value1[WmaBars-count-1]; WmaDenominator=WmaDenominator+count; End; Value2=WmaNumerator/WmaDenominator; IFish=(Exp(2*Value2)-1)/(Exp(2*Value2)+1); SetIndexValue(shift,IFish); // SetIndexValue(shift,RSI); // Plot dual-value Trigger Line If IFish >0 then SetIndexValue2(shift,HiTrigger) Else SetIndexValue2(shift,LoTrigger); //-------------------------------------------------------- // Update arrays. This technique minimizes array storage and thus allows more signal bars. If is_First Then For count=WmaBars-1 Downto 1 Begin Value1[count]=Value1[count-1]; End; //-------------------------------------------------------- End; is_First = False; cntdown = 0; loopbegin = 0;