Free AI web copilot to create summaries, insights and extended knowledge, download it at here
7423
Abstract
o lower. One should always remember that this indicator is very lagging and therefore has to be used with extreme caution.</p><p id="a101">Since it has been created by Wilder Wiles, also the creator of the Relative Strength Index, it uses Wilder’s own type of moving average, the smoothed kind. To simplify things, the smoothed moving average can be found through a simple transformation of the exponential moving average.</p><figure id="ef99"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*kcMsTOLJ3uJyUeN_.png"><figcaption></figcaption></figure><p id="485e">The above formula means that a 100 smoothed moving average is the same thing as (100 x 2) -1 = 199 exponential moving average. While we are on that, we can code the exponential moving average using this function:</p><div id="b794"><pre><span class="hljs-keyword">def</span> <span class="hljs-title function_">ma</span>(<span class="hljs-params">Data, lookback, what, where</span>):
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-built_in">len</span>(Data)):
<span class="hljs-keyword">try</span>:
Data[i, where] = (Data[i - lookback + <span class="hljs-number">1</span>:i + <span class="hljs-number">1</span>, what].mean())
<span class="hljs-keyword">except</span> IndexError:
<span class="hljs-keyword">pass</span>
<span class="hljs-keyword">return</span> Data</pre></div><div id="7a41"><pre>def ema(Data, alpha, lookback, what, <span class="hljs-built_in">where</span>):
<span class="hljs-comment"># alpha is the smoothing factor</span>
<span class="hljs-comment"># window is the lookback period</span>
<span class="hljs-comment"># what is the column that needs to have its average calculated</span>
<span class="hljs-comment"># where is where to put the exponential moving average</span>
alpha = alpha / (lookback + 1.0)
beta = 1 - alpha
<span class="hljs-comment"># First value is a simple SMA</span>
Data = ma(Data, lookback, what, <span class="hljs-built_in">where</span>)
<span class="hljs-comment"># Calculating first EMA</span>
Data[lookback + 1, <span class="hljs-built_in">where</span>] = (Data[lookback + 1, what] * alpha) + (Data[lookback, <span class="hljs-built_in">where</span>] * beta)</pre></div><div id="3da7"><pre><span class="hljs-comment"># Calculating the rest of EMA</span>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(lookback + <span class="hljs-number">2</span>, <span class="hljs-built_in">len</span>(Data)):
<span class="hljs-keyword">try</span>:
Data[i, where] = (Data[i, what] * alpha) + (Data[i - <span class="hljs-number">1</span>, where] * beta)
<span class="hljs-keyword">except</span> IndexError:
<span class="hljs-keyword">pass</span>
<span class="hljs-keyword">return</span> Data</pre></div><p id="8783">Below is the function code that calculates the ATR.</p><div id="b80a"><pre>def atr(<span class="hljs-keyword">data</span>, lookback, high, low, close, <span class="hljs-keyword">where</span>):
<span class="hljs-keyword">data</span> = adder(<span class="hljs-keyword">data</span>, <span class="hljs-number">1</span>)
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(<span class="hljs-keyword">data</span>)):
<span class="hljs-keyword">try</span>:
<span class="hljs-keyword">data</span>[i, <span class="hljs-keyword">where</span>] = max(<span class="hljs-keyword">data</span>[i, high] - <span class="hljs-keyword">data</span>[i, low], abs(<span class="hljs-keyword">data</span>[i, high] - <span class="hljs-keyword">data</span>[i - <span class="hljs-number">1</span>, close]), abs(<span class="hljs-keyword">data</span>[i, low] - <span class="hljs-keyword">data</span>[i - <span class="hljs-number">1</span>, close]))
except ValueError:
pass
<span class="hljs-keyword">data</span>[<span class="hljs-number">0</span>, <span class="hljs-keyword">where</span>] = <span class="hljs-number">0</span>
<span class="hljs-keyword">data</span> = ema(<span class="hljs-keyword">data</span>, <span class="hljs-number">2</span>, (lookback * <span class="hljs-number">2</span>) - <span class="hljs-number">1</span>, <span class="hljs-keyword">where</span>, <span class="hljs-keyword">where</span> + <span class="hljs-number">1</span>)</pre></div><div id="e149"><pre><span class="hljs-keyword">data</span> = deleter(<span class="hljs-keyword">data</span>, <span class="hljs-keyword">where</span>, <span class="hljs-number">1</span>)
<span class="hljs-keyword">data</span> = jump(<span class="hljs-keyword">data</span>, lookback)
<span class="hljs-keyword">return</span> <span class="hljs-keyword">data</span></pre></div><p id="3950">Let us try applying the code on OHLC data and see the plot of a 14-period Average True Range:</p><div id="da61"><pre><span class="hljs-attr">my_data</span> = atr(my_data, <span class="hljs-number">14</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>)</pre></div><figure id="8f6c"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*AI40oZyZ11lSAGcg.png"><figcaption><b>EURUSD daily values in the first panel with the 14-period Average True Range in the second panel.</b></figcaption></figure><p id="0934">Now we are ready to continue with the choppiness index. Let us consider that we will calculate a 20-period Average True Range on our OHLC historical data:</p><div id="0afd"><pre><span class="hljs-comment"># Adding a few columns</span>
<span class="hljs-attr">my_data</span> = adder(my_data, <span class="hljs-number">10</span>)</pre></div><div id="4e56"><pre><span class="hljs-comment"># Calculating a 20-period ATR</span>
<span class="hljs-attr">my_data</span> = atr(my_data, <span class="hljs-number">20</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>)</pre></div><p id="fe8e">Now, the first step into the indicator is, to sum up, the values of the ATR together. This intuition can be coded in the following manner (Full function code provided below):</p><div id="d525"><pre><span class="hljs-comment"># Calculating the Sum of ATR's (atr_col is the index where the ATR is stored, in our example, it is 4)</span>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-built_in">len</span>(my_data)):</pre></div><div id="8d39"><pre>my_data[i, <span class="hljs-built_in">where</span>] = my_data[i - lookback + 1:i + 1, atr_col].<span class="hljs-built_in">sum</span>()</pre></div><p id="f3d8">Now, we have to calculate the range from the highest to lowest using the max() and min() built-in functions. The code should resemble the following:</p><div id="4e6e"><pre><span class="hljs-comment"># Calculating the range</span>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">ran
Options
ge</span>(<span class="hljs-built_in">len</span>(my_data)):
<span class="hljs-keyword">try</span>:
my_data[i, <span class="hljs-number">5</span>] = <span class="hljs-built_in">max</span>(my_data[i - lookback + <span class="hljs-number">1</span>:i + <span class="hljs-number">1</span>, <span class="hljs-number">1</span>] - <span class="hljs-built_in">min</span>(my_data[i - lookback + <span class="hljs-number">1</span>:i + <span class="hljs-number">1</span>, <span class="hljs-number">2</span>]))
<span class="hljs-keyword">except</span>:
<span class="hljs-keyword">pass</span></pre></div><p id="8dd6">Next, we calculate the ratio between the two measures we have just derived. The code can be as simple as:</p><div id="6fde"><pre><span class="hljs-comment"># Calculating the Ratio</span>
<span class="hljs-section">my_data[:, 6] = my_data[:, 4] / my_data[:, 5]</span></pre></div><p id="90b7">And finally, we simply apply the function as presented above, using this code:</p><div id="2f0c"><pre># <span class="hljs-function">Calculate the Choppiness Index
<span class="hljs-keyword">for</span> i in <span class="hljs-title">range</span><span class="hljs-params">(len(Data))</span>:
Data[i, <span class="hljs-number">7</span>] =</span> <span class="hljs-number">100</span> * np.<span class="hljs-built_in">log</span>(Data[i, <span class="hljs-number">6</span>]) * (<span class="hljs-number">1</span> / np.<span class="hljs-built_in">log</span>(<span class="hljs-number">20</span>))</pre></div><figure id="84eb"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*Pdavt5otr708my32.png"><figcaption><b>EURUSD in the first panel with the 20-period Choppiness Index in the second panel.</b></figcaption></figure><div id="a88b"><pre><span class="hljs-keyword">def</span> <span class="hljs-title function_">choppiness_index</span>(<span class="hljs-params">Data, lookback, high, low, where</span>):
<span class="hljs-comment"># Calculating the Sum of ATR's</span>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-built_in">len</span>(Data)):
Data[i, where] = Data[i - lookback + <span class="hljs-number">1</span>:i + <span class="hljs-number">1</span>, <span class="hljs-number">4</span>].<span class="hljs-built_in">sum</span>()
<span class="hljs-comment"># Calculating the range</span>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> <span class="hljs-built_in">range</span>(<span class="hljs-built_in">len</span>(Data)):
<span class="hljs-keyword">try</span>:
Data[i, where + <span class="hljs-number">1</span>] = <span class="hljs-built_in">max</span>(Data[i - lookback + <span class="hljs-number">1</span>:i + <span class="hljs-number">1</span>, <span class="hljs-number">1</span>] - <span class="hljs-built_in">min</span>(Data[i - lookback + <span class="hljs-number">1</span>:i + <span class="hljs-number">1</span>, <span class="hljs-number">2</span>]))
<span class="hljs-keyword">except</span>:
<span class="hljs-keyword">pass</span></pre></div><div id="26e1"><pre><span class="hljs-comment"># Calculating the Ratio</span>
Data[:, <span class="hljs-built_in">where</span> + 2] = Data[:, <span class="hljs-built_in">where</span>] / Data[:, <span class="hljs-built_in">where</span> + 1]
<span class="hljs-comment"># Calculate the Choppiness Index</span>
<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(Data)):
Data[i, <span class="hljs-built_in">where</span> + 3] = 100 * np.log(Data[i, <span class="hljs-built_in">where</span> + 2]) * (1 / np.log(lookback))</pre></div><div id="afbd"><pre><span class="hljs-comment"># Cleaning</span>
Data = deleter(Data, 5, 3)
<span class="hljs-built_in">return</span> Data</pre></div><figure id="0506"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*Pus4gyPeLlz_vLbr.png"><figcaption><b>USDCHF in the first panel with the 20-period Choppiness Index in the second panel.</b></figcaption></figure><p id="a466">The choppiness index function can therefore be called using the following code:</p><div id="c8a9"><pre><span class="hljs-attr">my_data</span> = choppiness_index(my_data, <span class="hljs-number">20</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">4</span>)</pre></div><figure id="4ed9"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*_oe4B9oeIE-hr1Yz.png"><figcaption><b>GBPUSD in the first panel with the 20-period Choppiness Index in the second panel.</b></figcaption></figure><h1 id="f15a">Using the Choppiness Index</h1><p id="549d">The way to use the choppiness index is to place the barriers by default at 38.2% and 61.8%, then we interpret the readings as follow:</p><ul><li><b>Readings above 61.8% indicate a choppy market that is bound to breakout. We should be ready for some directional.</b></li><li><b>Readings below 38.2% indicate a strong trending market that is bound to stabilize. Hence, it may not be the best idea to follow the trend at the moment.</b></li></ul><figure id="7bc6"><img src="https://cdn-images-1.readmedium.com/v2/resize:fit:800/0*MA4E4UosNty1IRHD.png"><figcaption><b>EURCAD in the first panel with the 20-period Choppiness Index in the second panel.</b></figcaption></figure><p id="3618">If you want to see how to create all sorts of algorithms yourself, feel free to check out Lumiwealth. From algorithmic trading to blockchain and machine learning, they have <i>hands-on</i> detailed courses that I highly recommend.</p><div id="fead" class="link-block">
<a href="https://www.lumiwealth.com/algorithmic-trading-landing-page/?utm_source=influence&utm_medium=medium&utm_campaign=sofien">
<div>
<div>
<h2>Learn Algorithmic Trading with Python Lumiwealth</h2>
<div><h3>undefined</h3></div>
<div><p>undefined</p></div>
</div>
<div>
<div style="background-image: url(https://miro.readmedium.com/v2/resize:fit:320/0*FbCz_ARtbOdywMlC)"></div>
</div>
</div>
</a>
</div><h1 id="e420">Summary</h1><p id="05a4">To sum 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 subjective and scientifically unfounded.</p><p id="5d41">I recommend you always follow the the below steps whenever you come across a trading technique or strategy:</p><ul><li><i>Have a critical mindset and get rid of any emotions.</i></li><li><i>Back-test it using real life simulation and conditions.</i></li><li><i>If you find potential, try optimizing it and running a forward test.</i></li><li><i>Always include transaction costs and any slippage simulation in your tests.</i></li><li><i>Always include risk management and position sizing in your tests.</i></li></ul><p id="beb3">Finally, even after making sure of the above, stay careful and monitor the strategy because market dynamics may shift and make the strategy unprofitable.</p></article></body>