A Python Williams %R Trading Strategy (Backtest)


This tutorial will use Python to implement a profitable trading strategy using the Williams %R indicator. The first part will explain the indicator, and the second part will implement the Python code. 

The second goal is to illustrate how to improve the strategy by adding a second indicator in Python. In pursuit of this aim, this tutorial will put in place the Williams %R strategy and then add the RSI to improve it. However, please keep in mind that the main purpose is to show the Python code, not the strategy itself.

The last goal is to explain theargs and **kwargs arguments in Python functions.

Williams %R Indicator

The Williams %R Indicator is a momentum indicator that tries to find the entry and exit points in a trade. This indicator can be between 0 and -100. A value from 0 to 20 means it is overbought, while -80 to -100 means it is oversold. Larry Williams developed the indicator to measure the connection between the closing price and the highest high and lowest low in a look-back period.

The calculation is:

\%R = -100\left(\frac{{\text{{Highest High}} - \text{{Close}}}}{{\text{{Highest High}} - \text{{Lowest Low}}}}\right) 

Lowest Low: lowest low for the look-back period

Highest High: highest high for the look-back period

Close: closing price

%R: Williams %R indicator

The Williams %R indicator is also covered in our study called Which Is The Best Indicator For Swing Trading?


This tutorial will use the Vanguard Total Intl Stock Idx Fund (VXUS) ETF. The period of study is from the year 2011 to the year 2023.

Python Implementation

The first step is to import the Python libraries and download the historical data:

The above image shows two functions: download_data and download_data_old. They both download data from Yahoo Finance.

The download_data function has two parameters: security_name and *argsmeanwhile, the download_data_old function has three parameters: security_name, start, and end

The main difference between the implementations is the term “*args“. This term means there is no limit to the number of parameters to add. In the download_data function body, image args[0] and args[1] are the first and second arguments of *args, which are start and end, respectively.

The implementation and output of the download_data function is:

Although, the start date to request data is the year 2000. The first date in the dataset is “2011-01-28”. This is because its inception date was 2011-01-26.

Williams %R and RSI Indicators Plots

This section will use the ta Python package to calculate the Williams %R and the RSI indicators. Next, it will construct the plot_data function to plot the closing price and both indicators.

The following image shows the ta.momentum.williams_r function. It calculates the Williams %R indicator. This function has four parameters high, low, close, and lbp; the term lbp is the look-back window.

The ta.momentum.RSIIndicator function calculates the RSI using close price and window (look-back) as parameters. The Python commands print(williamsr) and print(rsi) show the outputs.

The plot_data function displays three charts: the closing price at the top, the Williams %R indicator in the middle, and the RSI indicator at the bottom. The function has four parameters: data, indicator1, indicator2, and *argsThe *args input has four parameters.

The first parameter in *args is a tuple with the Williams %R thresholds. The second parameter is a list with the RSI thresholds. The third parameter is a list with the name of the indicators.

The last parameter is a string with the financial instrument name. To divide the plot into three subplots, use the f, (a0, a1, a2) = plt.subplots(3, 1, gridspec_kw={‘height_ratios’: [3, 2, 2]}) command.

The subplots will be arranged in one column, with one above the other (three rows and one column). The a0, a1, and a2 indicates the first, second, and third plot respectively.

The chart is:

The previous image shows three charts in one frame. The charts aim to analyze the movement in the closing price by visualizing the two indicators.

The Williams %R indicator, the green time series, generates too many signals. Each signal occurs when the indicator is above the upper threshold or below the lower threshold.

It seems it will overtrade, placing too many long or short positions. The RSI indicator, the series in red color, shows fewer buy and sell signals. By adding this indicator, the strategy probably can reduce false signals generated by the Williams %R indicator.

Trading Strategies

This section will create two trading strategies. The first strategy will use only the Williams %R indicator. The second strategy will use both the Williams %R and the RSI indicators.

The first strategy is:

Go long when the Williams %R indicator crosses below -80%, and hold the position until it crosses above -20%.

Go short when the Williams %R indicator crosses above -20%, and hold the position until it crosses below -80%.

This strategy uses the default thresholds, -80% and -20%, of the Williams R to obtain the overbought and oversold bands.

The second strategy is:

Go long if the Williams %R indicator goes below -80% and the RSI goes below 30. Keep this position until the Williams %R indicator crosses above -20% and the RSI crosses above 70%.

Go short if the Williams %R indicator goes above -20% and the RSI goes above 70. Keep this position until the Williams %R indicator crosses below -80% and the RSI crosses below 30%.

The bands (or thresholds) are the default values. You can modify those values.

The next image displays the calculate_signal function. The function calculates the buy and sell signals for the Williams %R indicator. It generates a time series with values minus one (-1) or one (1).

This function has three input parameters: williamsindicator, threshold1, and threshold2. These parameters are the time series with the Williams %R indicator and its thresholds.

The body of the function uses a for loop (for value in williamsindicator) to check if there is a long position (position = 1) or a short position (position = -1). If none of these conditions are true, position stays the same as its previous value (position = position). Finally, the value is appended to the signal list.

The next image shows the calculate_mix_signals function. It calculates the second strategy that mixes the Williams %R Indicator and the RSI. You can pass as many input parameters as you wish to this function using **kwargs. Inside of the function, the first line shows print(“\n*KWARGS VALUES :”,kwargs, type(kwargs)).

In the output above, type(kwargs) is a Python dictionary. This means you can use the key name to access its values. Afterward, the function loops through for willimasvalue, rsivalue in zip(williamsindicator, rsindicator).

Inside the loop, it checks if willimasvalue > threshold1 and rsivalue < rsithreshold1. If both conditions are true, position =-1 (a short position). Also, the loop will check if willimasvalue < threshold2 and rsivalue > rsithreshold2. If both conditions are true, position = 1 (a long position).

The following image shows the function to calculate the equity from the strategies.

The result for the first strategy:

The previous images show a strategy with positive results, but since 2019 has lost more than 50%.

The result of the second strategy:

This strategy enhances the previous strategy and reduces the drawdown (or price decline) in the last five years of the time series.

This trading strategy is adapted to VXUS ETF. So, the same strategy might not perform well with another financial instrument. Because each financial instrument behaves differently.


What is the Williams %R indicator, and how does it work in trading?

The Williams %R indicator is a momentum indicator that helps identify entry and exit points in a trade. It measures the relationship between the closing price and the highest high and lowest low in a specified look-back period, providing insights into overbought and oversold conditions.

Why is the Williams %R strategy enhanced by adding the RSI indicator?

The Williams %R strategy alone may generate numerous signals, potentially leading to overtrading. By adding the RSI (Relative Strength Index) indicator, the strategy aims to filter out false signals and improve overall performance. The calculation for the Williams %R indicator is: %R = -100 * ((Highest High – Close) / (Highest High – Lowest Low)), where Highest High and Lowest Low are the extreme values in the specified look-back period.

How can I adapt these strategies for different financial instruments?

While the tutorial provides strategies tailored to the VXUS ETF, it emphasizes that each financial instrument behaves differently. Traders should adapt and test these strategies based on the characteristics of the specific instrument they are trading.

Similar Posts