Discover more from All About Trading!
The Premier Stochastic Oscillator
How to Code and Use the Premier Stochastic Oscillator
Super indicators are not frequent but they add immense values to our trading. Among these super indicators is the premier stochastic oscillator, a complex version that resembles the stochastic oscillator but enhances it and makes it more reactive. This article discusses all you need to know about the premier stochastic oscillator.
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.
The Stochastic Oscillator
The stochastic oscillator is one of the most famous technical indicators. It uses a simple formula to normalize the price action into values between 0 and 100 all while including the highs and the lows, thus incorporating volatility.
To calculate the stochastic oscillator (the raw version), use the following formula:
The next Figure shows USDCHF with the stochastic oscillator in the second panel. Typically, values close to the lower extremes (between 20 and 0) are associated with an expected bullish reaction as we tend to say that the market is oversold. In parallel, values close to the upper extremes (between 80 and 100) are associated with an expected bearish reaction as we tend to say that the market is overbought.
Assume you have an OHLC array in Python. To create a fifth column that contains the stochastic values, use the below syntax:
def add_column(data, times): for i in range(1, times + 1): new = np.zeros((len(data), 1), dtype = float) data = np.append(data, new, axis = 1)
def delete_column(data, index, times): for i in range(1, times + 1): data = np.delete(data, index, axis = 1)
def delete_row(data, number): data = data[number:, ] return data
def rounding(data, how_far): data = data.round(decimals = how_far) return data
def ma(data, lookback, close, position): data = add_column(data, 1) for i in range(len(data)): try: data[i, position] = (data[i - lookback + 1:i + 1, close].mean()) except IndexError: pass data = delete_row(data, lookback) return data
def stochastic_oscillator(data, lookback, high, low, close, position, slowing = False, smoothing = False, slowing_period = 1, smoothing_period = 1): data = add_column(data, 1) for i in range(len(data)): try: data[i, position] = (data[i, close] - min(data[i - lookback + 1:i + 1, low])) / (max(data[i - lookback + 1:i + 1, high]) - min(data[i - lookback + 1:i + 1, low])) except ValueError: pass data[:, position] = data[:, position] * 100 if slowing == True and smoothing == False: data = ma(data, slowing_period, position, position + 1) if smoothing == True and slowing == False: data = ma(data, smoothing_period, position, position + 1) if smoothing == True and slowing == True: data = ma(data, slowing_period, position, position + 1) data = ma(data, smoothing_period, position + 1, position + 2) data = delete_row(data, lookback)
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.
Creating the Premier Stochastic Oscillator in Python
Let’s now create this highly complex but extremely interesting indicator. Created and introduced by Lee Leibfarth in 2008, the premier stochastic oscillator (PSO) is a bounded indicator that is considered to be more reactive and leading than the original stochastic oscillator. Therefore, it is an enhanced version which has its own unique trading conditions that I will present later. First, we need to understand how to calculate it. Follow these steps:
Calculate an 8-period stochastic. You have already seen how to do this.
Calculate a transformed stochastic using the following formula:
Calculate a 5-period exponential moving average on the transformed stochastic.
Calculate another 5-period exponential moving average on the results from the previous step.
Calculate the exponents of the double smoothed values from the previous step.
Finally, apply the below normalization function on the results from the last step to obtain the PSO:
Now, you have a PSO calculated from an 8-period stochastic oscillator smoothed with a 5-period double exponential moving average. The next step is to visualize the indicator and discuss the trading conditions.
The PSO is used as follows:
A long (buy) signal is generated whenever the PSO drops below 0.90 after having been above it.
A short (sell) signal is generated whenever the PSO rises above -0.90 after having been below it.
Interestingly, the same conditions can be generated by using 0.20 and -0.20. However, in this article, I will stick to the -0.90/0.90 rules.
Before coding the PSO, make sure you define the function of the exponential moving average:
def ema(data, alpha, lookback, close, position): alpha = alpha / (lookback + 1.0) beta = 1 - alpha data = ma(data, lookback, close, position)
data[lookback + 1, position] = (data[lookback + 1, close] * alpha) + (data[lookback, position] * beta)
for i in range(lookback + 2, len(data)): try: data[i, position] = (data[i, close] * alpha) + (data[i - 1, position] * beta) except IndexError: pass return data
Let’s check the signals generated on the PSO. The below shows the EURUSD with triggers coming from the conditions discussed previously.
def pso(data, lookback_stochastic, lookback_smoothing, high, low, close, position): data = add_column(data, 10) data = stochastic_oscillator(data, lookback_stochastic, high, low, close, position) data[:, position + 1] = 0.10 * (data[:, position] - 50) lookback_smoothing = np.sqrt(lookback_smoothing) lookback_smoothing = int(round(lookback_smoothing, 0)) data = ema(data, 2, lookback_smoothing, position + 1, position + 2) data = ema(data, 2, lookback_smoothing, position + 2, position + 3) data[:, position + 4] = np.exp(data[:, position + 3]) data[:, position + 5] = (data[:, position + 4] - 1) / (data[:, position + 4] + 1) data = delete_column(data, position, 5) return data
The below shows the USDCHF with triggers coming from the conditions discussed previously.
In a future article, I will compare the original stochastic oscillator with the PSO.
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.