# Fisher Transform: OBV + RSI

#### jpmcewen

##### Member
VIP
I'm hoping for some help re-creating a strategy (LINK) I found.

Before I start scripting Arrows, I checked the crossovers and the results seem very poor compared to the strategy. My guess is that I'm using the indicators incorrectly, so I'm hoping others may be able to shed some light so that I can continue building the strategy.

Fisher Transform: OBV
Ruby:
``````declare lower;
def c = close;
def v = volume;
plot FTOBV = FisherTransform(TotalSum(Sign(c - c[1]) * v),12);
plot FTOBV2 = FisherTransform(TotalSum(Sign(c - c[1]) * v),12)[1];``````

Fisher Transform: RSI
Ruby:
``````declare lower;
def c = close;
plot FTRSI = FisherTransform(RSI(averageType = AverageType.WILDERS, price = c),14);
plot FTRSI2 = FisherTransform(RSI(averageType = AverageType.WILDERS, price = c),14)[1];``````

Image w/ Fisher Transform: OBV + RSI

Last edited:
Solution
Fisher Transform OBV

Code:
``````declare lower;
input Length = 12;
input Arrows = no;
input Dotsize = 3;
input APC =0;
def c = close;
def v = volume;
plot FTOBV = FisherTransform(TotalSum(Sign(c - c[1]) * v),Length);
plot FTOBV2 = FisherTransform(TotalSum(Sign(c - c[1]) * v),Length)[1];
def MnOBV =Min(FTOBV,FTOBV2);
def MxOBV =Max(FTOBV,FTOBV2);
Plot UZ = Average(FTOBV,34) + (1.3185*StDev(FTOBV,34));
UZ.SetPaintingStrategy(PaintingStrategy.Line);
UZ.SetLineWeight(2);
UZ.SetDefaultColor(Color.Yellow);
Plot LZ = Average(FTOBV,34) - (1.3185*StDev(FTOBV,34));
LZ.SetPaintingStrategy(PaintingStrategy.Line);
LZ.SetLineWeight(2);
LZ.SetDefaultColor(Color.Yellow);
FTOBV.SetdefaultColor(Color.Cyan);
FTOBV2.SetdefaultColor(Color.Magenta)...``````
It looks like the source article recommends doing the Fisher Transform to the Stochastic RSI - not the RSI. You could also play around with the length of the transform.

Code:
``````declare lower;
input length = 9;

def stochrsi = reference StochRSI();
plot ftsr = FisherTransform(stochrsi,length);
plot ftsr1b = ftsr[1];

plot zeroline = 0;``````

@bigboss Thank you for catching that. Toying with the StochRSI length and the FT length...Gonna be honest, I'm not sure this is worth messing around with. If it gave better signals off the bat, sure.

Fisher Transform OBV

Code:
``````declare lower;
input Length = 12;
input Arrows = no;
input Dotsize = 3;
input APC =0;
def c = close;
def v = volume;
plot FTOBV = FisherTransform(TotalSum(Sign(c - c[1]) * v),Length);
plot FTOBV2 = FisherTransform(TotalSum(Sign(c - c[1]) * v),Length)[1];
def MnOBV =Min(FTOBV,FTOBV2);
def MxOBV =Max(FTOBV,FTOBV2);
Plot UZ = Average(FTOBV,34) + (1.3185*StDev(FTOBV,34));
UZ.SetPaintingStrategy(PaintingStrategy.Line);
UZ.SetLineWeight(2);
UZ.SetDefaultColor(Color.Yellow);
Plot LZ = Average(FTOBV,34) - (1.3185*StDev(FTOBV,34));
LZ.SetPaintingStrategy(PaintingStrategy.Line);
LZ.SetLineWeight(2);
LZ.SetDefaultColor(Color.Yellow);
FTOBV.SetdefaultColor(Color.Cyan);
FTOBV2.SetdefaultColor(Color.Magenta);

#ARROWS
plot ArrowDown = if arrows and (FTOBV Crosses below FTOBV2[1]) then FTOBV else double.nan;
ArrowDown.setpaintingStrategy(paintingStrategy.Arrow_Down);
ArrowDown.setDefaultColor(color.Magenta);
ArrowDown.setLineWeight(dotsize);

plot ArrowUp = if arrows and (FTOBV crosses above FTOBV2[1]) then FTOBV else double.nan;
ArrowUp.setpaintingStrategy(paintingStrategy.Arrow_Up);
ArrowUp.setDefaultColor(color.Cyan);
ArrowUp.setLineWeight(dotsize);

plot ArrowDown2 = if arrows and (FTOBV Crosses below 0) then 0 else double.nan;
ArrowDown2.setpaintingStrategy(paintingStrategy.Arrow_Down);
ArrowDown2.setDefaultColor(color.Red);
ArrowDown2.setLineWeight(dotsize);

plot ArrowUp2 = if arrows and (FTOBV crosses above 0 ) then 0 else double.nan;
ArrowUp2.setpaintingStrategy(paintingStrategy.Arrow_Up);
ArrowUp2.setDefaultColor(color.Blue);
ArrowUp2.setLineWeight(dotsize);

plot ArrowDown3 = if arrows and (FTOBV Crosses below UZ) then UZ else double.nan;
ArrowDown3.setpaintingStrategy(paintingStrategy.Arrow_Down);
ArrowDown3.setDefaultColor(color.Yellow);
ArrowDown3.setLineWeight(dotsize);

plot ArrowUp3 = if arrows and (FTOBV crosses above LZ ) then LZ else double.nan;
ArrowUp3.setpaintingStrategy(paintingStrategy.Arrow_Up);
ArrowUp3.setDefaultColor(color.Yellow);
ArrowUp3.setLineWeight(dotsize);

AssignPriceColor( if APC ==1 and FTOBV >= FTOBV2 then Color.Cyan else if APC == 1 and FTOBV < FTOBV2 then Color.Magenta else If APC ==2 and FTOBV >=0 then Color.Green else If APC ==2 and FTOBV <0 then Color.Red else Color.Current);``````

Last edited:
Fisher Transform OBV

Code:
``````declare lower;
input Length = 12;
input Arrows = no;
input Dotsize = 3;
input APC =0;
def c = close;
def v = volume;
plot FTOBV = FisherTransform(TotalSum(Sign(c - c[1]) * v),Length);
plot FTOBV2 = FisherTransform(TotalSum(Sign(c - c[1]) * v),Length)[1];
def MnOBV =Min(FTOBV,FTOBV2);
def MxOBV =Max(FTOBV,FTOBV2);
Plot UZ = Average(FTOBV,34) + (1.3185*StDev(FTOBV,34));
UZ.SetPaintingStrategy(PaintingStrategy.Line);
UZ.SetLineWeight(2);
UZ.SetDefaultColor(Color.Yellow);
Plot LZ = Average(FTOBV,34) - (1.3185*StDev(FTOBV,34));
LZ.SetPaintingStrategy(PaintingStrategy.Line);
LZ.SetLineWeight(2);
LZ.SetDefaultColor(Color.Yellow);
FTOBV.SetdefaultColor(Color.Cyan);
FTOBV2.SetdefaultColor(Color.Magenta);

#ARROWS
plot ArrowDown = if arrows and (FTOBV Crosses below FTOBV2[1]) then FTOBV else double.nan;
ArrowDown.setpaintingStrategy(paintingStrategy.Arrow_Down);
ArrowDown.setDefaultColor(color.Magenta);
ArrowDown.setLineWeight(dotsize);

plot ArrowUp = if arrows and (FTOBV crosses above FTOBV2[1]) then FTOBV else double.nan;
ArrowUp.setpaintingStrategy(paintingStrategy.Arrow_Up);
ArrowUp.setDefaultColor(color.Cyan);
ArrowUp.setLineWeight(dotsize);

plot ArrowDown2 = if arrows and (FTOBV Crosses below 0) then 0 else double.nan;
ArrowDown2.setpaintingStrategy(paintingStrategy.Arrow_Down);
ArrowDown2.setDefaultColor(color.Red);
ArrowDown2.setLineWeight(dotsize);

plot ArrowUp2 = if arrows and (FTOBV crosses above 0 ) then 0 else double.nan;
ArrowUp2.setpaintingStrategy(paintingStrategy.Arrow_Up);
ArrowUp2.setDefaultColor(color.Blue);
ArrowUp2.setLineWeight(dotsize);

plot ArrowDown3 = if arrows and (FTOBV Crosses below UZ) then UZ else double.nan;
ArrowDown3.setpaintingStrategy(paintingStrategy.Arrow_Down);
ArrowDown3.setDefaultColor(color.Yellow);
ArrowDown3.setLineWeight(dotsize);

plot ArrowUp3 = if arrows and (FTOBV crosses above LZ ) then LZ else double.nan;
ArrowUp3.setpaintingStrategy(paintingStrategy.Arrow_Up);
ArrowUp3.setDefaultColor(color.Yellow);
ArrowUp3.setLineWeight(dotsize);

AssignPriceColor( if APC ==1 and FTOBV >= FTOBV2 then Color.Cyan else if APC == 1 and FTOBV < FTOBV2 then Color.Magenta else If APC ==2 and FTOBV >=0 then Color.Green else If APC ==2 and FTOBV <0 then Color.Red else Color.Current);``````
Fisher Transform RSI
Code:
``````declare lower;
input Length = 14;
input arrows = no;
input Dotsize = 3;
input APC = 0;
def c = close;
plot FTRSI = FisherTransform(RSI(averageType = AverageType.WILDERS, price = c),Length);
plot FTRSI2 = FisherTransform(RSI(averageType = AverageType.WILDERS, price = c),Length)[1];
def MnRSI =Min(FTRSI,FTRSI2);
def MxRSI =Max(FTRSI,FTRSI2);
Plot UZ = Average(FTRSI,34) + (1.3185*StDev(FTRSI,34));
UZ.SetPaintingStrategy(PaintingStrategy.Line);
UZ.SetLineWeight(2);
UZ.SetDefaultColor(Color.Yellow);
Plot LZ = Average(FTRSI,34) - (1.3185*StDev(FTRSI,34));
LZ.SetPaintingStrategy(PaintingStrategy.Line);
LZ.SetLineWeight(2);
LZ.SetDefaultColor(Color.Yellow);
FTRSI.SetdefaultColor(Color.Cyan);
FTRSI2.SetdefaultColor(Color.Magenta);

#ARROWS
plot ArrowDown = if arrows and (FTRSI Crosses below FTRSI2[1]) then FTRSI else double.nan;
ArrowDown.setpaintingStrategy(paintingStrategy.Arrow_Down);
ArrowDown.setDefaultColor(color.Magenta);
ArrowDown.setLineWeight(dotsize);
plot ArrowUp = if arrows and (FTRSI crosses above FTRSI2[1]) then FTRSI else double.nan;
ArrowUp.setpaintingStrategy(paintingStrategy.Arrow_Up);
ArrowUp.setDefaultColor(color.Cyan);
ArrowUp.setLineWeight(dotsize);
plot ArrowDown2 = if arrows and (FTRSI Crosses below 0) then 0 else double.nan;
ArrowDown2.setpaintingStrategy(paintingStrategy.Arrow_Down);
ArrowDown2.setDefaultColor(color.Red);
ArrowDown2.setLineWeight(dotsize);
plot ArrowUp2 = if arrows and (FTRSI crosses above 0 ) then 0 else double.nan;
ArrowUp2.setpaintingStrategy(paintingStrategy.Arrow_Up);
ArrowUp2.setDefaultColor(color.Blue);
ArrowUp2.setLineWeight(dotsize);
plot ArrowDown3 = if arrows and (FTRSI Crosses below UZ) then UZ else double.nan;
ArrowDown3.setpaintingStrategy(paintingStrategy.Arrow_Down);
ArrowDown3.setDefaultColor(color.Yellow);
ArrowDown3.setLineWeight(dotsize);
plot ArrowUp3 = if arrows and (FTRSI crosses above LZ ) then LZ else double.nan;
ArrowUp3.setpaintingStrategy(paintingStrategy.Arrow_Up);
ArrowUp3.setDefaultColor(color.Yellow);
ArrowUp3.setLineWeight(dotsize);

AssignPriceColor( if APC ==1 and FTRSI >= FTRSI2 then Color.Cyan else if APC == 1 and FTRSI < FTRSI2 then Color.Magenta else If APC ==2 and FTRSI >=0 then Color.Green else If APC ==2 and FTRSI <0 then Color.Red else Color.Current);``````

Fisher Transform Stoch RSI
Code:
``````declare lower;
input Length = 14;
input arrows = no;
input Dotsize = 3;
input APC =0;
def stochrsi = reference StochRSI();
plot ftsr = FisherTransform(stochrsi,length);
plot ftsr1b = ftsr[1];

def Mnftsr =Min(FTsr,FTsr1b);
def Mxftsr =Max(FTsr,FTsr1b);
Plot UZ = Average(FTsr,34) + (1.3185*StDev(FTsr,34));
UZ.SetPaintingStrategy(PaintingStrategy.Line);
UZ.SetLineWeight(2);
UZ.SetDefaultColor(Color.Yellow);
Plot LZ = Average(FTsr,34) - (1.3185*StDev(FTsr,34));
LZ.SetPaintingStrategy(PaintingStrategy.Line);
LZ.SetLineWeight(2);
LZ.SetDefaultColor(Color.Yellow);
FTsr.SetdefaultColor(Color.Cyan);
FTsr1b.SetdefaultColor(Color.Magenta);

#ARROWS
plot ArrowDown = if arrows and (FTsr Crosses below FTsr1b[1]) then FTsr else double.nan;
ArrowDown.setpaintingStrategy(paintingStrategy.Arrow_Down);
ArrowDown.setDefaultColor(color.Magenta);
ArrowDown.setLineWeight(dotsize);
plot ArrowUp = if arrows and (FTsr crosses above FTsr1b[1]) then FTsr else double.nan;
ArrowUp.setpaintingStrategy(paintingStrategy.Arrow_Up);
ArrowUp.setDefaultColor(color.Cyan);
ArrowUp.setLineWeight(dotsize);
plot ArrowDown2 = if arrows and (FTsr Crosses below 0) then 0 else double.nan;
ArrowDown2.setpaintingStrategy(paintingStrategy.Arrow_Down);
ArrowDown2.setDefaultColor(color.Red);
ArrowDown2.setLineWeight(dotsize);
plot ArrowUp2 = if arrows and (FTsr crosses above 0 ) then 0 else double.nan;
ArrowUp2.setpaintingStrategy(paintingStrategy.Arrow_Up);
ArrowUp2.setDefaultColor(color.Blue);
ArrowUp2.setLineWeight(dotsize);
plot ArrowDown3 = if arrows and (FTsr Crosses below UZ) then UZ else double.nan;
ArrowDown3.setpaintingStrategy(paintingStrategy.Arrow_Down);
ArrowDown3.setDefaultColor(color.Yellow);
ArrowDown3.setLineWeight(dotsize);
plot ArrowUp3 = if arrows and (FTsr crosses above LZ ) then LZ else double.nan;
ArrowUp3.setpaintingStrategy(paintingStrategy.Arrow_Up);
ArrowUp3.setDefaultColor(color.Yellow);
ArrowUp3.setLineWeight(dotsize);

AssignPriceColor( if APC ==1 and FTsr >= FTsr1b then Color.Cyan else if APC == 1 and FTsr < FTsr1b then Color.Magenta else If APC ==2 and FTsr >=0 then Color.Green else If APC ==2 and FTsr <0 then Color.Red else Color.Current);``````

Last edited:
@henry1224 Wow, thank you!. Can't wait to check it out tonight. I appreciate the work either way.

Dear @henry1224 , can you please help me to with some hands regarding FisherTransform, InverseFisherTransform, as well as the applications of them used in your indicators above?

-----------------
Q1: FT vs IFT - Which to use?
-----------------
I have done a little research, and referring to this site (https://www.mesasoftware.com/papers/TheInverseFisherTransform.pdf), it states:
• Financial market charts are usually based in "sine" wave instead of Normal/Gaussian distribution.
• FT and/or IFT can help to make "sine" pattern into "Normal/Gaussian" pattern, to create a better oscillator indicator with better probability distribution estimation.

- So do we use FT or IFT to do the Sine->Gaussian? I see some people uses FT, some uses IFT, and the plots are significantly different. What is the use cases for using each?

-----------------
Q2: FT vs IFT - Expansive/Compressive?
-----------------
Also in the above research link, it mentioned that "the Fisher Transform is expansive, the Inverse Fisher Transform is compressive", what does it mean?

-----------------
Q3: Your FT Indicator - Upper/Lower Zone
-----------------
- What is the meaning of the Upper/Lower Zone, and why you use some of the parameters?
==> For example in the FT_RSI, there is this:
Code:
``Plot UZ = Average(FT_RSI_1, 34) + (1.3185 * StDev(FT_RSI_1, 34) );``
==> Why do you use 1.3185 * StDev(FT_RSI_1, 34) ?
==> Also a MovingAverage Length of 34 have been used often, what is the purpose of that?

Dear @henry1224 , can you please help me to with some hands regarding FisherTransform, InverseFisherTransform, as well as the applications of them used in your indicators above?

-----------------
Q1: FT vs IFT - Which to use?
-----------------
I have done a little research, and referring to this site (https://www.mesasoftware.com/papers/TheInverseFisherTransform.pdf), it states:
• Financial market charts are usually based in "sine" wave instead of Normal/Gaussian distribution.
• FT and/or IFT can help to make "sine" pattern into "Normal/Gaussian" pattern, to create a better oscillator indicator with better probability distribution estimation.

- So do we use FT or IFT to do the Sine->Gaussian? I see some people uses FT, some uses IFT, and the plots are significantly different. What is the use cases for using each?

-----------------
Q2: FT vs IFT - Expansive/Compressive?
-----------------
Also in the above research link, it mentioned that "the Fisher Transform is expansive, the Inverse Fisher Transform is compressive", what does it mean?

-----------------
Q3: Your FT Indicator - Upper/Lower Zone
-----------------
- What is the meaning of the Upper/Lower Zone, and why you use some of the parameters?
==> For example in the FT_RSI, there is this:
Code:
``Plot UZ = Average(FT_RSI_1, 34) + (1.3185 * StDev(FT_RSI_1, 34) );``
==> Why do you use 1.3185 * StDev(FT_RSI_1, 34) ?
==> Also a MovingAverage Length of 34 have been used often, what is the purpose of that?
The use of upper and lower zones are meant to show extreme areas. 34 length is about a month and a half of trading on daily bars

87k+ Posts
336 Online

## The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
• Exclusive indicators
• Proven strategies & setups
• Private Discord community
• Exclusive members-only content
• 1 full year of unlimited support

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?