<p><div><div><div><div data-show-faces="false" data-height="21" data-width="100" data-layout="button_count" data-send="true" data-href="https://www.r-bloggers.com/updated-overboughtoversold-plot-function/"></div></div><div></div></div><div></div></div>
<div>
(This article was first published on <strong><a href="http://dirk.eddelbuettel.com/blog/2017/07/29#updated_overbought_oversold_plot"> Thinking inside the box </a></strong>, and kindly contributed to <a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers)</a> </div>
<p>A good six years ago I <a rel="nofollow" href="http://dirk.eddelbuettel.com/blog/2011/01/16#overbought_oversold_plot" target="_blank">blogged about <code>plotOBOS()</code></a> which charts a moving average (from one of several available variants) along with shaded standard deviation bands. That post has a bit more background on the why/how and motivation, but as a teaser here is the resulting chart of the SP500 index (with ticker ^GSCP):</p>
<p><img alt="Example chart of overbought/oversold levels from plotOBOS() function" src="https://i2.wp.com/dirk.eddelbuettel.com/blog/code/snippets/sp500obos.png?w=456" data-recalc-dims="1"> </p>
<p>The code uses a few standard finance packages for R (with most of them maintained by <a rel="nofollow" href="http://joshuaulrich.com/" target="_blank">Joshua Ulrich</a> given that <a rel="nofollow" href="https://github.com/jaryan" target="_blank">Jeff Ryan</a>, who co-wrote chunks of these, is effectively retired from public life). Among these, <a rel="nofollow" href="https://cran.r-project.org/package=xts" target="_blank">xts</a> had a recent release reflecting changes which occurred during the four (!!) years since the previous release, and covering at least two <a rel="nofollow" href="https://developers.google.com/open-source/gsoc/" target="_blank">GSoC</a> projects. With that came subtle API changes: something we all generally try to avoid but which is at times the only way forward. In this case, the shading code I used (via <code>polygon()</code> from base R) no longer cooperated with the beefed-up functionality of <code>plot.xts()</code>. Luckily, <a rel="nofollow" href="https://github.com/rossb34" target="_blank">Ross Bennett</a> incorporated that same functionality into a new function <a rel="nofollow" href="https://www.rdocumentation.org/packages/xts/versions/0.10-0/topics/addPolygon?tap_a=5644-dce66f&tap_s=10907-287229" target="_blank"><code>addPolygon</code></a> — which even credits this <a rel="nofollow" href="http://dirk.eddelbuettel.com/blog/2011/01/16#overbought_oversold_plot" target="_blank">same post of mine</a>.</p>
<p>With that, the updated code becomes</p>
<div>
<pre><code>## plotOBOS -- displaying overbough/oversold as eg in Bespoke's plots
##
## Copyright (C) 2010 - 2017  Dirk Eddelbuettel
##
## This is free software: you can redistribute it and/or modify it
## under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 2 of the License, or
## (at your option) any later version.

<span>suppressMessages</span>(<span>library</span>(quantmod))     <span># for getSymbols(), brings in xts too</span>
<span>suppressMessages</span>(<span>library</span>(TTR))          <span># for various moving averages</span>

plotOBOS &lt;-<span> </span><span>function</span>(symbol, <span>n=</span><span>50</span>, <span>type=</span><span>c</span>(<span>&quot;sma&quot;</span>, <span>&quot;ema&quot;</span>, <span>&quot;zlema&quot;</span>),
                     <span>years=</span><span>1</span>, <span>blue=</span><span>TRUE</span>, <span>current=</span><span>TRUE</span>, <span>title=</span>symbol,
                     <span>ticks=</span><span>TRUE</span>, <span>axes=</span><span>TRUE</span>) {

    today &lt;-<span> </span><span>Sys.Date</span>()
    <span>if</span> (<span>class</span>(symbol) <span>==</span><span> &quot;character&quot;</span>) {
        X &lt;-<span> </span><span>getSymbols</span>(symbol, <span>from=</span><span>format</span>(today<span>-</span><span>365</span><span>*</span>years<span>-</span><span>2</span><span>*</span>n), <span>auto.assign=</span><span>FALSE</span>)
        x &lt;-<span> </span>X[,<span>6</span>]                          <span># use Adjusted</span>
    } <span>else</span> <span>if</span> (<span>inherits</span>(symbol, <span>&quot;zoo&quot;</span>)) {
        x &lt;-<span> </span>X &lt;-<span> </span><span>as.xts</span>(symbol)
        current &lt;-<span> </span><span>FALSE</span>                <span># don't expand the supplied data</span>
    }

    n &lt;-<span> </span><span>min</span>(<span>nrow</span>(x)<span>/</span><span>3</span>, <span>50</span>)             <span># as we may not have 50 days</span>

    sub &lt;-<span> &quot;&quot;</span>
    <span>if</span> (current) {
        xx &lt;-<span> </span><span>getQuote</span>(symbol)
        xt &lt;-<span> </span><span>xts</span>(xx<span>$</span>Last, <span>order.by=</span><span>as.Date</span>(xx<span>$</span><span>`</span><span>Trade Time</span><span>`</span>))
        <span>colnames</span>(xt) &lt;-<span> </span><span>paste</span>(symbol, <span>&quot;Adjusted&quot;</span>, <span>sep=</span><span>&quot;.&quot;</span>)
        x &lt;-<span> </span><span>rbind</span>(x, xt)
        sub &lt;-<span> </span><span>paste</span>(<span>&quot;Last price: &quot;</span>, xx<span>$</span>Last, <span>&quot; at &quot;</span>,
                     <span>format</span>(<span>as.POSIXct</span>(xx<span>$</span><span>`</span><span>Trade Time</span><span>`</span>), <span>&quot;%H:%M&quot;</span>), <span>sep=</span><span>&quot;&quot;</span>)
    }

    type &lt;-<span> </span><span>match.arg</span>(type)
    xd &lt;-<span> </span><span>switch</span>(type,                  <span># compute xd as the central location via selected MA smoother</span>
                 <span>sma =</span> <span>SMA</span>(x,n),
                 <span>ema =</span> <span>EMA</span>(x,n),
                 <span>zlema =</span> <span>ZLEMA</span>(x,n))
    xv &lt;-<span> </span><span>runSD</span>(x, n)                   <span># compute xv as the rolling volatility</span>

    strt &lt;-<span> </span><span>paste</span>(<span>format</span>(today<span>-</span><span>365</span><span>*</span>years), <span>&quot;::&quot;</span>, <span>sep=</span><span>&quot;&quot;</span>)
    x  &lt;-<span> </span>x[strt]                       <span># subset plotting range using xts' nice functionality</span>
    xd &lt;-<span> </span>xd[strt]
    xv &lt;-<span> </span>xv[strt]

    xyd &lt;-<span> </span><span>xy.coords</span>(<span>.index</span>(xd),xd[,<span>1</span>]) <span># xy coordinates for direct plot commands</span>
    xyv &lt;-<span> </span><span>xy.coords</span>(<span>.index</span>(xv),xv[,<span>1</span>])

    n &lt;-<span> </span><span>length</span>(xyd<span>$</span>x)
    xx &lt;-<span> </span>xyd<span>$</span>x[<span>c</span>(<span>1</span>,<span>1</span><span>:</span>n,n<span>:</span><span>1</span>)]           <span># for polygon(): from first point to last and back</span>

    <span>if</span> (blue) {
        blues5 &lt;-<span> </span><span>c</span>(<span>&quot;#EFF3FF&quot;</span>, <span>&quot;#BDD7E7&quot;</span>, <span>&quot;#6BAED6&quot;</span>, <span>&quot;#3182BD&quot;</span>, <span>&quot;#08519C&quot;</span>) <span># cf brewer.pal(5, &quot;Blues&quot;)</span>
        fairlylight &lt;-<span> </span><span>rgb</span>(<span>189</span><span>/</span><span>255</span>, <span>215</span><span>/</span><span>255</span>, <span>231</span><span>/</span><span>255</span>, <span>alpha=</span><span>0.625</span>) <span># aka blues5[2]</span>
        verylight &lt;-<span> </span><span>rgb</span>(<span>239</span><span>/</span><span>255</span>, <span>243</span><span>/</span><span>255</span>, <span>255</span><span>/</span><span>255</span>, <span>alpha=</span><span>0.625</span>) <span># aka blues5[1]</span>
        dark &lt;-<span> </span><span>rgb</span>(<span>8</span><span>/</span><span>255</span>, <span>81</span><span>/</span><span>255</span>, <span>156</span><span>/</span><span>255</span>, <span>alpha=</span><span>0.625</span>) <span># aka blues5[5]</span>
        ## buglet in xts 0.10-0 requires the &lt;- here
    } <span>else</span> {
        fairlylight &lt;-<span> </span><span>rgb</span>(<span>204</span><span>/</span><span>255</span>, <span>204</span><span>/</span><span>255</span>, <span>204</span><span>/</span><span>255</span>, <span>alpha=</span><span>0.5</span>)  <span># two suitable grays, alpha-blending at 50%</span>
        verylight &lt;-<span> </span><span>rgb</span>(<span>242</span><span>/</span><span>255</span>, <span>242</span><span>/</span><span>255</span>, <span>242</span><span>/</span><span>255</span>, <span>alpha=</span><span>0.5</span>)
        dark &lt;-<span> 'black'</span>
    }

    <span>plot</span>(x, <span>ylim=</span><span>range</span>(<span>range</span>(x, xd<span>+</span><span>2</span><span>*</span>xv, xd<span>-</span><span>2</span><span>*</span>xv, <span>na.rm=</span><span>TRUE</span>)), <span>main=</span>title, <span>sub=</span>sub, 
         <span>major.ticks=</span>ticks, <span>minor.ticks=</span>ticks, <span>axes=</span>axes) <span># basic xts plot setup</span>
    <span>addPolygon</span>(<span>xts</span>(<span>cbind</span>(xyd<span>$</span>y<span>+</span>xyv<span>$</span>y, xyd<span>$</span>y<span>+</span><span>2</span><span>*</span>xyv<span>$</span>y), <span>order.by=</span><span>index</span>(x)), <span>on=</span><span>1</span>, <span>col=</span>fairlylight)  <span># upper</span>
    <span>addPolygon</span>(<span>xts</span>(<span>cbind</span>(xyd<span>$</span>y<span>-</span>xyv<span>$</span>y, xyd<span>$</span>y<span>+</span><span>1</span><span>*</span>xyv<span>$</span>y), <span>order.by=</span><span>index</span>(x)), <span>on=</span><span>1</span>, <span>col=</span>verylight)    <span># center</span>
    <span>addPolygon</span>(<span>xts</span>(<span>cbind</span>(xyd<span>$</span>y<span>-</span>xyv<span>$</span>y, xyd<span>$</span>y<span>-</span><span>2</span><span>*</span>xyv<span>$</span>y), <span>order.by=</span><span>index</span>(x)), <span>on=</span><span>1</span>, <span>col=</span>fairlylight)  <span># lower</span>
    <span>lines</span>(xd, <span>lwd=</span><span>2</span>, <span>col=</span>fairlylight)   <span># central smooted location</span>
    <span>lines</span>(x, <span>lwd=</span><span>3</span>, <span>col=</span>dark)           <span># actual price, thicker</span>
}</code></pre>
</div>
<p>and the main change are the three calls to <code>addPolygon</code>. To illustrate, we call <code>plotOBOS(&quot;SPY&quot;, years=2)</code> with an updated plot of the ETF representing the SP500 over the last two years:</p>
<p><img alt="Updated example chart of overbought/oversold levels from plotOBOS() function" src="https://i2.wp.com/dirk.eddelbuettel.com/blog/code/snippets/spyOBOS_2017.png?w=456" data-recalc-dims="1"> </p>
<p>Comments and further enhancements welcome!</p>
<p>
This post by <a rel="nofollow" href="http://dirk.eddelbuettel.com/" target="_blank">Dirk Eddelbuettel</a> originated on his <a rel="nofollow" href="http://dirk.eddelbuettel.com/blog/" target="_blank">Thinking inside the box</a> blog. Please report excessive re-aggregation in third-party for-profit settings.</p>
<p>
	<p>
<div>
<div>To <strong>leave a comment</strong> for the author, please follow the link and comment on their blog: <strong><a href="http://dirk.eddelbuettel.com/blog/2017/07/29#updated_overbought_oversold_plot"> Thinking inside the box </a></strong>.</div>
<hr>
<a rel="nofollow" href="https://www.r-bloggers.com/">R-bloggers.com</a> offers <strong><a rel="nofollow" href="https://feedburner.google.com/fb/a/mailverify?uri=RBloggers">daily e-mail updates</a></strong> about <a rel="nofollow" href="https://www.r-project.org/" title="The R Project for Statistical Computing">R</a> news and <a rel="nofollow" href="https://www.r-bloggers.com/search/tutorial" title="R tutorials">tutorials</a> on topics such as: <a rel="nofollow" href="https://www.r-bloggers.com/search/data%20science" title="Data science">Data science</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Big%20Data" title="Big Data">Big Data, <a rel="nofollow" href="https://www.r-users.com/" title="R jobs">R jobs</a>, visualization (<a rel="nofollow" href="https://www.r-bloggers.com/search/ggplot2" title="ggplot and ggplot2 tutorials">ggplot2</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/boxplot" title="Boxplots using lattice and ggplot2 tutorials">Boxplots</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/map" title="Maps and gis">maps</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/animation" title="Animation in R">animation</a>), programming (<a rel="nofollow" href="https://www.r-bloggers.com/search/RStudio" title="RStudio IDE for R">RStudio</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/sweave" title="Sweave and literate programming">Sweave</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/LaTeX" title="LaTeX in R">LaTeX</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/SQL" title="SQL and databases">SQL</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/eclipse" title="Eclipse IDE for R">Eclipse</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/git" title="git and github, Version Control System">git</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/hadoop" title="Large data in R using Hadoop">hadoop</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/Web+Scraping" title="Web Scraping of google, facebook, yahoo, twitter and more using R">Web Scraping</a>) statistics (<a rel="nofollow" href="https://www.r-bloggers.com/search/regression" title="Regressions and ANOVA analysis tutorials">regression</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/PCA" title="principal component analysis tutorial">PCA</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/time+series" title="Time series">time series</a>, <a rel="nofollow" href="https://www.r-bloggers.com/search/trading" title="finance trading">trading</a>) and more...
<img width="1" alt="" src="http://feeds.feedburner.com/~r/RBloggers/~4/mRRXzg-gI3w" height="1"></a></div>