Another famous and relatively complex indicator will be discussed in this article. It is a contrarian oscillator that is best used in ranging markets. I am of course talking about the Relative Vigor Index. In this article, we will present the fundamentals and how to code it.
I have released a new book after the success of my previous one “Trend Following Strategies in Python”. It features advanced contrarian indicators and strategies with a GitHub page dedicated to the continuously updated code. If you feel that this interests you, feel free to visit the below Amazon link (which contains a sample), or if you prefer to buy the PDF version, you could check the link at the end of the article.
Contrarian Trading Strategies in Python
Amazon.com: Contrarian Trading Strategies in Python: 9798434008075: Kaabar, Sofien: Bookswww.amazon.com
The Building Blocks
The Relative Vigor Index is composed of many building blocks, namely the totality of OHLC data and moving averages. It seeks to measure the strength of the trend by comparing the ranges between the open/close and high/low values. It is an unbounded indicator that oscillates around the zero line with many strategies possible to be formed using it, namely divergences and crosses.
The numerator line of the Relative Vigor can be calculated this way:
Calculate the current difference between the closing and opening price. Let’s call this variable A.
Calculate the difference between the current closing price and the opening price from one period ago. Let’s call this variable B. Multiply the result by 2.
Calculate the difference between the current closing price and the opening price two periods ago. Let’s call this variable C. Multiply the result by 2.
Calculate the difference between the current closing price and the opening price three periods ago. Let’s call this variable D.
The denominator line of the Relative Vigor can be calculated this way:
Calculate the current difference between the high and low price. Let’s call this variable E.
Calculate the difference between the current high price and the low price one period ago. Let’s call this variable F. Multiply the result by 2.
Calculate the difference between the current high price and the low price two periods ago. Let’s call this variable G. Multiply the result by 2.
Calculate the difference between the current high price and the low price three periods ago. Let’s call this variable H.
The formula for the Relative Vigor Index is as follows:
We can see that it is some form of a smoothed ratio between the range of the close/open and high/low. As it is unbounded, it is often accompanied by a signal line derived from its calculation as follows:
To code the indicator, we need an OHLC array and write the following syntax.
# The function to add a number of columns inside an array
def adder(Data, times):
for i in range(1, times + 1):
new_col = np.zeros((len(Data), 1), dtype = float)
Data = np.append(Data, new_col, axis = 1)
return Data
# The function to delete a number of columns starting from an index
def deleter(Data, index, times):
for i in range(1, times + 1):
Data = np.delete(Data, index, axis = 1)
return Data
# The function to delete a number of rows from the beginning
def jump(Data, jump):
Data = Data[jump:, ]
return Data
# Example of adding 3 empty columns to an array
my_ohlc_array = adder(my_ohlc_array, 3)
# Example of deleting the 2 columns after the column indexed at 3
my_ohlc_array = deleter(my_ohlc_array, 3, 2)
# Example of deleting the first 20 rows
my_ohlc_array = jump(my_ohlc_array, 20)
# Remember, OHLC is an abbreviation of Open, High, Low, and Close and it refers to the standard historical data file
def ma(Data, lookback, close, where):
Data = adder(Data, 1)
for i in range(len(Data)):
try:
Data[i, where] = (Data[i - lookback + 1:i + 1, close].mean())
except IndexError:
pass
# Cleaning
Data = jump(Data, lookback)
return Data
def rvi(Data, lookback, opening, high, low, close, where):
Data = adder(Data, 4)
# Numerator
for i in range(len(Data)):
Data[i, where] = ((Data[i, close] - Data[i, opening]) + \
(2 * (Data[i, close] - Data[i - 1, opening])) + \
(2 * (Data[i, close] - Data[i - 2, opening])) + \
(Data[i, close] - Data[i - 3, opening])) / 6
Data = ma(Data, lookback, where, where + 1)
# Denominator
for i in range(len(Data)):
Data[i, where + 2] = ((Data[i, high] - Data[i, low]) + \
(2 * (Data[i, high] - Data[i - 1, low])) + \
(2 * (Data[i, high] - Data[i - 2, low])) + \
(Data[i, high] - Data[i - 3, low])) / 6
Data = ma(Data, lookback, where + 2, where + 3)
# RVI
Data[:, where + 4] = Data[:, where + 1] / Data[:, where + 3]
# Signal
for i in range(len(Data)):
Data[i, where + 5] = ((Data[i, where + 4]) + \
(2 * (Data[i - 1, where + 4])) + \
(2 * (Data[i - 2, where + 4])) + \
(Data[i - 3, where + 4])) / 6
Data = deleter(Data, where, 4)
Data = jump(Data, lookback + 10)
return Data
Make sure to focus on the concepts and not the code. You can find the codes of most of my strategies in my books. The most important thing is to comprehend the techniques and strategies.
Trading the Relative Vigor Index
One of the usual techniques to apply on trading indicators is the signal line. This line is usually a very short-term moving average applied on the indicator, but it is calculated differently for this indicator as seen in the previous part.
A buy (Long) signal is generated whenever the RVI crosses its signal line from the below to the above.
A sell (Short) signal is generated whenever the RVI crosses its signal line from the above to the below.
def signal(Data, rvi_column, rvi_signal, buy, sell):
for i in range(len(Data)):
if Data[i, rvi_column] > Data[i, rvi_signal] and Data[i - 1, rvi_column] < Data[i - 1, rvi_signal] and Data[i - 2, rvi_column] < Data[i - 2, rvi_signal]:
Data[i, buy] = 1
if Data[i, rvi_column] < Data[i, rvi_signal] and Data[i - 1, rvi_column] > Data[i - 1, rvi_signal] and Data[i - 2, rvi_column] > Data[i - 2, rvi_signal]:
Data[i, sell] = -1
To avoid false signals from randomness of the crosses that occur when the indicator is not on its extremes, we can add an RSI condition where we only initiate positions if the cross happens while a certain condition is met on the RSI. For example, we can create the following trading rules:
A buy (Long) signal is generated whenever the 10-period RVI crosses its signal line from the below to the above while the 14-period RSI is below 30.
A sell (Short) signal is generated whenever the 10-period RVI crosses its signal line from the above to the below while the 14-period RSI is above 70.
Summary
To summarize up, what I am trying to do is to simply contribute to the world of objective technical analysis which is promoting more transparent techniques and strategies that need to be back-tested before being implemented. This way, technical analysis will get rid of the bad reputation of being a subjective and scientifically unfounded.
I recommend you always follow the the below steps whenever you come across a trading technique or strategy:
Have a critical mindset and get rid of any emotions.
Back-test it using real life simulation and conditions.
If you find potential, try optimizing it and running a forward test.
Always include transaction costs and any slippage simulation in your tests.
Always include risk management and position sizing in your tests.
Finally, even after making sure of the above, stay careful and monitor the strategy because market dynamics may shift and make the strategy unprofitable.
For the PDF alternative, the price of the book is 9.99 EUR. Please include your email in the note before paying so that you receive it on the right address. Also, once you receive it, make sure to download it through google drive.
Pay Kaabar using PayPal.Me
If you accept cookies, we’ll use them to improve and customize your experience and enable our partners to show you…www.paypal.com
Great post, thanks! The Relative Vigor Index seems popular these days... :)
https://medium.com/@chris_42047/relative-vigor-index-rvi-strategy-test-drive-21734bc79255