TTR/0000755000176200001440000000000014531274225010730 5ustar liggesusersTTR/NAMESPACE0000644000176200001440000000246514531142730012151 0ustar liggesusersexport(ADX) export(ALMA) export(ATR) export(BBands) export(CCI) export(CLV) export(CMF) export(CMO) export(CTI) export(DEMA) export(DPO) export(DVI) export(DonchianChannel) export(EMA) export(EMV) export(EVWMA) export(GMMA) export(HMA) export(KST) export(MACD) export(MFI) export(OBV) export(PBands) export(ROC) export(RSI) export(SAR) export(SMA) export(SMI) export(SNR) export(TDI) export(TR) export(TRIX) export(VHF) export(VWAP) export(VWMA) export(WMA) export(WPR) export(ZLEMA) export(ZigZag) export(adjRatios) export(aroon) export(chaikinAD) export(chaikinVolatility) export(getYahooData) export(growth) export(keltnerChannels) export(lags) export(momentum) export(naCheck) export(rollSFM) export(runCor) export(runCov) export(runMAD) export(runMax) export(runMean) export(runMedian) export(runMin) export(runPercentRank) export(runSD) export(runSum) export(runVar) export(stoch) export(stockSymbols) export(ultimateOscillator) export(volatility) export(wilderSum) export(williamsAD) import(xts) import(zoo) importFrom(curl,curl_download) importFrom(curl,new_handle) importFrom(stats,approx) importFrom(stats,embed) importFrom(stats,na.omit) importFrom(stats,sd) importFrom(stats,cor) importFrom(utils,flush.console) importFrom(utils,read.csv) importFrom(utils,read.table) useDynLib(TTR, .registration = TRUE, .fixes = "C_") TTR/THANKS0000644000176200001440000000053014450607776011654 0ustar liggesusersIn no particular order: - I can't thank Jeff Ryan enough for all his help with TTR via: motivation to submit TTR to CRAN, helpful comments, testing, and providing an example Fortran implementation of 'EMA' (from which all other included Fortran functions are based). - Many thanks to Ion Georgiadis for helpful suggestions and testing. TTR/README.md0000644000176200001440000000715014531225347012213 0ustar liggesusers### About TTR is an [R](https://www.r-project.org) package that provides the most popular technical analysis functions for financial market data. Many of these functions are used as components of systematic trading strategies and financial charts. ### TTR for enterprise Available as part of the Tidelift Subscription. The maintainers of `TTR` and thousands of other packages are working with Tidelift to deliver commercial support and maintenance for the open source dependencies you use to build your applications. Save time, reduce risk, and improve code health, while paying the maintainers of the exact dependencies you use. [Learn more.](https://tidelift.com/subscription/pkg/cran-ttr?utm_source=cran-ttr&utm_medium=referral&utm_campaign=enterprise&utm_term=repo) ### Supporting TTR development If you are interested in supporting the ongoing development and maintenance of TTR, please consider [becoming a sponsor](https://github.com/sponsors/joshuaulrich). ### Installation The current release is available on [CRAN](https://CRAN.R-project.org/package=TTR), which you can install via: ```r install.packages("TTR") ``` To install the development version, you need to clone the repository and build from source, or run one of: ```r # lightweight remotes::install_github("joshuaulrich/TTR") # or devtools::install_github("joshuaulrich/TTR") ``` You will need tools to compile C, C++, and Fortran code. See the relevant appendix in the [R Installation and Administration manual](https://cran.r-project.org/doc/manuals/r-release/R-admin.html) for your operating system: - [Windows](https://cran.r-project.org/doc/manuals/r-release/R-admin.html#The-Windows-toolset) - [MacOS](https://cran.r-project.org/doc/manuals/r-release/R-admin.html#macOS) (the [R for Mac OS X Developer's Page](https://mac.R-project.org/) might also be helpful) - [Unix-alike](https://cran.r-project.org/doc/manuals/r-release/R-admin.html#Essential-and-useful-other-programs-under-a-Unix_002dalike) ### Getting Started Here are a few examples of some of the more well-known indicators: ```r # "TTR Composite" (simulated data) data(ttrc) # Bollinger Bands bbands <- BBands( ttrc[,c("High","Low","Close")] ) # Directional Movement Index adx <- ADX(ttrc[,c("High","Low","Close")]) # Moving Averages ema <- EMA(ttrc[,"Close"], n=20) sma <- SMA(ttrc[,"Close"], n=20) # MACD macd <- MACD( ttrc[,"Close"] ) # RSI rsi <- RSI(ttrc[,"Close"]) # Stochastics stochOsc <- stoch(ttrc[,c("High","Low","Close")]) ``` TTR works with the `chartSeries()` function in [quantmod](https://github.com/joshuaulrich/quantmod). Here's an example that uses `chartSeries()` and adds TTR-calculated indicators and overlays to the chart. ```r # "TTR Composite" (simulated data) data(ttrc) # Use quantmod's OHLCV extractor function to help create an xts object xttrc <- xts(OHLCV(ttrc), ttrc[["Date"]]) chartSeries(xttrc, subset = "2006-09/", theme = "white") addBBands() addRSI() ``` ![](https://drive.google.com/uc?export=view&id=1TrgoZujgcI9GCMEWHlDgzkQQvBItyLwq) ###### Have a question? Ask your question on [Stack Overflow](https://stackoverflow.com/questions/tagged/r) or the [R-SIG-Finance](https://stat.ethz.ch/mailman/listinfo/r-sig-finance) mailing list (you must subscribe to post). ### Contributing Please see the [Contributing Guide](https://github.com/joshuaulrich/TTR/wiki/Contributing-Guide). ### See Also - [quantmod](https://CRAN.R-project.org/package=quantmod): quantitative financial modeling framework - [xts](https://CRAN.R-project.org/package=xts): eXtensible Time Series based on [zoo](https://CRAN.R-project.org/package=zoo) ### Author [Joshua Ulrich](https://about.me/joshuaulrich) TTR/data/0000755000176200001440000000000014450607776011654 5ustar liggesusersTTR/data/ttrc.rda0000644000176200001440000024363214450607776013332 0ustar liggesusers yU&ittw֘uoj0(626 "(2ABy H@dU9ʩ_?<{^?onᆗw^ҫƗ\w[_vy?nw\q| wmtõo'4`?}#9gB~ 7_~W_;_3o`%M7~og w~ogVdm1;`석3vllvl.(dOO?,_؟c+ /ľ2vW_co/a7ga]MUnKؗ7ɾ2&-m]={W)4{=˾}-:Q1qI<^`]v!{=b}}ٿʾd?e?쇳~ 7ُe'o`6,>ǟ~*K1>,Y{L?|c{,=>ٯ`1=Zc{~#Kt.c:|tb1=Cvc{Llc{\ ۲tg1=t7Y:|Kw;+,>tc{Lw=c{쟰߿dʮ媥wg߃;WdNcg!v=da Ktw@wKtw@wاX:<;x}oޟ>>(Y;gُctx@wtwxx@twxxx@wxx@w@xxx@wxx@wtw8x@tw@wxxtx@wtwϳtx@wtwxx@tw@wxxtxY;<<;<<z//p.///././/././c./p//p/././/g//./¹Ă////.///2//.///././///.//y/.K,p/.p/qna[YzOx9{w>ރOe|WzvKXzv+gqwvgw~v7gٽ||Ƿ?d|D ~mq|voN#i$;÷da&{o^Ƿd?a]e<߾mOCͷoe;|VǷe;#ķeO|f H ~7~߾/wK|f|f|gA|hzC>}뾃;>o?&߾-gαOۿ7?=}=䰮׳O߳}߾}:߾}&}do.>qBy|}[8"B?bs9>Ⱦ.|3/#Jx$j>ɾK'?n̾1g|}dgo%du}+dk8(7|<}e}/eKٿ{)~qUV>~GºqW6la٘8Y6liقs㸬,>:lyُ^c|O}g 0i>N~=Y>~ ?f#Ǔ/}gǙ/qf|w>~5845>~Gǥodǫw5]>~7߹B| mG|1fwg/8a89>q9s|=89>q99>qq~89>q<:9>q89>q:9>qj89.789.qq~|\9xs\8Źq>>q'89>q\=9>q󽰮s\89.qq|>9.Οqqs\9~s\x89p?9px8| 89?s<~7p,x8x>p78'u8Cs\9.qqsS89.qq89.qqs<_w>\|w89.qq|\8Hs\o8ŹQr\8z>.qqs\%9.qqo :.qq8o8Źmr\8>.qqs\}'9.qq8Ź߃8?8ǹߍr|8qs|K9>qu9>qs?89>q89>qw89>*89ps<x89Εx8 |<x8{Xv>.qq9.qqs89.qq;a]9x8ps.n~+p <\8pN\ݯ.px.px.^.p #..pqu<\.pq|<\x{d <\p <\8.Yp <\p <\.xx3|x.pWx.pw..^u<\.p <\|8xpN\..pq \\|,x ..pq..pqq |\|*>.N\gq |\>.qw]O |\>.qWiWq |\>.q |\|eXqq <\xZ>.p <\}.p.p ..pq..pq..3xÅ <\x>>.p <\ݽ.p.p x.p1xu8E.pp᜸;Qp <\|<\xPPxŏp <\B@..~&븸Ņ..~ \\/qq \\Wx;PPx p <\B=C|\\..pq ..pq \\ ..I..pqWs&J\\F>..3xåz%.._%..qqKu%..qqK\\(qqK\\RDK\\&J\\T7Q>&J|\&J|\T7Qǥ%>.Ot^\RDK|\&J|\T7Qǥa]W/QxT'Qxå:x%.Ix%.pN|\\$J\\T/QGuxT'Qx|N%.pK%.pK<\~x%.Mx%.K8%.qp^%.qpK%.qpKĥzx%.Kx%.pn%.p7pK<\RD|\\o:..qq^%..qqK%..qqK\\(qqK\\%..qqn%..qq^%.pK[%..K%..qq^%..qqK%..qqK\\(qqK\\RDK\\&J\\u%..qq^e%..M%..qqn%..qqKu%..qqK\\(qqK\\RD%>.M%>.qn%>.qKu ||\&J|\||\(qKť%>.M%>.qn%>.qKu%>.qK%..qqKu%.pK<\(*-Y>^u\WQp+<\p+<\JD+<\ WuW8RQ W8 W8W8ppN68R'Q W8: W8IT8GT¿o>¿o圸RQ W8 W8IT8ppNW;p>p+p+<\p+<\JD+<\ W$*<\ W#*\ W8R'Qp+<\p+<\JD+<\ Wo WxÕ: WxKTxp^.pq+.pq+\\ WxÕ: WxKTxp^p+՛xKTxp^RG\ WR/Q Wŕz W.KT.pq^.pq+u.pq].pq+..KT.pq^.pqְ W#*\ W8RQ W8(¿Jp+\J]Dqp+\pp6¿ V¿ET¿o.¿o+o+[o+[JD+[ºVRQ Vz;_}D{+[ʹp>¿o+o+[o+[JD+[pNpp|pp+p* YZpk<\Z}Dk<\k<\x~eXqpkzxõx5Gx5p>5pk5p :x5Ix5pN5pk<\xVQxõ:x5Ix5pN5pku5pk<\ ׸5.׸ŵ:׸5.IԸ5.qqN5.qqk5.qqku5.qqk\\qqk\\ZDk\\$j\\o:pk5pk<\pk<\úk\qpk\Z]Dn5p>5pk5pk<\8o"j\8VQ8:85I85qpN5qpku5qpk\qpk\w88~ $j\8V'Q8:x5pk<\Z}Dk<\#j5.qqk5.qqk\\qqqqku5p]Gk\\#j\\׸VQ׸ŵ׸5.GԸ5.qqN5.qqku5.qqk\\q5.qqk5.qqk\\qqk\\ZDk\\$j\\׸V'Q׸ŵ:׸5.Ik|\$j|\U'7Ǎ:7 >nK4 .nI4|7$|7Q'7Ǎ:7 >npq\7"<7x9uF=D7! np np<ܨhp<78 nC48 npp nppu nppܨh78Q7878 nG48 n>8sF]D7"78Q78ͳ|78Q |<78 nE48 nppNQ'7xQ7xÍ7x nG4xhppF]jfxÍ7xy7"<7xQ7xÍ7x nG4x np> np78QѨnn<6xQ6xy _Cw66xQ6xF]p{FC{66Q6:66΁FC{66Q6'úwu mpns mpnsۨwhpns6 |u:68:68 m;48 mpno|6|6Q6z6 m=4 mm mmnaW[\׶7qmk[\VCk[\ֹoŷ-mmo[u-mmo[|۪hmo[|VCo[|߶Zu-mqns[-mqns[u-mqns[۪{hOnw[۪{hnw[Vow[ZZ8UЪmnw[۪{hnw[VCw[ﶇ|xU>mnŻ-mnw[-mnw[8ŹxŻ-mxŻ-mnŻ-mnw[-mnw[۪hxUoVCŽ-mqoŽ-mqo{[-mqo{[۪hqo{[VC{[ ZZUvqoŽ-mqo&xŻ_u-mqns[۪whqns[߶ŷ-m9[Z:m{[-nqp<ſ-moΡſ-mo[u-mo[۪mo[Vo[ZUſſ-m?ſ-m=ſ-moſ-mo[-mo[۪ho[VC[-nqp[-nqp-nqp[u-nqp[ܪmx-n?x-npv>np_:nqp[uxíx-n=x-np-np[u-np[<ܪhp[ppޡNC;wÿoΡSw8Sw8zw8o;NC;v:=ǿvÿWvÿzvÿ;tÿoÿoưvSvSЩwo;NC;Yvÿ=tÿsw:ιo :ppޡppΡSw8Sw8:w8o;=WЩpp;ܩspp;NC;w:w8Sw8zw8;t8ppޡppyXo;upp;U|w8Sw8zw8;t8ppޡSwxSwxÝzwx;txpޡp;uxzwx;txpޡp;p;upp;ܩspp;NC;ǿ=oW=78=qpΡ=qp{u=qp{u^}C{zWǿz~{۟ :Oqoޡǽ=qo{{=qo{{۫wqo{{;;ǿ=oޡǿ=o{u=o{۫{o{;=8?޹p%8ޡ=qp{xýzx=x=p{zu=p{=p{<ܫwpgxWxýzx==x=p=p{u=p{<ܿ1xýzx==x=p=jj=x=p=p{u=p{<ܫ{=.==.qq=>q{u=>q{|ܫq{\ܫC=>E=>q>>q{|ܫq{|ú{\xý:x=qp{^C{zu=p{u=p{<ܫ+>p.88=?8=qp=qp{=qp{ܫqp{^=D{/qp{ܫov>!z8W88=E8=qp.=p? :qp=qp{Ϫkxx.bxxy#/E,//E,_uTKKTTKqoV5qMzgw~/k~ڏy_?ˮ>udo׫NW9|;܏9|7]:M~y_n;7]͇/;^q<|~W\g |5O{740|bGso|d^n>O7t_o5y ?GzZ??㍿{e2Nq}xߘ/}i#7Wx+3$Y<ߑssJ~|KV~'kɏfb¿<,n6x.yy^G?'xfH}%]xOwѯxyK{_a=Jq|q輱ȯw~J:z{{g%ɏ\OtG?1?yYu#䳷Gu^,s]^c#?#1وĝ_1x> CS>s1w3qny'_oygw]"_"{=ޛlQ=F~w7֑#O=UIV_%ޫ{^k\^WuO?5}Ƒ|O{+ڹxo{'sޛlݼ/.z>qOd~O_}4]}uq8Ƽh?~1|"و1svxvWqZZ?_?Oq> NxnxIG<Ѿ?ǃAyP4Cu8?d^t]b|ރ~h/%$R#.Ko|E<)1?Ɨڋ~Gܴ׭!{׍yxwq]NcGc̣yHyGa{6>euƇwC^OAN4{Xa7;#8r_|O6Xw#޳7=lnvNˋᴼ>Uֿ?ʗu{Oq|ק]s/=i?cΘxy3^?-N˳Sri]>R\c^cG#/"_!o^p]p`+x(8zo^<"nϰnϺ|C'g4a#bн듸/ })w{Oɿdo8g-OBG$ {*Ħv?Bb\Wt=I?E>#c|XUgv;k::1l#3|Z'_~"AG~sjwc_>l\7Db##/I,owO\oF##'NOi$+O/ww@-=eҺțڵ}9!lYQ:6#^B?"_cu =c{c>c-hMc?smD~yc/?}H~7c#_엡/k: Wi_<6z"/v_{<y#b'c_1}1Ѓ8}4:ڋs?gz_j'\? Xn]0gqpyT|&N>~D\l[tM|U?8gl|ߡqN{|/wZn>N1h?8cߊxF?x>~3h7~48nwtOyd|Ǽ;~G?GO 8#[t.[~u( St&ﱎ"|W۵_uyy+g;o~qYCB"o:&+u{G5/`د""?c|~ipPwK|z?wpH\.}"ֺ߃?~5.L>= WGy/rΞ/!ƗNta3i|?3q_ȣn|<;]E;]k׃G{&g=׿#_[O{g?;ڍ|0wYXǑ_߱.\k;w뜞U ȧȏȫ?siu:;~w=OOjN7h_mq|=pwѼvwh/~'8)uK-x 8cg;YMvI;c=9Ϙ35/fǹ|Lg>c?ވ[ϓ~F𣏕w=¼udݤ< ݉ng{u'z 4ϧb_:6Y'<|<Ǽy;3t6|\׮:֟g?8ga~w}}ayKzq׵8c>AZĺ ] П3X%?UgBwpuuGzډu_c]B7"n!v-nɏ |F#1G3h/Io\?= ?]XW߰8~DDy8빳1ϱY:xg'ў=+gu/gzk5qV^Fy?+>No?=.vr:x#1y03]vgMu_z=xj?Qgkkkpka{"?1?#"ݸ?y?q]k#ZqK63u::ϽN^N\5Gѣ_GˣxT?ՏGǣ#c1~Lǭc}:|,.3˧Ǎq~?~vݼ<.k}1Ǽ1q\~>.Ω=yy}L33?Ovv{ݳst =!Ox=n"Oh񈷼DRSqqq:&"N11oxxsss;?޼sjƫsh~zsO'_߹Vq:~}{.z>g|On{R/|v?q=;~y+?Vq}%+o<\I󒞋1ғ{<v_y|zOsWyxVy7o]~^yq?O6|=k}ݻcm^{WnM4M)7Kʟ.N?_ߧ?yg:%vRM_GMq KO"OOZO҇'ƕ4tMy齛qS~nʫMy)7yzn&=v/rӏMzi6M'gS77wS~^)koѵ-u+ܖyܲnk]m7gc|m[m[|sۺܱlG;#wpHeG^O־#v׮vJ׍cW>v|OXW;%׼jvpʎ]L溜K;厼߱Rt{=hޓ{q]ҫt|7{o]e?|ۣ{u_{8rGǾm:ߧ#a_t8#ݾg{q\E=:ϧD{ڿ(O=+쓻}ϺJָ'N??pWԯh/zs|]1{ѕ7yߵȻ-<#iHǶm-:ulg8v.ߴ{tg~GoS\w8B/߮|ލ~]%IcǾOwyz}0ƛtm:?=5DZO~ Ӿ4ߩGb_LJ;qٿyAqߋubqŘgSi~{٤E:QЛxH/Z?E~_G׾<7㾸\}bsB/C#tȼMzzI?qڟϞ}(^[GCwyޥxm}N\Kwۉu:): u$/=I GqKp^G˓4?xw$3_ґ֏IA¶xlɇ-y|-yB|OkNviq%>G&7qn@qp}pޓkS\fӼqs19 -Ωˣ8L:q6}s Ƴe}]{\!o'=bm{ʟ': ii'siﵰ=B9B_yBWy 7t~E~Do"]jOF>EyH:?0۱?F.?b}-:'tAiO:瑯{{8V't"H–ŭ8IkB7c|wm?ӹW]_ҩxEG|'x4h"xoK^e]3Ι^L=c;ޗCC?c[cߍ}}H|e}~q['a>ow7>{ہqɺ?@8=;S#1n;<;cޭKgؔt䀞_?)838!! 5=`;t)q]yy,߈u[u7hq_.ٿ/Sx)xsO˻)y4ފЁKW?vxh]+aXWuv>G؛캾ej|5k;iM=<ӻL@QC $J,p STҨ0 K40I$ RR11Ō5J(?C.:<zӚy_kY`Wgs O뿆[ek5<ז:x'o[S6KfƼ@> ɟ!0.Eِ[>Yģ?~|[{C+$0/9ꪆuI͸5US5M|R558ps`)nu/|;Crכַ#o3S׮ԕ }?r:zq?Y0,ꅾ nI%rg}Hݶdc}S%f:dI\+N]YS+q~Kv\ĝ}%7K=NE=SQuUbaՏbM_u=xCo~Ӛ ?NIOvc} S6abܯ9wwegyBL7sxS§w7f|7νH&֙wL^&rS'W3v%^#'C\u&/|+_ 98_[9~ rosco<s{V^8US+]9w {,<Ϲ{x(Xo%^֝9?:udS_q#rp}nYOC9Gu׵+}fcYOOub*zUUo{RYy>o~g[Y>߱~ͺ[#~+9w#Q .ju2L jGYGS'u.9W$tT+#`+[QׯîZa+⬢s\Wb.cyv伱"Ny̧~7*?(^UKy>]|G㹿@ݱOO6P ~Ki'& l7>VKyqW 됚kV9O뚸៊}/9ǁr{%*+]cW92/WO}}"?FxC?ܳ>=N^9035Xy>]s{9HC&v<}7K~=7c]z?Ls:x5~iGLp)?ɓ;IO$g>O|g^h>m5so=rK>n#5d9朆ϙȻ`ExhC u^C|>|ې?_M>5<"yz:%B?ハqWOAQʽ _f^֑'Womk_/kOk۵\&s6~}_ߚM_y&/x\kUhbg֧-q{&i+Og@{ ѐZPK~|8oE Y'Cr ^l˖z% [޳Zϴ3u]\kK@< kƾk5ްϰ&7JS/0 /RH"rH|-۾D\W%pxJ{2򽌼/s2ٯ%pql˗e+r)?qxy FnEɳg<zW9KyoŸi폜/}y =8Eg+2m?O@ r;~V>;3~_AWkZKWϫ*xx l_eU}8+ćr8~o縯}|y_W2m99/N{?W /~w<8@~/Kkq^,EwvFk| _Ckw {\c?ל;g;z~v<_hOؑqwZre΋::nu?^Gwyo`̓}ϸ7r7?.7 p}\^ʡ|uEǵU^U?a҂3W{{įS9NyO=wnb9-dyoOu|~|cǎ7M@?;_ZيCmig^;kUƿx~mٟbG-~PܗxǞg =6qf=3q\)o{ZU)^WÎo\+񍝮3ox]?E_#>_{|rc?xW~2hW+wTxLbC^w; ߗyƇ'yg{+2mN(||k[.>v.'/țָ}Ɠߗu-rͺ82O[/JuWAڷx}^>q2,G)_ԁ3:rNיuuI[#xǮz+uW4ÕzM~n~~{_]+zX(Ivײv^+OC۸?>bܟbRn[wؗȾm| ~~oUwu[ȕ}wz}Ϯ?Ps lWqb}hz|?E}S.륢ߕ:ļRUe}d=-;/<ɗ3ў֯e[gŐlq*Yߘ̃E޻qyzy<%qgr&_ڏyo-ƽw;~|YImc·*~Ÿg+e/7i՟]J7 JKηm=;?g/>NmH\(+}ٖr^\0n`+^/[^ޑ7#py}o"߿E\o![|wGZ#[uy2]~y}b<#]ӟ{sgw.rES.0OPC=hh~w' )_P~VyzEη〫[}2.O|8;w{c{N}9pO9qG~ůOwiK{W\WwJ[z}J{y#^u>` \GO>~_졼S{;qW"i?9>} G$..~xΣ;]i_σL' z9|>yd'ϑ:^ȑqJk?t:;o?T~>'-Ƴů2ϟ-|>{bpuĸGy_ua#>fcz1;31ߟ{' pr'_ ߟ bp{~'; rߣO>t2ǼW^' <^87y>׮19f~v yGwşk'38K|"|+ߦw;y _97s R:lwh̏#8 o-ߑ_ p /e|w{{(#K|(x.kp3PM_2|/e~2hwƙG7^y6<^NGƝx<¿G?^xy#yygy ?gvߎ<~ͼʡWc]`GW{7{lAy"~.$:Kϱk+T[7cef}CZK\[W9̸uxƅEyy];7kGȼ#.ŷu!vOq_~3ccq,oY/:YYyy-+v9o}ћ||ɏ~}u|7~|~wƷuiQGʣ/[Gz_|:l|vܲng2UҞ^wr_^ϙI[~<:!϶g׏C\W뇲)7yxޱ.>w.:j^u?jUkw{7Woگ\jG>Hi/B[o a;]ao]u!q/u]_],'w;1gŞ{F^;C32xO9ow+qqyěr+?7qxNĽqVƋz8яƋ~g ɸ5zƃ3ÙH;]{ψx=~>3SyǎEg<?.|me=~ߣ{=3>i>>8z]ȗwk(|]?q?/`8|?D<`b|`!qCx~C^xwੇ^!='G1v~ļ#~/q#%v c{̸1x~}d#r`Gį?׏ccߟTݼO>ɟy׺0p'BOk~~9??<>Ͽ9u:NspyWwzsC{9v;?z=בя;%iO?p . .~ux_y.T7~o'WG_O~ǟouvN|Ge7^<#NzӃz#nz?n=ⶇ<=⠇z|\0W ?~c7[x vN3pgīxzG>QyGu|CatL\(o=zx}Ѓ?=xGS x&O;؊OǮ}x'࢏I#_q>#oki'G}p\/Y\w8CFn>㟼O|hX񜿛}}p;EiWxk3wC3{i9¿>$_ yPyoq^w<7ߝGO 13:cx ^{D~87B1~1~Gԯ#}DS11q=&^F}%OĮ>~Cx_ὴ7D!yq? G}o>?O !gp?GH?8!yc> ;c} M=!M/ףּ)zN}'y~'䓉l NM ;MCxҿ{]t5N3H uxnF2cLoʼSn)uȣ3qzhMq'}}&ā_E|MX'W7/&}BN͔Sx4)=OO\8SXɈzsDY'$ȯG?ȟcp>1ј8|lS_;'\Ns'y=Oy||%S 1>_{d>6<7DJ=b~7yw1XOS?%?Cf>yL?x"i f=sƟ{* =gwf仼GyCgbgyh nT'/x 31&ʯaN/gğqwƗI㌨RXW{p:T^7 3h&ԛ1f\G^.$!πԥ90uO]߹7 :} -<>ӿ7'3}_ rf=~7O)zػ(~Z~< ><{sF9tb^cuOp=I>ɺ ;;q}g\(UѲ?zt =⤧ݟ?ca>r[0xt]g<>9%rƐ<}-⏼^ӾY/*++ƿ+:OYà8~ vg~>zgIr-y#w~a⾀{3-Ođq/W#gq'-O<2}pW x~3\P?O9XG'.}y~ ?c9:vg#ǃs^슼>S=!q4'Ϩyf'~z&r xe܂Xayx\a՟ngߊ~guW_}>V?Wڍ[l'gEVkNW?ͼē]_3^C={6س!/6R? 8iЫ!n5'ǴNE>?e\{;6gp6-vo5x߃:yjpZ7;E^7 ZN8imW P_;}Zڎq-i;[#-Zh7{٩=cg<ϵgCsC9q[K]8[a֟ԩ8v5P?7Y5kg7qEހx~ZCi˰В[xZܶkLY#oxk5ݚ|n߉5uYyk_;y6/wڂ <Ƿ|øp{ikOې"<kX5;k;9xnk낇ĿPާ>H?ks-i z%?9B4O}k5בKxUqP81OM8_3xҸOE^ϮgķYۍ)zκuu.=tzz$keI;]쟰nXuwhjPQc7B:KX~͒oV+$Odv+ +\q>bN[%/ۊߊzc{]o*U8Ya >gq\gE>^=+y%S+} Y_ .zRTv?LSU䱬#U oUSO?]76~_n;_, n+~Sŏ*-Ufec{NOa"<{"E+#܏'#{C:ϡW67pOϏs>r\ I<{ΉB#a#>r_^ }o4WXŮ?&{{/k &īWENܫۓr/Ǟ{j|8E}E ǹƼcp{{oGO=9iu=&<3=_ԓc1@U}W}G'>M`v!g+s? /c {IGԻ:6{~?`S~sy\9x OYbogo<0)x䔼-;j^SW37+= ϹgN|:z{<%QޛGS彏/Ξ!_)ܟ?3䛹dOW{w޿P.Yνb97vN?fGwoN,J &-<;BQx={%u'q$^+c%dKM3sgۮǒ<$?.wsJz|s+׳/ÿO'VTXnz8ꗊןO͹EE>˺=+䬈8X.*0* ;T#fo{b^e k3Oe}Zkx(v}N=W_YW5~'pξB}q]'yv]K~B|W'3TWV|3Gw\gMF9F}Y>`䭊u]jg-sˌ/ `wwZsڃ+~u xm[3.hklso;}7rxO}<^=Op^q>)˚}ԋ5Zgj9|OM]S{YEss9ۀ6yu!?^ 8y z瞂7rC|Mq9eC<5Iy˽Ly!x?~њz&?Գ]\oxя[q)'&5-ya*=_|sNMKݗDx5熶-mǖqH>?ٯysZy0J-8JKAC{;>Sz/#篹'.cGx9gʕ{7_K{4[o۟, w _v .<+<<-.ɹe|w~ǖ:e+>iK>w_T|륖qGn5yxM}f{C=nOxy>r}̓e_c_m7q~7u}6Ǵ6ȿAwuzlㆼ쵁7n qW5c ߓr.#Y/=u^?=q;CvaL?wkzmG=c}c_w~ҏ|QmK^R'mݱQO>B|7-3ȟ-<[sxtȧ-q/ّvف<~=ݡupvvq+;#O{/ړu =u%x o]?>}%r\ƒ/.Kփ}Ix~OyJ^xJ=⿧)YOK%봧Siw)^}GGɛy>3z\@yEpbEEx~^Nz/“/og{^B%꽗ex|DwxEKW?E"uȋu/0 ȭ}^^;ꇲsOW)WW^9-~G7-Gg<1kq!5w!5|ks5q ;_S[{ ^ָ|}>c/Nk;Σ]ԏߣ]{q~ u}c:v>suוgבr7v=o`/qr<o0~9-vvأC;krʏvr3Z7Mƹɸ7&r>7&D|7Mwg}~WNRyߣOvY|y܄WjY{2kGӎ4NŹ/}/ mZ*@OƟ%oK-]O峿(r;+ึߕ|{uɕ:B9ę|ŭ!g2gڢKP4~|\%n5۲ne=ׯġt޲>wY%W>|#M%~^y/ϫ}V2Z<Ok{q:=^y^^'}:<'?cּb쐖_x:yo޵->_~OoCZ)^~ͳW} x}Օ|z\9yWW=|'-xI{]x~9=na״6Bmvmzyo#ו~6zv|7 s<9ߌy?Y=ēvovC[ȝKyhoyiቻ! ^w]zy<{a;̗yhcz \i+ݵ˼wCnS.ržȑq]-.v̓Fm6{z9w;|~nڛr>ڍmr:~~{~C{3}Owyb_#-_q\ʭ|.>z|w>@:~}Łrĭ~'S N9ONCDOxȸ:C._}veg̃]2ώ=37v:>>;>_+S~^їvv|O{ɿwB\bS{_ؑ8]{D.q:GpG|1Ovr3qa_=@w>nCqűqe9(9Įo0x8^#ȷgx/Haok!~KzG9~Gޗ_KߵzA/y>i_G`ļ`v>x7mSA'.lŏq _GsiyH|? Oxwy a#):43y,<;qQEgȯ'ߕyO/;*u|đV~ځ̸N|o~?_/d`!N': >Ym}e]y3Oio37vЯƅ_/\K8ҿy|3M\~q_ GqSz:R/uoa#3-#O)OOGcwOpGӺm~|޵γ.oUI|kUnҏ86g}fSV[{3[%?pxǼO&":FOG%^}_]ljKNOUgG{N{BQ~?Ƈ˼a]zFoĹJ̣}_#>[7kyź(SqlVգ2u*H;Cٺn,c]e}k]h={r:gJ~w5u8'u]?g&Xo?31qrG\f]zX޿b+Ayo~" ~ʹx='QA<<_t\C|3/~ܟ")zS9%q|HƇ_N)~)8=~ʹ'c|w9?sb{EsSq Ŀg-nW;yjy~{1~ȳ(j7;+P\?_􇸁g/tʸrs;%x.y.T.y|d^Q?p\ן^ .O|rq{;%l{ ƍv2~:+ub7εN_ޅr7Ei/M;h8ȳc O[W]ħ_o}򝼭ůY)xvyħrwS}~gu^gwgwgT v9.g!gC\w aƇvxc=p|>w}}?@|>DCp!%??@}@>!r>@wxx!⧇!v=p!gp7-y?aG=bGC!xꇾ#!z!~|;#y?!#=}.?g{?V~GQa~b?q}RW}?xD\d>߃LJ>?Ŏ>O yL\=A'n''`'}g> oO zr}α˝\K9|~csmU^p8~G9UgΧ]suaN"r?#x?W{<:9/` yA_w_`p].?{ƽx@ 什.sqwOcyEqvӌ[_7q#n.qu+ϱ#Å~.ũOr/vz~>/= =#hsx:]=>O|Y^B9.Ճ_{k?|+>}ɛ}GG~f}yOF><ٿO?Lc>0;yv}߿&>wy߯߱za=pD|Ĺ ~_; N7=ؗ7w-v'2-?ğCuHy:b c蝿#fnK>7g#5"6F!??c5uǟ#|x_:!7d|77?ocz!q]1b]8C~}/ԛd/ ~Wg]ϳ~=!z zF<=į;O`D<qS q3> q6 v;.;/v󰞙q'aB]|5E)|6/&iJL)v1 ?ۂz䟂)/8߱'LrOD?8MR7s Oc}&xc_po*'y>Ί~e\~BĞi^r[ɋc^m\c[xoowc&8ax3ɗyC|cG/<'!g'~c61E5c?:#qS%φ_SxE"Nۄ:o͐g=1:YS]'oOO&zJLY7O/<!ĝqU܌̧ܤC:O>~&^QCI]lk]mݪʭ7cfOC y_OwzzueH~ܸ#o$^}ۑqb=?Nd쓹 >G .q:GC҃?{ȗs\}W澞_9~tg/_z? }|קn^7ZS\ϸ^0nSs.g뉁Ch}g_F;aUW7xw{qS>Zn^u_N_SGYw.ׅ3Eޘ!猸f' >%xȺ:ܹ0ߦ7gfy/੩u7Uk̈q)y93xeFf=L<ߌ<1#?᡹û39?sC3p ++%%.%y~I|ܤ?8XKp$,\,%~X# 4sogrf>>îS}.Ğ'0gY7~HM2ē<*x3. yy!Ω{7/3|!^Ž'_(I~ &Ka ^{+gOe1>Ǽ#;畇9`ԓ3pJ}^soN;0a%Z%x[.%/Vq">V:=\Ņn ?U_Q}ag U?8FO~>N:?v/[M\c7:yǝ vi!55qQ0/<]Ύ5~ߠw{&k\5M'oc~w⼆_?[5~[ 5cNAuvkuUN;7_;րr`5Q;}]ܷn>lᏖ|ڲh~ӧ-|NkC >⩅[j+[ӂXp?]ࣚz-x;bOƏovqG hOOG;oAo6{ͿѰiowhiЧE||r-G-*ux#X> ppjJ|%_%x_7lk,-K`x<+~+xw^_SWO+pt|]_t:y=X›Ku?VW|` |Xf@UQ_qn>%_Xre}ԍ~Gq38g^gq%?;Z6(n7B߁|zO#<){ָV3rܳxO| ^W[:>[t = yP O` Kyu6}t ᩉTo?'7s7f|L_}0^H>#ϹEνϼ{oaMq|F r=]{/0Y?{3W##W"_3~rα9-3$?@^k7;GrNb#b%xya}{4ح.!˿w^ ˿GAo=Rه/?=دϾGȿ{{G4~~w{Ź?x''N3;$μ{1c8_r>q;x>3/+W_:`?-e=9%/sywk{B=Op|i5>$|{xgN'^vgǛ"u{ybJ^GΗ73Ožyծh?֧ww_Uk*{|'<{RO+\G`ƕc!,#/溜+>=&}+.9'xU쬝8ߨ69gq_*Uԕտa^!z. ; *#gG7b< IfVGrn¹Q)5 7rno6䑜3ëh<&vhS4إ{x\뼷?y+#~=y=8C7'sVUF^.yf^c Csuaߚ8Nr(˜sDɖW-|bnZ% j[b%ϷƑx ^Z<<& ɷ-q`mM <> qR'#wk pnm+qh_@?nkc3_Ȗy=|ܒWZ,x$/ۃ?y%%ZA> X߬׬[鹏~<{gq~M^ku|+ɳk\mӆzs} v` Qp!n拻y6!xsCyاkifF{q@X/F5}$fy#?6ԭˆ A;?0="{LЮ''s O I~;AyL$D_'}M0oN~%$'#  u0? OmZ߱Vgi|c0 Y gC`oI<,`0dȟ$|N;<$Y/KRS̯S3SsyKzdb_L1I-*EJQoSRs|S;)uA&EI^pF !ҋv'zўy&{s-)w[?֧kޖ-oIPޭu0Cއv{N8ξܿ/K8>o몥_:}z_pSoI.='?D?gtd}$d\a-bj]އȇ ڷ7֛p&z~ko_ Pkt]/G%wjO3K.(/} O_crG:[ɫG;bZ|ȇVZm-܊x8ҩG>'~ܯߏnEZi=WpXKz{nE:oE>zWxnE8oph?C/a}Dgʷ Q`VWDr+=ݔ~J4O-`J~7x/|o&az/!Ow=?%o!O8}7 \8oskw?z%k1t}>><$GtѾ#|F'/<r@k#@e }r@Kr߁@u 9D>kWp|[.Yp " 'ϾU;!|C=p{m-g}m'\CH{OzٺC7 xL}Ij [g ~jE'3''_dNCS~?UOB S@uՑT TwQ}.\_o]ʏ}W3(V|Z}ޤ|X?AuW4_t ^+>fw5>wV]Bq~8>T\3qS8ޑs5_P!;AuU܊q MYmPGQ@[>87~3/n/ l(.`=g4?Z+{(;OYd(6,ud)fSqlj_o'|C/yWk([KY %j}+?*x8ZqZGEpj76|zi-4rh}5#q05#q8ǩFqa0e֣< ~I ֣i0p{c4xH'ir"+>CZGs0ʣ%~|ɿQ_ .U|&W ˉk?陞?; |ZOEr~8q8VrD<o;_r)y I͗Z+y^H܂Wp3kI[kFt4=< 'Z>wkokg}ok5ۚz7}GpԷcGpZIp[K>~RFoZHy:x$H7Jg$žQ—:?t)HiHE>>C%Gq(>ݵ!jh?hc-m-׳hMxC1?!z?xm%p1k,|,ck,=KY87p#=Gs53zu ^I|uhʷ]t!~I/+CCxoc/F/Q#_ ?gt">8uoF=G<6XG}8]uc_? ?Os\w<?x$?S}o%>.џhz>k]ߛ܊?eEG/zI~G#xIk'c ~?NX O &_ ;k5|p52pNX:䇵s-֗ S;z0A''lyL&rD9L$)$3r2y$aיDP.J8[B'Q'#^%|_BK%ܿg -u6|,%֙LL|9o21O&'?r 8'/zyzOz(5=Ir6 8OM 3y<>KsΛ@M|6OzyZ0!KyL 9ƓIy+_u>}MEoʉ]Ɠw>ꩵm)6|1;# ֥<'ݍNc?qWʎi=<_gt%_쨭K{):\;G;i_:+g]גw|D9o"DtDD>ML$m=}@:M$= N+?L$'R''^h>gKeх|6O !&>] ǚ/?.+&0xE]vZ_q'[_s/z֛@{ȏoQ4R'Ҟ龜)D5SY?8{.= -K?ϭ\UhL"^$qIokʃ'/=9KK*l?CN( ˭P%+T[[ⓞ??^Gr,|IX~I)?ʃ,~򧤇?dwKǐ3(V_K%Z/DokGSVB%%WDy k7,~KLmX>w;^vF{yHod^Wh_٫lʾi=S#A߉OK=3S_̞i?Ct]dw p>kk]rd4^%O{ɽp<_P^Kp:uqVyڟ~*ΐWI_8~6 ONAFh_ə kY.Tv]t?d5_e8X(}zipqSYr&;,? ,? '8y]~JVT>'Sqo(o _ S_Uަ8zG0||5\TܭNɵpAqɑD]ɓH-=^f!SLuɣCz"9 ɗK\'y$'ʗ9_(_%ʗI Q/Kg;S;פ<=>t|ti]A}(/]u~sJM8j_5|:Ig2Zo2k2LO&OsM{Ox\TdWpNzG6/?DK竢H8lGF2^H/HOg[y'~I:/\OΓzmtTK&>/lT+Kp)lr"# י,NwjEML9LA+KpnI.t|4?KdD-  ɿS wɏ~Iz ə6^_t|ayѾ~n yS$wB{8ttB8m>??O~o0>R?6h)S(S(Sm6))ꉭG>Zʵё|B{`C~|4^z/9R =}ea,xroMԧN=BzmC܆Z\w*d*j*7tJxST7r3tFyJyJ8NӸ4eF|qi[4cO'<^ӹt;tzO}N|k} 7Πk0ϤΤ3ILy&b&h&yG20tIE9fQfYl,,;̢"((o,;sٔ6lm6M|fю"ϳ,Y\O}ۇ|M9E/)MMCy}9gpu.|͡Ѻj9K_s/{/: ?]ͦ=0PgzNϦ̦Egɕ#ۗz5rorΛC5k.ᙻ2>\cs zRoJ ))*!FJbRڟR_z^J~ҋ'}/os)ws~)g뒮mp ^ͣ>>[K,_嬬/SvPF/[{8YF9yƑ?eb2o߲4O91gY;+;r|,'i)7rUNS[Ar[г2[/[M奌.ΕN?XF,~66V*|RKLO.!|hʸNwğ|,((S);[zb+LOߗ~u:zIrvxZ&У]UAR%Ok\N;fC;Ws]UxI~E?vcm'SG.TA-&6^I ꃭ}+#|ƒ|}_gʃ38wi*'*ȯ bzgWM;PIzWR+J'mUUYK$奲xWR*,̷&+H GÏr]A?PA1ٷ׺{_';vpU2ΰ&+)'X|7N?YIT*ҡzTE;i鯪o=gmkR^M;[M>Siikא5ĿVMVӯTSN)Ow|OYͼxO5P.jN 5jk!:2n~V >c5o5t\.gxjoKSqU***ڋ*[EUTQh߫oᯢTnR'7U1g5WM?b|"ߵsџqɟ_i7j^ WK먇?GjGrZγi!}kO cZw^?֒iooL]h:I=Zyzz^O9ӿՓZlq_z\vzRGzG3SO(u{zfoO:2aVKPkiGjijIg-Akjeq^-᫥%k)ǵs~Oݮ &<JZIjC3嵊pVV*[#55 S )>HhjN-q!5G !> 媚L55SkWPjdDC]0? B[dO}ڝ*=?׾e7)gդC5 7[#=2N߈_-Z|Q?Z'_ph]='uZxΒu{-R';3gWO<(~^:OWt5!;8 #a{(:/FVF>,oYC8N#I۞Xܨ8xQ5VSUj).\+UbvzR#&]R"<$zUG91@8j(ޤ]b^cAyw)?d}pZՁ$W)sJ\XI|eRI",ߦ}7=P|NrQ˺T-5׊34O>X\W=|j6 Ʒķ~֡|Snzڛzҿ^9qYG8zu KĿxS .ҩ6.[~vW@( zGk6@@l`@8r@xeeCиu?*8?@z5Fo#F媑QrD1k_{\}xэq@_/9RMXJ:wY|?Sumʁ0guLrѓ5O;e_4^t7=尞v/40Ҿ&vʮ4>8 5>z ?k>62/lhbݹ]F 巉4ʹĿzL?}~=BR_5:x2~^y)5卪~r]oW=Yvu f7S?f5N*8.8Q~G+;(}fQϸB~tk}.eqQпKTOg|";nCR ~3Fك3#{ {!03jOvvHyih")_ǤL3LiE8Lz ̑P"s@ȉX7Byu#+8B77r.G;zH=qpxjxDI虠g;n?J:yã#OM.7J?]QC'GҮz([Czޥl)|}G=!'1U1Atq\r{UѕF/9_t|RokAGܟ#zw0 wA+8G w1BK8c-\nl~Eiߣ )$/mсQ=ݜ)QI+,8!J`xzA?ҟDi[Ttc_>z^GI':F8'}b78iw=_|rތ_qHLvg7c/\4& ;NL>e\`!~i_7Q)e^#bc(_[Sw!`v8F;")JQ.=Dpk]G;1N;FJoEڑ:{tscT:a>VGx|WܭY.A<o+OR>}G+﷼HqsFѤRqRϪ{0ϳz 52n_: 岑k&פC /?"ۈvYy9ԿfEß<~Y͔f%oW4?&ұ~YtW@~z8-"ѯF?h aIc~f݃7v?(/8 ¸=3:9Bz[^QvAu%x|l$闚hMhyi#vt2_zۨT9霆V;kع|chtQKxtFctG&'F;PK#8^Dн;c|YE_-QKy}sֽ> Ok)/névߜqs5y5@ |!_%մvOt=n6zSt{Uvop:sj]$wSAjKU;g|UU CUw(c)wh]ݿ5g}gBz mߗp=C9{ԯ ڻ /5t_pTnh"~UѾVNvo|{.Ի*ڛj/;j)?J~I/G99޲'b#(vL9>E:69s!?jYwA<FډFFE}Akw&FDb*f|se\pPδFQ徉r`3IL8hWG>=W>Lm&)o(b}Z_neݖ.º[LLfv#9揖_Tg&=l!#K<#?t汾^\I"kK{a9B:GDhg=X>JP/i7 $c#L}fDGwD[J:EX4_ɏD;xPum^5m>:NAYIu)Ջ/4ѮD}~63>V)Whdrv#B"92}bܣyoxGZ]?I~ jʝƺ_窻/Ay~3ڇo:'yΕժxUb:7vZڝ= ځahz@% % Nп$%X ʵ<%W +A?ڇuL`% rjt]IRL.>ԣyE0NS ;AOkQ/$$K^I‘|hSSWNIu'CsS+)gا^Ϥ)ƉiK~ 82M~zbҌ+Ro5Z|/XƵ޼^;~dEv/ux왮}/\Iiio2oޮAoۗu_4=<47cNk EN}q\!4/\k)7~jky{{ݰ͵_]M>{n?acfu8ۗ^q?N7/=Xg+-;]>n13xޮm=6xknȅgrtM=c\pmp}g~)xmX@Ϟ][]q&س/vqo7/A~~鍮߶_f׬{b p.wc ._? /Ȟr{z1u{zl~dV֝K O ǀȵKK+97 n ~W?kO/!6gqצW~o~0sx?P}m{u,ڦkwO?zu;]}X]ខM=7.{ |8{f~W>э5[nXw[؇ڷǸ'Qwz) ?/4}^7[;pO?;Op=M='G|}gaV68 v?8yˀxSw2y;\yWk+KNWOGG? >{s =¾Ch?ւ7:/uw<}U䏶y{l#}]2ǽ/ 7gqاh>ާ޸}րu? tj}p̹ߡ銋\W!sgoč7n}n|n|19xgS6޵:v[ߙ/][ºMmݍ4/yu}6}n\W^a9=ZOaڱX{@'^?2΅ۡ um½M3ˍ z=/6þW'?r69KZO ~6a׃@uoewatPo,sfL!W~"1> ӽk#oub!_4y/!n݉uVx!K/B?־#yT Ulד]:8Uط{ߕ׿ܵ6R+2 >{-ƭ_#:3:秂AohM9_mX{{Pf9k=Sc_?ֽOa O'S-:<['y/qO{S^u'3~%:st\ptHϝ3q{_q詮|,X\zo}: H9p{\Ⅰ1}Y kK^Oɮ͟č/šZ^ibWE-zɖAxyg_D_;\%Kl rcoU2˶rm;W轸?r h`|3="pƻ>|9-{/[>z_ 5MGZCy^|07؉W7S7hIv[o n#n}S >xڵmg]7~޽Ϸ vmЫ5ȯ|wwQG-;sn|b"Pz$/ykvvシa _vWXym!~,yTz!穽3êrwr7]~ |$ݸs\?٠cw":~(׶sܟ{K,E滶k_rrtM!f'зq¿vw.:,?̭v<Β5//v%t9Nv{胉?0Jov@ח`'3/#+? zs: E뚷ܸJ]iߠw?~Ϲ~p/q']nG^_x Vsn޶oΑaݗ^n뀻T7p;A Vy]xOvPA8-|-7ta>`t`WSy@oܼe~ŷMݸÿumFm~tſ/Yu{vq{~ҵ3/i9{7O9C-.ڭ`塘د;!7{]|aZn{qk>KWqy{oW|tnvK)o<Ƶ1>ԑ[g Gn~ NUx6ɸ~kXɅsN/Ծm7"_8@]Az~{]yGjīI]sqA?㋨ F>v.~ ϽO?~x_̽_|̩+{2KE4هyo_?v7<XByAw_W~C\ qF'/mgw[s/olzw @H{Oyg߹ؗ-P?L^ }LD7zDQ?He/|f >-@$9Fw`g2sqMo {.%g>c-viގK>hwtmD޸# GÞοyߺ= nj uǥ)TEݮ'ok/qmjvy|k`仸|;yZUw;EmݹwqQ b~5nk;o.Ά,vs(Tg2?]{޳us_=o9E7} <yC uܼyl ^ٶ))'Dݭvco~|+ppl{ksasaNj?rmmܼ:Х97\{hێYo;)^ɟ0^o{uxnu :ve+u-<i,ϯ^]&G { +`'yn`C:|u t! Wjkw=`W3so%R?tmK_ zǶصY;{%Oߙn7QH>1Ql"_ϛo}xt$Ld.o:p%#=A{#^{ߺ `-po ~o|߽۫-ږuqgvwǹT"{OpNnܼ<pvG=?x\1,1 }7D& >M~O_0se+v%:b\_{]f!gmupĞD&~.Wh}t<y`qxe#L\5?VG_@u|띂8{V߈$ ^CKLOuwF;]1=C?~iڭȇ|֏xk3]/.p_R )n"zev[OA2t8 /ZzPprBR[7Lf1ɮ|d6m{s^_~w~wDlbk3E<%\?WqQhs:7r8'G8L>9ګs|I>3+_:VՀak@v,v7&o!j>f_sBo! {?wmc< 8|]rġ-}Go~qWߡzHa&}!ԫro^+(WN#\&KǦ.ɆO7qm|x9ZovQWH\8sn=3#;!goۢ8o3z o{ƍ]s0sa57w;.mwڍ<z4=m=-\v%O~5/>=Ox5sBl{!~[oziyMP\sܼS!-#pT<𻝇:=s~3$3|;߆7ײ';!z W/W|0t^82; R Eq^\eVZpf؍qZ:AG>Gcce?]w.ú[ WU|8:5D=׍{M\[zqLSPHxx?9tӀsW=/tpplnC~sτ]?[J֬Cz| o>Lt8t\?ھ7ݽ_"`trs h:yJ]?yBヨ'MAOw6{9G@Wx`SkG!zw jrԡ˙ሳb?zܰ vr<%A8{гYڋa!M4r5Ssop·/Š?;~n~b9<Χ:z8xY'/[E>v9rHQ Dݭ<8^q%k1Iۣ w0aC^zq@rS+/CPJ0 aG3ھ>v-u/qA)n^nDMw\{ ]ȏr._|mK>ӹw}x.!.=Ѱ?_؜~ok7yud^(Fo|=~w ͥ>4qpѨ$W~=g7F[kLJEW!_-D!O3/\[%=6q? q??W [usw~$/ _}ylw뽰0۩[nX+MB[yK^s :Ta:-_&_3Qw4vsVȏ+\gCOL s8q_{ӓ==_|ı{}״=k ~H䋅")l8ط ?qg'sq^;݈8 uConIg ځ8aBEY9 }:< : χkz{;YW~u$ ^Ei';ys ÆcK,߉o w!'z hZùbyS /Q;م[7,.wqk翌䮈/ksm[gp =y]q&=ռ0$jq/yܳMn{r$帗\ ImhMcq#Qp5}&{3}iAYw>g| > ~"{(ո9q/ԣk#eeХ{Soc:%yO`л|@ ,T'JUxsoqv9uoNXૄ='ZnF̄>P4]Tw@Zg=s[Vmww[8 Ơ;v;mp~+蟡oގWۧsoFFA"G_<+r(k"nNUn^}]OIzc=3`? M] -ɓ|%gj-GGn.nk6e\YE<{ӿ8\`f ?y>7,A o&؅#q?G@nu =V 82C At w3o#gvOo~O桞9b^͠sish/quG8=Jw'ƽַq.߇'t;awݨw(_f{FD=q@ %7L_R&A\;P1yG{0?N{TWޗ`H몣]|t GF^Yy]?ùm]ԗ/Ы^Ay`3;|!;绲t}ΧQ_>|*il{ycs w77y;A0uȧU͸wbկ7zMC^ ,F"&=,}X:)b7rˉ"!.lvG]9sỰw6k׎s`ꆑJu"cw%΀|9"׶gGC8?\:D~1_p}:pj5κF-G;r1ڀ_c8oJ|zmf>Soδl~){h|^z7r "8oz3N OEwFF1^{p% 9ɥ"~~wK Ԧ#m82yfr·Zz}q?? lupgn(PrAfg_x$w'C;<" v\rġ7p'r63"O|ܩ׷f|6xF76~2tw/*u/#N|.>3 ' ğ-=b7p(:lE ~}`t&^w-s&a"!NK߭pl k]SӃ,3pac{9~03#cAp_;~ h9<~&~E{^@sעn]RȽaq.Ă߅6ҧ1WNK+N9us;;W1 Yv"#<{9d=9 .F~;?;qF"-P={oݸy1w?{ Rxܷ)nWs֛"K ~$ IrqĥQ?yU| qv~i d  y~`4Q?o;yގG`?*_Ͻ?~96米c>޶Nt%#?>Քw >Eܖsc.ĹS"iO)Qs"CNة<y߇%}@C\"V֗q""-ݨk7^[DG ={3.ɍH-둯8?-%ob~G$gڅ: uȇ;NyʡQN܁<9;p_'w#\=Eց'mumfι[m<?|N_R]S7^:{GYw~coÞGrxu}y\Jwݍ>ǎ?S{?yJ]_,Gfsg<"|[|,~4KƑ/Dm{_M9Bf-ϖ@ދq$8InM)L .n.d>r^v:Ha &{pNwo%k?'/ï޿;n9|##9Ǐ>SQthx\m~7رsoC c5~o U5}ak!Q~=uԅߧ45-E uDlaZWZp>QdBo?SyO+`P!>~sT;Ո+:k1>8"Ժ {AnGwgn %ނ/t @ī}!aS`W>~ |ONy+v%vE]w}ݖ)7"(k}\#հ _P?9-ԓG.SΞ݊!܎qm _\S{FA],ry{__GpyO4W~ 0)I#G!n ťk>'M^2׍ky ysC_$ᡞO}c% 5~"w_=j/`m~w-#GnykựLͳEb{~8 y7 7 gD<ǓUnwе c5͈}Wuw5<׋ebܯ%|08-'/o;߷A}pws_r罹"?ȏ6z?z,Kr4oq&݈8" 2wî;o-KiaJe%~8׉ x$WuSOw}ؑSÈc'qЯ􉸗,}ˬȗsw_lsJ>gW䃉g[xjV^i3n+ >R!ΣZ= \ DzዼW gݶߙ5܃󒶁 yY< vu*QͿe~~*}͝ }͗\.> AG߻^D >/ԬzQ3[CCb &[y| O]}sfn~ǡ5^;;wR%u%.o-ooGV &ı(-VWZwB|W)Qkv4<{Gom Y r>|8(׹~(HC;y?h؉[W4:^/7_zr8NmQ8WˎF6 upS{[~]O ĽjuܷODKqxE3Z;׵=)7xGW~/͏uRkjf/m}q^=Knב'nS[?} ^[x9*ߡf"wwǹ+Pw >/C4 9Sw  _<&=NZ co/=P;x%g)fqnU\@-x"[ y;]~+|]>waF:]1ONrH>r'evE]eW |<:8yn[' |nݲoyGđt;gag<ߎs|uPėﰧVγ^r|GY\#:0@?[9MY熩uP͎}[wFCy_,i|X|mOS_:(SD"]EQCA@BBBHnR 5RP"E bET"R,((?3kofgwgvgy 3~Je0e:M?9ocg;5qiIǫSyaǒq:'e>>&('WFp|>rOz:#{%JW"V33ç!*?D!vdߧ/BQ}ye?t=$B~:+xG_Om_>Y7Oto|{O;Iel{?41~ƣ|ב8}e؋3_fK=ugoBwHt)`Ru F_/q2e?>1~Ɵ ce; זyϐr~ߩcϭ~NBދR7#s8/<<{x KʸѦEFf`/ub?'G_HeB9ψ<_s70)~j\G࿡ 7 ?w{^`0g| '?e: .6ϯ |3=q/j#$<#6P݈_7R(#k~-Z[}Y;i͓w|9sS31 n ( 웬_vv?jq_ٵ0Ѽ,emF۸ N"yسC֔zNgYBdg^^tϟ{\;+2o>ʞ+(I(p٬a芕ĥly 㕾̏B9笓& 5~rU'>N}q5'H\ v}\Bvj-q+xc17{X=/ rNf>Қ&\v}ܯxM{ίg~ ^ ^7ܚ<ߚo o~Y#;9D&oD{~0Ns aF:3/Kj:=O+ڽV("򡥴o^ӏfHܵy){ ̱K9c^*ؗO_0[pc%<j% 6+ig_N* GB:igxj@~NH]OF*Dyk祖ǙG91%sZt=(LV tJWp ~Oj~%QNۃӅ9w'G3_軉n:߁v|B(Wjccx‹y2[|emAwm,ڵq;ԂkVTmKy j;_xD&\U&Q>#r@O*G׮_GTVr~? Հ'7v⾋#i#ȃLJ}y\C>G\ lC;`_3y*~Why#dv}sUϭ`~7^!f^"_GoELww\mϑtt8,h9U ﭾI[m :7mPc??bW?K}&x΢a=0o$&-x}ZQbEEL[=_oy1zݞorlQ_bw Sž~^~+xp8/y--8-v>}Hz( yYcYk[ym}Q)ȫW:SsF#δv$m˸8mb[=W6qKvOmM9xMqܞ Ï*}_.E%gzo oUZ}_!^X7!?Ί//~1[h߯? N{24OCd")r-畉h7֌œw9؀l@u%)[3^I'߃_;":?ʗ?z#N1qC-[VC_1Aۉ{>׵7}'6 ,( ޗX9@O:x-gVʷSK̋W1>c}m -YתI{8n Q}8OrOGB:k-v 9ާIyD>ǯaQO`v7HSǺ:y .c*})Q_0 } c=oݎ^J/N&JtQY~RfL Mأ؟~ pЖ0>kD^pl-Ƽ_*eqq<|2ըO~u[|J~h}\5 n590oO) Ÿy=CW׈ü֬/e֑y^DW弙[oE ykÔjr +J?w`蓥/zu̯o"[{䃉=¸cΛJk6Go,̺l~&c>rZ:n^JY_2|YA{?;@;~̱ƫGh=!w6_j_D?li\nOIWSlƉ܀)ԈJ{,6#o{4hqKL]~zC)U[qt<ޅq3A_tX%>$(;Eԯ^zȸہ=e ~^c4lf|˯[bs|8R3s[_ZyLNK^?gfQ _(_0"/,ߝ2W rE|_QpnIUNmD[[m:`0y8?VH>NgD\'\S̓Ɠ]jrN~sܨXO[D7`]D{彌!N_`w08ChfϿq}7iAlQ.~xwqf>nbطna{u/{qjw^ g 'm2?-W:3}2'MD Q~n ۚr!n#+. =(N9i e^v J= i߯V3|>HWҵ0+,;gwSEk4w#}s䋷WOaodCN8a🕥m3%4&J|+{ιuug7i݈Ws v@Y]4p+ DBT{vu]ܶCNgtDy}~H++HUpX:` [?|$zǜ&̛^}y 7sDAdQzX3%K\h9"SJ"s{b/bϒGОμD9/G/AT6M۰V!~Ҹr4|?:6yOHfseLmF}9~<)g\,#3Zoۖ~Z’8)g{u㽺r;יSt.Fzqb?1]jx߈V4Qj`F;y{yz#I:E+VY\=I-K\4+GvUr <]-c:kd3u6:a~u-u4I!m}"ϭ/Fku&9)q37!>hgnwnҏ7FgxTZ[߉8^&G~/#/9D惤;jUgJ%A>t*Eo.'=$zU[&ul7Oc-{ c\w傣>ȏ&g @H|\ooWﱾbtGSǝYQ/{`/6әat=Ncxyԍ Ix[t38`5T~.t}^5F;1̼` `~+C{m>_k=x~Ex׺L\']88wt*~h;LEi+sM^e_cFâ\Fa5zp>; 9wuTOM=z)꣙_@o x)`â{~Y |KO,~+6vY/|crbZga{*Kp_0~OK9V)yvTr]p!7x=8/~R&]W\}=Eۘ/ٴg ^t< Oz'RP^@q5JFyհo!v_E'INކHUЍ{]ߺOݵ'w8ߚO1~| m)?`4#}S^j6.E/l^w4|p }Gg~.9#X][z @`RKD'}[O9f>b Nç%[IǓӎbd݋³RqLl>TA ~_ 21!+|ǹ?M‡\Xw? }d5A;t(k)b?~I(_QTeo*_r3g?E;/B:x\ Ex'q5;"udO_Ӊ,XK;bOV]zp1pؕ<R!wAg[v~ ;4v!vy(vu^cvǖY[oeG[ƺ o%ΊJ|L?P>^/NfLo`\Os<%mD{ƿ|R| #YsߍyzT۝ ]iRry~^`+d:$<|Q8b/q^â|ALiZ[nQ͛*y$7n:s: [}ϜB7N =Ko3O%F? Kl$o6z|Tgcx햌@q:򋹯gzSV;=L@񍸎}Iqp2ޒ;RfMoO߈uޜM+[Ǘx5[|p[4qx(#̶ƹ̫q/,GG?r'\7hȅe\|EϘ}h)b4F9Aw)Kڗ{Q<sBys pw3y<#QᢼyZHc>F|Qb_X[l}!#jicwk2΀w.صؑi;D=)/:CKނ"HGk$7:]}xg(ǍğcgU'?Txqg{ѯ W'ǘOmW&jمJEbݍx LPp_ st/]w)oRxIüo:}݉'VQ$鯕њO!u]͓s2Wѯ~{;q}8۞^?wPoxCg[=^!Q˙Ͻw[᱃ӼxX*xq|{wUYM$)+ yoOc/NnQk)a%KEXp\ޒ k-^35'/4ijzE>//pGJ+}=hocڱUH!ߕzG2jc֣ f6.GǬ(Zc3=$WֻR0h ">ş >~;~wu7iz{7%Ҍ78 i}}- }xAcx6_яs1(P1/V8Eč+Gy:xS|6xxxL4g 81Z+Ipp%iwi|WOGyA|1 -泽ߍ茌ħꭉf,x3P9u\x>/IsV}qT5\H{qT9E>ۅN:/؛UN'῭6N'{=cxoǸg8p"9wՎn9C7Eۯ?S,IQ"KQ8GF\SdGvK=`L6[!ZoLjt5k ֊ poEbz{sڌg99W;u$O} <8,yoay m1DwĢSj(XƑՎ~j i!VtK=}iyE ~'ȸ毈}%{Fa/%I8Z-"OHg/=q~&OI)w?w)=8:]n)itB'wρw ߼εy8m[过4!7Qq':?H; ?̃׏'x;$~ z&^}/}s+_ᏢS牓y/7V'wϤ|g-OOW3WeЯϬQ8p Cs-:z@]R1Ac =pbI:;;k+9CAS]ʩ%ŧO7#Ċ[Y_o/ʭaUWJ6Q (ы^FU"o&>6H 3jD ];? =!"~hϮ qw-ya'x]HTD_Gk@<>kKza/;k^sݞZrT<>R6P0޸*&Vӧ~`n7Uuxj[|_$yB?MiiF7emvN' h+ͱ뱛lX@ܯ㱃[v_us0dir@i?F/iw>Wk53/am~@'qYvϸs8OG7JޝLpg~Ad}M)' OUNu]Enuzƿ3wbe8߉Sv JT忉2>+z KO{=|~ӞO^|KxIoi36%?$_7k:y"`jqR?[$>ā*Q[йzãG G3q#=Wޏ|eâ]C(g#χ!*[l⏽=VtbA%+ќBpC4zTp)B/n;]Obp|zTLF5' `?{J moD*S̋7rZܟgwo|p}p?0ľsz_Ⴣ{DqnB\G܇'iWQ oMvonKxG<_O$JLMynQ\X ƧĜu< Rx*:X-љG'pw'%_7F_%{#ݽ4 F//SO%Ǝz1_E s/}^IGpAƖVTTR/man/0000755000176200001440000000000014531225347011504 5ustar liggesusersTTR/man/CMO.Rd0000644000176200001440000000235614531142730012411 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/CMO.R \name{CMO} \alias{CMO} \title{Chande Momentum Oscillator} \usage{ CMO(x, n = 14) } \arguments{ \item{x}{Price, volume, etc. series that is coercible to xts or matrix.} \item{n}{Number of periods to use.} } \value{ A object of the same class as \code{x} or a vector (if \code{try.xts} fails) containing Chande Momentum Oscillator values. } \description{ The Chande Momentum Oscillator (CMO) is a modified RSI. Developed by Tushar S. Chande. } \details{ The CMO divides the total movement by the net movement ([up - down] / [up + down]), where RSI divides the upward movement by the net movement (up / [up + down]). } \note{ There are several ways to interpret the CMO: \enumerate{ \item Values over/under +/- 50 indicate overbought/oversold conditions. \item High CMO values indicate strong trends. \item When the CMO crosses above/below a moving average of the CMO, it is a buy/sell signal. } } \examples{ data(ttrc) cmo <- CMO(ttrc[,"Close"]) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.fmlabs.com/reference/CMO.htm}\cr } \seealso{ See \code{\link{RSI}}. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/ADX.Rd0000644000176200001440000000454114531142730012405 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ADX.R \name{ADX} \alias{ADX} \alias{DI} \alias{DX} \title{Welles Wilder's Directional Movement Index} \usage{ ADX(HLC, n = 14, maType, ...) } \arguments{ \item{HLC}{Object that is coercible to xts or matrix and contains High-Low-Close prices.} \item{n}{Number of periods to use for DX calculation (not ADX calculation).} \item{maType}{A function or a string naming the function to be called.} \item{\dots}{Other arguments to be passed to the \code{maType} function.} } \value{ A object of the same class as \code{HLC} or a matrix (if \code{try.xts} fails) containing the columns: \describe{ \item{ DIp }{ The positive Direction Index. } \item{ DIn }{ The negative Direction Index. } \item{ DX }{ The Direction Index. } \item{ ADX }{ The Average Direction Index (trend strength). } } } \description{ Directional Movement Index; developed by J. Welles Wilder. } \details{ The \code{DIp}/\code{DIn} (positive/negative) is the percentage of the true range that is up/down. } \note{ A buy/sell signal is generated when the +/-DI crosses up over the -/+DI, when the DX/ADX signals a strong trend. A high/low DX signals a strong/weak trend. DX is usually smoothed with a moving average (i.e. the ADX). } \examples{ data(ttrc) dmi.adx <- ADX(ttrc[,c("High","Low","Close")]) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.fmlabs.com/reference/DI.htm}\cr \url{https://www.fmlabs.com/reference/DX.htm}\cr \url{https://www.fmlabs.com/reference/ADX.htm}\cr \url{https://www.fmlabs.com/reference/ADXR.htm}\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=49}\cr \url{https://www.linnsoft.com/techind/directional-indicator-diplus-diminus}\cr \url{https://www.linnsoft.com/techind/adx-avg-directional-movement}\cr \url{https://www.linnsoft.com/techind/adxr-avg-directional-movement-rating}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:average_directional_index_adx}\cr } \seealso{ See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average options; and note Warning section. The DX calculation uses \code{\link{ATR}}. See \code{\link{aroon}}, \code{\link{CCI}}, \code{\link{TDI}}, \code{\link{VHF}}, \code{\link{GMMA}} for other indicators that measure trend direction/strength. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/CMF.Rd0000644000176200001440000000317314531142730012376 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/CMF.R \name{CMF} \alias{CMF} \title{Chaikin Money Flow} \usage{ CMF(HLC, volume, n = 20) } \arguments{ \item{HLC}{Object that is coercible to xts or matrix and contains High-Low-Close prices.} \item{volume}{Vector or matrix of volume observations corresponding to the \code{HLC} object.} \item{n}{Number of periods to use.} } \value{ A object of the same class as \code{HLC} and \code{volume} or a vector (if \code{try.xts} fails) containing the Chaikin Money Flow values. } \description{ Chaikin Money Flow compares total volume over the last \code{n} time periods to total volume times the Close Location Value (CLV) over the last \code{n} time periods. Developed by Marc Chaikin. } \details{ Chaikin Money Flow is calculated by taking dividing the sum of the Chaikin Accumulation / Distribution line over the past \code{n} periods by the sum of volume over the past \code{n} periods. } \note{ When Chaikin Money Flow is above/below +/- 0.25 it is a bullish/bearish signal. If Chaikin Money Flow remains below zero while the price is rising, it indicates a probable reversal. } \examples{ data(ttrc) cmf <- CMF(ttrc[,c("High","Low","Close")], ttrc[,"Volume"]) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.fmlabs.com/reference/ChaikinMoneyFlow.htm}\cr \url{https://www.linnsoft.com/techind/chaikin-money-flow-cmf}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:chaikin_money_flow_cmf}\cr } \seealso{ See \code{\link{CLV}}, and \code{\link{chaikinAD}}. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/priceBands.Rd0000644000176200001440000000437714531142730014052 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/priceBands.R \name{PBands} \alias{PBands} \alias{priceBands} \title{Construct (optionally further smoothed and centered ) volatility bands around prices} \usage{ PBands( prices, n = 20, maType = "SMA", sd = 2, ..., fastn = 2, centered = FALSE, lavg = FALSE ) } \arguments{ \item{prices}{A univariate series of prices.} \item{n}{Number of periods to average over.} \item{maType}{A function or a string naming the function to be called.} \item{sd}{The number of standard deviations to use.} \item{\dots}{any other pass-thru parameters, usually for function named by \code{maType}.} \item{fastn}{Number of periods to use for smoothing higher-frequency 'noise'.} \item{centered}{Whether to center the bands around a series adjusted for high frequency noise, default \code{FALSE}.} \item{lavg}{Whether to use a longer \code{(n*2)} smoothing period for centering, default \code{FALSE}.} } \value{ A object of the same class as \code{prices} or a matrix (if \code{try.xts} fails) containing the columns: \describe{ \item{ dn }{ The lower price volatility Band. } \item{ center }{ The smoothed centerline (see details). } \item{ up }{ The upper price volatility Band. } } } \description{ John Bollinger's famous adaptive volatility bands most often use the typical price of an HLC series, or may be calculated on a univariate price series (see \code{\link{BBands}}). } \details{ This function applies a second moving average denoted by \code{fastn} to filter out higher-frequency noise, making the bands somewhat more stable to temporary fluctuations and spikes. If \code{centered} is \code{TRUE}, the function also further smoothes and centers the bands around a centerline adjusted to remove this higher frequency noise. If \code{lavg} is also \code{TRUE}, the smoothing applied for the middle band (but not the volatility bands) is doubled to further smooth the price-response function. If you have multiple different price series in \code{prices}, and want to use this function, call this functions using \code{lapply(prices,PBands,...)}. } \examples{ data(ttrc) pbands.close <- PBands( ttrc[,"Close"] ) } \seealso{ \code{\link{BBands}} } \author{ Brian G. Peterson } \keyword{ts} TTR/man/runFun.Rd0000644000176200001440000000571414531142730013251 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/runFun.R \name{runSum} \alias{runSum} \alias{runFun} \alias{runMin} \alias{runMax} \alias{runMean} \alias{runMedian} \alias{runCov} \alias{runCor} \alias{runVar} \alias{runSD} \alias{runMAD} \alias{wilderSum} \title{Analysis of Running/Rolling/Moving Windows} \usage{ runSum(x, n = 10, cumulative = FALSE) runMin(x, n = 10, cumulative = FALSE) runMax(x, n = 10, cumulative = FALSE) runMean(x, n = 10, cumulative = FALSE) runMedian(x, n = 10, non.unique = "mean", cumulative = FALSE) runCov(x, y, n = 10, use = "all.obs", sample = TRUE, cumulative = FALSE) runCor(x, y, n = 10, use = "all.obs", sample = TRUE, cumulative = FALSE) runVar(x, y = NULL, n = 10, sample = TRUE, cumulative = FALSE) runSD(x, n = 10, sample = TRUE, cumulative = FALSE) runMAD( x, n = 10, center = NULL, stat = "median", constant = 1.4826, non.unique = "mean", cumulative = FALSE ) wilderSum(x, n = 10) } \arguments{ \item{x}{Object coercible to xts or matrix.} \item{n}{Number of periods to use in the window or, if \code{cumulative=TRUE}, the number of observations to use before the first result is returned. Must be between 1 and \code{nrow(x)}, inclusive.} \item{cumulative}{Logical, use from-inception calculation?} \item{non.unique}{One of 'mean', 'max', or 'min'; which compute their respective statistics for the two middle values of even-sized samples.} \item{y}{Object coercible to xts or matrix.} \item{use}{Only \code{"all.obs"} currently implemented.} \item{sample}{Logical, sample covariance if \code{TRUE} (denominator of \code{n-1})} \item{center}{The values to use as the measure of central tendency, around which to calculate deviations. The default (\code{NULL}) uses the median.} \item{stat}{Statistic to calculate, one of 'median' or 'mean' (e.g. median absolute deviation or mean absolute deviation, respectively.)} \item{constant}{Scale factor applied to approximate the standard deviation.} } \value{ A object of the same class as \code{x} and \code{y} or a vector (if \code{try.xts} fails). \describe{ \item{runSum}{returns sums over a n-period moving window.} \item{runMin}{returns minimums over a n-period moving window.} \item{runMax}{returns maximums over a n-period moving window.} \item{runMean}{returns means over a n-period moving window.} \item{runMedian}{returns medians over a n-period moving window.} \item{runCov}{returns covariances over a n-period moving window.} \item{runCor}{returns correlations over a n-period moving window.} \item{runVar}{returns variances over a n-period moving window.} \item{runSD}{returns standard deviations over a n-period moving window.} \item{runMAD}{returns median/mean absolute deviations over a n-period moving window.} \item{wilderSum}{retuns a Welles Wilder style weighted sum over a n-period moving window.} } } \description{ Various functions to analyze data over a moving window of periods. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/MFI.Rd0000644000176200001440000000340414531142730012401 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/MFI.R \name{MFI} \alias{MFI} \alias{moneyFlow} \title{Money Flow Index} \usage{ MFI(HLC, volume, n = 14) } \arguments{ \item{HLC}{Object that is coercible to xts or matrix and contains High-Low-Close prices. If only a univariate series is given, it will be used. See details.} \item{volume}{Vector or matrix of volume observations corresponding to \code{HLC} object.} \item{n}{Number of periods to use.} } \value{ A object of the same class as \code{HLC} and \code{volume} or a vector (if \code{try.xts} fails) containing the MFI values. } \description{ The MFI is a ratio of positive and negative money flow over time. } \details{ Money Flow (MF) is the product of price and volume. Positive/negative MF occur when today's price is higher/lower than yesterday's price. The MFI is calculated by dividing positive MF by negative MF for the past \code{n} periods. It is then scaled between 0 and 100. MFI is usually calculated using the typical price, but if a univariate series (e.g. Close, Weighted Close, Median Price, etc.) is provided, it will be used instead. } \note{ Divergence between MFI and price can be indicative of a reversal. In addition, values above/below 80/20 indicate market tops/bottoms. } \examples{ data(ttrc) mfi <- MFI(ttrc[,c("High","Low","Close")], ttrc[,"Volume"]) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.fmlabs.com/reference/default.htm?url=MoneyFlowIndex.htm}\cr \url{https://www.linnsoft.com/techind/money-flow-index-mfi}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:money_flow_index_mfi}\cr } \seealso{ See \code{\link{OBV}} and \code{\link{CMF}}. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/TTRtools.Rd0000644000176200001440000000230614450607776013540 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/TTRtools.R \name{lags} \alias{lags} \alias{growth} \alias{naCheck} \title{Miscellaneous Tools} \usage{ lags(x, n = 1) growth(price, signals, ...) naCheck(x, n = 0) } \arguments{ \item{x}{Object that is coercible to xts or matrix.} \item{n}{Number of periods to use.} \item{price}{Price series that is coercible to xts or matrix.} \item{signals}{Signals to use (defaults to vector of ones). Use '0' for no position, '1' for long position, and '-1' for short position.} \item{\dots}{Further arguments to be passed from or to other methods.} } \value{ \code{growth} returns a vector of the growth of the investment. \code{lags} returns a matrix of lagged values of the original vector. } \description{ Various functions that may be useful in designing technical trading rules. } \details{ \code{growth} calculates the growth of an investment using given prices and signals. \code{lags} calculates the lags of a given series. } \note{ In \code{growth} you can specify the number of periods and type of compounding to use when calculating returns of the price series via the \code{'\dots'} argument. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/VHF.Rd0000644000176200001440000000272614531142730012417 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/VHF.R \name{VHF} \alias{VHF} \title{Vertical Horizontal Filter} \usage{ VHF(price, n = 28) } \arguments{ \item{price}{Object that is coercible to xts or matrix and contains a Close price series, or a High-Low-Close price series.} \item{n}{Number of periods to use.} } \value{ A object of the same class as \code{price} or a vector (if \code{try.xts} fails) containing the VHF values. } \description{ The Vertical Horizontal Filter (VHF) attempts to identify starting and ending trends. Developed by Adam White. } \details{ The VHF is calculated by subtracting the \code{n}-period lowest low from the \code{n}-period highest high and dividing that result by the \code{n}-period rolling sum of the close price changes. } \note{ If Close prices are given, the function calculates the max/min using only those prices (the default). If HLC prices are given, the function calculates the max/min using the high/low prices (added for flexibility). } \examples{ data(ttrc) vhf.close <- VHF(ttrc[,"Close"]) vhf.hilow <- VHF(ttrc[,c("High","Low","Close")]) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=119}\cr } \seealso{ See \code{\link{aroon}}, \code{\link{CCI}}, \code{\link{ADX}}, \code{\link{TDI}}, \code{\link{GMMA}} for other indicators that measure trend direction/strength. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/MACD.Rd0000644000176200001440000000634314531142730012477 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/MACD.R \name{MACD} \alias{MACD} \title{MACD Oscillator} \usage{ MACD(x, nFast = 12, nSlow = 26, nSig = 9, maType, percent = TRUE, ...) } \arguments{ \item{x}{Object that is coercible to xts or matrix; usually price, but can be volume, etc.} \item{nFast}{Number of periods for fast moving average.} \item{nSlow}{Number of periods for slow moving average.} \item{nSig}{Number of periods for signal moving average.} \item{maType}{Either: \enumerate{ \item A function or a string naming the function to be called. \item A \emph{list} with the first component like (1) above, and additional parameters specified as \emph{named} components. See Examples. }} \item{percent}{logical; if \code{TRUE}, the percentage difference between the fast and slow moving averages is returned, otherwise the difference between the respective averages is returned.} \item{\dots}{Other arguments to be passed to the \code{maType} function in case (1) above.} } \value{ A object of the same class as \code{x} or a matrix (if \code{try.xts} fails) containing the columns: \describe{ \item{ macd }{ The price (volume, etc.) oscillator. } \item{ signal }{ The oscillator signal line (a moving average of the oscillator). } } } \description{ The MACD was developed by Gerald Appel and is probably the most popular price oscillator. The MACD function documented in this page compares a fast moving average (MA) of a series with a slow MA of the same series. It can be used as a generic oscillator for any univariate series, not only price. } \details{ The MACD function either subtracts the fast MA from the slow MA, or finds the rate of change between the fast MA and the slow MA. } \note{ The MACD is a special case of the general oscillator applied to price. The MACD can be used as a general oscillator applied to any series. Time periods for the MACD are often given as 26 and 12, but the original formula used exponential constants of 0.075 and 0.15, which are closer to 25.6667 and 12.3333 periods. } \examples{ data(ttrc) macd <- MACD( ttrc[,"Close"], 12, 26, 9, maType="EMA" ) macd2 <- MACD( ttrc[,"Close"], 12, 26, 9, maType=list(list(SMA), list(EMA, wilder=TRUE), list(SMA)) ) } \references{ The following site(s) were used to code/document this indicator: \cr Moving Average Convergence/Divergence (MACD):\cr \url{https://www.fmlabs.com/reference/MACD.htm}\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=66}\cr \url{https://www.linnsoft.com/techind/macd}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:moving_average_convergence_divergence_macd}\cr \cr Price Oscillator:\cr \url{https://www.fmlabs.com/reference/PriceOscillator.htm}\cr \url{https://www.fmlabs.com/reference/PriceOscillatorPct.htm}\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=94}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:price_oscillators_ppo}\cr \cr Volume Oscillator:\cr \url{https://www.fmlabs.com/reference/PVO.htm}\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=122}\cr } \seealso{ See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average options; and note Warning section. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/SAR.Rd0000644000176200001440000000265114531142730012416 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/SAR.R \name{SAR} \alias{SAR} \title{Parabolic Stop-and-Reverse} \usage{ SAR(HL, accel = c(0.02, 0.2)) } \arguments{ \item{HL}{Object that is coercible to xts or matrix and contains High-Low prices.} \item{accel}{accel[1]: Acceleration factor.\cr accel[2]: Maximum acceleration factor.} } \value{ A object of the same class as \code{HL} or a vector (if \code{try.xts} fails) containing the Parabolic Stop and Reverse values. } \description{ The Parabolic Stop-and-Reverse calculates a trailing stop. Developed by J. Welles Wilder. } \details{ The calculation for the SAR is quite complex. See the URLs in the references section for calculation notes. The SAR assumes that you are always in the market, and calculates the Stop And Reverse point when you would close a long position and open a short position or vice versa. } \examples{ data(ttrc) sar <- SAR(ttrc[,c("High","Low")]) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.linnsoft.com/techind/parabolic-sar-sar}\cr \url{https://www.fmlabs.com/reference/SAR.htm}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:parabolic_sar}\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=87} } \seealso{ See \code{\link{ATR}} and \code{\link{ADX}}, which were also developed by Welles Wilder. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/chaikinVolatility.Rd0000644000176200001440000000301714531142730015455 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chaikinVolatility.R \name{chaikinVolatility} \alias{chaikinVolatility} \title{Chaikin Volatility} \usage{ chaikinVolatility(HL, n = 10, maType, ...) } \arguments{ \item{HL}{Object that is coercible to xts or matrix and contains High-Low prices.} \item{n}{Number of periods for moving average.} \item{maType}{A function or a string naming the function to be called.} \item{\dots}{Other arguments to be passed to the \code{maType} function.} } \value{ A object of the same class as \code{HL} or a vector (if \code{try.xts} fails) containing the Chaikin Volatility values. } \description{ Chaikin Volatility measures the rate of change of the security's trading range. Developed by Marc Chaikin. } \details{ The Chaikin Volatility indicator defines volatility as an increase in the difference between the high and low. } \note{ A rapid increase in Chaikin Volatility indicates an approaching bottom. A slow decrease in Chaikin Volatility indicates an approaching top. } \examples{ data(ttrc) volatility <- chaikinVolatility(ttrc[,c("High","Low")]) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.fmlabs.com/reference/ChaikinVolatility.htm}\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=120}\cr } \seealso{ See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average options; and note Warning section. See \code{\link{TR}} for another volatility measure. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/DPO.Rd0000644000176200001440000000417614531142730012417 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/DPO.R \name{DPO} \alias{DPO} \title{De-Trended Price Oscillator} \usage{ DPO(x, n = 10, maType, shift = n/2 + 1, percent = FALSE, ...) } \arguments{ \item{x}{Price, volume, etc. series that is coercible to xts or matrix.} \item{n}{Number of periods for moving average.} \item{maType}{A function or a string naming the function to be called.} \item{shift}{The number of periods to shift the moving average.} \item{percent}{logical; if \code{TRUE}, the percentage difference between the slow and fast moving averages is returned, otherwise the difference between the respective averages is returned.} \item{\dots}{Other arguments to be passed to the \code{maType} function.} } \value{ A object of the same class as \code{x} or a vector (if \code{try.xts} fails) containing the DPO values. } \description{ The Detrended Price Oscillator (DPO) removes the trend in prices - or other series - by subtracting a moving average of the price from the price. } \details{ The Detrended Price shows cycles and overbought / oversold conditions. } \note{ DPO does not extend to the last date because it is based on a displaced moving average. The calculation shifts the results \code{shift} periods, so the last \code{shift} periods will be zero.\cr As stated above, the DPO can be used on any univariate series, not just price. } \section{Warning}{ The detrended price oscillator removes the trend in the series by centering the moving average. Centering the moving average causes it to include future data. Therefore, even though this indicator looks like a classic oscillator, it should not be used for trading rule signals. } \examples{ data(ttrc) priceDPO <- DPO(ttrc[,"Close"]) volumeDPO <- DPO(ttrc[,"Volume"]) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:detrended_price_osci}\cr } \seealso{ See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average options; and note Warning section. See \code{\link{MACD}} for a general oscillator. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/CLV.Rd0000644000176200001440000000201314531142730012405 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/CLV.R \name{CLV} \alias{CLV} \title{Close Location Value} \usage{ CLV(HLC) } \arguments{ \item{HLC}{Object that is coercible to xts or matrix and contains High-Low-Close prices.} } \value{ A object of the same class as \code{HLC} or a vector (if \code{try.xts} fails) containing the Close Location Values of a High-Low-Close price series. } \description{ The Close Location Value (CLV) relates the day's close to its trading range. } \details{ The CLV will fall in a range of -1 to +1. If the CLV is +/-1, the close is at the high/low; if the CLV is 0, the close is directly between the high and low. } \examples{ data(ttrc) clv <- CLV(ttrc[,c("High","Low","Close")]) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:accumulation_distribution_line}\cr } \seealso{ See \code{\link{chaikinAD}}, which uses CLV. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/williamsAD.Rd0000644000176200001440000000231214531142730014011 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/williamsAD.R \name{williamsAD} \alias{williamsAD} \title{Williams Accumulation / Distribution} \usage{ williamsAD(HLC) } \arguments{ \item{HLC}{Object that is coercible to xts or matrix and contains High-Low-Close prices.} } \value{ A object of the same class as \code{HLC} or a vector (if \code{try.xts} fails) containing the accumulation / distribution values. } \description{ The Williams Accumulation / Distribution (AD) line is a measure of market momentum. Developed by Larry Williams. } \details{ The Williams AD line differs from OBV and chaikinAD in that it doesn't take volume into account. } \note{ The Accumulation/Distribution Line is interpreted by looking for a divergence in the direction of the indicator relative to price. } \examples{ data(ttrc) ad <- williamsAD(ttrc[,c("High","Low","Close")]) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.fmlabs.com/reference/WilliamsAD.htm}\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=125}\cr } \seealso{ See \code{\link{OBV}}, \code{\link{chaikinAD}}, and \code{\link{ATR}}. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/volatility.Rd0000644000176200001440000001434614531142730014175 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/volatility.R \name{volatility} \alias{volatility} \alias{garman.klass} \alias{parkinson} \alias{rogers.satchell} \alias{gk.yz} \alias{yang.zhang} \title{Volatility} \usage{ volatility(OHLC, n = 10, calc = "close", N = 260, mean0 = FALSE, ...) } \arguments{ \item{OHLC}{Object that is coercible to xts or matrix and contains Open-High-Low-Close prices (or only Close prices, if \code{calc="close"}).} \item{n}{Number of periods for the volatility estimate.} \item{calc}{The calculation (type) of estimator to use.} \item{N}{Number of periods per year.} \item{mean0}{Use a mean of 0 rather than the sample mean.} \item{\dots}{Arguments to be passed to/from other methods.} } \value{ A object of the same class as \code{OHLC} or a vector (if \code{try.xts} fails) containing the chosen volatility estimator values. } \description{ Selected volatility estimators/indicators; various authors. } \details{ \itemize{ \item Close-to-Close Volatility (\code{calc="close"})\cr \deqn{ \sigma_{cl} = \sqrt{\frac{N}{n-2} \sum_{i=1}^{n-1}(r_i-\bar{r})^2} }{sqrt(N) * runSD(ROC(Cl), n-1)} \deqn{where\;\; r_i = \log \left(\frac{C_i}{C_{i-1}}\right) } \deqn{and\;\; \bar{r} = \frac{r_1+r_2+\ldots +r_{n-1}}{n-1} } \item OHLC Volatility: Garman and Klass (\code{calc="garman.klass"})\cr The Garman and Klass estimator for estimating historical volatility assumes Brownian motion with zero drift and no opening jumps (i.e. the opening = close of the previous period). This estimator is 7.4 times more efficient than the close-to-close estimator.\cr \deqn{ \sigma = \sqrt{ \frac{N}{n} \sum \left[ \textstyle\frac{1}{2}\displaystyle \left( \log \frac{H_i}{L_i} \right)^2 - (2\log 2-1) \left( \log \frac{C_i}{O_i} \right)^2 \right] } }{sqrt(N/n * runSum(0.5 * log(Hi/Lo)^2 - (2*log(2)-1) * log(Cl/Op)^2, n))} \item High-Low Volatility: Parkinson (\code{calc="parkinson"})\cr The Parkinson formula for estimating the historical volatility of an underlying based on high and low prices.\cr \deqn{ \sigma = \sqrt{ \frac{N}{4 n \times \log 2} \sum_{i=1}^{n} \left(\log \frac{H_i}{L_i}\right)^2} }{sqrt(N/(4*n*log(2)) * runSum(log(Hi/Lo)^2, n))} \item OHLC Volatility: Rogers and Satchell (\code{calc="rogers.satchell"})\cr The Roger and Satchell historical volatility estimator allows for non-zero drift, but assumed no opening jump.\cr \deqn{ \sigma = \sqrt{ \textstyle\frac{N}{n} \sum \left[ \log \textstyle\frac{H_i}{C_i} \times \log \textstyle\frac{H_i}{O_i} + \log \textstyle\frac{L_i}{C_i} \times \log \textstyle\frac{L_i}{O_i} \right] } }{sqrt(N/n * runSum(log(Hi/Cl) * log(Hi/Op) + log(Lo/Cl) * log(Lo/Op), n))} \item OHLC Volatility: Garman and Klass - Yang and Zhang (\code{calc="gk.yz"})\cr This estimator is a modified version of the Garman and Klass estimator that allows for opening gaps.\cr \deqn{ \sigma = \sqrt{ \textstyle\frac{N}{n} \sum \left[ \left( \log \textstyle\frac{O_i}{C_{i-1}} \right)^2 + \textstyle\frac{1}{2}\displaystyle \left( \log \textstyle\frac{H_i}{L_i} \right)^2 - (2 \times \log 2-1) \left( \log \textstyle\frac{C_i}{O_i} \right)^2 \right] } }{sqrt(N/n * runSum(log(Op/lag(Cl,1))^2 + 0.5 * log(Hi/Lo)^2 - (2*log(2)-1) * log(Cl/Op)^2 , n))} \item OHLC Volatility: Yang and Zhang (\code{calc="yang.zhang"})\cr The Yang and Zhang historical volatility estimator has minimum estimation error, and is independent of drift and opening gaps. It can be interpreted as a weighted average of the Rogers and Satchell estimator, the close-open volatility, and the open-close volatility. Users may override the default values of \eqn{\alpha} (1.34 by default) or \eqn{k} used in the calculation by specifying \code{alpha} or \code{k} in \code{\dots}, respectively. Specifying \code{k} will cause \code{alpha} to be ignored, if both are provided.\cr \deqn{ \sigma^2 = \sigma_o^2 + k\sigma_c^2 + (1-k)\sigma_{rs}^2 }{ s <- sqrt(s2o + k*s2c + (1-k)*(s2rs^2)) } \deqn{ \sigma_o^2 =\textstyle \frac{N}{n-1} \sum \left( \log \frac{O_i}{C_{i-1}}-\mu_o \right)^2 }{ s2o <- N * runVar(log(Op/lag(Cl,1)), n=n) } \deqn{ \mu_o=\textstyle \frac{1}{n} \sum \log \frac{O_i}{C_{i-1}} } \deqn{ \sigma_c^2 =\textstyle \frac{N}{n-1} \sum \left( \log \frac{C_i}{O_i}-\mu_c \right)^2 }{ s2c <- N * runVar(log(Cl/Op), n=n) } \deqn{ \mu_c=\textstyle \frac{1}{n} \sum \log \frac{C_i}{O_i} } \deqn{ \sigma_{rs}^2 = \textstyle\frac{N}{n} \sum \left( \log \textstyle\frac{H_i}{C_i} \times \log \textstyle\frac{H_i}{O_i} + \log \textstyle\frac{L_i}{C_i} \times \log \textstyle\frac{L_i}{O_i} \right) }{ s2rs <- volatility(OHLC, n, "rogers.satchell", N, ...) } \deqn{ k=\frac{\alpha-1}{alpha+\frac{n+1}{n-1}} }{ k <- (alpha-1) / (alpha + (n+1)/(n-1)) } } } \examples{ data(ttrc) ohlc <- ttrc[,c("Open","High","Low","Close")] vClose <- volatility(ohlc, calc="close") vClose0 <- volatility(ohlc, calc="close", mean0=TRUE) vGK <- volatility(ohlc, calc="garman") vParkinson <- volatility(ohlc, calc="parkinson") vRS <- volatility(ohlc, calc="rogers") } \references{ The following sites were used to code/document these indicators. All were created by Thijs van den Berg under the GNU Free Documentation License and were retrieved on 2008-04-20. The original links are dead, but can be accessed via internet archives.\cr \cr Close-to-Close Volatility (\code{calc="close"}):\cr \url{https://web.archive.org/web/20100421083157/http://www.sitmo.com/eq/172}\cr \cr OHLC Volatility: Garman Klass (\code{calc="garman.klass"}):\cr \url{https://web.archive.org/web/20100326172550/http://www.sitmo.com/eq/402}\cr \cr High-Low Volatility: Parkinson (\code{calc="parkinson"}):\cr \url{https://web.archive.org/web/20100328195855/http://www.sitmo.com/eq/173}\cr \cr OHLC Volatility: Rogers Satchell (\code{calc="rogers.satchell"}):\cr \url{https://web.archive.org/web/20091002233833/http://www.sitmo.com/eq/414}\cr \cr OHLC Volatility: Garman Klass - Yang Zhang (\code{calc="gk.yz"}):\cr \url{https://web.archive.org/web/20100326215050/http://www.sitmo.com/eq/409}\cr \cr OHLC Volatility: Yang Zhang (\code{calc="yang.zhang"}):\cr \url{https://web.archive.org/web/20100326215050/http://www.sitmo.com/eq/409}\cr } \seealso{ See \code{\link{TR}} and \code{\link{chaikinVolatility}} for other volatility measures. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/aroon.Rd0000644000176200001440000000433414531142730013107 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/aroon.R \name{aroon} \alias{aroon} \title{Aroon} \usage{ aroon(HL, n = 20) } \arguments{ \item{HL}{Object that is coercible to xts or matrix and contains either a High-Low price series, or a Close price series.} \item{n}{Number of periods to use in the calculation.} } \value{ A object of the same class as \code{HL} or a matrix (if \code{try.xts} fails) containing the columns: \describe{ \item{ aroonUp }{ The Aroon up indicator. } \item{ aroonDn }{ The Aroon down indicator. } \item{ oscillator }{ The Aroon oscillator (\code{aroonUp - aroonDn}). } } } \description{ The Aroon indicator attempts to identify starting trends. The indicator consists of up and down lines, which measure how long it has been since the highest high/lowest low has occurred in the last \code{n} periods. Developed by Tushar Chande in 1995. } \details{ Aroon up (down) is the elapsed time, expressed as a percentage, between today and the highest (lowest) price in the last \code{n} periods. If today's price is a new high (low) Aroon up (down) will be 100. Each subsequent period without another new high (low) causes Aroon up (down) to decrease by (1 / \code{n}) x 100. } \note{ If High-Low prices are given, the function calculates the max/min using the high/low prices. Otherwise the function calculates the max/min of the single series. Up (down) trends are indicated when the aroonUp(Dn) is between 70 and 100. Strong trends are indicated when when the aroonUp(Dn) is above 70 while the aroonDn(Up) is below 30. Also, crossovers may be useful. } \examples{ ## Get Data and Indicator ## data(ttrc) trend <- aroon( ttrc[,c("High", "Low")], n=20 ) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.fmlabs.com/reference/Aroon.htm}\cr \url{https://www.fmlabs.com/reference/AroonOscillator.htm}\cr \url{https://www.linnsoft.com/techind/aroon-arn}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:aroon}\cr } \seealso{ See \code{\link{CCI}}, \code{\link{ADX}}, \code{\link{TDI}}, \code{\link{VHF}}, \code{\link{GMMA}} for other indicators that measure trend direction/strength. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/stochastics.Rd0000644000176200001440000001205214531142730014314 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/stochastics.R \name{stoch} \alias{stoch} \alias{stochastics} \alias{stochastic} \alias{SMI} \alias{\%K} \alias{\%D} \title{Stochastic Oscillator / Stochastic Momentum Index} \usage{ stoch( HLC, nFastK = 14, nFastD = 3, nSlowD = 3, maType, bounded = TRUE, smooth = 1, ... ) SMI(HLC, n = 13, nFast = 2, nSlow = 25, nSig = 9, maType, bounded = TRUE, ...) } \arguments{ \item{HLC}{Object that is coercible to xts or matrix and contains High-Low-Close prices. If only a univariate series is given, it will be used. See details.} \item{nFastK}{Number of periods for fast \%K (i.e. the number of past periods to use).} \item{nFastD}{Number of periods for fast \%D (i.e. the number smoothing periods to apply to fast \%K).} \item{nSlowD}{Number of periods for slow \%D (i.e. the number smoothing periods to apply to fast \%D).} \item{maType}{Either: \enumerate{ \item A function or a string naming the function to be called. \item A \emph{list} with the first component like (1) above, and additional parameters specified as \emph{named} components. See Examples. }} \item{bounded}{Logical, should current period's values be used in the calculation?} \item{smooth}{Number of internal smoothing periods to be applied before calculating FastK. See Details.} \item{\dots}{Other arguments to be passed to the \code{maType} function in case (1) above.} \item{n}{Number of periods to use.} \item{nFast}{Number of periods for initial smoothing.} \item{nSlow}{Number of periods for double smoothing.} \item{nSig}{Number of periods for signal line.} } \value{ A object of the same class as \code{HLC} or a matrix (if \code{try.xts} fails) containing the columns: \describe{ \item{ fastK }{ Stochastic Fast \%K } \item{ fastD }{ Stochastic Fast \%D } \item{ slowD }{ Stochastic Slow \%D } \item{ SMI }{ Stochastic Momentum Index } \item{ signal }{ Stochastic Momentum Index signal line } } } \description{ The stochastic oscillator is a momentum indicator that relates the location of each day's close relative to the high/low range over the past \code{n} periods. Developed by George C. Lane in the late 1950s. The SMI relates the close to the midpoint of the high/low range. Developed by William Blau in 1993. } \details{ If a High-Low-Close series is provided, the indicator is calculated using the high/low values. If a vector is provided, the calculation only uses that series. This allows stochastics to be calculated for: (1) series that have no HLC definition (e.g. foreign exchange), and (2) stochastic indicators (e.g. stochastic RSI - see examples). The \code{smooth} argument is the number of periods of internal smoothing to apply to the differences in the high-low-close range before calculating Fast K. Thanks to Stanley Neo for the suggestion. } \note{ The calculation for William's \%R is similar to that of stochastics' fast \%K. The value for fast \%K will be 0.5 whenever the highest high and lowest low are the same over the last \code{n} periods. The stochastic oscillator and SMI calculate relative value of the close versus the high/low range and the midpoint of the high/low range, respectively. The stochastic oscillator and the stochastic momentum index are interpreted similarly. Readings below 20 (above 80) are considered oversold (overbought). However, readings below 20 (above 80) are not necessarily bearish (bullish). Lane believed some of the best sell (buy) signals occurred when the oscillator moved from overbought (oversold) back below 80 (above 20). For the stochastic oscillator, buy (sell) signals can also be given when \%K crosses above (below) \%D. Crossover signals are quite frequent however, which may result in whipsaws. } \examples{ data(ttrc) stochOSC <- stoch(ttrc[,c("High","Low","Close")]) stochWPR <- WPR(ttrc[,c("High","Low","Close")]) plot(tail(stochOSC[,"fastK"], 100), type="l", main="Fast \%K and Williams \%R", ylab="", ylim=range(cbind(stochOSC, stochWPR), na.rm=TRUE) ) lines(tail(stochWPR, 100), col="blue") lines(tail(1-stochWPR, 100), col="red", lty="dashed") stoch2MA <- stoch( ttrc[,c("High","Low","Close")], maType=list(list(SMA), list(EMA, wilder=TRUE), list(SMA)) ) SMI3MA <- SMI(ttrc[,c("High","Low","Close")], maType=list(list(SMA), list(EMA, wilder=TRUE), list(SMA)) ) stochRSI <- stoch( RSI(ttrc[,"Close"]) ) } \references{ The following site(s) were used to code/document these indicators: \cr Stochastic Oscillator:\cr \url{https://www.fmlabs.com/reference/StochasticOscillator.htm}\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=106}\cr \url{https://www.linnsoft.com/techind/stochastics}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:stochastic_oscillator_fast_slow_and_full}\cr \cr SMI:\cr \url{https://www.fmlabs.com/reference/default.htm?url=SMI.htm}\cr } \seealso{ See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average options; and note Warning section. See \code{\link{WPR}} to compare it's results to fast \%K. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/RSI.Rd0000644000176200001440000000512114531142730012421 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/RSI.R \name{RSI} \alias{RSI} \title{Relative Strength Index} \usage{ RSI(price, n = 14, maType, ...) } \arguments{ \item{price}{Price series that is coercible to xts or matrix.} \item{n}{Number of periods for moving averages.} \item{maType}{Either: \enumerate{ \item A function or a string naming the function to be called. \item A \emph{list} with the first component like (1) above, and additional parameters specified as \emph{named} components. See Examples. }} \item{\dots}{Other arguments to be passed to the \code{maType} function in case (1) above.} } \value{ A object of the same class as \code{price} or a vector (if \code{try.xts} fails) containing the RSI values. } \description{ The Relative Strength Index (RSI) calculates a ratio of the recent upward price movements to the absolute price movement. Developed by J. Welles Wilder. } \details{ The RSI calculation is \code{RSI = 100 - 100 / ( 1 + RS )}, where \code{RS} is the smoothed ratio of 'average' gains over 'average' losses. The 'averages' aren't true averages, since they're divided by the value of \code{n} and not the number of periods in which there are gains/losses. } \note{ The RSI is usually interpreted as an overbought/oversold (over 70 / below 30) indicator. Divergence with price may also be useful. For example, if price is making new highs/lows, but RSI is not, it could indicate a reversal. You can calculate a stochastic RSI by using the function \code{\link{stoch}} on RSI values. } \examples{ data(ttrc) price <- ttrc[,"Close"] # Default case rsi <- RSI(price) # Case of one 'maType' for both MAs rsiMA1 <- RSI(price, n=14, maType="WMA", wts=ttrc[,"Volume"]) # Case of two different 'maType's for both MAs rsiMA2 <- RSI(price, n=14, maType=list(maUp=list(EMA),maDown=list(WMA))) } \references{ The following site(s) were used to code/document this indicator: \cr Relative Strength Index:\cr \url{https://www.fmlabs.com/reference/RSI.htm}\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=100}\cr \url{https://www.linnsoft.com/techind/relative-strength-index-rsi}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:relative_strength_index_rsi}\cr \cr Stochastic RSI:\cr \url{https://www.fmlabs.com/reference/StochRSI.htm}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:stochrsi}\cr } \seealso{ See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average options; and note Warning section. See \code{\link{CMO}} for a variation on RSI. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/DVI.Rd0000644000176200001440000000313214531142730012406 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/DVI.R \name{DVI} \alias{DVI} \title{DV Intermediate Oscillator} \usage{ DVI( price, n = 252, wts = c(0.8, 0.2), smooth = 3, magnitude = c(5, 100, 5), stretch = c(10, 100, 2), exact.multiplier = 1 ) } \arguments{ \item{price}{Price series that is coercible to xts or matrix.} \item{n}{Number of periods for the percent rank.} \item{wts}{The weight given to the smoothed returns (magnitude) component and the up/down days (stretch) component, respectively.} \item{smooth}{The number of periods to smooth price.} \item{magnitude}{A set of 3 periods used to smooth magnitude.} \item{stretch}{A set of 3 periods used to smooth stretch.} \item{exact.multiplier}{The weight applied to identical values in the window. See \code{runPercentRank}.} } \value{ A object of the same class as \code{price} or a vector (if \code{try.xts} fails) containing the DVI values. } \description{ The DV Intermediate oscillator (DVI) is a very smooth momentum oscillator that can also be used as a trend indicator. Created by David Varadi. } \details{ The DVI combines smoothed returns over different time windows and the relative number of up versus down days (stretch) over different time windows. } \examples{ data(ttrc) dvi <- DVI(ttrc[,"Close"]) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://cssanalytics.wordpress.com/2009/12/13/what-is-the-dvi/}\cr \url{https://marketsci.wordpress.com/2010/07/27/css-analytics\%E2\%80\%99-dvi-indicator-revealed/}\cr } \author{ Joshua Ulrich } \keyword{ts} TTR/man/OBV.Rd0000644000176200001440000000260714531142730012420 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/OBV.R \name{OBV} \alias{OBV} \title{On Balance Volume (OBV)} \usage{ OBV(price, volume) } \arguments{ \item{price}{Price series that is coercible to xts or matrix.} \item{volume}{Volume series that is coercible to xts or matrix, that corresponds to price object.} } \value{ A object of the same class as \code{price} and \code{volume} or a vector (if \code{try.xts} fails) containing the OBV values. } \description{ On Balance Volume (OBV) is a measure of the money flowing into or out of a security. It is similar to Chaikin Accumulation / Distribution. } \details{ OBV is calculated by adding (subtracting) each day's volume to a running cumulative total when the security's price closes higher (lower). } \note{ OBV is usually compared with the price chart of the underlying security to look for divergences/confirmation. } \examples{ data(ttrc) obv <- OBV(ttrc[,"Close"], ttrc[,"Volume"]) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.fmlabs.com/reference/OBV.htm}\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=82}\cr \url{https://www.linnsoft.com/techind/balance-open-interest}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:on_balance_volume_obv}\cr } \seealso{ See \code{\link{chaikinAD}}. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/SNR.Rd0000644000176200001440000000236214531142730012432 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/SNR.R \name{SNR} \alias{SNR} \title{Signal to Noise Ratio} \usage{ SNR(HLC, n, ...) } \arguments{ \item{HLC}{Object that is coercible to xts or matrix and contains High-Low-Close prices.} \item{n}{Number of periods for moving average.} \item{...}{Other arguments to be passed to \code{\link{ATR}}.} } \value{ A object of the same class as HLC or a matrix (if try.xts fails) containing the signal to noise ratio. } \description{ The n-day SNR for a given market is calculated by taking the absolute price change over an n-day period and dividing it by the average n-day volatility. } \details{ \deqn{SNR_n = \frac{|C_t - C_{t-n}|}{ATR_n} }{SNR = abs(Cl - lag(Cl,n)) / ATR(HLC, n)$atr} Using average true range as the volatility measure captures more of the intraday and overnight volatility in a way that a measurement of Close-to-Close price change does not. The interpretation is then relatively intuitive: an SNR value of five indicates that the market has moved five times the volatility (average true range) over the given look-back period. } \references{ Skeggs, James and Hill, Alex (2015). Back in Black Part 2: The Opportunity Set for Trend Following. } \author{ Peter Carl } TTR/man/GMMA.Rd0000644000176200001440000000312114531142730012503 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/GMMA.R \name{GMMA} \alias{GMMA} \alias{Guppy} \alias{guppy} \title{Guppy Multiple Moving Averages} \usage{ GMMA( x, short = c(3, 5, 8, 10, 12, 15), long = c(30, 35, 40, 45, 50, 60), maType ) } \arguments{ \item{x}{Price, volume, etc. series that is coercible to xts or matrix.} \item{short}{Vector of short-term periods.} \item{long}{Vector of long-term periods.} \item{maType}{Either: \enumerate{ \item A function or a string naming the function to be called. \item A \emph{list} with the first component like (1) above, and additional parameters specified as \emph{named} components. See Examples. }} } \value{ A object of the same class as \code{x} or \code{price} or a vector (if \code{try.xts} fails) containing the Guppy Multiple Moving Average. } \description{ Calculate the Guppy Multiple Moving Average of a series. } \details{ The Guppy Multiple Moving Average signals a changing trend when the \code{short} and \code{long} groups of moving averages intersect. An up/down trend exists when the short/long-term moving averages are greater than the long/short-term averages. } \examples{ data(ttrc) gmma <- GMMA(ttrc[,"Close"]) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.investopedia.com/terms/g/guppy-multiple-moving-average.asp}\cr } \seealso{ See \code{\link{aroon}}, \code{\link{CCI}}, \code{\link{ADX}}, \code{\link{VHF}}, \code{\link{TDI}} for other indicators that measure trend direction/strength. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/changes.Rd0000644000176200001440000000224214531142730013375 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/changes.R \name{ROC} \alias{ROC} \alias{changes} \alias{momentum} \title{Rate of Change / Momentum} \usage{ ROC(x, n = 1, type = c("continuous", "discrete"), na.pad = TRUE) momentum(x, n = 1, na.pad = TRUE) } \arguments{ \item{x}{Price, volume, etc. series that is coercible to xts or matrix.} \item{n}{Number of periods to use.} \item{type}{Compounding type; either \code{"continuous"} (the default) or \code{"discrete"}.} \item{na.pad}{Should periods prior to \code{n} be appended? Default is \code{TRUE}.} } \value{ A object of the same class as \code{x} or a vector (if \code{try.xts} fails) containing the rate-of-change (or return) values for \code{ROC} or a vector containing the differenced price series for \code{momentum}. } \description{ Calculate the (rate of) change of a series over \code{n} periods. } \details{ The ROC indicator provides the percentage difference of a series over two observations, while the momentum indicator simply provides the difference. } \examples{ data(ttrc) roc <- ROC(ttrc[,"Close"]) mom <- momentum(ttrc[,"Close"]) } \author{ Joshua Ulrich } \keyword{ts} TTR/man/WPR.Rd0000644000176200001440000000324014531142730012434 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/WPR.R \name{WPR} \alias{WPR} \title{William's \%R} \usage{ WPR(HLC, n = 14) } \arguments{ \item{HLC}{Object that is coercible to xts or matrix and contains High-Low-Close prices. If only a univariate series is given, it will be used. See details.} \item{n}{Number of periods to use.} } \value{ A object of the same class as \code{HLC} or a vector (if \code{try.xts} fails) containing the William's \%R values. } \description{ William's \% R. } \details{ If an High-Low-Close series is provided, the indicator is calculated using the high/low values. If a vector is provided, the calculation only uses that series. } \note{ The William's \%R calculation is similar to stochastics' fast \%K. The value for William's \%R will be 0.5 whenever the highest high and lowest low are the same over the last \code{n} periods. } \examples{ data(ttrc) stochOsc <- stoch(ttrc[,c("High","Low","Close")]) stochWPR<- WPR(ttrc[,c("High","Low","Close")]) plot(tail(stochOsc[,"fastK"], 100), type="l", main="Fast \%K and Williams \%R", ylab="", ylim=range(cbind(stochOsc, stochWPR), na.rm=TRUE) ) lines(tail(stochWPR, 100), col="blue") lines(tail(1-stochWPR, 100), col="red", lty="dashed") } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.fmlabs.com/reference/WilliamsR.htm}\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=126}\cr \url{https://www.linnsoft.com/techind/williams-r-wpr}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:williams_r}\cr } \seealso{ See \code{\link{stoch}}. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/TTR.Rd0000644000176200001440000000341714531142730012443 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/TTR-package.R \docType{package} \name{TTR} \alias{TTR} \alias{TTR-package} \title{Functions to create Technical Trading Rules (TTR)} \description{ This package contains many of the most popular technical analysis functions, as well as functions to retrieve U.S. stock symbols, and data from Yahoo Finance. } \details{ Users will probably be most interested in the following functions:\cr \code{\link{ADX}}\cr \code{\link{BBands}}\cr \code{\link{changes}}\cr \code{\link{MovingAverages}}\cr \code{\link{MACD}}\cr \code{\link{RSI}}\cr \code{\link{runFun}}\cr \code{\link{stoch}}\cr \code{\link{VWAP}}\cr \code{\link{WebData}}\cr } \examples{ data(ttrc) # Bollinger Bands bbands <- BBands( ttrc[,c("High","Low","Close")] ) # Directional Movement Index adx <- ADX(ttrc[,c("High","Low","Close")]) # Moving Averages ema <- EMA(ttrc[,"Close"], n=20) sma <- SMA(ttrc[,"Close"], n=20) # MACD macd <- MACD( ttrc[,"Close"] ) # RSI rsi <- RSI(ttrc[,"Close"]) # Stochastics stochOsc <- stoch(ttrc[,c("High","Low","Close")]) ### Note: you must have a working internet connection ### for the examples below to work! if (interactive()) { # Fetch U.S. symbols from the internet nyseSymbols <- stockSymbols("NYSE") # Fetch Yahoo! Finance data from the internet ge <- getYahooData("GE", 19990404, 20050607, adjust = FALSE) } } \references{ The following sites were used to code/document this package:\cr \url{https://www.fmlabs.com/reference/default.htm}\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/}\cr \url{https://www.linnsoft.com/indicators}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators}\cr } \author{ Joshua Ulrich Maintainer: Joshua Ulrich } \keyword{package} TTR/man/runPercentRank.Rd0000644000176200001440000000461514450607776014754 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/percentRank.R \name{runPercentRank} \alias{runPercentRank} \alias{percentRank} \alias{PercentRank} \title{Percent Rank over a Moving Window} \usage{ runPercentRank(x, n = 260, cumulative = FALSE, exact.multiplier = 0.5) } \arguments{ \item{x}{Object coercible to xts or matrix.} \item{n}{Number of periods to use in the window or, if \code{cumulative=TRUE}, the number of observations to use before the first result is returned. Must be between 1 and \code{nrow(x)}, inclusive.} \item{cumulative}{Logical, use from-inception calculation?} \item{exact.multiplier}{The weight applied to identical values in the window. Must be between 0 and 1, inclusive. See details.} } \value{ A object of percent ranks over a n-period moving window of the same class as \code{x} and \code{y} or a vector (if \code{try.xts} fails). } \description{ This function computes a running/rolling percentage rank. } \details{ The computation for a percentage rank can vary depending on the weight given to values in the window that are equal to the value being ranked. This weight can be set using the \code{exact.multiplier} argument which defaults to 0.5. \code{exact.multiplier = 0} scores equal values in the lookback window as always being greater than the value being ranked. \code{exact.multiplier = 1} scores equal values as being below the value being ranked. Any multiplier between 0 and 1 counts that proportion of the equal values as being below the value being ranked. The value of \code{exact.multiplier} has the most impact when the window is relatively small or when the number of discrete values in the window is small. For non-repeating values, changing \code{exact.multiplier = 0} to \code{exact.multiplier = 1} for a window of size \code{N} will shift the resulting percentile rankings by \code{1/N}. It is equivalent to changing the question from, "how many values are < the value" to "how many values are <= the value". } \note{ This computation is different from the one used in Microsoft Excel's \code{PERCENTRANK} formula. Excel's computation is rather strange and gives inconsistent results as it uses interpolation to rank values that are not found within the lookback window. } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://en.wikipedia.org/wiki/Percentile_rank}\cr } \author{ Charlie Friedemann } \keyword{ts} TTR/man/chaikinAD.Rd0000644000176200001440000000323114531142730013577 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/chaikinAD.R \name{chaikinAD} \alias{chaikinAD} \title{Chaikin Accumulation / Distribution} \usage{ chaikinAD(HLC, volume) } \arguments{ \item{HLC}{Object that is coercible to xts or matrix and contains High-Low-Close prices.} \item{volume}{Vector or matrix of volume observations corresponding to the \code{HLC} object.} } \value{ A object of the same class as \code{HLC} and \code{volume} or a vector (if \code{try.xts} fails) containing the accumulation / distribution values. } \description{ The Chaikin Accumulation / Distribution (AD) line is a measure of the money flowing into or out of a security. It is similar to On Balance Volume (OBV). Developed by Marc Chaikin. } \details{ The AD line is similar to OBV; the difference is that OBV sums volume multiplied by +/- 1 if the close is higher/lower than the previous close, while the AD line multiplies volume by the close location value (CLV). } \note{ The Accumulation/Distribution Line is interpreted by looking for a divergence in the direction of the indicator relative to price. } \examples{ data(ttrc) ad <- chaikinAD(ttrc[,c("High","Low","Close")], ttrc[,"Volume"]) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.fmlabs.com/reference/AccumDist.htm}\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=27}\cr \url{https://www.linnsoft.com/techind/accumulation-distribution}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:accumulation_distribution_line}\cr } \seealso{ See \code{\link{OBV}}, and \code{\link{CLV}}. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/bollingerBands.Rd0000644000176200001440000000521314531142730014713 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/bollingerBands.R \name{BBands} \alias{BBands} \alias{bollingerBands} \title{Bollinger Bands} \usage{ BBands(HLC, n = 20, maType, sd = 2, ...) } \arguments{ \item{HLC}{Object that is coercible to xts or matrix and contains High-Low-Close prices. If only a univariate series is given, it will be used. See details.} \item{n}{Number of periods for moving average.} \item{maType}{A function or a string naming the function to be called.} \item{sd}{The number of standard deviations to use.} \item{\dots}{Other arguments to be passed to the \code{maType} function.} } \value{ A object of the same class as \code{HLC} or a matrix (if \code{try.xts} fails) containing the columns: \describe{ \item{ dn }{ The lower Bollinger Band. } \item{ mavg }{ The middle Moving Average (see notes). } \item{ up }{ The upper Bollinger Band. } \item{ pctB }{ The \%B calculation. } } } \description{ Bollinger Bands are a way to compare a security's volatility and price levels over a period of time. Developed by John Bollinger. } \details{ Bollinger Bands consist of three lines: The middle band is generally a 20-period SMA of the typical price ([high + low + close]/3). The upper and lower bands are \code{sd} standard deviations (generally 2) above and below the MA. The middle band is usually calculated using the typical price, but if a univariate series (e.g. Close, Weighted Close, Median Price, etc.) is provided, it will be used instead. } \note{ Using any moving average other than SMA will result in inconsistencies between the moving average calculation and the standard deviation calculation. Since, by definition, a rolling standard deviation uses a simple moving average. } \examples{ ## The examples below show the differences between using a ## High-Low-Close series, and just a close series when ## calculating Bollinger Bands. data(ttrc) bbands.HLC <- BBands( ttrc[,c("High","Low","Close")] ) bbands.close <- BBands( ttrc[,"Close"] ) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.fmlabs.com/reference/Bollinger.htm}\cr \url{https://www.fmlabs.com/reference/BollingerWidth.htm}\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=36}\cr \url{https://www.linnsoft.com/techind/bollinger-bands}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:bollinger_bands}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:bollinger_band_width}\cr } \seealso{ See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average options; and note Warning section. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/MovingAverages.Rd0000644000176200001440000001500414531225347014710 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/MovingAverages.R \name{SMA} \alias{SMA} \alias{MovingAverages} \alias{EMA} \alias{WMA} \alias{DEMA} \alias{GD} \alias{T3} \alias{EVWMA} \alias{ZLEMA} \alias{VWAP} \alias{VWMA} \alias{MA} \alias{HMA} \alias{ALMA} \title{Moving Averages} \usage{ SMA(x, n = 10, ...) EMA(x, n = 10, wilder = FALSE, ratio = NULL, ...) DEMA(x, n = 10, v = 1, wilder = FALSE, ratio = NULL) WMA(x, n = 10, wts = 1:n, ...) EVWMA(price, volume, n = 10, ...) ZLEMA(x, n = 10, ratio = NULL, ...) VWAP(price, volume, n = 10, ...) HMA(x, n = 20, ...) ALMA(x, n = 9, offset = 0.85, sigma = 6, ...) } \arguments{ \item{x}{Price, volume, etc. series that is coercible to xts or matrix.} \item{n}{Number of periods to average over. Must be between 1 and \code{nrow(x)}, inclusive.} \item{\dots}{any other passthrough parameters} \item{wilder}{logical; if \code{TRUE}, a Welles Wilder type EMA will be calculated; see notes.} \item{ratio}{A smoothing/decay ratio. \code{ratio} overrides \code{wilder} in \code{EMA}.} \item{v}{The 'volume factor' (a number in [0,1]). See Notes.} \item{wts}{Vector of weights. Length of \code{wts} vector must equal the length of \code{x}, or \code{n} (the default).} \item{price}{Price series that is coercible to xts or matrix.} \item{volume}{Volume series that is coercible to xts or matrix, that corresponds to price series, or a constant. See Notes.} \item{offset}{Percentile at which the center of the distribution should occur.} \item{sigma}{Standard deviation of the distribution.} } \value{ A object of the same class as \code{x} or \code{price} or a vector (if \code{try.xts} fails) containing the columns: \describe{ \item{SMA}{ Simple moving average. } \item{EMA}{ Exponential moving average. } \item{WMA}{ Weighted moving average. } \item{DEMA}{ Double-exponential moving average. } \item{EVWMA}{ Elastic, volume-weighted moving average. } \item{ZLEMA}{ Zero lag exponential moving average. } \item{VWMA}{ Volume-weighed moving average (same as \code{VWAP}). } \item{VWAP}{ Volume-weighed average price (same as \code{VWMA}). } \item{VWA}{ Variable-length moving average. } \item{HMA}{ Hull moving average. } \item{ALMA}{ Arnaud Legoux moving average. } } } \description{ Calculate various moving averages (MA) of a series. } \details{ \code{SMA} calculates the arithmetic mean of the series over the past \code{n} observations. \code{EMA} calculates an exponentially-weighted mean, giving more weight to recent observations. See Warning section below. \code{WMA} is similar to an EMA, but with linear weighting if the length of \code{wts} is equal to \code{n}. If the length of \code{wts} is equal to the length of \code{x}, the WMA will use the values of \code{wts} as weights. \code{DEMA} is calculated as: \code{DEMA = (1 + v) * EMA(x,n) - EMA(EMA(x,n),n) * v} (with the corresponding \code{wilder} and \code{ratio} arguments). \code{EVWMA} uses volume to define the period of the MA. \code{ZLEMA} is similar to an EMA, as it gives more weight to recent observations, but attempts to remove lag by subtracting data prior to \code{(n-1)/2} periods (default) to minimize the cumulative effect. \code{VWMA} and \code{VWAP} calculate the volume-weighted moving average price. \code{HMA} a WMA of the difference of two other WMAs, making it very reponsive. \code{ALMA} inspired by Gaussian filters. Tends to put less weight on most recent observations, reducing tendency to overshoot. } \note{ For \code{EMA}, \code{wilder=FALSE} (the default) uses an exponential smoothing ratio of \code{2/(n+1)}, while \code{wilder=TRUE} uses Welles Wilder's exponential smoothing ratio of \code{1/n}. The \code{EMA} result is initialized with the \code{n}-period sample average at period \code{n}. The exponential decay is applied from that point forward. Since \code{WMA} can accept a weight vector of length equal to the length of \code{x} or of length \code{n}, it can be used as a regular weighted moving average (in the case \code{wts=1:n}) or as a moving average weighted by volume, another indicator, etc. Since \code{DEMA} allows adjusting \code{v}, it is technically Tim Tillson's generalized DEMA (GD). When \code{v=1} (the default), the result is the standard DEMA. When \code{v=0}, the result is a regular EMA. All other values of \code{v} return the GD result. This function can be used to calculate Tillson's T3 indicator (see example below). Thanks to John Gavin for suggesting the generalization. For \code{EVWMA}, if \code{volume} is a series, \code{n} should be chosen so the sum of the volume for \code{n} periods approximates the total number of outstanding shares for the security being averaged. If \code{volume} is a constant, it should represent the total number of outstanding shares for the security being averaged. } \section{Warning }{ Some indicators (e.g. EMA, DEMA, EVWMA, etc.) are calculated using the indicators' own previous values, and are therefore unstable in the short-term. As the indicator receives more data, its output becomes more stable. See example below. } \examples{ data(ttrc) ema.20 <- EMA(ttrc[,"Close"], 20) sma.20 <- SMA(ttrc[,"Close"], 20) dema.20 <- DEMA(ttrc[,"Close"], 20) evwma.20 <- EVWMA(ttrc[,"Close"], ttrc[,"Volume"], 20) zlema.20 <- ZLEMA(ttrc[,"Close"], 20) alma <- ALMA(ttrc[,"Close"]) hma <- HMA(ttrc[,"Close"]) ## Example of Tim Tillson's T3 indicator T3 <- function(x, n=10, v=1) DEMA(DEMA(DEMA(x,n,v),n,v),n,v) t3 <- T3(ttrc[,"Close"]) ## Example of short-term instability of EMA ## (and other indicators mentioned above) x <- rnorm(100) tail( EMA(x[90:100],10), 1 ) tail( EMA(x[70:100],10), 1 ) tail( EMA(x[50:100],10), 1 ) tail( EMA(x[30:100],10), 1 ) tail( EMA(x[10:100],10), 1 ) tail( EMA(x[ 1:100],10), 1 ) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.fmlabs.com/reference/ExpMA.htm}\cr \url{https://www.fmlabs.com/reference/WeightedMA.htm}\cr \url{https://www.fmlabs.com/reference/DEMA.htm}\cr \url{https://www.fmlabs.com/reference/T3.htm}\cr \url{https://www.linnsoft.com/techind/evwma-elastic-volume-weighted-moving-average}\cr \url{https://www.fmlabs.com/reference/ZeroLagExpMA.htm}\cr \url{https://www.fmlabs.com/reference/VIDYA.htm}\cr \url{https://www.traderslog.com/hullmovingaverage}\cr \url{https://web.archive.org/web/20180222085959/http://arnaudlegoux.com/}\cr } \seealso{ See \code{\link{wilderSum}}, which is used in calculating a Welles Wilder type MA. } \author{ Joshua Ulrich, Ivan Popivanov (HMA, ALMA) } \keyword{ts} TTR/man/CTI.Rd0000644000176200001440000000314414450607776012426 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/CTI.R \name{CTI} \alias{CTI} \title{Ehler's Correlation Trend Indicator} \usage{ CTI(price, n = 20, slope = 1) } \arguments{ \item{price}{Price series that is coercible to xts or matrix.} \item{n}{Number of periods to use.} \item{slope}{Slope of desired trend.} } \value{ A object of the same class as \code{price} or a matrix (if \code{try.xts} fails) with the column: \describe{ \item{cti}{ The Correlation Trend Indicator. } } } \description{ Ehler's Correlation Trend Indicator (CTI) measures the Spearman correlation of the price with the ideal trend line: a straight line with increasing slope. } \details{ The CTI measures the Spearman correlation between the price and the ideal trend line with slope of \code{slope}, over the past \code{n} days. See URL in references section for further details. } \note{ Positive/negative CTI values signal positive/negative correlation with the desired trend line slope. A simple strategy could be long when the CTI is positive and, short when it is negative. } \examples{ data(ttrc) cti <- CTI(ttrc[,"Close"], n = 20) } \references{ John Ehlers, Correlation Trend Indicator, Stocks & Commodities May-2020 The following site(s) were used to code/document this indicator:\cr \url{https://financial-hacker.com/petra-on-programming-a-unique-trend-indicator/}\cr } \seealso{ See \code{\link{aroon}}, \code{\link{CCI}}, \code{\link{ADX}}, \code{\link{VHF}}, \code{\link{GMMA}}, \code{\link{TDI}} for other indicators that measure trend direction/strength. } \author{ Ethan Smith, Joshua Ulrich } \keyword{ts} TTR/man/WebData.Rd0000644000176200001440000001016314531142730013275 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/WebData.R \name{stockSymbols} \alias{stockSymbols} \alias{WebData} \alias{getYahooData} \title{Fetch Internet Data} \usage{ stockSymbols( exchange = c("AMEX", "NASDAQ", "NYSE", "ARCA", "BATS", "IEX"), sort.by = c("Exchange", "Symbol"), quiet = FALSE ) getYahooData( symbol, start, end, freq = "daily", type = "price", adjust = TRUE, quiet = FALSE ) } \arguments{ \item{exchange}{Character vector of exchange names on which desired instrument symbols are traded.} \item{sort.by}{Character vector of columns by which returned data will be sorted. Must be one or more of \code{"Name"}, \code{"Symbol"}, \code{"Market.Cap"}, or \code{"Exchange"}.} \item{quiet}{Logical; if \code{TRUE}, status messages will be printed to the console.} \item{symbol}{Yahoo! Finance instrument symbol.} \item{start}{Numeric; first date of desired data, in YYYYMMDD format. Default is first date of series.} \item{end}{Numeric; last date of desired data, in YYYYMMDD format. Default is last date of series.} \item{freq}{Desired data frequency. One of \code{"daily"}, \code{"weekly"}, \code{"monthly"}.} \item{type}{Type of data to return. One of \code{"price"}, or \code{"split"}. \code{type="split"} will return both split and dividend data.} \item{adjust}{Logical; if \code{TRUE}, the Open, High, Low, and Close prices will be adjusted for dividends and splits, and Volume will be adjusted for dividends.} } \value{ \code{getYahooData} returns an xts object containing the columns: \code{stockSymbols} returns a character vector containing all the listed symbols for the given exchanges. \describe{ \item{ Date }{ Trade date, in CCYYMMDD format. } \item{ Open }{ Open price. } \item{ High }{ High price. } \item{ Low }{ Low price. } \item{ Close }{ Close price. } \item{ Volume }{ Volume. } } } \description{ Get investment data from the internet. } \details{ \code{getYahooData} fetches individual stock data from the Yahoo! Finance website. It also adjusts price for splits and dividends, and volume for splits. See the Warning section, and note that it is deprecated in favor of getSymbols in the quantmod package. \code{stockSymbols} fetches instrument symbols from the nasdaq.com website, and adjusts the symbols to be compatible with the Yahoo! Finance website. } \note{ The symbols returned by \code{stockSymbols} may not be in the format necessary to retrieve data using \code{getYahooData}. \code{getYahooData} has only been tested on daily data. It isn't known if the function correctly adjusts data for any other frequency. } \section{Warning}{ As of TTR 0.23-2, \code{getYahooData} has been patched to work with changes to Yahoo Finance, which also included the following changes to the raw data: \itemize{ \item The adjusted close column appears to no longer include dividend adjustments \item The open, high, and low columns are adjusted for splits, and \item The raw data may contain missing values. \item The raw data may contain errors. } As of TTR 0.24.2, \code{stockSymbols} began using data from NASDAQ's FTP site because the data from the original site is no longer available. This new file does not contain data for the columns: LastSale, MarketCap, IPOyear, Sector, and Industry. All the columns still appear in the results,#' but all the values in the columns are set to \code{NA}. } \examples{ ### Note: you must have a working internet ### connection for these examples to work! if (interactive()) { ge <- getYahooData("GE", 19990404, 20050607, adjust = FALSE) nyse.symbols <- stockSymbols("NYSE") } } \references{ \itemize{ \item \href{https://quant.stackexchange.com/questions/1640/where-to-download-list-of-all-common-stocks-traded-on-nyse-nasdaq-and-amex/1862}{Quant StackExchange: Download list of all stock symbols?} \item \href{https://www.nasdaqtrader.com/trader.aspx?id=CQSsymbolconvention}{CQS symbol convention} \item \href{https://web.archive.org/web/20111023221931/http://help.yahoo.com/l/us/yahoo/finance/quotes/quote-02.html}{Yahoo Finance symbol conventions} } } \author{ Joshua Ulrich } \keyword{ts} TTR/man/ZigZag.Rd0000644000176200001440000000417014531142730013162 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ZigZag.R \name{ZigZag} \alias{ZigZag} \alias{zigzag} \title{Zig Zag} \usage{ ZigZag(HL, change = 10, percent = TRUE, retrace = FALSE, lastExtreme = TRUE) } \arguments{ \item{HL}{Object that is coercible to xts or matrix and contains either a High-Low price series, or a Close price series.} \item{change}{Minimum price movement, either in dollars or percent (see \code{percent}).} \item{percent}{Use percentage or dollar change?} \item{retrace}{Is \code{change} a retracement of the previous move, or an absolute change from peak to trough?} \item{lastExtreme}{If the extreme price is the same over multiple periods, should the extreme price be the first or last observation?} } \value{ A object of the same class as \code{HL} or a vector (if \code{try.xts} fails) containing the Zig Zag indicator. } \description{ Zig Zag higlights trends by removing price changes smaller than \code{change} and interpolating lines between the extreme points. } \details{ The Zig Zag is non-predictive. The purpose of the Zig Zag is filter noise and make chart patterns clearer. It's more a visual tool than an indicator. } \note{ If High-Low prices are given, the function calculates the max/min using the high/low prices. Otherwise the function calculates the max/min of the single series. } \section{Warning}{ The last value of the ZigZag indicator is unstable (i.e. unknown) until the turning point actually occurs. Therefore this indicator isn't well-suited for use for systematic trading strategies. } \examples{ ## Get Data and Indicator ## data(ttrc) zz <- ZigZag( ttrc[,c("High", "Low")], change=20 ) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.fmlabs.com/reference/default.htm?url=ZigZag.htm}\cr \url{https://www.linnsoft.com/techind/zig-zag-indicator-zig-zzo}\cr \url{https://www.linnsoft.com/techind/zig-zag-oscillator-indicator-zzo}\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=127}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:zigzag}\cr } \author{ Joshua Ulrich } \keyword{ts} TTR/man/ultimateOscillator.Rd0000644000176200001440000000171214450607776015666 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ultimateOscillator.R \name{ultimateOscillator} \alias{ultimateOscillator} \title{The Ultimate Oscillator} \usage{ ultimateOscillator(HLC, n = c(7, 14, 28), wts = c(4, 2, 1)) } \arguments{ \item{HLC}{Object that is coercible to xts or matrix and contains High-Low-Close prices.} \item{n}{A vector of the number of periods to use for each average calculation.} \item{wts}{The weights applied to each average.} } \description{ The Ultimate Oscillator is a momentum oscillator designed to capture momentum across three different time frames. } \details{ Created by Larry Williams in 1976. } \examples{ data(ttrc) ult.osc <- ultimateOscillator(ttrc[,c("High","Low","Close")]) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:ultimate_oscillator}\cr } \author{ Ivan Popivanov } \keyword{ts} TTR/man/EMV.Rd0000644000176200001440000000371014531142730012415 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/EMV.R \name{EMV} \alias{EMV} \title{Arms' Ease of Movement Value} \usage{ EMV(HL, volume, n = 9, maType, vol.divisor = 10000, ...) } \arguments{ \item{HL}{Object that is coercible to xts or matrix and contains High-Low prices.} \item{volume}{Vector or matrix of volume observations corresponding to the \code{HL} object.} \item{n}{Number of periods for moving average.} \item{maType}{A function or a string naming the function to be called.} \item{vol.divisor}{An increment to make the results larger and easier to work with.} \item{\dots}{Other arguments to be passed to the \code{maType} function.} } \value{ A object of the same class as \code{HL} and \code{volume} or a matrix (if \code{try.xts} fails) containing the columns: \describe{ \item{ emv }{ The ease of movement values. } \item{ maEMV }{ The smoothed (as specified by \code{ma}) ease of movement values. } } } \description{ Arms' Ease of Movement Value (EMV) emphasizes days where the security moves easily and minimizes days where the security does not move easily. Developed by Richard W. Arms, Jr. } \details{ The EMV is calculated by dividing the midpoint ([high + low]/2) move by the 'Box Ratio' (volume divided by the high minus low). } \note{ A buy/sell signal is generated when the EMV crosses above/below zero. When the EMV hovers around zero, there are small price movements and/or high volume, and the price is not moving easily. } \examples{ data(ttrc) emv <- EMV(ttrc[,c("High","Low")], ttrc[,"Volume"]) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.fmlabs.com/reference/ArmsEMV.htm}\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=51}\cr \url{https://www.linnsoft.com/techind/arms-ease-movement}\cr } \seealso{ See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average options; and note Warning section. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/TRIX.Rd0000644000176200001440000000433114531142730012554 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/TRIX.R \name{TRIX} \alias{TRIX} \title{Triple Smoothed Exponential Oscillator} \usage{ TRIX(price, n = 20, nSig = 9, maType, percent = TRUE, ...) } \arguments{ \item{price}{Price series that is coercible to xts or matrix.} \item{n}{Number of periods for moving average.} \item{nSig}{Number of periods for signal line moving average.} \item{maType}{Either: \enumerate{ \item A function or a string naming the function to be called. \item A \emph{list} with the first component like (1) above, and additional parameters specified as \emph{named} components. See Examples. }} \item{percent}{logical; if \code{TRUE}, the rate of change is calculated using the \code{ROC} function, otherwise the \code{momentum} function is used.} \item{\dots}{Other arguments to be passed to the \code{maType} function in case (1) above.} } \value{ A object of the same class as \code{price} or a vector (if \code{try.xts} fails) containing the TRIX values. } \description{ The TRIX indicator calculates the rate of change of a triple exponential moving average. Developed by Jack K. Hutson. } \details{ The TRIX is calculated as follows:\cr 3MA = \code{MA}( \code{MA}( \code{MA}(\code{price}) ) )\cr trix = 100 * [ 3MA(t) / 3MA(t-1) - 1 ] } \note{ Buy/sell signals are generated when the TRIX crosses above/below zero. A nine-period EMA of the TRIX is used as a default signal line. Buy/sell signals are generated when the TRIX crosses above/below the signal line and is also above/below zero. } \examples{ data(ttrc) trix <- TRIX(ttrc[,"Close"]) trix4 <- TRIX(ttrc[,"Close"], maType=list(list(SMA), list(EMA, wilder=TRUE), list(SMA), list(DEMA))) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.fmlabs.com/reference/default.htm?url=TRIX.htm}\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=114}\cr \url{https://www.linnsoft.com/techind/trix-triple-smoothed-exponential-oscillator}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:trix}\cr } \seealso{ See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average options; and note Warning section. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/KST.Rd0000644000176200001440000000510014531142730012422 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/KST.R \name{KST} \alias{KST} \title{Know Sure Thing} \usage{ KST( price, n = c(10, 10, 10, 15), nROC = c(10, 15, 20, 30), nSig = 9, maType, wts = 1:NROW(n), ... ) } \arguments{ \item{price}{Price series that is coercible to xts or matrix.} \item{n}{A vector of the number of periods to use in the MA calculations.} \item{nROC}{A vector of the number of periods to use in the ROC calculations.} \item{nSig}{The number of periods to use for the KST signal line.} \item{maType}{Either: \enumerate{ \item A function or a string naming the function to be called. \item A \emph{list} with the first component like (1) above, and additional parameters specified as \emph{named} components. See Examples. }} \item{wts}{A vector the same length as \code{n}, of the weight for each period (need not sum to one).} \item{\dots}{Other arguments to be passed to the \code{maType} function in case (1) above.} } \value{ A object of the same class as \code{price} or a vector (if \code{try.xts} fails) containing the Know Sure Thing values. } \description{ The Know Sure Thing (KST) is a smooth, summed, rate of change indicator. Developed by Martin Pring. } \details{ For each day (week, month, etc.), the KST calculates the ROC over several periods. Those ROCs are smoothed using the given moving averages, then multiplied by their respective weighting values. The resulting values are summed for each day (month, week, etc.). } \note{ The KST indicates bullish/bearish momentum as it crosses above/below its moving average. Because the KST tends to lead price action, look for trend confirmation in the price. The default arguments are for the daily KST. There is also the Long-Term KST, with arguments: \code{n=c(9, 12, 18, 24)} - where the periods are months, not days - and the moving average periods are 6, 6, 6, and 9 months, respectively. } \examples{ data(ttrc) kst <- KST(ttrc[,"Close"]) kst4MA <- KST(ttrc[,"Close"], maType=list(list(SMA),list(EMA),list(DEMA),list(WMA))) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://web.archive.org/web/20110715112957/http://www.pring.com/movieweb/daily_kst.htm}\cr \url{https://web.archive.org/web/20100101162707/http://www.pring.com/movieweb/KST_MCM.htm}\cr } \seealso{ See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average options; and note Warning section. See \code{\link{ROC}} for the rate-of-change function. See \code{\link{MACD}} for a generic oscillator. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/DonchianChannel.Rd0000644000176200001440000000360214531142730015002 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/DonchianChannel.R \name{DonchianChannel} \alias{DonchianChannel} \alias{Donchian} \title{Donchian Channel} \usage{ DonchianChannel(HL, n = 10, include.lag = FALSE) } \arguments{ \item{HL}{Object that is coercible to xts or matrix and contains High-Low prices.} \item{n}{Number of periods for moving average.} \item{include.lag}{Should values be lagged so that today's prices are not included in the calculation? See Note.} } \value{ A object of the same class as \code{HL} or a matrix (if \code{try.xts} fails) containing the columns: \describe{ \item{ high }{ The highest high series. } \item{ mid }{ The average of \code{high} and \code{low}. } \item{ low }{ The lowest low series. } } } \description{ Donchian Channels were created by Richard Donchian and were used to generate buy and sell signals for the Turtle Trading system. } \details{ Donchian Channels consist of two (sometimes three) lines: The top line is the highest high of the past \code{n} periods. The bottom line is the lowest low of the past \code{n} periods. The middle line is the average of the top and bottom lines. } \note{ The default of \code{include.lag=FALSE} makes \code{DonchainChannel} consistent with other \pkg{TTR} functions, in that it includes the current period in the calculation. The default is different than the original calculation, which would calculate the indicator using periods t-1 through t-n. Setting \code{include.lag=TRUE} will return the result of the original calculation. The default of this argument may change in the future. } \examples{ data(ttrc) dc <- DonchianChannel( ttrc[,c("High","Low")] ) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.linnsoft.com/techind/donchian-channels}\cr } \seealso{ See \code{\link{BBands}}. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/keltnerChannels.Rd0000644000176200001440000000476314531142730015117 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/keltnerChannels.R \name{keltnerChannels} \alias{keltnerChannels} \title{Keltner Channels} \usage{ keltnerChannels(HLC, n = 20, maType, atr = 2, ...) } \arguments{ \item{HLC}{Object that is coercible to xts or matrix and contains High-Low-Close prices. If only a univariate series is given, it will be used. See details.} \item{n}{Number of periods for moving average.} \item{maType}{A function or a string naming the function to be called.} \item{atr}{The number of average true range distances to apply.} \item{...}{Other arguments to be passed to the maType function.} } \value{ A object of the same class as \code{HLC} or a matrix (if \code{try.xts} fails) containing the columns: \describe{ \item{SMA}{ Simple moving average. } \item{EMA}{ Exponential moving average. } } \item{dn}{ The lower Keltner Channel. } \item{mavg}{ The middle moving average. } \item{up}{ The upper Keltner Channel. } } \description{ Keltner Channels are volatility-based envelopes set above and below a moving average. This indicator is similar to Bollinger Bands, but Keltner Channels use the Average True Range (ATR) to set channel distance. } \details{ Keltner Channels are a trend following indicator, and can also be used to identify overbought and oversold levels when there is no trend. Chester Keltner is credited with the original version of Keltner Channels in his 1960 book. Linda Bradford Raschke introduced the newer version of Keltner Channels in the 1980s. } \section{Details }{ Keltner Channels consist of three lines: The middle band is generally a 20-period EMA of the typical price ([high + low + close]/3). The upper and lower bands are multiples of average true range (usually 2) above and below the MA. The middle band is usually calculated using the typical price, but if a univariate series (e.g. Close, Weighted Close, Median Price, etc.) is provided, it will be used instead. } \examples{ data(ttrc) kc <- keltnerChannels(ttrc[,c("High","Low","Close")]) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:keltner_channels}\cr \url{https://www.linnsoft.com/techind/keltner-channels-keltu-keltd}\cr \url{https://www.investopedia.com/terms/k/keltnerchannel.asp}\cr } \seealso{ See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average options; and note Warning section. } \author{ Nick Procyk, Joshua Ulrich References } \keyword{ts} TTR/man/CCI.Rd0000644000176200001440000000424214531142730012365 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/CCI.R \name{CCI} \alias{CCI} \title{Commodity Channel Index} \usage{ CCI(HLC, n = 20, maType, c = 0.015, ...) } \arguments{ \item{HLC}{Object that is coercible to xts or matrix and contains High-Low-Close prices. If only a univariate series is given, it will be used. See details.} \item{n}{Number of periods for moving average.} \item{maType}{A function or a string naming the function to be called.} \item{c}{Constant to apply to the mean deviation.} \item{\dots}{Other arguments to be passed to the \code{maType} function.} } \value{ A object of the same class as \code{HLC} or a vector (if \code{try.xts} fails) containing the CCI values. } \description{ The Commodity Channel Index (CCI) attempts to identify starting and ending trends. } \details{ CCI relates the current price and the average of price over \code{n} periods. The CCI usually falls in a channel of -100 to 100. A basic CCI trading system is: Buy (sell) if CCI rises above 100 (falls below -100) and sell (buy) when it falls below 100 (rises above -100). CCI is usually calculated using the typical price, but if a univariate series (e.g. Close, Weighted Close, Median Price, etc.) is provided, it will be used instead. } \note{ If \code{HLC} is a High-Low-Close matrix, then typical price will be calculated. If \code{HLC} is a vector, then those values will be used instead of the typical price. } \examples{ data(ttrc) cci <- CCI(ttrc[,c("High","Low","Close")]) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.fmlabs.com/reference/CCI.htm}\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=42}\cr \url{https://www.linnsoft.com/techind/cci-commodity-channel-index}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:commodity_channel_index_cci}\cr } \seealso{ See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average options; and note Warning section. See \code{\link{aroon}}, \code{\link{ADX}}, \code{\link{TDI}}, \code{\link{VHF}}, \code{\link{GMMA}} for other indicators that measure trend direction/strength. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/ttrc.Rd0000644000176200001440000000167014531142730012745 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/TTR-package.R \docType{data} \name{ttrc} \alias{ttrc} \title{Technical Trading Rule Composite data} \format{ The format is: \tabular{lll}{ Date: \tab Class 'Date' \tab 5480 5481 5482 5485 5486 ...\cr Open: \tab num \tab 3.18 3.09 3.11 3.09 3.10 ...\cr High: \tab num \tab 3.18 3.15 3.12 3.12 3.12 ...\cr Low: \tab num \tab 3.08 3.09 3.08 3.07 3.08 ...\cr Close: \tab num \tab 3.08 3.11 3.09 3.10 3.11 ...\cr Volume: \tab num \tab 1870906 3099506 2274157 2086758 2166348 ...\cr } } \source{ Randomly generated. } \description{ Historical Open, High, Low, Close, and Volume data for the periods January 2, 1985 to December 31, 2006. Randomly generated. } \details{ These data do not represent an actual security. They are provided so examples do not necessitate an internet connection. } \examples{ data(ttrc) plot(tail(ttrc[,"Close"],100), type="l") } \keyword{datasets} TTR/man/ATR.Rd0000644000176200001440000000414714531142730012421 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/ATR.R \name{TR} \alias{TR} \alias{ATR} \title{True Range / Average True Range} \usage{ TR(HLC) ATR(HLC, n = 14, maType, ...) } \arguments{ \item{HLC}{Object that is coercible to xts or matrix and contains High-Low-Close prices.} \item{n}{Number of periods for moving average.} \item{maType}{A function or a string naming the function to be called.} \item{\dots}{Other arguments to be passed to the \code{maType} function.} } \value{ A object of the same class as \code{HLC} or a matrix (if \code{try.xts} fails) containing the columns: \describe{ \item{ tr }{ The true range of the series. } \item{ atr }{ The average (as specified by \code{ma}) true range of the series. } \item{ trueHigh }{ The true high of the series. } \item{ trueLow }{ The true low of the series. } } } \description{ True range (TR) is a measure of volatility of a High-Low-Close series; average true range (ATR) is a Welles Wilder's style moving average of the TR. Developed by J. Welles Wilder in 1978. } \details{ TR incorporates yesterday's close in the calculation (high minus low). E.g. if yesterday's close was higher than today's high, then the TR would equal yesterday's close minus today's low. The ATR is a component of the Welles Wilder Directional Movement Index (\code{DX}, \code{ADX}). } \examples{ data(ttrc) tr <- TR(ttrc[,c("High","Low","Close")]) atr <- ATR(ttrc[,c("High","Low","Close")], n=14) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.fmlabs.com/reference/TR.htm}\cr \url{https://www.fmlabs.com/reference/ATR.htm}\cr \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=35}\cr \url{https://www.linnsoft.com/techind/true-range-tr}\cr \url{https://school.stockcharts.com/doku.php?id=technical_indicators:average_true_range_atr}\cr } \seealso{ See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average options; and note Warning section. See \code{\link{DX}}, which uses true range. See \code{\link{chaikinVolatility}} for another volatility measure. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/rollFun.Rd0000644000176200001440000000170614531142730013412 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/rollFun.R \name{rollSFM} \alias{rollSFM} \alias{rollFun} \title{Analysis of Running/Rolling/Moving Windows} \usage{ rollSFM(Ra, Rb, n = 60) } \arguments{ \item{Ra}{Object coercible to xts or matrix, containing the excess return for an individual security} \item{Rb}{Object coercible to xts or matrix, containing the market / benchmark return} \item{n}{Number of periods to use in the window} } \value{ A object of the same class as \code{Ra} (and \code{Rb}?) or a vector (if \code{try.xts} fails). \describe{ \item{rollSFM}{returns single-factor model parameters and R-squared over a n-period moving window.} } } \description{ Various functions to analyze data over a moving window of periods. } \references{ The following site(s) were used to code/document this indicator: \url{https://en.wikipedia.org/wiki/Simple_linear_regression}\cr } \author{ Joshua Ulrich } \keyword{ts} TTR/man/TDI.Rd0000644000176200001440000000346714531142730012417 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/TDI.R \name{TDI} \alias{TDI} \title{Trend Detection Index} \usage{ TDI(price, n = 20, multiple = 2) } \arguments{ \item{price}{Price series that is coercible to xts or matrix.} \item{n}{Number of periods to use.} \item{multiple}{Multiple used to calculate (2).} } \value{ A object of the same class as \code{price} or a matrix (if \code{try.xts} fails) containing the columns: \describe{ \item{ tdi }{ The Trend Detection Index. } \item{ di }{ The Direction Indicator. } } } \description{ The Trend Detection Index (TDI) attempts to identify starting and ending trends. Developed by M. H. Pee. } \details{ The TDI is the (1) absolute value of the \code{n}-day sum of the \code{n}-day momentum, minus the quantity of (2) \code{multiple}*\code{n}-day sum of the absolute value of the \code{n}-day momentum, minus (3) \code{n}-day sum of the absolute value of the \code{n}-day momentum. I.e. TDI = (1) - [ (2) - (3) ] The direction indicator is the sum of the \code{n}-day momentum over the last \code{n} days. See URL in references section for further details. } \note{ Positive/negative TDI values signal a trend/consolidation. A positive/ negative direction indicator signals a up/down trend. I.e. buy if the TDI and the direction indicator are positive, and sell if the TDI is positive while the direction indicator is negative. } \examples{ data(ttrc) tdi <- TDI(ttrc[,"Close"], n=30) } \references{ The following site(s) were used to code/document this indicator:\cr \url{https://www.linnsoft.com/techind/trend-detection-index-tdi}\cr } \seealso{ See \code{\link{aroon}}, \code{\link{CCI}}, \code{\link{ADX}}, \code{\link{VHF}}, \code{\link{GMMA}} for other indicators that measure trend direction/strength. } \author{ Joshua Ulrich } \keyword{ts} TTR/man/adjRatios.Rd0000644000176200001440000000205014531142730013702 0ustar liggesusers% Generated by roxygen2: do not edit by hand % Please edit documentation in R/adjRatios.R \name{adjRatios} \alias{adjRatios} \alias{adjust} \title{Split and dividend adjustment ratios} \usage{ adjRatios(splits, dividends, close) } \arguments{ \item{splits}{Split series that is coercible to xts.} \item{dividends}{Dividend series that is coercible to xts.} \item{close}{Close price series that is coercible to xts.} } \value{ A xts object containing the columns: \describe{ \item{ Split }{ The split adjustment ratio. } \item{ Div }{ The dividend adjustment ratio. } } } \description{ Create split and dividend adjustment ratio vectors. } \details{ \itemize{ \item If only \code{splits} is provided, the resulting object will only have as many observations as \code{splits}. \item If \code{splits} and \code{close} are provided, the resulting object will have as many observations as \code{max(NROW(splits), NROW(close))}. \item \code{close} is required if \code{dividends} is provided. } } \author{ Joshua Ulrich } \keyword{ts} TTR/DESCRIPTION0000644000176200001440000000160114531274225012434 0ustar liggesusersPackage: TTR Type: Package Title: Technical Trading Rules Version: 0.24.4 Authors@R: c( person(given="Joshua", family="Ulrich", role=c("cre","aut"), email="josh.m.ulrich@gmail.com"), person(given=c("Ethan","B."), family="Smith", role="ctb") ) Imports: xts (>= 0.10-0), zoo, curl LinkingTo: xts Enhances: quantmod Suggests: RUnit Description: A collection of over 50 technical indicators for creating technical trading rules. The package also provides fast implementations of common rolling-window functions, and several volatility calculations. License: GPL (>= 2) URL: https://github.com/joshuaulrich/TTR BugReports: https://github.com/joshuaulrich/TTR/issues NeedsCompilation: yes Packaged: 2023-11-28 00:12:35 UTC; josh Author: Joshua Ulrich [cre, aut], Ethan B. Smith [ctb] Maintainer: Joshua Ulrich Repository: CRAN Date/Publication: 2023-11-28 05:20:21 UTC TTR/tests/0000755000176200001440000000000014450607776012105 5ustar liggesusersTTR/tests/doRUnit.R0000644000176200001440000000457314450607776013625 0ustar liggesusers## unit tests will not be done if RUnit is not available if(require("RUnit", quietly=TRUE)) { ## --- Setup --- R_CMD_CHECK <- Sys.getenv("RCMDCHECK") != "FALSE" pkg <- "TTR" # <-- Change to package name! if (R_CMD_CHECK) { ## Path to unit tests for R CMD check ## PKG.Rcheck/PKG/unitTests path <- system.file("unitTests", package=pkg) } else { ## Path to unit tests for standalone running under Makefile (not R CMD check) ## PKG/tests/../inst/unitTests path <- file.path(getwd(), "..", "inst", "unitTests") } cat("\nRunning unit tests\n") print(list(pkg=pkg, getwd=getwd(), pathToUnitTests=path)) library(package=pkg, character.only=TRUE) ## If desired, load the name space to allow testing of private functions ## if (is.element(pkg, loadedNamespaces())) ## attach(loadNamespace(pkg), name=paste("namespace", pkg, sep=":"), pos=3) ## ## or simply call PKG:::myPrivateFunction() in tests ## --- Testing --- ## Define tests testSuite <- defineTestSuite(name=paste(pkg, "unit testing"), dirs=path) ## Run tests <- runTestSuite(testSuite) ## Report to stdout cat("------------------- UNIT TEST SUMMARY ---------------------\n\n") printTextProtocol(tests, showDetails=FALSE) ## Report text files (only if not under R CMD check) if (!R_CMD_CHECK) { ## Default report name pathReport <- file.path(path, "report") printTextProtocol(tests, showDetails=FALSE, fileName=paste(pathReport, "Summary.txt", sep="")) printTextProtocol(tests, showDetails=TRUE, fileName=paste(pathReport, ".txt", sep="")) ## Report to HTML file printHTMLProtocol(tests, fileName=paste(pathReport, ".html", sep="")) } ## Return stop() to cause R CMD check stop in case of ## - failures i.e. FALSE to unit tests or ## - errors i.e. R errors testErrors <- getErrors(tests) if(testErrors$nFail > 0) { msg <- paste0(" unit test", if(testErrors$nFail > 1) "s" else "", " failed") stop("\n", testErrors$nFail, msg, sep="") } if(testErrors$nErr > 0) { msg <- paste0(" unit test", if(testErrors$nErr > 1) "s" else "", " had errors") stop("\n", testErrors$nErr, msg, sep="") } if (testErrors$nTestFunc < 1) { stop("No test functions ran!") } } else { warning("cannot run unit tests -- package RUnit is not available") } TTR/src/0000755000176200001440000000000014531230163011510 5ustar liggesusersTTR/src/ttr.h0000644000176200001440000000133414531142730012475 0ustar liggesusers#ifndef _TTR_H_ #define _TTR_H_ #include /* declare functions called via .Call() */ SEXP adjRatios(SEXP, SEXP, SEXP); SEXP aroon_max(SEXP, SEXP); SEXP ema(SEXP, SEXP, SEXP, SEXP); SEXP evwma(SEXP, SEXP, SEXP); SEXP sar(SEXP, SEXP, SEXP, SEXP); SEXP ttr_rollPercentRank(SEXP, SEXP, SEXP, SEXP); SEXP ttr_zigzag(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); SEXP wilderSum(SEXP, SEXP); SEXP wma(SEXP, SEXP, SEXP); SEXP zlema(SEXP, SEXP, SEXP); SEXP runsum(SEXP, SEXP); SEXP runmin(SEXP, SEXP); SEXP runmax(SEXP, SEXP); SEXP runmedian(SEXP, SEXP, SEXP, SEXP); SEXP runmad(SEXP, SEXP, SEXP, SEXP, SEXP, SEXP); SEXP runcov(SEXP, SEXP, SEXP, SEXP, SEXP); /* declare xts imports */ extern SEXP (*xts_na_check)(SEXP, SEXP); #endif TTR/src/percent_rank.c0000644000176200001440000000470614450607776014360 0ustar liggesusers/* * TTR: Technical Trading Rules * * Copyright (C) 2012-2017 Charlie Friedemann, Joshua M. Ulrich * * This program 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include double calc_n_less(double* x, double mult, int i, int j1) { double n_less = mult; /* Loop over window */ for (int j = j1; j < i; j++) { double diff = x[j] - x[i]; if (diff < 0) { n_less = n_less + 1.0; } else if (fabs(diff) < 1e-8) { n_less = n_less + mult; } } return n_less; } /* Calculate a running/rolling percent rank, * or a cumulative version */ SEXP ttr_rollPercentRank(SEXP _x, SEXP _n, SEXP _cumul, SEXP _mult) { int i, P = 0; /* ensure correct types */ if (TYPEOF(_x) != REALSXP) { PROTECT(_x = coerceVector(_x, REALSXP)); P++; } double *d_x = REAL(_x); int n = asInteger(_n); int cumul = asLogical(_cumul); double mult = asReal(_mult); int nr = nrows(_x); /* Initialize result R object */ SEXP result; PROTECT(result = allocVector(REALSXP, nr)); P++; double *d_result = REAL(result); /* Find first non-NA input value */ int beg = n - 1; int n_na = 0; for (i = 0; i < beg; i++) { /* first 'n' observations are set to NA */ d_result[i] = NA_REAL; /* Account for leading NAs in input */ if (ISNA(d_x[i])) { beg++; n_na++; if (beg >= nr) { error("runPercentRank input has %d rows, %d NA. Cannot calculate result with n = %d.", nr, n_na, n); } } } /* Loop over non-NA input values */ if (cumul) { d_result[beg] = mult; for (i = beg+1; i < nr; i++) { double n_less = calc_n_less(d_x, mult, i, 0); d_result[i] = n_less / (i + 1); } } else { for (i = beg; i < nr; i++) { double n_less = calc_n_less(d_x, mult, i, i-n+1); d_result[i] = n_less / n; } } UNPROTECT(P); return(result); } TTR/src/aroon.c0000644000176200001440000000510314450607776013013 0ustar liggesusers/* * TTR: Technical Trading Rules * * Copyright (C) 2007-2013 Joshua M. Ulrich * * This program 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "ttr.h" SEXP aroon_max (SEXP x, SEXP n) { /* Initialize loop, loc, and PROTECT counters */ int i, j, loc=0, P=0; /* Ensure x argument is double */ if(TYPEOF(x) != REALSXP) { PROTECT(x = coerceVector(x, REALSXP)); P++; } /* Pointers to function arguments */ double *real_x = REAL(x); int int_n = asInteger(n); /* Input object length */ int nr = length(x); /* Initialize result R object */ SEXP result; PROTECT(result = allocVector(REALSXP, nr)); P++; double *real_result = REAL(result); /* check for non-leading NAs and get first non-NA location */ SEXP first = PROTECT(xts_na_check(x, ScalarLogical(TRUE))); P++; int int_first = asInteger(first); if(int_n + int_first > nr) error("not enough non-NA values"); double real_max = real_x[0]; /* set leading NAs and find initial max value */ for (i = 0; i < int_first + int_n-1; i++) { real_result[i] = NA_REAL; if(real_x[i] >= real_max) { real_max = real_x[i]; /* set max value */ loc = 0; /* set max location in window */ } loc++; continue; } /* Loop over non-NA input values */ for (i = int_first + int_n-1; i < nr; i++) { /* if the max leaves the window */ if(loc > int_n) { /* find the max over the (n+1) window */ real_max = real_x[i]; loc = 0; //for(j=0; j real_max) { real_max = real_x[i-j]; loc = j; } } } else { /* if the new value is the new max */ if(real_x[i] >= real_max) { real_max = real_x[i]; loc = 0; } } /* set result, increment location */ real_result[i] = (100.0 * (int_n - loc)) / int_n; loc++; } /* UNPROTECT R objects and return result */ UNPROTECT(P); return(result); } TTR/src/init.c0000644000176200001440000000366414531142730012632 0ustar liggesusers/* * TTR: Technical Trading Rules * * Copyright (C) 2007-2017 Joshua M. Ulrich * * This program 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ /* Includes and defines from WRE Section 5.4.2 */ #include "ttr.h" #include #include /* for NULL */ #include #define CALLDEF(name, n) {#name, (DL_FUNC) &name, n} /* define xts imports */ SEXP (*xts_na_check)(SEXP,SEXP); static const R_CallMethodDef CallEntries[] = { CALLDEF(adjRatios, 3), CALLDEF(aroon_max, 2), CALLDEF(ema, 4), CALLDEF(evwma, 3), CALLDEF(sar, 4), CALLDEF(ttr_rollPercentRank, 4), CALLDEF(ttr_zigzag, 6), CALLDEF(wilderSum, 2), CALLDEF(wma, 3), CALLDEF(zlema, 3), CALLDEF(runsum, 2), CALLDEF(runmin, 2), CALLDEF(runmax, 2), CALLDEF(runmedian, 4), CALLDEF(runmad, 6), CALLDEF(runcov, 5), {NULL, NULL, 0} }; /* Restrict .Call etc to use only registered symbols */ void R_init_TTR(DllInfo *dll) { R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); R_useDynamicSymbols(dll, FALSE); R_forceSymbols(dll, TRUE); /* imports from xts C code */ xts_na_check = (SEXP(*)(SEXP,SEXP)) R_GetCCallable("xts", "naCheck"); } TTR/src/adjRatios.c0000644000176200001440000000464214450607776013624 0ustar liggesusers/* * TTR: Technical Trading Rules * * Copyright (C) 2007-2013 Joshua M. Ulrich * * This program 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include SEXP adjRatios (SEXP split, SEXP div, SEXP close) { /* Initialize REAL pointers to function arguments */ double *real_close = REAL(close); double *real_split = REAL(split); double *real_div = REAL(div); /* Initialize loop and PROTECT counters */ int i, P = 0; /* Initialize object length (NOTE: all arguments are the same length) */ int N = length(close); /* Initialize result R objects */ SEXP result; PROTECT(result = allocVector(VECSXP, 2)); P++; SEXP s_ratio; PROTECT(s_ratio = allocVector(REALSXP,N)); P++; SEXP d_ratio; PROTECT(d_ratio = allocVector(REALSXP,N)); P++; /* Initialize REAL pointers to R objects and set their last value to '1' */ double *rs_ratio = REAL(s_ratio); double *rd_ratio = REAL(d_ratio); rs_ratio[N-1] = 1; rd_ratio[N-1] = 1; /* Loop over split/div vectors from newest period to oldest */ for(i = N-1; i > 0; i--) { /* Carry newer ratio value backward */ if(ISNA(real_split[i])) { rs_ratio[i-1] = rs_ratio[i]; /* Update split ratio */ } else { rs_ratio[i-1] = rs_ratio[i] * real_split[i]; } /* Carry newer ratio value backward */ if(ISNA(real_div[i])) { rd_ratio[i-1] = rd_ratio[i]; } else { /* Update dividend ratio */ rd_ratio[i-1] = rd_ratio[i] * (1.0 - real_div[i] / real_close[i-1]); } } /* Assign results to list */ SET_VECTOR_ELT(result, 0, s_ratio); SET_VECTOR_ELT(result, 1, d_ratio); /* UNPROTECT R objects and return result */ UNPROTECT(P); return(result); } TTR/src/zigzag.c0000644000176200001440000001066114450607776013175 0ustar liggesusers/* * TTR: Technical Trading Rules * * Copyright (C) 2007-2017 Joshua M. Ulrich * * This program 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include /* price and its array index */ typedef struct { double price; int index; } price_and_index; SEXP ttr_zigzag (SEXP _high, SEXP _low, SEXP _change, SEXP _percent, SEXP _retrace, SEXP _last_extreme) { double* high = REAL(_high); double* low = REAL(_low); double change = asReal(_change); int use_percent = asLogical(_percent); int use_retrace = asLogical(_retrace); int use_last_ex = asLogical(_last_extreme); if (use_percent) change = change / 100.0; int n = length(_high); SEXP _zigzag = PROTECT(allocVector(REALSXP, n)); double* zigzag = REAL(_zigzag); price_and_index reference, inflection; reference.price = (high[0] + low[0]) / 2; reference.index = 0; inflection.price = (high[1] + low[1]) / 2; inflection.index = 1; double extreme_min, extreme_max, local_min, local_max; int signal = 0; for (int i = 1; i < n; i++) { /* Initialize all zigzag values to NA */ zigzag[i] = NA_REAL; if (use_percent) { /* If % change given (absolute move) */ extreme_min = inflection.price * (1.0 - change); extreme_max = inflection.price * (1.0 + change); } else { /* If $ change given (only absolute moves make sense) */ extreme_min = inflection.price - change; extreme_max = inflection.price + change; } /* Find local maximum and minimum */ local_max = inflection.price > high[i] ? inflection.price : high[i]; local_min = inflection.price < low[i] ? inflection.price : low[i]; /* Find first trend */ if (signal == 0) { if (use_retrace) { /* Retrace prior move */ signal = (inflection.price >= reference.price) ? 1 : -1; } else { /* Absolute move */ if (local_min <= extreme_min) { /* Confirmed Downtrend */ signal = -1; } if (local_max >= extreme_max) { /* Confirmed Uptrend */ signal = 1; } } } /* Downtrend */ if (signal == -1) { /* New Minimum */ if (low[i] == local_min) { /* Last Extreme */ if (use_last_ex) { inflection.price = low[i]; inflection.index = i; } else { /* First Extreme */ if (low[i] != low[i-1]) { inflection.price = low[i]; inflection.index = i; } } } /* Retrace prior move */ if (use_retrace) { extreme_max = inflection.price + ((reference.price - inflection.price) * change); } /* Trend Reversal */ if (high[i] >= extreme_max) { zigzag[reference.index] = reference.price; reference = inflection; inflection.price = high[i]; inflection.index = i; signal = 1; continue; } } /* Uptrend */ if (signal == 1) { /* New Maximum */ if (high[i] == local_max) { /* Last Extreme */ if (use_last_ex) { inflection.price = high[i]; inflection.index = i; } else { /* First Extreme */ if (high[i] != high[i-1]) { inflection.price = high[i]; inflection.index = i; } } } /* Retrace prior move */ if (use_retrace) { extreme_min = inflection.price - ((inflection.price - reference.price) * change); } /* Trend Reversal */ if (low[i] <= extreme_min) { zigzag[reference.index] = reference.price; reference = inflection; inflection.price = low[i]; inflection.index = i; signal = -1; continue; } } } zigzag[reference.index] = reference.price; zigzag[inflection.index] = inflection.price; UNPROTECT(1); return _zigzag; } TTR/src/wilderSum.c0000644000176200001440000000402414450607776013651 0ustar liggesusers/* * TTR: Technical Trading Rules * * Copyright (C) 2007-2013 Joshua M. Ulrich * * This program 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include SEXP wilderSum (SEXP x, SEXP n) { /* Initialize loop and PROTECT counters */ int i, P=0; /* assure that 'x' is double */ if(TYPEOF(x) != REALSXP) { PROTECT(x = coerceVector(x, REALSXP)); P++; } /* Pointers to function arguments */ double *d_x = REAL(x); int i_n = asInteger(n); /* Input object length */ int nr = nrows(x); /* Initialize result R object */ SEXP result; PROTECT(result = allocVector(REALSXP,nr)); P++; double *d_result = REAL(result); /* Find first non-NA input value */ int beg = i_n - 1; double sum = 0; for(i = 0; i < beg; i++) { /* Account for leading NAs in input */ if(ISNA(d_x[i])) { d_result[i] = NA_REAL; beg++; d_result[beg] = 0; continue; } /* Set leading NAs in output */ if(i < beg) { d_result[i] = NA_REAL; } /* Calculate raw sum to start */ sum += d_x[i]; } d_result[beg] = d_x[i] + sum * (i_n-1)/i_n; /* Loop over non-NA input values */ for(i = beg+1; i < nr; i++) { d_result[i] = d_x[i] + d_result[i-1] * (i_n-1)/i_n; } /* UNPROTECT R objects and return result */ UNPROTECT(P); return(result); } TTR/src/sar.c0000644000176200001440000000715214450607776012470 0ustar liggesusers/* * TTR: Technical Trading Rules * * Copyright (C) 2007-2013 Joshua M. Ulrich * * This program 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include SEXP sar (SEXP hi, SEXP lo, SEXP xl, SEXP ig) { /* Initialize loop and PROTECT counters */ int i, P=0; /* Ensure all arguments are double */ if(TYPEOF(hi) != REALSXP) { PROTECT(hi = coerceVector(hi, REALSXP)); P++; } if(TYPEOF(lo) != REALSXP) { PROTECT(lo = coerceVector(lo, REALSXP)); P++; } if(TYPEOF(xl) != REALSXP) { PROTECT(xl = coerceVector(xl, REALSXP)); P++; } double initGap = asReal(ig); /* Pointers to function arguments */ double *d_hi = REAL(hi); double *d_lo = REAL(lo); double *d_xl = REAL(xl); /* Input object length */ int nr = nrows(hi); /* Initialize result R object */ SEXP sar; PROTECT(sar = allocMatrix(REALSXP, nr, 1)); P++; double *d_sar = REAL(sar); /* Find first non-NA value */ int beg = 1; for(i=0; i < nr; i++) { if( ISNA(d_hi[i]) || ISNA(d_lo[i]) ) { d_sar[i] = NA_REAL; beg++; } else { break; } } /* Initialize values needed by the routine */ int sig0 = 1, sig1 = 0; double xpt0 = d_hi[beg-1], xpt1 = 0; double af0 = d_xl[0], af1 = 0; double lmin, lmax; d_sar[beg-1] = d_lo[beg-1]-initGap; for(i=beg; i < nr; i++) { /* Increment signal, extreme point, and acceleration factor */ sig1 = sig0; xpt1 = xpt0; af1 = af0; /* Local extrema */ lmin = fmin(d_lo[i-1], d_lo[i]); lmax = fmax(d_hi[i-1], d_hi[i]); /* Create signal and extreme price vectors */ if( sig1 == 1 ) { /* Previous buy signal */ sig0 = (d_lo[i] > d_sar[i-1]) ? 1 : -1; /* New signal */ xpt0 = fmax(lmax, xpt1); /* New extreme price */ } else { /* Previous sell signal */ sig0 = (d_hi[i] < d_sar[i-1]) ? -1 : 1; /* New signal */ xpt0 = fmin(lmin, xpt1); /* New extreme price */ } /* * Calculate acceleration factor (af) * and stop-and-reverse (sar) vector */ /* No signal change */ if( sig0 == sig1 ) { /* Initial calculations */ d_sar[i] = d_sar[i-1] + ( xpt1 - d_sar[i-1] ) * af1; af0 = (af1 == d_xl[1]) ? d_xl[1] : (d_xl[0] + af1); /* Current buy signal */ if( sig0 == 1 ) { af0 = (xpt0 > xpt1) ? af0 : af1; /* Update acceleration factor */ d_sar[i] = fmin(d_sar[i],lmin); /* Determine sar value */ } /* Current sell signal */ else { af0 = (xpt0 < xpt1) ? af0 : af1; /* Update acceleration factor */ d_sar[i] = fmax(d_sar[i],lmax); /* Determine sar value */ } } /* New signal */ else { af0 = d_xl[0]; /* reset acceleration factor */ d_sar[i] = xpt0; /* set sar value */ } } /* UNPROTECT R objects and return result */ UNPROTECT(P); return(sar); } TTR/src/runfun.c0000644000176200001440000003033414531142730013176 0ustar liggesusers/* * TTR: Technical Trading Rules * * Copyright (C) 2007-2018 Joshua M. Ulrich * * This program 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include /* for memcpy */ #include "ttr.h" SEXP runsum(SEXP _x, SEXP _n) { int i, P = 0; /* ensure that 'x' is double */ if (TYPEOF(_x) != REALSXP) { _x = PROTECT(coerceVector(_x, REALSXP)); P++; } double *x = REAL(_x); int n = asInteger(_n); /* Input object length */ int nr = nrows(_x); /* Initialize result R object */ SEXP _result = PROTECT(allocVector(REALSXP, nr)); P++; double *result = REAL(_result); /* check for non-leading NAs and get first non-NA location */ SEXP _first = PROTECT(xts_na_check(_x, ScalarLogical(TRUE))); P++; int first = INTEGER(_first)[0]; if (n + first > nr) { error("not enough non-NA values"); } /* Set leading NAs in output */ for (i = 0; i < first; i++) { result[i] = NA_REAL; } /* Raw sum to start running sum */ double seed = 0.0; for (i = first; i < first + n; i++) { result[i] = NA_REAL; seed += x[i]; } result[first + n - 1] = seed; /* Loop over non-NA input values */ for (i = first + n; i < nr; i++) { result[i] = result[i-1] + x[i] - x[i-n]; } /* UNPROTECT R objects and return result */ UNPROTECT(P); return _result; } SEXP runmin(SEXP _x, SEXP _n) { int i, j, P = 0; /* ensure that 'x' is double */ if (TYPEOF(_x) != REALSXP) { _x = PROTECT(coerceVector(_x, REALSXP)); P++; } double *x = REAL(_x); int n = asInteger(_n); /* Input object length */ int nr = nrows(_x); /* Initialize result R object */ SEXP _result = PROTECT(allocVector(REALSXP, nr)); P++; double *result = REAL(_result); /* check for non-leading NAs and get first non-NA location */ SEXP _first = PROTECT(xts_na_check(_x, ScalarLogical(TRUE))); P++; int first = INTEGER(_first)[0]; if (n + first > nr) { error("not enough non-NA values"); } /* Set leading NAs in output */ for (i = 0; i < first; i++) { result[i] = NA_REAL; } /* start running min */ double lmin = x[first]; for (i = first; i < first + n; i++) { result[i] = NA_REAL; if (x[i] < lmin) { lmin = x[i]; } } result[first + n - 1] = lmin; /* Loop over non-NA input values */ for (i = first + n; i < nr; i++) { lmin = x[i]; for (j = 1; j < n; j++) { if (x[i-j] < lmin) { lmin = x[i-j]; } } result[i] = lmin; } /* UNPROTECT R objects and return result */ UNPROTECT(P); return _result; } SEXP runmax(SEXP _x, SEXP _n) { int i, j, P = 0; /* ensure that 'x' is double */ if (TYPEOF(_x) != REALSXP) { _x = PROTECT(coerceVector(_x, REALSXP)); P++; } double *x = REAL(_x); int n = asInteger(_n); /* Input object length */ int nr = nrows(_x); /* Initialize result R object */ SEXP _result = PROTECT(allocVector(REALSXP, nr)); P++; double *result = REAL(_result); /* check for non-leading NAs and get first non-NA location */ SEXP _first = PROTECT(xts_na_check(_x, ScalarLogical(TRUE))); P++; int first = INTEGER(_first)[0]; if (n + first > nr) { error("not enough non-NA values"); } /* Set leading NAs in output */ for (i = 0; i < first; i++) { result[i] = NA_REAL; } /* start running max */ double lmax = x[first]; for (i = first; i < first + n; i++) { result[i] = NA_REAL; if (x[i] > lmax) { lmax = x[i]; } } result[first + n - 1] = lmax; /* Loop over non-NA input values */ for (i = first + n; i < nr; i++) { lmax = x[i]; for (j = 1; j < n; j++) { if (x[i-j] > lmax) { lmax = x[i-j]; } } result[i] = lmax; } /* UNPROTECT R objects and return result */ UNPROTECT(P); return _result; } typedef double (*tiebreaker)(const double, const double); static inline double tiebreaker_lt(const double a, const double b) { return (a < b) ? a : b; } static inline double tiebreaker_gt(const double a, const double b) { return (a > b) ? a : b; } static inline double tiebreaker_eq(const double a, const double b) { return (a + b) / 2.0; } static inline double ttr_median(double *x, int i, int n, tiebreaker tie_func) { /* NOTE: 'i' and 'n' are 1-based */ int N = n-i+1; // number of observations in the window int flag = N-2*(N/2); // even number of observations? int mid = (i-1)+N/2-1; // 0-based index midpoint R_qsort(x, i, n); double median = (flag) ? x[mid+1] : tie_func(x[mid] , x[mid+1]); return median; } SEXP runmedian(SEXP _x, SEXP _n, SEXP _tiebreak, SEXP _cumulative) { int i, P = 0; /* ensure that 'x' is double */ if (TYPEOF(_x) != REALSXP) { _x = PROTECT(coerceVector(_x, REALSXP)); P++; } double *x = REAL(_x); int n = asInteger(_n); int tiebreak = asInteger(_tiebreak); int cumulative = asLogical(_cumulative); /* Input object length */ int nr = nrows(_x); /* Initialize result R object */ SEXP _result = PROTECT(allocVector(REALSXP, nr)); P++; double *result = REAL(_result); /* check for non-leading NAs and get first non-NA location */ SEXP _first = PROTECT(xts_na_check(_x, ScalarLogical(TRUE))); P++; int first = INTEGER(_first)[0]; if (n + first > nr) { error("not enough non-NA values"); } /* Set leading NAs in output */ for (i = 0; i < first + n; i++) { result[i] = NA_REAL; } tiebreaker tie_func = NULL; if (tiebreak == 0) { tie_func = tiebreaker_eq; } else if (tiebreak < 0) { tie_func = tiebreaker_lt; } else if (tiebreak > 0) { tie_func = tiebreaker_gt; } SEXP _window; double *window; int first_i = first + n - 1; if (cumulative) { _window = PROTECT(duplicate(_x)); P++; window = REAL(_window); for (i = first_i; i < nr; i++) { result[i] = ttr_median(window, first+1, i+1, tie_func); } } else { _window = PROTECT(allocVector(REALSXP, n)); P++; window = REAL(_window); for (i = first_i; i < nr; i++) { memcpy(window, &x[i-n+1], n * sizeof(double)); result[i] = ttr_median(window, 1, n, tie_func); } } /* UNPROTECT R objects and return result */ UNPROTECT(P); return _result; } static inline double ttr_mean(const double *x, const int n) { double mean = x[0] / n; int i; for (i = 1; i < n; i++) { mean += x[i] / n; } return mean; } SEXP runmad(SEXP _x, SEXP _center, SEXP _n, SEXP _type, SEXP _tiebreak, SEXP _cumulative) { int i, j, P = 0; /* ensure 'x' and 'center' are double */ if (TYPEOF(_x) != REALSXP) { _x = PROTECT(coerceVector(_x, REALSXP)); P++; } if (TYPEOF(_center) != REALSXP) { _center = PROTECT(coerceVector(_center, REALSXP)); P++; } double *x = REAL(_x); double *center = REAL(_center); int n = asInteger(_n); int type = asInteger(_type); int tiebreak = asInteger(_tiebreak); int cumulative = asLogical(_cumulative); /* Input object length */ int nr = nrows(_x); if (nr != nrows(_center)) { error("'x' and 'center' must have the same number of observations"); } /* Initialize result R object */ SEXP _result = PROTECT(allocVector(REALSXP, nr)); P++; double *result = REAL(_result); /* check for non-leading NAs and get first non-NA location */ SEXP _first = PROTECT(xts_na_check(_x, ScalarLogical(TRUE))); P++; int first = INTEGER(_first)[0]; if (n + first > nr) { error("not enough non-NA values in 'x'"); } /* Set leading NAs in output */ for (i = 0; i < first + n; i++) { result[i] = NA_REAL; } tiebreaker tie_func = NULL; if (tiebreak == 0) { tie_func = tiebreaker_eq; } else if (tiebreak < 0) { tie_func = tiebreaker_lt; } else if (tiebreak > 0) { tie_func = tiebreaker_gt; } SEXP _window; double *window; int first_i = first + n - 1; if (cumulative) { _window = PROTECT(duplicate(_x)); P++; window = REAL(_window); if (type) { for (i = first_i; i < nr; i++) { int N = i-first+1; for (j = 0; j < N; j++) { window[j] = fabs(x[i-j] - center[i]); } result[i] = ttr_median(window, 1, N, tie_func); } } else { for (i = first_i; i < nr; i++) { for (j = 0; j <= i; j++) { window[j] = fabs(x[i-j] - center[i]); } result[i] = ttr_mean(window, i+1); } } } else { _window = PROTECT(allocVector(REALSXP, n)); P++; window = REAL(_window); if (type) { for (i = first_i; i < nr; i++) { for (j = 0; j < n; j++) { window[j] = fabs(x[i-j] - center[i]); } result[i] = ttr_median(window, 1, n, tie_func); } } else { for (i = first_i; i < nr; i++) { for (j = 0; j < n; j++) { window[j] = fabs(x[i-j] - center[i]); } result[i] = ttr_mean(window, n); } } } /* UNPROTECT R objects and return result */ UNPROTECT(P); return _result; } SEXP runcov(SEXP _x, SEXP _y, SEXP _n, SEXP _sample, SEXP _cumulative) { int i, j, P = 0; /* ensure 'x' and 'y' are double */ if (TYPEOF(_x) != REALSXP) { _x = PROTECT(coerceVector(_x, REALSXP)); P++; } if (TYPEOF(_y) != REALSXP) { _y = PROTECT(coerceVector(_y, REALSXP)); P++; } double *x = REAL(_x); double *y = REAL(_y); int n = asInteger(_n); int cumulative = asLogical(_cumulative); int sample = asLogical(_sample); /* Input object length */ int nr = nrows(_x); if (nr != nrows(_y)) { error("'x' and 'y' must have the same number of observations"); } /* Initialize result R object */ SEXP _result = PROTECT(allocVector(REALSXP, nr)); P++; double *result = REAL(_result); /* check for non-leading NAs and get first non-NA location */ SEXP _first_x = PROTECT(xts_na_check(_x, ScalarLogical(TRUE))); P++; int first_x = INTEGER(_first_x)[0]; if (n + first_x > nr) { error("not enough non-NA values in 'x'"); } SEXP _first_y = PROTECT(xts_na_check(_y, ScalarLogical(TRUE))); P++; int first_y = INTEGER(_first_y)[0]; if (n + first_y > nr) { error("not enough non-NA values in 'y'"); } int first = (first_x > first_y) ? first_x : first_y; int first_i = first + n - 1; /* Set leading NAs in output */ for (i = 0; i < first_i; i++) { result[i] = NA_REAL; } SEXP _window; double *window, mu_x, mu_y; if (cumulative) { double sum_x = 0.0; double sum_y = 0.0; // Initialize means for (i = first; i < first_i; i++) { sum_x += x[i]; sum_y += y[i]; } mu_x = sum_x / (first+1); mu_y = sum_y / (first+1); for (i = first_i; i < nr; i++) { double n_window = (double)(i-first_i+n); sum_x += x[i]; sum_y += y[i]; mu_x = sum_x / n_window; mu_y = sum_y / n_window; result[i] = 0.0; for (j = first; j <= i; j++) { result[i] += (x[j] - mu_x) * (y[j] - mu_y); } result[i] /= sample ? (n_window-1.0) : n_window; } /* Set first non-NA element to NA to match var() and sd() * because var/sd of 1 observation is not defined */ result[first] = NA_REAL; } else { double denom = sample ? (n-1) : n; if (n == 1) { warning("(co-)variance is not defined for one observation; returning NA"); for (i = first_i; i < nr; i++) { result[i] = NA_REAL; } } else { _window = PROTECT(allocVector(REALSXP, n)); P++; window = REAL(_window); size_t window_size = n * sizeof(double); for (i = first_i; i < nr; i++) { memcpy(window, &x[i-n+1], window_size); mu_x = ttr_mean(window, n); memcpy(window, &y[i-n+1], window_size); mu_y = ttr_mean(window, n); result[i] = 0.0; for (j = 0; j < n; j++) { result[i] += (x[i-j] - mu_x) * (y[i-j] - mu_y); } result[i] /= denom; } } } /* UNPROTECT R objects and return result */ UNPROTECT(P); return _result; } TTR/src/moving_averages.c0000644000176200001440000002076514531225355015051 0ustar liggesusers/* * TTR: Technical Trading Rules * * Copyright (C) 2007-2013 Joshua M. Ulrich * * This program 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "ttr.h" SEXP ema (SEXP x, SEXP n, SEXP ratio, SEXP wilder) { /* Initialize loop and PROTECT counters */ int i, P=0; /* ensure that 'x' is double */ if(TYPEOF(x) != REALSXP) { PROTECT(x = coerceVector(x, REALSXP)); P++; } double *d_x = REAL(x); if(ncols(x) > 1) { error("ncol(x) > 1; EMA only supports univariate 'x'"); } int i_n = asInteger(n); double d_ratio = asReal(ratio); if(R_NilValue == n || i_n <= 0) { if(R_NilValue == ratio || d_ratio <= 0.0) { error("either 'n' or 'ratio' must be specified and > 0\n'n' is %d and 'ratio' is %1.6f", i_n, d_ratio); } else { /* If ratio is specified, and n is not, set n to approx 'correct' * value backed out from ratio */ i_n = (int)(2.0 / d_ratio - 1.0); } } else { /* Determine decay ratio */ if(R_NilValue == ratio) { int isWilder = asInteger(wilder); d_ratio = (isWilder) ? 1.0 / i_n : 2.0 / (i_n + 1); } else { /* ratio != NULL -> warn that 'n' will be used instead */ warning("both 'n' and 'ratio' are specified; using 'n'"); } } /* Input object length */ int nr = nrows(x); /* Initialize result R object */ SEXP result; PROTECT(result = allocVector(REALSXP,nr)); P++; double *d_result = REAL(result); /* check for non-leading NAs and get first non-NA location */ SEXP _first = PROTECT(xts_na_check(x, ScalarLogical(TRUE))); P++; int first = INTEGER(_first)[0]; if(i_n + first > nr) { error("not enough non-NA values"); } /* Set leading NAs in output */ for(i = 0; i < first; i++) { d_result[i] = NA_REAL; } /* Raw mean to start EMA */ double seed = 0.0; for(i = first; i < first + i_n; i++) { d_result[i] = NA_REAL; seed += d_x[i] / i_n; } d_result[first + i_n - 1] = seed; /* Loop over non-NA input values */ for(i = first + i_n; i < nr; i++) { d_result[i] = d_x[i] * d_ratio + d_result[i-1] * (1-d_ratio); } /* UNPROTECT R objects and return result */ UNPROTECT(P); return(result); } SEXP evwma (SEXP pr, SEXP vo, SEXP n) { /* Initialize loop and PROTECT counters */ int i, P=0; /* ensure that 'pr' is double */ if(TYPEOF(pr) != REALSXP) { PROTECT(pr = coerceVector(pr, REALSXP)); P++; } /* ensure that 'vo' is double */ if(TYPEOF(vo) != REALSXP) { PROTECT(vo = coerceVector(vo, REALSXP)); P++; } /* Pointers to function arguments */ double *d_pr = REAL(pr); double *d_vo = REAL(vo); int i_n = asInteger(n); /* Input object length */ int nr = nrows(pr); /* Initialize result R object */ SEXP result; PROTECT(result = allocVector(REALSXP,nr)); P++; double *d_result = REAL(result); /* check for non-leading NAs and get first non-NA location */ SEXP _first_pr = PROTECT(xts_na_check(pr, ScalarLogical(TRUE))); P++; int first_pr = asInteger(_first_pr); if(i_n + first_pr > nr) { error("not enough non-NA values in 'price'"); } SEXP _first_vo = PROTECT(xts_na_check(vo, ScalarLogical(TRUE))); P++; int first_vo = asInteger(_first_vo); if(i_n + first_vo > nr) { error("not enough non-NA values in 'volume'"); } int first = first_pr > first_vo ? first_pr : first_vo; int begin = first + i_n - 1; /* Set leading NAs in output */ for(i = 0; i < begin; i++) { d_result[i] = NA_REAL; } /* First non-NA result is the first non-NA value of 'x' */ d_result[begin] = d_pr[begin]; /* Initialize volume sum */ double volSum = 0.0; for(i = first; i < begin+1; i++) { volSum += d_vo[i]; } /* Loop over the rest of the values */ for(i = begin + 1; i < nr; i++) { volSum = volSum + d_vo[i] - d_vo[i-i_n]; d_result[i] = ((volSum-d_vo[i])*d_result[i-1]+d_vo[i]*d_pr[i])/volSum; } /* UNPROTECT R objects and return result */ UNPROTECT(P); return(result); } SEXP wma (SEXP x, SEXP w, SEXP n) { /* Initialize loop and PROTECT counters */ int i, j, P=0; /* ensure that 'x' is double */ if(TYPEOF(x) != REALSXP) { PROTECT(x = coerceVector(x, REALSXP)); P++; } /* ensure that 'w' is double */ if(TYPEOF(w) != REALSXP) { PROTECT(w = coerceVector(w, REALSXP)); P++; } int i_n = asInteger(n); /* Pointers to function arguments */ double *d_x = REAL(x); double *d_w = REAL(w); /* Input object length */ int nr = nrows(x); /* Initialize result R object */ SEXP result; PROTECT(result = allocVector(REALSXP,nr)); P++; double *d_result = REAL(result); /* check for non-leading NAs and get first non-NA location */ SEXP _first = PROTECT(xts_na_check(x, ScalarLogical(TRUE))); P++; int first = INTEGER(_first)[0]; if(i_n + first > nr) { error("not enough non-NA values"); } int begin = first + i_n - 1; /* Set leading NAs in output */ for(i = 0; i < begin; i++) { d_result[i] = NA_REAL; } /* Sum of weights (w does not have NA) */ double wtsum = 0.0; for(j = 0; j < i_n; j++) { if(ISNA(d_w[j])) { error("wts cannot contain NA"); } wtsum += d_w[j]; } /* Loop over non-NA input values */ for(i = begin; i < nr; i++) { double num = 0.0; int ni = i - i_n + 1; for(j = 0; j < i_n; j++) { num += d_x[ni+j] * d_w[j]; } d_result[i] = num / wtsum; } /* UNPROTECT R objects and return result */ UNPROTECT(P); return(result); } SEXP zlema (SEXP x, SEXP n, SEXP ratio) { /* Initialize loop and PROTECT counters */ int i, P=0; /* ensure that 'x' is double */ if(TYPEOF(x) != REALSXP) { PROTECT(x = coerceVector(x, REALSXP)); P++; } double *d_x = REAL(x); if(ncols(x) > 1) { error("ncol(x) > 1; ZLEMA only supports univariate 'x'"); } int i_n = asInteger(n); double d_ratio = asReal(ratio); if(R_NilValue == n || i_n <= 0) { if(R_NilValue == ratio || d_ratio <= 0.0) { error("either 'n' or 'ratio' must be specified and > 0\n'n' is %d and 'ratio' is %1.6f", i_n, d_ratio); } else { /* If ratio is specified, and n is not, set n to approx 'correct' * value backed out from ratio */ i_n = (int)(2.0 / d_ratio - 1.0); } } else { /* Determine decay ratio */ if(R_NilValue == ratio) { d_ratio = 2.0 / (i_n + 1); } else { /* ratio != NULL -> warn that 'n' will be used instead */ warning("both 'n' and 'ratio' are specified; using 'n'"); } } /* Input object length */ int nr = nrows(x); /* Initialize result R object */ SEXP result; PROTECT(result = allocVector(REALSXP,nr)); P++; double *d_result = REAL(result); /* check for non-leading NAs and get first non-NA location */ SEXP _first = PROTECT(xts_na_check(x, ScalarLogical(TRUE))); P++; int first = INTEGER(_first)[0]; if(i_n + first > nr) { error("not enough non-NA values"); } /* Set leading NAs in output */ for(i = 0; i < first; i++) { d_result[i] = NA_REAL; } /* Raw mean to start EMA */ double seed = 0.0; for(i = first; i < first + i_n; i++) { d_result[i] = NA_REAL; seed += d_x[i] / i_n; } d_result[first + i_n - 1] = seed; double lag = 1.0 / d_ratio; double wt = fmod(lag, 1.0); double w1 = 1.0 - wt; double r1 = 1.0 - d_ratio; /* Loop over non-NA input values */ for(i = first + i_n; i < nr; i++) { int loc = (int)(i - lag); double value = 2 * d_x[i] - (w1 * d_x[loc] + wt * d_x[loc+1]); d_result[i] = d_ratio * value + r1 * d_result[i-1]; } /* UNPROTECT R objects and return result */ UNPROTECT(P); return(result); } TTR/R/0000755000176200001440000000000014531230163011122 5ustar liggesusersTTR/R/DonchianChannel.R0000644000176200001440000000726214531142730014272 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Donchian Channel #' #' Donchian Channels were created by Richard Donchian and were used to generate #' buy and sell signals for the Turtle Trading system. #' #' Donchian Channels consist of two (sometimes three) lines: #' #' The top line is the highest high of the past \code{n} periods. The bottom #' line is the lowest low of the past \code{n} periods. The middle line is the #' average of the top and bottom lines. #' #' @aliases DonchianChannel Donchian #' @param HL Object that is coercible to xts or matrix and contains High-Low #' prices. #' @param n Number of periods for moving average. #' @param include.lag Should values be lagged so that today's prices are not #' included in the calculation? See Note. #' @return A object of the same class as \code{HL} or a matrix (if #' \code{try.xts} fails) containing the columns: #' \describe{ #' \item{ high }{ The highest high series. } #' \item{ mid }{ The average of \code{high} and \code{low}. } #' \item{ low }{ The lowest low series. } #' } #' @note The default of \code{include.lag=FALSE} makes \code{DonchainChannel} #' consistent with other \pkg{TTR} functions, in that it includes the current #' period in the calculation. #' #' The default is different than the original calculation, which would calculate #' the indicator using periods t-1 through t-n. Setting \code{include.lag=TRUE} #' will return the result of the original calculation. #' #' The default of this argument may change in the future. #' @author Joshua Ulrich #' @seealso See \code{\link{BBands}}. #' @references The following site(s) were used to code/document this #' indicator:\cr \url{https://www.linnsoft.com/techind/donchian-channels}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' dc <- DonchianChannel( ttrc[,c("High","Low")] ) #' 'DonchianChannel' <- function(HL, n=10, include.lag=FALSE) { # Donchian Channel # Notes from John Bollinger: # # "In the old paper-calculation days you would calculate the numbers # after the close by hand and for use in the next day's trading to gauge # the "n-day" breakouts and you would have used n-days worth of data the # calc. Thus an n-day calc with a lag of one would be consistent with # practice in Donchian's day. (Total window of n+1.) Another example are # the floor traders numbers or pivots, which are calculated from the # prior period's data for use on the current period. In both case # including the current period in the calculation would not be correct." HL <- try.xts(HL, error=as.matrix) if(!(NCOL(HL) %in% c(1,2))) { stop("Price series must be either High-Low, or Close/univariate.") } if(NCOL(HL)==2) { hi <- HL[,1] lo <- HL[,2] } else { hi <- HL lo <- HL } high <- runMax(hi,n) low <- runMin(lo,n) mid <- (high+low)/2 result <- cbind(high,mid,low) colnames(result) <- c("high","mid","low") if(include.lag) { # use lag.xts in case 'result' is a matrix result <- lag.xts(result) } reclass(result, HL) } TTR/R/MFI.R0000644000176200001440000000665614531142730011677 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Money Flow Index #' #' The MFI is a ratio of positive and negative money flow over time. #' #' Money Flow (MF) is the product of price and volume. Positive/negative MF #' occur when today's price is higher/lower than yesterday's price. The MFI is #' calculated by dividing positive MF by negative MF for the past \code{n} #' periods. It is then scaled between 0 and 100. #' #' MFI is usually calculated using the typical price, but if a univariate series #' (e.g. Close, Weighted Close, Median Price, etc.) is provided, it will be used #' instead. #' #' @aliases MFI moneyFlow #' @param HLC Object that is coercible to xts or matrix and contains #' High-Low-Close prices. If only a univariate series is given, it will be #' used. See details. #' @param volume Vector or matrix of volume observations corresponding to #' \code{HLC} object. #' @param n Number of periods to use. #' @return A object of the same class as \code{HLC} and \code{volume} or a #' vector (if \code{try.xts} fails) containing the MFI values. #' @note Divergence between MFI and price can be indicative of a reversal. In #' addition, values above/below 80/20 indicate market tops/bottoms. #' @author Joshua Ulrich #' @seealso See \code{\link{OBV}} and \code{\link{CMF}}. #' @references The following site(s) were used to code/document this #' indicator:\cr #' \url{https://www.fmlabs.com/reference/default.htm?url=MoneyFlowIndex.htm}\cr #' \url{https://www.linnsoft.com/techind/money-flow-index-mfi}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:money_flow_index_mfi}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' mfi <- MFI(ttrc[,c("High","Low","Close")], ttrc[,"Volume"]) #' "MFI" <- function(HLC, volume, n=14) { # Money Flow Index HLC <- try.xts(HLC, error=as.matrix) volume <- try.xts(volume, error=as.matrix) if(!(is.xts(HLC) && is.xts(volume))) { HLC <- as.matrix(HLC) volume <- as.matrix(volume) } if(NCOL(HLC)==3) { if(is.xts(HLC)) { HLC <- xts(apply(HLC, 1, mean),index(HLC)) } else { HLC <- apply(HLC, 1, mean) } } else if(NCOL(HLC)!=1) { stop("Price series must be either High-Low-Close, or Close/univariate.") } if(is.xts(HLC)) { priceLag <- lag.xts(HLC) } else { priceLag <- c( NA, HLC[-NROW(HLC)] ) } # Calculate Money Flow mf <- HLC * volume # Calculate positive and negative Money Flow pmf <- ifelse( HLC > priceLag, mf, 0 ) nmf <- ifelse( HLC < priceLag, mf, 0 ) # Calculate Money Ratio and Money Flow Index num <- runSum( pmf, n ) den <- runSum( nmf, n ) mr <- num / den mfi <- 100 - ( 100 / ( 1 + mr ) ) mfi[0 == den] <- 100 mfi[0 == den & 0 == num] <- 50 if(is.xts(mfi)) colnames(mfi) <- 'mfi' reclass( mfi, HLC ) } TTR/R/MACD.R0000644000176200001440000001336014531142730011756 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' MACD Oscillator #' #' The MACD was developed by Gerald Appel and is probably the most popular price #' oscillator. The MACD function documented in this page compares a fast moving #' average (MA) of a series with a slow MA of the same series. It can be used #' as a generic oscillator for any univariate series, not only price. #' #' The MACD function either subtracts the fast MA from the slow MA, or finds the #' rate of change between the fast MA and the slow MA. #' #' @param x Object that is coercible to xts or matrix; usually price, but can be #' volume, etc. #' @param nFast Number of periods for fast moving average. #' @param nSlow Number of periods for slow moving average. #' @param nSig Number of periods for signal moving average. #' @param maType Either: #' \enumerate{ #' \item A function or a string naming the function to be called. #' \item A \emph{list} with the first component like (1) above, and #' additional parameters specified as \emph{named} components. #' See Examples. #' } #' @param percent logical; if \code{TRUE}, the percentage difference between the #' fast and slow moving averages is returned, otherwise the difference between #' the respective averages is returned. #' @param \dots Other arguments to be passed to the \code{maType} function in #' case (1) above. #' @return A object of the same class as \code{x} or a matrix (if \code{try.xts} #' fails) containing the columns: #' \describe{ #' \item{ macd }{ The price (volume, etc.) oscillator. } #' \item{ signal }{ The oscillator signal line (a moving average of the oscillator). } #' } #' @note The MACD is a special case of the general oscillator applied to price. #' The MACD can be used as a general oscillator applied to any series. Time #' periods for the MACD are often given as 26 and 12, but the original formula #' used exponential constants of 0.075 and 0.15, which are closer to #' 25.6667 and 12.3333 periods. #' @author Joshua Ulrich #' @seealso See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average #' options; and note Warning section. #' @references The following site(s) were used to code/document this #' indicator: #' \cr Moving Average Convergence/Divergence (MACD):\cr #' \url{https://www.fmlabs.com/reference/MACD.htm}\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=66}\cr #' \url{https://www.linnsoft.com/techind/macd}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:moving_average_convergence_divergence_macd}\cr #' \cr Price Oscillator:\cr #' \url{https://www.fmlabs.com/reference/PriceOscillator.htm}\cr #' \url{https://www.fmlabs.com/reference/PriceOscillatorPct.htm}\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=94}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:price_oscillators_ppo}\cr #' \cr Volume Oscillator:\cr #' \url{https://www.fmlabs.com/reference/PVO.htm}\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=122}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' #' macd <- MACD( ttrc[,"Close"], 12, 26, 9, maType="EMA" ) #' macd2 <- MACD( ttrc[,"Close"], 12, 26, 9, #' maType=list(list(SMA), list(EMA, wilder=TRUE), list(SMA)) ) #' "MACD" <- function(x, nFast=12, nSlow=26, nSig=9, maType, percent=TRUE, ...) { # Oscillators # WISHLIST: # Add capability to allow 'ma.slow' and 'ma.fast' to be vectors # containing MAs, which would allow the oscillator to be constructed # using MAs of different prices. # Default MA if(missing(maType)) { maType <- 'EMA' } # Case of two different 'maType's for both MAs. if( is.list(maType) ) { # Make sure maType is a list of lists maTypeInfo <- sapply(maType,is.list) if( !(all(maTypeInfo) && length(maTypeInfo) == 3) ) { stop("If \'maType\' is a list, you must specify\n ", "*three* MAs (see Examples section of ?MACD)") } # If MA function has 'n' arg, see if it's populated in maType; # if it isn't, populate it with function's formal 'n' if( !is.null( formals(maType[[1]][[1]])$n ) && is.null( maType[[1]]$n ) ) { maType[[1]]$n <- nFast } if( !is.null( formals(maType[[2]][[1]])$n ) && is.null( maType[[2]]$n ) ) { maType[[2]]$n <- nSlow } if( !is.null( formals(maType[[3]][[1]])$n ) && is.null( maType[[3]]$n ) ) { maType[[3]]$n <- nSig } mavg.fast <- do.call( maType[[1]][[1]], c( list(x), maType[[1]][-1] ) ) mavg.slow <- do.call( maType[[2]][[1]], c( list(x), maType[[2]][-1] ) ) } # Case of one 'maType' for both MAs. else { mavg.fast <- do.call( maType, c( list(x), list(n=nFast, ...) ) ) mavg.slow <- do.call( maType, c( list(x), list(n=nSlow, ...) ) ) } if(percent) { macd <- 100 * ( mavg.fast / mavg.slow - 1 ) } else { macd <- mavg.fast - mavg.slow } if( is.list(maType) ) { signal <- do.call( maType[[3]][[1]], c( list( macd ), maType[[3]][-1] ) ) } else signal <- do.call( maType, c( list( macd ), list(n=nSig, ...) ) ) result <- cbind( macd, signal ) colnames(result) <- c( "macd", "signal" ) return( result ) } TTR/R/TRIX.R0000644000176200001440000001142714531142730012042 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Triple Smoothed Exponential Oscillator #' #' The TRIX indicator calculates the rate of change of a triple exponential #' moving average. Developed by Jack K. Hutson. #' #' The TRIX is calculated as follows:\cr 3MA = \code{MA}( \code{MA}( #' \code{MA}(\code{price}) ) )\cr trix = 100 * [ 3MA(t) / 3MA(t-1) - 1 ] #' #' @param price Price series that is coercible to xts or matrix. #' @param n Number of periods for moving average. #' @param nSig Number of periods for signal line moving average. #' @param maType Either: #' \enumerate{ #' \item A function or a string naming the function to be called. #' \item A \emph{list} with the first component like (1) above, and #' additional parameters specified as \emph{named} components. #' See Examples. #' } #' @param percent logical; if \code{TRUE}, the rate of change is calculated #' using the \code{ROC} function, otherwise the \code{momentum} function is #' used. #' @param \dots Other arguments to be passed to the \code{maType} function in #' case (1) above. #' @return A object of the same class as \code{price} or a vector (if #' \code{try.xts} fails) containing the TRIX values. #' @note Buy/sell signals are generated when the TRIX crosses above/below zero. #' A nine-period EMA of the TRIX is used as a default signal line. Buy/sell #' signals are generated when the TRIX crosses above/below the signal line and #' is also above/below zero. #' @author Joshua Ulrich #' @seealso See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average #' options; and note Warning section. #' @references The following site(s) were used to code/document this #' indicator:\cr #' \url{https://www.fmlabs.com/reference/default.htm?url=TRIX.htm}\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=114}\cr #' \url{https://www.linnsoft.com/techind/trix-triple-smoothed-exponential-oscillator}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:trix}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' trix <- TRIX(ttrc[,"Close"]) #' trix4 <- TRIX(ttrc[,"Close"], #' maType=list(list(SMA), list(EMA, wilder=TRUE), list(SMA), list(DEMA))) #' "TRIX" <- function(price, n=20, nSig=9, maType, percent=TRUE, ...) { # Triple Smoothed Exponential Oscillator # Default MA if(missing(maType)) { maType <- 'EMA' } # Case of different 'maType's for all MAs. if( is.list(maType) ) { # Make sure maType is a list of lists maTypeInfo <- sapply(maType,is.list) if( !(all(maTypeInfo) && length(maTypeInfo) == 4) ) { stop("If \'maType\' is a list, you must specify\n ", "*four* MAs (see Examples section of ?TRIX)") } # If MA function has 'n' arg, see if it's populated in maType; # if it isn't, populate it with function's formal 'n' if( !is.null( formals(maType[[1]][[1]])$n ) && is.null( maType[[1]]$n ) ) { maType[[1]]$n <- n } if( !is.null( formals(maType[[2]][[1]])$n ) && is.null( maType[[2]]$n ) ) { maType[[2]]$n <- n } if( !is.null( formals(maType[[3]][[1]])$n ) && is.null( maType[[3]]$n ) ) { maType[[3]]$n <- n } if( !is.null( formals(maType[[4]][[1]])$n ) && is.null( maType[[4]]$n ) ) { maType[[4]]$n <- nSig } mavg1 <- do.call( maType[[1]][[1]], c( list(price), maType[[1]][-1] ) ) mavg2 <- do.call( maType[[2]][[1]], c( list(mavg1), maType[[2]][-1] ) ) mavg3 <- do.call( maType[[3]][[1]], c( list(mavg2), maType[[3]][-1] ) ) } # Case of one 'maType' for all MAs. else { mavg1 <- do.call( maType, c( list(price), list(n=n, ...) ) ) mavg2 <- do.call( maType, c( list(mavg1), list(n=n, ...) ) ) mavg3 <- do.call( maType, c( list(mavg2), list(n=n, ...) ) ) } if(percent) { TRIX <- 100 * ROC(mavg3, n=1, na.pad=TRUE, type="discrete") } else { TRIX <- momentum( mavg3, n=1, na.pad=TRUE ) } if( is.list(maType) ) { signal <- do.call( maType[[4]][[1]], c( list(TRIX), maType[[4]][-1] ) ) } else { signal <- do.call( maType, c( list(TRIX), list(n=nSig, ...) ) ) } result <- cbind( TRIX, signal ) colnames(result) <- c( "TRIX", "signal" ) return( result ) } TTR/R/CLV.R0000644000176200001440000000363414531142730011701 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Close Location Value #' #' The Close Location Value (CLV) relates the day's close to its trading range. #' #' The CLV will fall in a range of -1 to +1. If the CLV is +/-1, the close is #' at the high/low; if the CLV is 0, the close is directly between the high and #' low. #' #' @param HLC Object that is coercible to xts or matrix and contains #' High-Low-Close prices. #' @return A object of the same class as \code{HLC} or a vector (if #' \code{try.xts} fails) containing the Close Location Values of a #' High-Low-Close price series. #' @author Joshua Ulrich #' @seealso See \code{\link{chaikinAD}}, which uses CLV. #' @references The following site(s) were used to code/document this #' indicator:\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:accumulation_distribution_line}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' clv <- CLV(ttrc[,c("High","Low","Close")]) #' "CLV" <- function(HLC) { # Close Location Value HLC <- try.xts(HLC, error=as.matrix) clv <- ((HLC[,3]-HLC[,2]) - (HLC[,1]-HLC[,3])) / (HLC[,1]-HLC[,2]) # Account for H=L=C clv[is.nan(clv) | is.infinite(clv)] <- 0 if(is.xts(clv)) colnames(clv) <- 'clv' reclass( clv, HLC ) } TTR/R/CTI.R0000644000176200001440000000503614531142730011672 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2020 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Ehler's Correlation Trend Indicator #' #' Ehler's Correlation Trend Indicator (CTI) measures the Spearman correlation #' of the price with the ideal trend line: a straight line with increasing #' slope. #' #' The CTI measures the Spearman correlation between the price and the ideal #' trend line with slope of \code{slope}, over the past \code{n} days. #' #' See URL in references section for further details. #' #' @param price Price series that is coercible to xts or matrix. #' @param n Number of periods to use. #' @param slope Slope of desired trend. #' @return A object of the same class as \code{price} or a matrix (if #' \code{try.xts} fails) with the column: #' \describe{ #' \item{cti}{ The Correlation Trend Indicator. } #' } #' @note Positive/negative CTI values signal positive/negative correlation with #' the desired trend line slope. A simple strategy could be long when the CTI #' is positive and, short when it is negative. #' @author Ethan Smith, Joshua Ulrich #' @seealso See \code{\link{aroon}}, \code{\link{CCI}}, \code{\link{ADX}}, #' \code{\link{VHF}}, \code{\link{GMMA}}, \code{\link{TDI}} for other #' indicators that measure trend direction/strength. #' @references #' John Ehlers, Correlation Trend Indicator, Stocks & Commodities May-2020 #' The following site(s) were used to code/document this indicator:\cr #' \url{https://financial-hacker.com/petra-on-programming-a-unique-trend-indicator/}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' cti <- CTI(ttrc[,"Close"], n = 20) #' CTI <- function(price, n = 20, slope = 1) { x <- try.xts(price, error = as.matrix) y <- slope * seq_along(x) f <- function(.) { cor(.[,1], .[,2], method = "spearman") } cti <- rollapplyr(cbind(x, y), n, f, by.column = FALSE, fill = NA) if(!is.null(dim(cti))) { colnames(cti) <- "cti" } reclass(cti, x) } TTR/R/stochastics.R0000644000176200001440000002637214531142730013610 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Stochastic Oscillator / Stochastic Momentum Index #' #' The stochastic oscillator is a momentum indicator that relates the location #' of each day's close relative to the high/low range over the past \code{n} #' periods. Developed by George C. Lane in the late 1950s. The SMI relates #' the close to the midpoint of the high/low range. Developed by William Blau #' in 1993. #' #' If a High-Low-Close series is provided, the indicator is calculated using the #' high/low values. If a vector is provided, the calculation only uses that #' series. This allows stochastics to be calculated for: (1) series that have #' no HLC definition (e.g. foreign exchange), and (2) stochastic indicators #' (e.g. stochastic RSI - see examples). #' #' The \code{smooth} argument is the number of periods of internal smoothing to #' apply to the differences in the high-low-close range before calculating Fast #' K. Thanks to Stanley Neo for the suggestion. #' #' @aliases stochastics stochastic stoch SMI %K %D #' @param HLC Object that is coercible to xts or matrix and contains #' High-Low-Close prices. If only a univariate series is given, it will be #' used. See details. #' @param n Number of periods to use. #' @param nFastK Number of periods for fast \%K (i.e. the number of past periods #' to use). #' @param nFastD Number of periods for fast \%D (i.e. the number smoothing #' periods to apply to fast \%K). #' @param nSlowD Number of periods for slow \%D (i.e. the number smoothing #' periods to apply to fast \%D). #' @param smooth Number of internal smoothing periods to be applied before #' calculating FastK. See Details. #' @param nFast Number of periods for initial smoothing. #' @param nSlow Number of periods for double smoothing. #' @param nSig Number of periods for signal line. #' @param maType Either: #' \enumerate{ #' \item A function or a string naming the function to be called. #' \item A \emph{list} with the first component like (1) above, and #' additional parameters specified as \emph{named} components. #' See Examples. #' } #' @param bounded Logical, should current period's values be used in the #' calculation? #' @param \dots Other arguments to be passed to the \code{maType} function in #' case (1) above. #' @return A object of the same class as \code{HLC} or a matrix (if #' \code{try.xts} fails) containing the columns: #' \describe{ #' \item{ fastK }{ Stochastic Fast \%K } #' \item{ fastD }{ Stochastic Fast \%D } #' \item{ slowD }{ Stochastic Slow \%D } #' \item{ SMI }{ Stochastic Momentum Index } #' \item{ signal }{ Stochastic Momentum Index signal line } #' } #' @note The calculation for William's \%R is similar to that of stochastics' #' fast \%K. #' #' The value for fast \%K will be 0.5 whenever the highest high and #' lowest low are the same over the last \code{n} periods. #' #' The stochastic oscillator and SMI calculate relative value of the close #' versus the high/low range and the midpoint of the high/low range, #' respectively. #' #' The stochastic oscillator and the stochastic momentum index are interpreted #' similarly. Readings below 20 (above 80) are considered oversold #' (overbought). However, readings below 20 (above 80) are not necessarily #' bearish (bullish). Lane believed some of the best sell (buy) signals #' occurred when the oscillator moved from overbought (oversold) back below 80 #' (above 20). #' #' For the stochastic oscillator, buy (sell) signals can also be given when \%K #' crosses above (below) \%D. Crossover signals are quite frequent however, #' which may result in whipsaws. #' @author Joshua Ulrich #' @seealso See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average #' options; and note Warning section. See \code{\link{WPR}} to compare it's #' results to fast \%K. #' @references The following site(s) were used to code/document these #' indicators: #' \cr Stochastic Oscillator:\cr #' \url{https://www.fmlabs.com/reference/StochasticOscillator.htm}\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=106}\cr #' \url{https://www.linnsoft.com/techind/stochastics}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:stochastic_oscillator_fast_slow_and_full}\cr #' \cr SMI:\cr #' \url{https://www.fmlabs.com/reference/default.htm?url=SMI.htm}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' stochOSC <- stoch(ttrc[,c("High","Low","Close")]) #' stochWPR <- WPR(ttrc[,c("High","Low","Close")]) #' #' plot(tail(stochOSC[,"fastK"], 100), type="l", #' main="Fast %K and Williams %R", ylab="", #' ylim=range(cbind(stochOSC, stochWPR), na.rm=TRUE) ) #' lines(tail(stochWPR, 100), col="blue") #' lines(tail(1-stochWPR, 100), col="red", lty="dashed") #' #' stoch2MA <- stoch( ttrc[,c("High","Low","Close")], #' maType=list(list(SMA), list(EMA, wilder=TRUE), list(SMA)) ) #' #' SMI3MA <- SMI(ttrc[,c("High","Low","Close")], #' maType=list(list(SMA), list(EMA, wilder=TRUE), list(SMA)) ) #' #' stochRSI <- stoch( RSI(ttrc[,"Close"]) ) #' @rdname stochastics "stoch" <- function(HLC, nFastK=14, nFastD=3, nSlowD=3, maType, bounded=TRUE, smooth=1, ...) { # Stochastics HLC <- try.xts(HLC, error=as.matrix) # Calculation if HLC series is given if(NCOL(HLC)==3) { high <- HLC[,1] low <- HLC[,2] close <- HLC[,3] } else # Calculation if price vector is given if(NCOL(HLC)==1) { high <- HLC low <- HLC close <- HLC } else stop("Price series must be either High-Low-Close, or Close") if(bounded) { hmax <- runMax(high, nFastK) lmin <- runMin( low, nFastK) } else { hmax <- runMax(c(high[1],high[-NROW(HLC)]), nFastK) lmin <- runMin(c( low[1], low[-NROW(HLC)]), nFastK) } num <- close - lmin den <- hmax - lmin if(missing(maType)) { maType <- 'SMA' } # Case of two different 'maType's for both MAs. # e.g. stoch(price, 14, 3, 3, # maType=list(maUp=list(EMA,ratio=1/5), maDown=list(WMA,wts=1:10)) ) if( is.list(maType) ) { # Make sure maType is a list of lists maTypeInfo <- sapply(maType,is.list) if( !(all(maTypeInfo) && length(maTypeInfo) == 3) ) { stop("If \'maType\' is a list, you must specify\n ", "*three* MAs (see Examples section of ?stochastics)") } # If MA function has 'n' arg, see if it's populated in maType; # if it isn't, populate it with function's formal 'n' if( !is.null( formals(maType[[1]][[1]])$n ) && is.null( maType[[1]]$n ) ) { maType[[1]]$n <- nFastD } if( !is.null( formals(maType[[2]][[1]])$n ) && is.null( maType[[2]]$n ) ) { maType[[2]]$n <- nSlowD } if( !is.null( formals(maType[[3]][[1]])$n ) && is.null( maType[[3]]$n ) ) { maType[[3]]$n <- smooth } numMA <- do.call( maType[[3]][[1]], c( list(num), maType[[3]][-1] ) ) denMA <- do.call( maType[[3]][[1]], c( list(den), maType[[3]][-1] ) ) fastK <- numMA / denMA fastK[!is.finite(fastK) & !is.na(fastK)] <- 0.5 fastD <- do.call( maType[[1]][[1]], c( list(fastK), maType[[1]][-1] ) ) slowD <- do.call( maType[[2]][[1]], c( list(fastD), maType[[2]][-1] ) ) } # Case of one 'maType' for both MAs. # e.g. stoch(price, 14, 3, 3, maType="WMA", wts=volume ) else { numMA <- do.call( maType, c( list(num), list(n=smooth) ) ) denMA <- do.call( maType, c( list(den), list(n=smooth) ) ) fastK <- numMA / denMA fastK[!is.finite(fastK) & !is.na(fastK)] <- 0.5 fastD <- do.call( maType, c( list(fastK), list(n=nFastD, ...) ) ) slowD <- do.call( maType, c( list(fastD), list(n=nSlowD, ...) ) ) } result <- cbind( fastK, fastD, slowD ) colnames(result) <- c( "fastK", "fastD", "slowD" ) reclass(result, HLC) } #-------------------------------------------------------------------------# #' @rdname stochastics "SMI" <- function(HLC, n=13, nFast=2, nSlow=25, nSig=9, maType, bounded=TRUE, ...) { # Stochastic Momentum Index # Not Validated # http://www.fmlabs.com/reference/default.htm?url=SMI.htm # The median in the SMI formula on the above site is incorrect. # Calculation if HLC series is given if(ncol(HLC)==3) { high <- HLC[,1] low <- HLC[,2] close <- HLC[,3] } else # Calculation if price vector is given if(ncol(HLC)==1) { high <- HLC low <- HLC close <- HLC } else stop("Price series must be either High-Low-Close, or Close") if(bounded) { hmax <- runMax(high, n) lmin <- runMin( low, n) } else { hmax <- runMax(c(high[1],high[-NROW(HLC)]), n) lmin <- runMax(c( low[1], low[-NROW(HLC)]), n) } hmax <- ifelse( is.na(hmax), high, hmax ) lmin <- ifelse( is.na(lmin), low, lmin ) HLdiff <- hmax - lmin Cdiff <- close - ( hmax + lmin ) / 2 if(missing(maType)) { maType <- 'EMA' } # Case of two different 'maType's for both MAs. # e.g. SMI(price, 13, 2, 25, 9, # maType=list(maUp=list(EMA,ratio=1/5), maDown=list(WMA,wts=1:10)) ) if( is.list(maType) ) { # Make sure maType is a list of lists maTypeInfo <- sapply(maType,is.list) if( !(all(maTypeInfo) && length(maTypeInfo) == 3) ) { stop("If \'maType\' is a list, you must specify\n ", "*three* MAs (see Examples section of ?SMI)") } # If MA function has 'n' arg, see if it's populated in maType; # if it isn't, populate it with function's formal 'n' if( !is.null( formals(maType[[1]][[1]])$n ) && is.null( maType[[1]]$n ) ) { maType[[1]]$n <- nFast } if( !is.null( formals(maType[[2]][[1]])$n ) && is.null( maType[[2]]$n ) ) { maType[[2]]$n <- nSlow } if( !is.null( formals(maType[[3]][[1]])$n ) && is.null( maType[[3]]$n ) ) { maType[[3]]$n <- nSig } num1 <- do.call( maType[[1]][[1]], c( list(Cdiff ), maType[[1]][-1] ) ) den1 <- do.call( maType[[1]][[1]], c( list(HLdiff), maType[[1]][-1] ) ) num2 <- do.call( maType[[2]][[1]], c( list( num1 ), maType[[2]][-1] ) ) den2 <- do.call( maType[[2]][[1]], c( list( den1 ), maType[[2]][-1] ) ) SMI <- 100 * ( num2 / ( den2 / 2 ) ) signal <- do.call( maType[[3]][[1]], c( list(SMI), maType[[3]][-1] ) ) } # Case of one 'maType' for both MAs. # e.g. SMI(price, 13, 2, 25, 9, maType="WMA", wts=volume ) else { num1 <- do.call( maType, c( list(Cdiff ), list(n=nSlow, ... ) ) ) den1 <- do.call( maType, c( list(HLdiff), list(n=nSlow, ... ) ) ) num2 <- do.call( maType, c( list( num1 ), list(n=nFast, ... ) ) ) den2 <- do.call( maType, c( list( den1 ), list(n=nFast, ... ) ) ) SMI <- 100 * ( num2 / ( den2 / 2 ) ) signal <- do.call( maType, c( list(SMI), list(n=nSig, ... ) ) ) } result <- cbind( SMI, signal ) colnames(result) <- c( "SMI", "signal" ) reclass( result, HLC ) } TTR/R/volatility.R0000644000176200001440000002402714531142730013454 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Volatility #' #' Selected volatility estimators/indicators; various authors. #' #' \itemize{ #' \item Close-to-Close Volatility (\code{calc="close"})\cr #' \deqn{ \sigma_{cl} = \sqrt{\frac{N}{n-2} \sum_{i=1}^{n-1}(r_i-\bar{r})^2} #' }{sqrt(N) * runSD(ROC(Cl), n-1)} #' \deqn{where\;\; r_i = \log \left(\frac{C_i}{C_{i-1}}\right) } #' \deqn{and\;\; \bar{r} = \frac{r_1+r_2+\ldots +r_{n-1}}{n-1} } #' #' \item OHLC Volatility: Garman and Klass (\code{calc="garman.klass"})\cr The #' Garman and Klass estimator for estimating historical volatility assumes #' Brownian motion with zero drift and no opening jumps (i.e. the opening = #' close of the previous period). This estimator is 7.4 times more efficient #' than the close-to-close estimator.\cr #' \deqn{ \sigma = \sqrt{ \frac{N}{n} \sum #' \left[ \textstyle\frac{1}{2}\displaystyle #' \left( \log \frac{H_i}{L_i} \right)^2 - (2\log 2-1) #' \left( \log \frac{C_i}{O_i} \right)^2 \right] } #' }{sqrt(N/n * runSum(0.5 * log(Hi/Lo)^2 - #' (2*log(2)-1) * log(Cl/Op)^2, n))} #' #' \item High-Low Volatility: Parkinson (\code{calc="parkinson"})\cr #' The Parkinson formula for estimating the historical volatility of #' an underlying based on high and low prices.\cr #' \deqn{ \sigma = \sqrt{ \frac{N}{4 n \times \log 2} \sum_{i=1}^{n} #' \left(\log \frac{H_i}{L_i}\right)^2} #' }{sqrt(N/(4*n*log(2)) * runSum(log(Hi/Lo)^2, n))} #' #' \item OHLC Volatility: Rogers and Satchell (\code{calc="rogers.satchell"})\cr #' The Roger and Satchell historical volatility estimator allows for non-zero #' drift, but assumed no opening jump.\cr #' \deqn{ \sigma = \sqrt{ \textstyle\frac{N}{n} \sum \left[ #' \log \textstyle\frac{H_i}{C_i} \times \log \textstyle\frac{H_i}{O_i} + #' \log \textstyle\frac{L_i}{C_i} \times \log \textstyle\frac{L_i}{O_i} \right] } #' }{sqrt(N/n * runSum(log(Hi/Cl) * log(Hi/Op) + #' log(Lo/Cl) * log(Lo/Op), n))} #' #' \item OHLC Volatility: Garman and Klass - Yang and Zhang #' (\code{calc="gk.yz"})\cr This estimator is a modified version of the Garman #' and Klass estimator that allows for opening gaps.\cr #' \deqn{ \sigma = \sqrt{ \textstyle\frac{N}{n} \sum \left[ #' \left( \log \textstyle\frac{O_i}{C_{i-1}} \right)^2 + #' \textstyle\frac{1}{2}\displaystyle #' \left( \log \textstyle\frac{H_i}{L_i} \right)^2 - (2 \times \log 2-1) #' \left( \log \textstyle\frac{C_i}{O_i} \right)^2 \right] } #' }{sqrt(N/n * runSum(log(Op/lag(Cl,1))^2 + #' 0.5 * log(Hi/Lo)^2 - (2*log(2)-1) * log(Cl/Op)^2 , n))} #' #' \item OHLC Volatility: Yang and Zhang (\code{calc="yang.zhang"})\cr The Yang #' and Zhang historical volatility estimator has minimum estimation error, and #' is independent of drift and opening gaps. It can be interpreted as a #' weighted average of the Rogers and Satchell estimator, the close-open #' volatility, and the open-close volatility. #' #' Users may override the default values of \eqn{\alpha} (1.34 by default) or #' \eqn{k} used in the calculation by specifying \code{alpha} or \code{k} in #' \code{\dots}, respectively. Specifying \code{k} will cause \code{alpha} to be #' ignored, if both are provided.\cr #' \deqn{ \sigma^2 = \sigma_o^2 + k\sigma_c^2 + (1-k)\sigma_{rs}^2 #' }{ s <- sqrt(s2o + k*s2c + (1-k)*(s2rs^2)) } #' \deqn{ \sigma_o^2 =\textstyle \frac{N}{n-1} \sum #' \left( \log \frac{O_i}{C_{i-1}}-\mu_o \right)^2 #' }{ s2o <- N * runVar(log(Op/lag(Cl,1)), n=n) } #' \deqn{ \mu_o=\textstyle \frac{1}{n} \sum \log \frac{O_i}{C_{i-1}} } #' \deqn{ \sigma_c^2 =\textstyle \frac{N}{n-1} \sum #' \left( \log \frac{C_i}{O_i}-\mu_c \right)^2 #' }{ s2c <- N * runVar(log(Cl/Op), n=n) } #' \deqn{ \mu_c=\textstyle \frac{1}{n} \sum \log \frac{C_i}{O_i} } #' \deqn{ \sigma_{rs}^2 = \textstyle\frac{N}{n} \sum \left( #' \log \textstyle\frac{H_i}{C_i} \times \log \textstyle\frac{H_i}{O_i} + #' \log \textstyle\frac{L_i}{C_i} \times \log \textstyle\frac{L_i}{O_i} #' \right) #' }{ s2rs <- volatility(OHLC, n, "rogers.satchell", N, ...) } #' \deqn{ k=\frac{\alpha-1}{alpha+\frac{n+1}{n-1}} #' }{ k <- (alpha-1) / (alpha + (n+1)/(n-1)) } #' } #' #' @aliases volatility garman.klass parkinson rogers.satchell gk.yz yang.zhang #' @param OHLC Object that is coercible to xts or matrix and contains #' Open-High-Low-Close prices (or only Close prices, if \code{calc="close"}). #' @param n Number of periods for the volatility estimate. #' @param calc The calculation (type) of estimator to use. #' @param N Number of periods per year. #' @param mean0 Use a mean of 0 rather than the sample mean. #' @param \dots Arguments to be passed to/from other methods. #' @return A object of the same class as \code{OHLC} or a vector (if #' \code{try.xts} fails) containing the chosen volatility estimator values. #' @author Joshua Ulrich #' @seealso See \code{\link{TR}} and \code{\link{chaikinVolatility}} for other #' volatility measures. #' @references The following sites were used to code/document these #' indicators. All were created by Thijs van den Berg under the GNU Free #' Documentation License and were retrieved on 2008-04-20. The original #' links are dead, but can be accessed via internet archives.\cr #' \cr Close-to-Close Volatility (\code{calc="close"}):\cr #' \url{https://web.archive.org/web/20100421083157/http://www.sitmo.com/eq/172}\cr #' \cr OHLC Volatility: Garman Klass (\code{calc="garman.klass"}):\cr #' \url{https://web.archive.org/web/20100326172550/http://www.sitmo.com/eq/402}\cr #' \cr High-Low Volatility: Parkinson (\code{calc="parkinson"}):\cr #' \url{https://web.archive.org/web/20100328195855/http://www.sitmo.com/eq/173}\cr #' \cr OHLC Volatility: Rogers Satchell (\code{calc="rogers.satchell"}):\cr #' \url{https://web.archive.org/web/20091002233833/http://www.sitmo.com/eq/414}\cr #' \cr OHLC Volatility: Garman Klass - Yang Zhang (\code{calc="gk.yz"}):\cr #' \url{https://web.archive.org/web/20100326215050/http://www.sitmo.com/eq/409}\cr #' \cr OHLC Volatility: Yang Zhang (\code{calc="yang.zhang"}):\cr #' \url{https://web.archive.org/web/20100326215050/http://www.sitmo.com/eq/409}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' ohlc <- ttrc[,c("Open","High","Low","Close")] #' vClose <- volatility(ohlc, calc="close") #' vClose0 <- volatility(ohlc, calc="close", mean0=TRUE) #' vGK <- volatility(ohlc, calc="garman") #' vParkinson <- volatility(ohlc, calc="parkinson") #' vRS <- volatility(ohlc, calc="rogers") #' "volatility" <- function(OHLC, n=10, calc="close", N=260, mean0=FALSE, ...) { OHLC <- try.xts(OHLC, error=as.matrix) # Choose an arg name that doesn't clash with ROC's 'type' arg calc <- match.arg(calc, c("close","garman.klass","parkinson", "rogers.satchell","gk.yz","yang.zhang")) # s Volatility # N Number of closing prices in a year # n Number of historical prices used for the volatility estimate # ci The closing price on the ith day # ri Log return on the ith day # Historical Close-to-Close Volatility # http://www.sitmo.com/eq/172 if( calc=="close" ) { # Add univariate case from Cedrick Johnson's R-SIG-Finance post if( NCOL(OHLC) == 1 ) { r <- ROC(OHLC[, 1], 1, ...) } else { r <- ROC(OHLC[, 4], 1, ...) } if( isTRUE(mean0) ) { # This is an alternative SD calculation using an effective mean of 0 s <- sqrt(N) * sqrt(runSum(r^2, n-1) / (n-2)) } else { # This is the standard SD calculation using the sample mean s <- sqrt(N) * runSD(r, n-1) } } # Historical Open-High-Low-Close Volatility: Garman Klass # http://www.sitmo.com/eq/402 if( calc=="garman.klass" ) { s <- sqrt( N/n * runSum( .5 * log(OHLC[,2]/OHLC[,3])^2 - (2*log(2)-1) * log(OHLC[,4]/OHLC[,1])^2 , n ) ) } if( calc=="parkinson" ) { # Historical High-Low Volatility: Parkinson # http://www.sitmo.com/eq/173 s <- sqrt( N/(4*n*log(2)) * runSum( log(OHLC[,2]/OHLC[,3])^2, n ) ) } if( calc=="rogers.satchell" ) { # Historical Open-High-Low-Close Volatility: Rogers Satchell # http://www.sitmo.com/eq/414 s <- sqrt( N/n * runSum( log(OHLC[,2]/OHLC[,4]) * log(OHLC[,2]/OHLC[,1]) + log(OHLC[,3]/OHLC[,4]) * log(OHLC[,3]/OHLC[,1]), n ) ) } if( calc=="gk.yz" ) { #if( calc=="garman.klass.yang.zhang" ) { # Historical Open-High-Low-Close Volatility: Garman and Klass (Yang Zhang) # http://www.sitmo.com/eq/409 if(is.xts(OHLC)) { Cl1 <- lag.xts(OHLC[,4]) } else { Cl1 <- c( NA, OHLC[-NROW(OHLC),4] ) } s <- sqrt( N/n * runSum( log(OHLC[,1]/Cl1)^2 + .5 * log(OHLC[,2]/OHLC[,3])^2 - (2*log(2)-1) * log(OHLC[,4]/OHLC[,1])^2 , n) ) #s <- sqrt( Z/n * runSum( # log(op/cl[-1])^2 + # .5*log(hi/lo)^2 - # (2*log(2)-1)*log(cl/op)^2 ) ) } if( calc=="yang.zhang" ) { # Historical Open-High-Low-Close Volatility: Yang Zhang # http://www.sitmo.com/eq/417 if(is.xts(OHLC)) { Cl1 <- lag.xts(OHLC[,4]) } else { Cl1 <- c( NA, OHLC[-NROW(OHLC),4] ) } dots <- list(...) if(is.null(dots$alpha)) { alpha <- 1.34 } if(is.null(dots$k)) { k <- (alpha-1) / ( alpha + (n+1)/(n-1) ) } s2o <- N * runVar(log(OHLC[,1] / Cl1), n=n) s2c <- N * runVar(log(OHLC[,4] / OHLC[,1]), n=n) s2rs <- volatility(OHLC=OHLC, n=n, calc="rogers.satchell", N=N, ...) s <- sqrt(s2o + k*s2c + (1-k)*(s2rs^2)) } reclass(s,OHLC) } TTR/R/zzz.R0000644000176200001440000000147514470445701012121 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2017 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # .env <- new.env() .onUnload <- function(libpath) { library.dynam.unload("TTR", libpath) } TTR/R/keltnerChannels.R0000644000176200001440000000765014531142730014377 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2020 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Keltner Channels #' #' Keltner Channels are volatility-based envelopes set above and below a moving #' average. This indicator is similar to Bollinger Bands, but Keltner Channels #' use the Average True Range (ATR) to set channel distance. #' #' Keltner Channels are a trend following indicator, and can also be used to #' identify overbought and oversold levels when there is no trend. #' #' Chester Keltner is credited with the original version of Keltner Channels in #' his 1960 book. Linda Bradford Raschke introduced the newer version of #' Keltner Channels in the 1980s. #' #' @aliases keltnerChannels #' #' @param HLC Object that is coercible to xts or matrix and contains #' High-Low-Close prices. If only a univariate series is given, it will be used. #' See details. #' @param n Number of periods for moving average. #' @param maType A function or a string naming the function to be called. #' @param atr The number of average true range distances to apply. #' @param ... Other arguments to be passed to the maType function. #' #' @section Details : Keltner Channels consist of three lines: #' The middle band is generally a 20-period EMA of the typical price #' ([high + low + close]/3). The upper and lower bands are multiples of average #' true range (usually 2) above and below the MA. #' #' The middle band is usually calculated using the typical price, but if a #' univariate series (e.g. Close, Weighted Close, Median Price, etc.) is #' provided, it will be used instead. #' #' @return A object of the same class as \code{HLC} or a matrix (if #' \code{try.xts} fails) containing the columns: #' \describe{ #' \item{SMA}{ Simple moving average. } #' \item{EMA}{ Exponential moving average. } #' } #' #' \item{dn}{ The lower Keltner Channel. } #' \item{mavg}{ The middle moving average. } #' \item{up}{ The upper Keltner Channel. } #' #' @author Nick Procyk, Joshua Ulrich #' #' References #' @references The following site(s) were used to code/document this #' indicator:\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:keltner_channels}\cr #' \url{https://www.linnsoft.com/techind/keltner-channels-keltu-keltd}\cr #' \url{https://www.investopedia.com/terms/k/keltnerchannel.asp}\cr #' #' @seealso See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average #' options; and note Warning section. #' #' @examples #' #' data(ttrc) #' kc <- keltnerChannels(ttrc[,c("High","Low","Close")]) #' #' @keywords ts #' @rdname keltnerChannels keltnerChannels <- function (HLC, n = 20, maType, atr = 2, ...) { atrHLC <- HLC HLC <- try.xts(HLC, error = as.matrix) if (NCOL(HLC) == 3) { if (is.xts(HLC)) { xa <- xcoredata(HLC) HLC <- xts(apply(HLC, 1, mean), index(HLC)) xcoredata(HLC) <- xa } else { HLC <- apply(HLC, 1, mean) } } else if (NCOL(HLC) != 1) { stop("Price series must be either High-Low-Close, or Close/univariate.") } maArgs <- list(n = n, ...) if (missing(maType)) { maType <- "EMA" } mavg <- do.call(maType, c(list(HLC), maArgs)) avgtruerange <- ATR(atrHLC, n = n) up <- mavg + atr * avgtruerange[,2] dn <- mavg - atr * avgtruerange[,2] res <- cbind(dn, mavg, up) colnames(res) <- c("dn", "mavg", "up") reclass(res, HLC) } TTR/R/CMF.R0000644000176200001440000000510714531142730011657 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Chaikin Money Flow #' #' Chaikin Money Flow compares total volume over the last \code{n} time periods #' to total volume times the Close Location Value (CLV) over the last \code{n} #' time periods. Developed by Marc Chaikin. #' #' Chaikin Money Flow is calculated by taking dividing the sum of the Chaikin #' Accumulation / Distribution line over the past \code{n} periods by the sum of #' volume over the past \code{n} periods. #' #' @param HLC Object that is coercible to xts or matrix and contains #' High-Low-Close prices. #' @param volume Vector or matrix of volume observations corresponding to the #' \code{HLC} object. #' @param n Number of periods to use. #' @return A object of the same class as \code{HLC} and \code{volume} or a #' vector (if \code{try.xts} fails) containing the Chaikin Money Flow values. #' @note When Chaikin Money Flow is above/below +/- 0.25 it is a bullish/bearish #' signal. If Chaikin Money Flow remains below zero while the price is rising, #' it indicates a probable reversal. #' @author Joshua Ulrich #' @seealso See \code{\link{CLV}}, and \code{\link{chaikinAD}}. #' @references The following site(s) were used to code/document this #' indicator:\cr \url{https://www.fmlabs.com/reference/ChaikinMoneyFlow.htm}\cr #' \url{https://www.linnsoft.com/techind/chaikin-money-flow-cmf}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:chaikin_money_flow_cmf}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' cmf <- CMF(ttrc[,c("High","Low","Close")], ttrc[,"Volume"]) #' "CMF" <- function(HLC, volume, n=20) { # Chaikin Money Flow HLC <- try.xts(HLC, error=as.matrix) volume <- try.xts(volume, error=as.matrix) if(!(is.xts(HLC) && is.xts(volume))) { clv <- CLV(as.matrix(HLC)) volume <- as.matrix(volume) } clv <- CLV(HLC) cmf <- runSum(clv*volume, n) / runSum(volume, n) reclass(cmf, HLC) } TTR/R/bollingerBands.R0000644000176200001440000001024614531142730014177 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Bollinger Bands #' #' Bollinger Bands are a way to compare a security's volatility and price levels #' over a period of time. Developed by John Bollinger. #' #' Bollinger Bands consist of three lines: #' #' The middle band is generally a 20-period SMA of the typical price ([high + #' low + close]/3). The upper and lower bands are \code{sd} standard deviations #' (generally 2) above and below the MA. #' #' The middle band is usually calculated using the typical price, but if a #' univariate series (e.g. Close, Weighted Close, Median Price, etc.) is #' provided, it will be used instead. #' #' @aliases bollingerBands BBands #' @param HLC Object that is coercible to xts or matrix and contains #' High-Low-Close prices. If only a univariate series is given, it will be #' used. See details. #' @param n Number of periods for moving average. #' @param maType A function or a string naming the function to be called. #' @param sd The number of standard deviations to use. #' @param \dots Other arguments to be passed to the \code{maType} function. #' @return A object of the same class as \code{HLC} or a matrix (if #' \code{try.xts} fails) containing the columns: #' \describe{ #' \item{ dn }{ The lower Bollinger Band. } #' \item{ mavg }{ The middle Moving Average (see notes). } #' \item{ up }{ The upper Bollinger Band. } #' \item{ pctB }{ The \%B calculation. } #' } #' @note Using any moving average other than SMA will result in inconsistencies #' between the moving average calculation and the standard deviation #' calculation. Since, by definition, a rolling standard deviation uses a #' simple moving average. #' @author Joshua Ulrich #' @seealso See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average #' options; and note Warning section. #' @references The following site(s) were used to code/document this #' indicator:\cr \url{https://www.fmlabs.com/reference/Bollinger.htm}\cr #' \url{https://www.fmlabs.com/reference/BollingerWidth.htm}\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=36}\cr #' \url{https://www.linnsoft.com/techind/bollinger-bands}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:bollinger_bands}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:bollinger_band_width}\cr #' @keywords ts #' @examples #' #' ## The examples below show the differences between using a #' ## High-Low-Close series, and just a close series when #' ## calculating Bollinger Bands. #' data(ttrc) #' bbands.HLC <- BBands( ttrc[,c("High","Low","Close")] ) #' bbands.close <- BBands( ttrc[,"Close"] ) #' @rdname bollingerBands "BBands" <- function(HLC, n=20, maType, sd=2, ...) { # Bollinger Bands HLC <- try.xts(HLC, error=as.matrix) if(NCOL(HLC)==3) { if(is.xts(HLC)) { xa <- xcoredata(HLC) HLC <- xts(apply(HLC, 1, mean),index(HLC)) xcoredata(HLC) <- xa } else { HLC <- apply(HLC, 1, mean) } } else if(NCOL(HLC)!=1) { stop("Price series must be either High-Low-Close, or Close/univariate.") } maArgs <- list(n=n, ...) # Default MA if(missing(maType)) { maType <- 'SMA' } mavg <- do.call( maType, c( list(HLC), maArgs ) ) # Calculate standard deviation by hand to incorporate various MAs sdev <- runSD(HLC, n, sample=FALSE) up <- mavg + sd * sdev dn <- mavg - sd * sdev pctB <- (HLC - dn) / (up - dn) res <- cbind(dn, mavg, up, pctB) colnames(res) <- c("dn", "mavg", "up", "pctB") reclass(res, HLC) } TTR/R/RSI.R0000644000176200001440000001162614531142730011712 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Relative Strength Index #' #' The Relative Strength Index (RSI) calculates a ratio of the recent upward #' price movements to the absolute price movement. Developed by J. Welles #' Wilder. #' #' The RSI calculation is \code{RSI = 100 - 100 / ( 1 + RS )}, where \code{RS} #' is the smoothed ratio of 'average' gains over 'average' losses. The #' 'averages' aren't true averages, since they're divided by the value of #' \code{n} and not the number of periods in which there are gains/losses. #' #' @param price Price series that is coercible to xts or matrix. #' @param n Number of periods for moving averages. #' @param maType Either: #' \enumerate{ #' \item A function or a string naming the function to be called. #' \item A \emph{list} with the first component like (1) above, and #' additional parameters specified as \emph{named} components. #' See Examples. #' } #' @param \dots Other arguments to be passed to the \code{maType} function in #' case (1) above. #' @return A object of the same class as \code{price} or a vector (if #' \code{try.xts} fails) containing the RSI values. #' @note The RSI is usually interpreted as an overbought/oversold (over 70 / #' below 30) indicator. Divergence with price may also be useful. For example, #' if price is making new highs/lows, but RSI is not, it could indicate a #' reversal. #' #' You can calculate a stochastic RSI by using the function \code{\link{stoch}} #' on RSI values. #' @author Joshua Ulrich #' @seealso See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average #' options; and note Warning section. See \code{\link{CMO}} for a variation on #' RSI. #' @references The following site(s) were used to code/document this #' indicator: #' \cr Relative Strength Index:\cr #' \url{https://www.fmlabs.com/reference/RSI.htm}\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=100}\cr #' \url{https://www.linnsoft.com/techind/relative-strength-index-rsi}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:relative_strength_index_rsi}\cr #' \cr Stochastic RSI:\cr #' \url{https://www.fmlabs.com/reference/StochRSI.htm}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:stochrsi}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' price <- ttrc[,"Close"] #' #' # Default case #' rsi <- RSI(price) #' #' # Case of one 'maType' for both MAs #' rsiMA1 <- RSI(price, n=14, maType="WMA", wts=ttrc[,"Volume"]) #' #' # Case of two different 'maType's for both MAs #' rsiMA2 <- RSI(price, n=14, maType=list(maUp=list(EMA),maDown=list(WMA))) #' #' "RSI" <- function(price, n=14, maType, ...) { price <- try.xts(price, error=as.matrix) up <- momentum(price, n=1, na.pad=TRUE) which.dn <- which(up < 0) dn <- up*0 dn[which.dn] <- -up[which.dn] up[which.dn] <- 0 maArgs <- list(n=n, ...) # Default Welles Wilder EMA if(missing(maType)) { maType <- 'EMA' if(is.null(maArgs$wilder)) { # do not overwrite user-provided value maArgs$wilder <- TRUE } } # Case of two different 'maType's for both MAs. # e.g. RSI(price, n=14, maType=list(maUp=list(EMA,ratio=1/5), maDown=list(WMA,wts=1:10)) ) if( is.list(maType) ) { # Make sure maType is a list of lists maTypeInfo <- sapply(maType,is.list) if( !(all(maTypeInfo) && length(maTypeInfo) == 2) ) { stop("If \'maType\' is a list, you must specify\n ", "*two* MAs (see Examples section of ?RSI)") } # If MA function has 'n' arg, see if it's populated in maType; # if it isn't, populate it with RSI's formal 'n' for(i in 1:length(maType)) { if( !is.null( formals(maType[[i]][[1]])$n ) && is.null( maType[[i]]$n ) ) { maType[[i]]$n <- n } mavgUp <- do.call( maType[[1]][[1]], c( list(up), maType[[1]][-1] ) ) mavgDn <- do.call( maType[[2]][[1]], c( list(dn), maType[[2]][-1] ) ) } } # Case of one 'maType' for both MAs. # e.g. RSI(price, n=14, maType="WMA", wts=volume ) else { mavgUp <- do.call( maType, c( list(up), maArgs ) ) mavgDn <- do.call( maType, c( list(dn), maArgs ) ) } rsi <- 100 * mavgUp / ( mavgUp + mavgDn ) if (!is.null(dim(rsi)) && ncol(rsi) == 1L) { colnames(rsi) <- "rsi" } reclass( rsi, price ) } TTR/R/KST.R0000644000176200001440000001304014531142730011706 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Know Sure Thing #' #' The Know Sure Thing (KST) is a smooth, summed, rate of change indicator. #' Developed by Martin Pring. #' #' For each day (week, month, etc.), the KST calculates the ROC over several #' periods. Those ROCs are smoothed using the given moving averages, then #' multiplied by their respective weighting values. The resulting values are #' summed for each day (month, week, etc.). #' #' @param price Price series that is coercible to xts or matrix. #' @param n A vector of the number of periods to use in the MA calculations. #' @param nROC A vector of the number of periods to use in the ROC calculations. #' @param nSig The number of periods to use for the KST signal line. #' @param maType Either: #' \enumerate{ #' \item A function or a string naming the function to be called. #' \item A \emph{list} with the first component like (1) above, and #' additional parameters specified as \emph{named} components. #' See Examples. #' } #' @param wts A vector the same length as \code{n}, of the weight for each #' period (need not sum to one). #' @param \dots Other arguments to be passed to the \code{maType} function in #' case (1) above. #' @return A object of the same class as \code{price} or a vector (if #' \code{try.xts} fails) containing the Know Sure Thing values. #' @note The KST indicates bullish/bearish momentum as it crosses above/below #' its moving average. Because the KST tends to lead price action, look for #' trend confirmation in the price. #' #' The default arguments are for the daily KST. There is also the Long-Term #' KST, with arguments: \code{n=c(9, 12, 18, 24)} - where the periods are #' months, not days - and the moving average periods are 6, 6, 6, and 9 months, #' respectively. #' @author Joshua Ulrich #' @seealso See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average #' options; and note Warning section. See \code{\link{ROC}} for the #' rate-of-change function. See \code{\link{MACD}} for a generic oscillator. #' @references The following site(s) were used to code/document this #' indicator:\cr #' \url{https://web.archive.org/web/20110715112957/http://www.pring.com/movieweb/daily_kst.htm}\cr #' \url{https://web.archive.org/web/20100101162707/http://www.pring.com/movieweb/KST_MCM.htm}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' kst <- KST(ttrc[,"Close"]) #' #' kst4MA <- KST(ttrc[,"Close"], #' maType=list(list(SMA),list(EMA),list(DEMA),list(WMA))) #' "KST" <- function(price, n=c(10,10,10,15), nROC=c(10,15,20,30), nSig=9, maType, wts=1:NROW(n), ...) { # Know Sure Thing # Technical Analysis Explained: The Successful Investor's Guide to # Spotting Investment Trends and Turning Points # Martin J. Pring # http://www.pring.com/index.html # Daily: http://www.pring.com/movieweb/daily_kst.htm # Long-Term: http://www.pring.com/articles/article28.htm # Daily KST # MA(ROC(10)10) + MA(ROC(15)10) + MA(ROC(20)10) + MA(ROC(30)15) # # Intermediate KST # MA(ROC(10)10) + MA(ROC(13)13) + MA(ROC(15)15) + MA(ROC(20)20) # # Long-Term Monthly KST # MA(ROC(9)6) + MA(ROC(12)6) + MA(ROC(18)6) + MA(ROC(24)9) if( !all.equal(NROW(n), NROW(wts), NROW(nROC)) ) { stop("'n', 'nROC', and 'wts' must be the same length.") } else { N <- NROW(n) } #price <- as.vector(price) ret <- NULL # Default MA if(missing(maType)) { maType <- 'SMA' } # Case of two different 'maType's for both MAs. if( is.list(maType) ) { # Make sure maType is a list of lists maTypeInfo <- sapply(maType,is.list) if( !(all(maTypeInfo) && length(maTypeInfo) == N) ) { stop("If \'maType\' is a list, you must specify\n ", "the same number of MAs as elements in \'n\' and\n ", "\'nROC\' (see Examples section of ?KST)") } # If MA function has 'n' arg, see if it's populated in maType; # if it isn't, populate it with formal 'n' for(i in 1:length(maType)) { if( !is.null( formals(maType[[i]][[1]])$n ) && is.null( maType[[i]]$n ) ) { maType[[i]]$n <- n[i] } roc <- ROC(price, nROC[i], na.pad=TRUE) ma.roc <- do.call( maType[[i]][[1]], c( list(roc), maType[[i]][-1] ) ) * wts[i] ret <- cbind( ret, ma.roc ) } } # Case of one 'maType' for both MAs. else { for(i in 1:NROW(n)) { roc <- ROC(price, nROC[i], na.pad=TRUE) ma.roc <- do.call( maType, c( list(roc), list(n=n[i], ...) ) ) * wts[i] ret <- cbind( ret, ma.roc ) } } if(is.xts(ret)) { kst <- xts(100 * rowSums(ret),index(ret)) } else { kst <- 100 * rowSums(ret) } if( is.list(maType) ) { sigMA <- length(maType) signal <- do.call( maType[[sigMA]][[1]], c( list(kst), maType[[sigMA]][-1] ) ) } else { signal <- do.call( maType, c( list(kst), list(n=nSig, ...) ) ) } result <- cbind( kst, signal ) colnames(result) <- c( "kst", "signal" ) return( result ) } TTR/R/TDI.R0000644000176200001440000000557714531142730011705 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Trend Detection Index #' #' The Trend Detection Index (TDI) attempts to identify starting and ending #' trends. Developed by M. H. Pee. #' #' The TDI is the (1) absolute value of the \code{n}-day sum of the \code{n}-day #' momentum, minus the quantity of (2) \code{multiple}*\code{n}-day sum of the #' absolute value of the \code{n}-day momentum, minus (3) \code{n}-day sum of #' the absolute value of the \code{n}-day momentum. #' #' I.e. TDI = (1) - [ (2) - (3) ] #' #' The direction indicator is the sum of the \code{n}-day momentum over the last #' \code{n} days. #' #' See URL in references section for further details. #' #' @param price Price series that is coercible to xts or matrix. #' @param n Number of periods to use. #' @param multiple Multiple used to calculate (2). #' @return A object of the same class as \code{price} or a matrix (if #' \code{try.xts} fails) containing the columns: #' \describe{ #' \item{ tdi }{ The Trend Detection Index. } #' \item{ di }{ The Direction Indicator. } #' } #' @note Positive/negative TDI values signal a trend/consolidation. A positive/ #' negative direction indicator signals a up/down trend. I.e. buy if the TDI #' and the direction indicator are positive, and sell if the TDI is positive #' while the direction indicator is negative. #' @author Joshua Ulrich #' @seealso See \code{\link{aroon}}, \code{\link{CCI}}, \code{\link{ADX}}, #' \code{\link{VHF}}, \code{\link{GMMA}} for other indicators that measure trend #' direction/strength. #' @references The following site(s) were used to code/document this #' indicator:\cr #' \url{https://www.linnsoft.com/techind/trend-detection-index-tdi}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' tdi <- TDI(ttrc[,"Close"], n=30) #' "TDI" <- function(price, n=20, multiple=2) { # Trend Detection Index price <- try.xts(price, error=as.matrix) mom <- momentum(price, n, na.pad=TRUE) mom[is.na(mom)] <- 0 di <- runSum(mom, n) abs.di <- abs(di) abs.mom.2n <- runSum(abs(mom), n*multiple) abs.mom.1n <- runSum(abs(mom), n ) tdi <- abs.di - (abs.mom.2n - abs.mom.1n) result <- cbind( tdi,di ) colnames(result) <- c( "tdi","di" ) reclass( result, price ) } TTR/R/changes.R0000644000176200001440000000566214531142730012670 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Rate of Change / Momentum #' #' Calculate the (rate of) change of a series over \code{n} periods. #' #' The ROC indicator provides the percentage difference of a series over two #' observations, while the momentum indicator simply provides the difference. #' #' @aliases changes ROC momentum #' @param x Price, volume, etc. series that is coercible to xts or matrix. #' @param n Number of periods to use. #' @param type Compounding type; either \code{"continuous"} (the default) or #' \code{"discrete"}. #' @param na.pad Should periods prior to \code{n} be appended? Default is #' \code{TRUE}. #' @return A object of the same class as \code{x} or a vector (if \code{try.xts} #' fails) containing the rate-of-change (or return) values for \code{ROC} or a #' vector containing the differenced price series for \code{momentum}. #' @author Joshua Ulrich #' @keywords ts #' @examples #' #' data(ttrc) #' roc <- ROC(ttrc[,"Close"]) #' mom <- momentum(ttrc[,"Close"]) #' @rdname changes "ROC" <- function(x, n=1, type=c("continuous","discrete"), na.pad=TRUE) { # Rate of Change x <- try.xts(x, error=as.matrix) type <- match.arg(type) if(is.xts(x)) { if(type=="discrete") { roc <- x / lag.xts(x,n,na.pad=na.pad) - 1 } # Continuous change if(type=="continuous") { roc <- diff(log(x),n,na.pad=na.pad) } # Convert back to original class reclass(roc, x) } else { NAs <- NULL if(na.pad) { NAs <- rep(NA,n) } # Discrete changes if(type=="discrete") { roc <- c( NAs, x[(n+1):NROW(x)] / x[1:(NROW(x)-n)] - 1 ) } # Continuous changes if(type=="continuous") { roc <- c( NAs, diff(log(x),n) ) } return(roc) } } #-------------------------------------------------------------------------# #' @rdname changes "momentum" <- function(x, n=1, na.pad=TRUE) { # Momentum # http://www.fmlabs.com/reference/Momentum.htm # https://www.metastock.com/Customer/Resources/TAAZ/?p=95 # https://www.linnsoft.com/tour/techind/momentum.htm x <- try.xts(x, error=as.matrix) if(is.xts(x)) { mom <- diff(x,n,na.pad=na.pad) } else { NAs <- NULL if(na.pad) { NAs <- rep(NA,n) } mom <- c( NAs, diff(x, n) ) } reclass(mom,x) } TTR/R/ultimateOscillator.R0000644000176200001440000000421314531142730015127 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' The Ultimate Oscillator #' #' The Ultimate Oscillator is a momentum oscillator designed to capture momentum across three #' different time frames. #' #' Created by Larry Williams in 1976. #' #' @param HLC Object that is coercible to xts or matrix and contains #' High-Low-Close prices. #' @param n A vector of the number of periods to use for each average calculation. #' @param wts The weights applied to each average. #' @author Ivan Popivanov #' @references The following site(s) were used to code/document this #' indicator:\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:ultimate_oscillator}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' ult.osc <- ultimateOscillator(ttrc[,c("High","Low","Close")]) #' ultimateOscillator <- function(HLC, n=c(7,14,28), wts=c(4,2,1)) { # Ultimate Oscillator if(length(n) != 3 || length(wts) != 3) stop("length(n) and length(wts) must both be 3") HLC <- try.xts(HLC, error=as.matrix) # avoid reclassing in ATR and runSum HLC.RECLASS <- attr(HLC, ".RECLASS") attr(HLC, ".RECLASS") <- FALSE # only need 'tr' and 'trueLow' atr <- ATR(HLC, n=1) buyPressure <- HLC[,3] - atr[,'trueLow'] osc <- buyPressure * 0.0 for(i in 1:3) { osc <- osc + wts[i] * (runSum(buyPressure, n[i]) / runSum(atr[,'tr'], n[i])) } osc <- 100.0 * osc / sum(wts) # restore HLC .RECLASS attribute attr(HLC, ".RECLASS") <- HLC.RECLASS reclass(osc, HLC) } TTR/R/TTRtools.R0000644000176200001440000000627314531142730013011 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Miscellaneous Tools #' #' Various functions that may be useful in designing technical trading rules. #' #' \code{growth} calculates the growth of an investment using given prices and #' signals. #' #' \code{lags} calculates the lags of a given series. #' #' @aliases growth lags #' @param price Price series that is coercible to xts or matrix. #' @param signals Signals to use (defaults to vector of ones). Use '0' for no #' position, '1' for long position, and '-1' for short position. #' @param x Object that is coercible to xts or matrix. #' @param n Number of periods to use. #' @param \dots Further arguments to be passed from or to other methods. #' @return \code{growth} returns a vector of the growth of the investment. #' #' \code{lags} returns a matrix of lagged values of the original vector. #' #' @note In \code{growth} you can specify the number of periods and type of #' compounding to use when calculating returns of the price series via the #' \code{'\dots'} argument. #' @author Joshua Ulrich #' @keywords ts #' @rdname TTRtools "lags" <- function(x, n=1) { #.Deprecated(c("xts::lag.xts","quantmod::Lag"),"TTR") # Calculate lags of a series x <- as.matrix(x) if( is.null(colnames(x)) ) colnames(x) <- paste("V",1:NCOL(x),sep="") out <- embed(x, n+1) if(n==1) lag.names <- 1 else if(NCOL(x)==1) lag.names <- 1:n else lag.names <- rep(1:n,NCOL(x)) colnames(out) <- c( colnames(x), paste(colnames(x), sort(lag.names), sep=".") ) return( out ) } #-------------------------------------------------------------------------# #' @rdname TTRtools "growth" <- function(price, signals, ...) { # Calculate growth of $1 for a series of returns (and signals). if(missing(signals)) { signals <- rep(1,NROW(price)) } else { signals <- as.vector(signals) } price <- as.vector(price) growth <- cumprod( 1 + ROC(price, ...) * signals ) return( growth ) } #-------------------------------------------------------------------------# #' @rdname TTRtools 'naCheck' <- function(x, n=0) { # Ensure NAs are only at beginning of data. if(is.null(dim(x)[2])) { NAs <- sum(is.na(x)) if( NAs > 0 ) { if( any( is.na(x[-(1:NAs)]) ) ) stop("Series contains non-leading NAs") } } else { NAs <- sum( rowSums(is.na(x)) > 0 ) if( NAs > 0 ) { if( any( is.na(x[-(1:NAs),]) ) ) stop("Series contains non-leading NAs") } } res <- list() res$NAs <- NAs res$nonNA <- (1+NAs):NROW(x) res$beg <- n+NAs invisible(res) } TTR/R/chaikinVolatility.R0000644000176200001440000000463014531142730014741 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Chaikin Volatility #' #' Chaikin Volatility measures the rate of change of the security's trading #' range. Developed by Marc Chaikin. #' #' The Chaikin Volatility indicator defines volatility as an increase in the #' difference between the high and low. #' #' @param HL Object that is coercible to xts or matrix and contains High-Low #' prices. #' @param n Number of periods for moving average. #' @param maType A function or a string naming the function to be called. #' @param \dots Other arguments to be passed to the \code{maType} function. #' @return A object of the same class as \code{HL} or a vector (if #' \code{try.xts} fails) containing the Chaikin Volatility values. #' @note A rapid increase in Chaikin Volatility indicates an approaching bottom. #' A slow decrease in Chaikin Volatility indicates an approaching top. #' @author Joshua Ulrich #' @seealso See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average #' options; and note Warning section. See \code{\link{TR}} for another #' volatility measure. #' @references The following site(s) were used to code/document this #' indicator:\cr \url{https://www.fmlabs.com/reference/ChaikinVolatility.htm}\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=120}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' volatility <- chaikinVolatility(ttrc[,c("High","Low")]) #' "chaikinVolatility" <- function(HL, n=10, maType, ...) { # Chaikin Volatility HL <- try.xts(HL, error=as.matrix) maArgs <- list(n=n, ...) # Default MA if(missing(maType)) { maType <- 'EMA' } mavg <- do.call( maType, c( list(HL[,1]-HL[,2]), maArgs ) ) volatility <- ROC( mavg, n, type="discrete" ) reclass(volatility, HL) } TTR/R/MovingAverages.R0000644000176200001440000003147114531225347014200 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Moving Averages #' #' Calculate various moving averages (MA) of a series. #' #' \code{SMA} calculates the arithmetic mean of the series over the past #' \code{n} observations. #' #' \code{EMA} calculates an exponentially-weighted mean, giving more weight to #' recent observations. See Warning section below. #' #' \code{WMA} is similar to an EMA, but with linear weighting if the length of #' \code{wts} is equal to \code{n}. If the length of \code{wts} is equal to the #' length of \code{x}, the WMA will use the values of \code{wts} as weights. #' #' \code{DEMA} is calculated as: \code{DEMA = (1 + v) * EMA(x,n) - #' EMA(EMA(x,n),n) * v} (with the corresponding \code{wilder} and \code{ratio} #' arguments). #' #' \code{EVWMA} uses volume to define the period of the MA. #' #' \code{ZLEMA} is similar to an EMA, as it gives more weight to recent #' observations, but attempts to remove lag by subtracting data prior to #' \code{(n-1)/2} periods (default) to minimize the cumulative effect. #' #' \code{VWMA} and \code{VWAP} calculate the volume-weighted moving average #' price. #' #' \code{HMA} a WMA of the difference of two other WMAs, making it very #' reponsive. #' #' \code{ALMA} inspired by Gaussian filters. Tends to put less weight on most #' recent observations, reducing tendency to overshoot. #' #' @aliases MovingAverages SMA EMA WMA DEMA GD T3 EVWMA ZLEMA VWAP VWMA MA #' @param x Price, volume, etc. series that is coercible to xts or matrix. #' @param price Price series that is coercible to xts or matrix. #' @param volume Volume series that is coercible to xts or matrix, that #' corresponds to price series, or a constant. See Notes. #' @param n Number of periods to average over. Must be between 1 and #' \code{nrow(x)}, inclusive. #' @param v The 'volume factor' (a number in [0,1]). See Notes. #' @param wts Vector of weights. Length of \code{wts} vector must equal the #' length of \code{x}, or \code{n} (the default). #' @param wilder logical; if \code{TRUE}, a Welles Wilder type EMA will be #' calculated; see notes. #' @param ratio A smoothing/decay ratio. \code{ratio} overrides \code{wilder} #' in \code{EMA}. #' @param offset Percentile at which the center of the distribution should occur. #' @param sigma Standard deviation of the distribution. #' @param \dots any other passthrough parameters #' @return A object of the same class as \code{x} or \code{price} or a vector #' (if \code{try.xts} fails) containing the columns: #' \describe{ #' \item{SMA}{ Simple moving average. } #' \item{EMA}{ Exponential moving average. } #' \item{WMA}{ Weighted moving average. } #' \item{DEMA}{ Double-exponential moving average. } #' \item{EVWMA}{ Elastic, volume-weighted moving average. } #' \item{ZLEMA}{ Zero lag exponential moving average. } #' \item{VWMA}{ Volume-weighed moving average (same as \code{VWAP}). } #' \item{VWAP}{ Volume-weighed average price (same as \code{VWMA}). } #' \item{VWA}{ Variable-length moving average. } #' \item{HMA}{ Hull moving average. } #' \item{ALMA}{ Arnaud Legoux moving average. } #' } #' @note For \code{EMA}, \code{wilder=FALSE} (the default) uses an exponential #' smoothing ratio of \code{2/(n+1)}, while \code{wilder=TRUE} uses Welles #' Wilder's exponential smoothing ratio of \code{1/n}. The \code{EMA} result #' is initialized with the \code{n}-period sample average at period \code{n}. #' The exponential decay is applied from that point forward. #' #' Since \code{WMA} can accept a weight vector of length equal to the length of #' \code{x} or of length \code{n}, it can be used as a regular weighted moving #' average (in the case \code{wts=1:n}) or as a moving average weighted by #' volume, another indicator, etc. #' #' Since \code{DEMA} allows adjusting \code{v}, it is technically Tim Tillson's #' generalized DEMA (GD). When \code{v=1} (the default), the result is the #' standard DEMA. When \code{v=0}, the result is a regular EMA. All other #' values of \code{v} return the GD result. This function can be used to #' calculate Tillson's T3 indicator (see example below). Thanks to John Gavin #' for suggesting the generalization. #' #' For \code{EVWMA}, if \code{volume} is a series, \code{n} should be chosen so #' the sum of the volume for \code{n} periods approximates the total number of #' outstanding shares for the security being averaged. If \code{volume} is a #' constant, it should represent the total number of outstanding shares for the #' security being averaged. #' @section Warning : Some indicators (e.g. EMA, DEMA, EVWMA, etc.) are #' calculated using the indicators' own previous values, and are therefore #' unstable in the short-term. As the indicator receives more data, its output #' becomes more stable. See example below. #' @author Joshua Ulrich, Ivan Popivanov (HMA, ALMA) #' @seealso See \code{\link{wilderSum}}, which is used in calculating a Welles #' Wilder type MA. #' @references The following site(s) were used to code/document this #' indicator:\cr \url{https://www.fmlabs.com/reference/ExpMA.htm}\cr #' \url{https://www.fmlabs.com/reference/WeightedMA.htm}\cr #' \url{https://www.fmlabs.com/reference/DEMA.htm}\cr #' \url{https://www.fmlabs.com/reference/T3.htm}\cr #' \url{https://www.linnsoft.com/techind/evwma-elastic-volume-weighted-moving-average}\cr #' \url{https://www.fmlabs.com/reference/ZeroLagExpMA.htm}\cr #' \url{https://www.fmlabs.com/reference/VIDYA.htm}\cr #' \url{https://www.traderslog.com/hullmovingaverage}\cr #' \url{https://web.archive.org/web/20180222085959/http://arnaudlegoux.com/}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' ema.20 <- EMA(ttrc[,"Close"], 20) #' sma.20 <- SMA(ttrc[,"Close"], 20) #' dema.20 <- DEMA(ttrc[,"Close"], 20) #' evwma.20 <- EVWMA(ttrc[,"Close"], ttrc[,"Volume"], 20) #' zlema.20 <- ZLEMA(ttrc[,"Close"], 20) #' alma <- ALMA(ttrc[,"Close"]) #' hma <- HMA(ttrc[,"Close"]) #' #' ## Example of Tim Tillson's T3 indicator #' T3 <- function(x, n=10, v=1) DEMA(DEMA(DEMA(x,n,v),n,v),n,v) #' t3 <- T3(ttrc[,"Close"]) #' #' ## Example of short-term instability of EMA #' ## (and other indicators mentioned above) #' x <- rnorm(100) #' tail( EMA(x[90:100],10), 1 ) #' tail( EMA(x[70:100],10), 1 ) #' tail( EMA(x[50:100],10), 1 ) #' tail( EMA(x[30:100],10), 1 ) #' tail( EMA(x[10:100],10), 1 ) #' tail( EMA(x[ 1:100],10), 1 ) #' #' @rdname MovingAverages "SMA" <- function(x, n=10, ...) { # Simple Moving Average ma <- runMean( x, n ) if(!is.null(dim(ma))) { colnames(ma) <- "SMA" } return(ma) } #-------------------------------------------------------------------------# #' @rdname MovingAverages "EMA" <- function (x, n=10, wilder=FALSE, ratio=NULL, ...) { # Exponential Moving Average x <- try.xts(x, error=as.matrix) if( n < 1 || n > NROW(x) ) stop(sprintf("n = %d is outside valid range: [1, %d]", n, NROW(x))) # If ratio is specified, and n is not, set n to approx 'correct' # value backed out from ratio if(missing(n) && !missing(ratio)) n <- NULL # Call C routine ma <- .Call(C_ema, x, n, ratio, isTRUE(wilder)) ma <- reclass(ma,x) if(!is.null(dim(ma))) { colnames(ma) <- "EMA" } return(ma) } #-------------------------------------------------------------------------# #' @rdname MovingAverages "DEMA" <- function(x, n=10, v=1, wilder=FALSE, ratio=NULL) { # Double Exponential Moving Average # Thanks to John Gavin for the v-factor generalization x <- try.xts(x, error=as.matrix) if( n < 1 || n > NROW(x) ) stop(sprintf("n = %d is outside valid range: [1, %d]", n, NROW(x))) if(NCOL(x) > 1) { stop("ncol(x) > 1. DEMA only supports univariate 'x'") } if(v < 0 || v > 1) { stop("Please ensure 0 <= v <= 1") } if(missing(n) && !missing(ratio)) n <- NULL # Call C routine ma1 <- .Call(C_ema, x, n, ratio, isTRUE(wilder)) d <- .Call(C_ema, ma1, n, ratio, isTRUE(wilder)) dema <- (1 + v) * ma1 - d * v dema <- reclass(dema, x) if(!is.null(dim(dema))) { colnames(dema) <- "DEMA" } return(dema) } #-------------------------------------------------------------------------# #' @rdname MovingAverages "WMA" <- function(x, n=10, wts=1:n, ...) { # Weighted Moving Average x <- try.xts(x, error=as.matrix) wts <- try.xts(wts, error=as.matrix) if( !any( NROW(wts) == c( NROW(x), n ) ) ) stop("Length of 'wts' must equal the length of 'x' or 'n'") if( n < 1 || n > NROW(x) ) stop(sprintf("n = %d is outside valid range: [1, %d]", n, NROW(x))) if(NCOL(x) > 1 || NCOL(wts) > 1) { stop("ncol(x) > 1 or ncol(wts) > 1. WMA only supports univariate 'x' and 'w'") } # Count NAs, ensure they're only at beginning of data, then remove. NAx <- sum( is.na(x) ) NAw <- sum( is.na(wts) ) NAs <- max( NAx, NAw ) if( NAs > 0 ) { if( any( is.na( x[-(1:NAx)]) ) ) stop("'x' contains non-leading NAs") if( any( is.na(wts[-(1:NAw)]) ) ) stop("'wts' contains non-leading NAs") } if( NROW(wts) == n ) { NAs <- NAx if( any(is.na(wts)) ) stop("'wts' vector of length 'n' cannot have NA values") # Call C routine ma <- .Call(C_wma, x, wts, n) } else { xw <- cbind(x, wts) ma <- runSum( xw[,1]*xw[,2], n) / runSum(xw[,2], n) } # replace 1:(n-1) with NAs and prepend NAs from original data ma[1:(n-1)] <- NA if(!is.null(dim(ma))) { colnames(ma) <- "WMA" } reclass(ma,x) } #-------------------------------------------------------------------------# #' @rdname MovingAverages "EVWMA" <- function(price, volume, n=10, ...) { # Elastic, Volume-Weighted Moving Average price <- try.xts(price, error=as.matrix) volume <- try.xts(volume, error=as.matrix) if( !any( NROW(volume) == c( NROW(price), 1 ) ) ) stop("Length of 'volume' must equal 1 or the length of 'price'") if( n < 1 || n > NROW(price) ) stop(sprintf("n = %d is outside valid range: [1, %d]", n, NROW(price))) if(NCOL(price) > 1 || NCOL(volume) > 1) { stop("ncol(price) > 1 or ncol(volume) > 1.", " EVWMA only supports univariate 'price' and 'volume'") } pv <- cbind(price, volume) if( any(nNonNA <- n > colSums(!is.na(pv))) ) stop("n > number of non-NA values in ", paste(c("price","volume")[which(nNonNA)], collapse=", ")) # Call C routine ma <- .Call(C_evwma, pv[,1], pv[,2], n) if(!is.null(dim(ma))) { colnames(ma) <- "EVWMA" } # Convert back to original class reclass(ma, price) } #-------------------------------------------------------------------------# #' @rdname MovingAverages "ZLEMA" <- function (x, n=10, ratio=NULL, ...) { # Zero-Lag Exponential Moving Average x <- try.xts(x, error=as.matrix) if(NCOL(x) > 1) { stop("ncol(x) > 1. ZLEMA only supports univariate 'x'") } # If ratio is specified, and n is not, set n to approx 'correct' # value backed out from ratio if(missing(n) && !missing(ratio)) n <- NULL # Call C routine ma <- .Call(C_zlema, x, n, ratio) if(!is.null(dim(ma))) { colnames(ma) <- "ZLEMA" } reclass(ma,x) } #-------------------------------------------------------------------------# #' @rdname MovingAverages "VWAP" <- "VWMA" <- function(price, volume, n=10, ...) { # Volume-weighted average price # Volume-weighted moving average res <- WMA(price, n=n, volume) if(!is.null(dim(res))) { colnames(res) <- "VWAP" } return(res) } #-------------------------------------------------------------------------# #' @rdname MovingAverages "HMA" <- function(x, n=20, ...) { # Hull Moving Average madiff <- 2 * WMA(x, n = trunc(n / 2), ...) - WMA(x, n = n, ...) hma <- WMA(madiff, n = trunc(sqrt(n)), ...) reclass(hma, x) } #-------------------------------------------------------------------------# #' @rdname MovingAverages "ALMA" <- function(x, n=9, offset=0.85, sigma=6, ...) { # ALMA (Arnaud Legoux Moving Average) x <- try.xts(x, error=as.matrix) if(offset < 0 || offset > 1) { stop("Please ensure 0 <= offset <= 1") } if(sigma <= 0) stop("sigma must be > 0") m <- floor(offset*(n-1)) s <- n/sigma wts <- exp(-((seq(0,n-1)-m)^2)/(2*s*s)) sumWeights <- sum(wts) if(sumWeights != 0) wts <- wts/sumWeights alma <- x * NA_real_ for(i in seq_len(NCOL(x))) { alma[,i] <- WMA(x[,i], n, wts) } reclass(alma, x) } TTR/R/aroon.R0000644000176200001440000000701314531142730012366 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Aroon #' #' The Aroon indicator attempts to identify starting trends. The indicator #' consists of up and down lines, which measure how long it has been since the #' highest high/lowest low has occurred in the last \code{n} periods. Developed #' by Tushar Chande in 1995. #' #' Aroon up (down) is the elapsed time, expressed as a percentage, between today #' and the highest (lowest) price in the last \code{n} periods. If today's #' price is a new high (low) Aroon up (down) will be 100. Each subsequent period #' without another new high (low) causes Aroon up (down) to decrease by (1 / #' \code{n}) x 100. #' #' @param HL Object that is coercible to xts or matrix and contains either a #' High-Low price series, or a Close price series. #' @param n Number of periods to use in the calculation. #' @return A object of the same class as \code{HL} or a matrix (if #' \code{try.xts} fails) containing the columns: #' \describe{ #' \item{ aroonUp }{ The Aroon up indicator. } #' \item{ aroonDn }{ The Aroon down indicator. } #' \item{ oscillator }{ The Aroon oscillator (\code{aroonUp - aroonDn}). } #' } #' @note If High-Low prices are given, the function calculates the max/min using #' the high/low prices. Otherwise the function calculates the max/min of the #' single series. #' #' Up (down) trends are indicated when the aroonUp(Dn) is between 70 and 100. #' Strong trends are indicated when when the aroonUp(Dn) is above 70 while the #' aroonDn(Up) is below 30. Also, crossovers may be useful. #' @author Joshua Ulrich #' @seealso See \code{\link{CCI}}, \code{\link{ADX}}, \code{\link{TDI}}, #' \code{\link{VHF}}, \code{\link{GMMA}} for other indicators that measure trend #' direction/strength. #' @references The following site(s) were used to code/document this #' indicator:\cr \url{https://www.fmlabs.com/reference/Aroon.htm}\cr #' \url{https://www.fmlabs.com/reference/AroonOscillator.htm}\cr #' \url{https://www.linnsoft.com/techind/aroon-arn}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:aroon}\cr #' @keywords ts #' @examples #' #' ## Get Data and Indicator ## #' data(ttrc) #' trend <- aroon( ttrc[,c("High", "Low")], n=20 ) #' "aroon" <- function(HL, n=20) { # Aroon up, down, and oscillator. HL <- try.xts(HL, error=as.matrix) # Calculation if price vector is given if(NCOL(HL)==1) { high <- HL low <- HL } else # Calculation if HL series is given if(NCOL(HL)==2) { high <- HL[,1] low <- HL[,2] } else stop("Price series must be either High-Low, or Close") # Calculate Aroon UP and DOWN aroonUp <- .Call(C_aroon_max, high, n) aroonDn <- .Call(C_aroon_max, -low, n) oscillator <- aroonUp - aroonDn result <- cbind( aroonUp, aroonDn, oscillator ) colnames(result) <- c( "aroonUp", "aroonDn", "oscillator" ) reclass( result, HL ) } TTR/R/SNR.R0000644000176200001440000000402614531142730011713 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2016 Peter Carl, Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Signal to Noise Ratio #' #' The n-day SNR for a given market is calculated by taking the absolute #' price change over an n-day period and dividing it by the average #' n-day volatility. #' #' \deqn{SNR_n = \frac{|C_t - C_{t-n}|}{ATR_n} #' }{SNR = abs(Cl - lag(Cl,n)) / ATR(HLC, n)$atr} #' #' Using average true range as the volatility measure captures more of the #' intraday and overnight volatility in a way that a measurement of #' Close-to-Close price change does not. #' #' The interpretation is then relatively intuitive: an SNR value of five #' indicates that the market has moved five times the volatility (average true #' range) over the given look-back period. #' #' @param HLC Object that is coercible to xts or matrix and contains #' High-Low-Close prices. #' @param n Number of periods for moving average. #' @param ... Other arguments to be passed to \code{\link{ATR}}. #' @return A object of the same class as HLC or a matrix (if try.xts fails) #' containing the signal to noise ratio. #' @author Peter Carl #' @references Skeggs, James and Hill, Alex (2015). Back in Black Part 2: The #' Opportunity Set for Trend Following. #' SNR <- function(HLC, n, ...) { HLC <- try.xts(HLC, error=as.matrix) snr <- abs(HLC[,3] - lag.xts(HLC[,3], n)) / ATR(HLC, n, ...)[,"atr"] return(reclass(snr, HLC)) } TTR/R/percentRank.R0000644000176200001440000000732414531142730013531 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Percent Rank over a Moving Window #' #' This function computes a running/rolling percentage rank. #' #' The computation for a percentage rank can vary depending on the weight given #' to values in the window that are equal to the value being ranked. This weight #' can be set using the \code{exact.multiplier} argument which defaults to 0.5. #' #' \code{exact.multiplier = 0} scores equal values in the lookback window as #' always being greater than the value being ranked. \code{exact.multiplier = 1} #' scores equal values as being below the value being ranked. Any multiplier #' between 0 and 1 counts that proportion of the equal values as being below #' the value being ranked. #' #' The value of \code{exact.multiplier} has the most impact when the window is #' relatively small or when the number of discrete values in the window is #' small. For non-repeating values, changing \code{exact.multiplier = 0} to #' \code{exact.multiplier = 1} for a window of size \code{N} will shift the #' resulting percentile rankings by \code{1/N}. It is equivalent to changing #' the question from, "how many values are < the value" to "how many values #' are <= the value". #' #' @aliases runPercentRank percentRank PercentRank #' @param x Object coercible to xts or matrix. #' @param n Number of periods to use in the window or, if #' \code{cumulative=TRUE}, the number of observations to use before the first #' result is returned. Must be between 1 and \code{nrow(x)}, inclusive. #' @param cumulative Logical, use from-inception calculation? #' @param exact.multiplier The weight applied to identical values in the window. #' Must be between 0 and 1, inclusive. See details. #' #' @return A object of percent ranks over a n-period moving window of the same #' class as \code{x} and \code{y} or a vector (if \code{try.xts} fails). #' #' @note This computation is different from the one used in Microsoft Excel's #' \code{PERCENTRANK} formula. Excel's computation is rather strange and gives #' inconsistent results as it uses interpolation to rank values that are not #' found within the lookback window. #' #' @author Charlie Friedemann #' #' @references The following site(s) were used to code/document this #' indicator:\cr \url{https://en.wikipedia.org/wiki/Percentile_rank}\cr #' #' @keywords ts runPercentRank <- function(x, n=260, cumulative = FALSE, exact.multiplier = 0.5) { x <- try.xts(x, error = as.matrix) if (n < 1 || n > NROW(x)) stop(sprintf("n = %d is outside valid range: [1, %d]", n, NROW(x))) if (exact.multiplier < 0 || exact.multiplier > 1) stop(sprintf("exact.multiplier = %d is outside valid range: [0, 1]", exact.multiplier)) NAs <- sum(is.na(x)) if (NAs > 0) { if (any(is.na(x[-(1:NAs)]))) stop("Series contains non-leading NAs") } if (!isTRUE(cumulative) && identical(as.integer(n), 1L)) { result <- double(NROW(x)) result[] <- exact.multiplier } else { result <- .Call(C_ttr_rollPercentRank, x, n, isTRUE(cumulative), exact.multiplier) } reclass(result, x) } TTR/R/DVI.R0000644000176200001440000000634114531142730011675 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' DV Intermediate Oscillator #' #' The DV Intermediate oscillator (DVI) is a very smooth momentum oscillator #' that can also be used as a trend indicator. Created by David Varadi. #' #' The DVI combines smoothed returns over different time windows and the #' relative number of up versus down days (stretch) over different time windows. #' #' @param price Price series that is coercible to xts or matrix. #' @param n Number of periods for the percent rank. #' @param wts The weight given to the smoothed returns (magnitude) component and #' the up/down days (stretch) component, respectively. #' @param smooth The number of periods to smooth price. #' @param magnitude A set of 3 periods used to smooth magnitude. #' @param stretch A set of 3 periods used to smooth stretch. #' @param exact.multiplier The weight applied to identical values in the window. #' See \code{runPercentRank}. #' @return A object of the same class as \code{price} or a vector (if #' \code{try.xts} fails) containing the DVI values. #' @author Joshua Ulrich #' @references The following site(s) were used to code/document this #' indicator:\cr #' \url{https://cssanalytics.wordpress.com/2009/12/13/what-is-the-dvi/}\cr #' \url{https://marketsci.wordpress.com/2010/07/27/css-analytics\%E2\%80\%99-dvi-indicator-revealed/}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' dvi <- DVI(ttrc[,"Close"]) #' DVI <- function(price, n=252, wts=c(0.8,0.2), smooth=3, magnitude=c(5,100,5), stretch=c(10,100,2), exact.multiplier=1) { # David Varadi's DVI indicator # try to convert 'price' to xts price <- try.xts(price, error=as.matrix) # ensure magnitude + stretch = 1 wts.sum <- sum(wts) wts[1] <- wts[1] / wts.sum wts[2] <- wts[2] / wts.sum # calculate magnitude, based on average price return r <- price/SMA(price,smooth)-1 mag <- SMA( ( SMA(r,magnitude[1]) + SMA(r,magnitude[2])/10 )/2, magnitude[3] ) # calculate stretch, based on whether return is +/- b <- ifelse( price > lag.xts(price), 1, -1 ) str <- SMA( ( runSum(b,stretch[1]) + runSum(b,stretch[2])/10 )/2, stretch[3] ) # calculate the DVI magnitude and stretch for each period dvi.mag <- runPercentRank(mag, n, FALSE, exact.multiplier) dvi.str <- runPercentRank(str, n, FALSE, exact.multiplier) # calculate final DVI value dvi <- wts[1] * dvi.mag + wts[2] * dvi.str result <- cbind(dvi.mag, dvi.str, dvi) colnames(result) <- c("dvi.mag", "dvi.str", "dvi") # convert final DVI, magnitude, and stretch back to # original class of 'price' reclass(result, price) } TTR/R/priceBands.R0000644000176200001440000000766614531142730013340 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Construct (optionally further smoothed and centered ) volatility bands around #' prices #' #' John Bollinger's famous adaptive volatility bands most often use the typical #' price of an HLC series, or may be calculated on a univariate price series #' (see \code{\link{BBands}}). #' #' This function applies a second moving average denoted by \code{fastn} to #' filter out higher-frequency noise, making the bands somewhat more stable to #' temporary fluctuations and spikes. #' #' If \code{centered} is \code{TRUE}, the function also further smoothes and #' centers the bands around a centerline adjusted to remove this higher #' frequency noise. If \code{lavg} is also \code{TRUE}, the smoothing applied #' for the middle band (but not the volatility bands) is doubled to further #' smooth the price-response function. #' #' If you have multiple different price series in \code{prices}, and want to use #' this function, call this functions using \code{lapply(prices,PBands,...)}. #' #' @aliases PBands priceBands #' @param prices A univariate series of prices. #' @param n Number of periods to average over. #' @param maType A function or a string naming the function to be called. #' @param sd The number of standard deviations to use. #' @param \dots any other pass-thru parameters, usually for function named by #' \code{maType}. #' @param fastn Number of periods to use for smoothing higher-frequency 'noise'. #' @param centered Whether to center the bands around a series adjusted for high #' frequency noise, default \code{FALSE}. #' @param lavg Whether to use a longer \code{(n*2)} smoothing period for #' centering, default \code{FALSE}. #' @return A object of the same class as \code{prices} or a matrix (if #' \code{try.xts} fails) containing the columns: #' \describe{ #' \item{ dn }{ The lower price volatility Band. } #' \item{ center }{ The smoothed centerline (see details). } #' \item{ up }{ The upper price volatility Band. } #' } #' @author Brian G. Peterson #' @seealso \code{\link{BBands}} #' @keywords ts #' @examples #' #' data(ttrc) #' pbands.close <- PBands( ttrc[,"Close"] ) #' #' @rdname priceBands PBands <- function(prices, n=20, maType="SMA", sd=2, ..., fastn=2, centered=FALSE, lavg=FALSE ) { # Price Bands, implemented by Brian G. Peterson # inspired by the univariate Bollinger Bands, and Ram Ben-David if(!is.vector(prices) && ncol(prices)>1) stop('prices should be a univariate series, maybe use', 'lapply(prices,PBands) instead?') prices <- try.xts(prices, error=as.matrix) # Default MA if(missing(maType)) { maType <- 'SMA' } maArgs <- list(n=n, ...) mavg <- do.call( maType, c( list(prices), maArgs ) ) maFastArgs <-list(n=fastn,...) fastmavg <- do.call( maType, c( list(prices), maFastArgs ) ) sdev <- runSD((mavg-fastmavg),n=n,sample=FALSE) if(!isTRUE(centered)){ center <- mavg } else { centerrun <- (mavg-fastmavg)/sdev if(isTRUE(lavg)){ maArgs <- list(n=(n*2), ...) } center <- mavg + ( do.call(maType, c( list(centerrun), maArgs ) ) ) } up <- center + sd * sdev dn <- center - sd * sdev res <- cbind(dn, center, up) colnames(res) <- c("dn", "center", "up") reclass(res, prices) } TTR/R/adjRatios.R0000644000176200001440000000555214531142730013176 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Split and dividend adjustment ratios #' #' Create split and dividend adjustment ratio vectors. #' #' @aliases adjRatios adjust #' @param splits Split series that is coercible to xts. #' @param dividends Dividend series that is coercible to xts. #' @param close Close price series that is coercible to xts. #' @return A xts object containing the columns: #' \describe{ #' \item{ Split }{ The split adjustment ratio. } #' \item{ Div }{ The dividend adjustment ratio. } #' } #' @details #' \itemize{ #' \item If only \code{splits} is provided, the resulting object will #' only have as many observations as \code{splits}. #' \item If \code{splits} and \code{close} are provided, the resulting #' object will have as many observations as \code{max(NROW(splits), #' NROW(close))}. #' \item \code{close} is required if \code{dividends} is provided. #' } #' #' @author Joshua Ulrich #' @keywords ts 'adjRatios' <- function(splits, dividends, close) { if( !missing(dividends) && missing(close) ) stop('"close" must be specified to adjust dividends') # Really need a better error message if as.xts fails... seriously if(missing(close) || all(is.na(close)) || NROW(close)==0) { close <- NA } else { if(NCOL(close)!=1) stop('"close" must be univariate') close <- try.xts(close, error=stop('"as.xts(close)" failed')) } if(missing(splits) || all(is.na(splits)) || NROW(splits)==0) { splits <- NA } else { if(NCOL(splits)!=1) stop('"splits" must be univariate') splits <- try.xts(splits, error=stop('"as.xts(splits)" failed')) } if(missing(dividends) || all(is.na(dividends)) || NROW(dividends)==0) { dividends <- NA } else { if(NCOL(dividends)!=1) stop('"dividends" must be univariate') dividends <- try.xts(dividends, error=stop('"as.xts(dividends)" failed')) } obj <- merge.xts(close,splits,dividends) if(!isTRUE(is.na(close))) { obj <- obj[!is.na(obj[,1]),] # drop rows missing close prices } adj <- .Call(C_adjRatios, obj[,2], obj[,3], obj[,1]) adj <- xts(cbind(adj[[1]],adj[[2]]),index(obj)) colnames(adj) <- c('Split','Div') return(adj) } TTR/R/ZigZag.R0000644000176200001440000000710614531142730012446 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Zig Zag #' #' Zig Zag higlights trends by removing price changes smaller than \code{change} #' and interpolating lines between the extreme points. #' #' The Zig Zag is non-predictive. The purpose of the Zig Zag is filter noise #' and make chart patterns clearer. It's more a visual tool than an indicator. #' #' @aliases ZigZag zigzag #' @param HL Object that is coercible to xts or matrix and contains either a #' High-Low price series, or a Close price series. #' @param change Minimum price movement, either in dollars or percent (see #' \code{percent}). #' @param percent Use percentage or dollar change? #' @param retrace Is \code{change} a retracement of the previous move, or an #' absolute change from peak to trough? #' @param lastExtreme If the extreme price is the same over multiple periods, #' should the extreme price be the first or last observation? #' @return A object of the same class as \code{HL} or a vector (if #' \code{try.xts} fails) containing the Zig Zag indicator. #' @note If High-Low prices are given, the function calculates the max/min using #' the high/low prices. Otherwise the function calculates the max/min of the #' single series. #' @section Warning: The last value of the ZigZag indicator is unstable (i.e. #' unknown) until the turning point actually occurs. Therefore this indicator #' isn't well-suited for use for systematic trading strategies. #' @author Joshua Ulrich #' @references The following site(s) were used to code/document this #' indicator:\cr #' \url{https://www.fmlabs.com/reference/default.htm?url=ZigZag.htm}\cr #' \url{https://www.linnsoft.com/techind/zig-zag-indicator-zig-zzo}\cr #' \url{https://www.linnsoft.com/techind/zig-zag-oscillator-indicator-zzo}\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=127}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:zigzag}\cr #' @keywords ts #' @examples #' #' ## Get Data and Indicator ## #' data(ttrc) #' zz <- ZigZag( ttrc[,c("High", "Low")], change=20 ) #' "ZigZag" <- function( HL, change=10, percent=TRUE, retrace=FALSE, lastExtreme=TRUE ) { # Zig Zag Indicator # Adapted from Alberto Santini's code HL <- try.xts(HL, error=as.matrix) HL.na <- naCheck(HL,0) # Calculation if HL series is given if(NCOL(HL)==2) { high <- HL[HL.na$nonNA,1] low <- HL[HL.na$nonNA,2] } else # Calculation if price vector is given if(NCOL(HL.na)==1) { high <- HL[HL.na$nonNA] low <- HL[HL.na$nonNA] } else stop("Price series must be either High-Low, or Univariate") # Call C routine zz <- .Call(C_ttr_zigzag, as.numeric(high), as.numeric(low), as.numeric(change), as.logical(percent), as.logical(retrace), as.logical(lastExtreme)) # Interpolate results zz <- na.approx(zz, na.rm = FALSE) # Prepend NAs from original data zz <- c( rep( NA, HL.na$NAs ), zz ) reclass( zz, HL ) } TTR/R/williamsAD.R0000644000176200001440000000433014531142730013275 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Williams Accumulation / Distribution #' #' The Williams Accumulation / Distribution (AD) line is a measure of market #' momentum. Developed by Larry Williams. #' #' The Williams AD line differs from OBV and chaikinAD in that it doesn't take #' volume into account. #' #' @param HLC Object that is coercible to xts or matrix and contains #' High-Low-Close prices. #' @return A object of the same class as \code{HLC} or a vector (if #' \code{try.xts} fails) containing the accumulation / distribution values. #' @note The Accumulation/Distribution Line is interpreted by looking for a #' divergence in the direction of the indicator relative to price. #' @author Joshua Ulrich #' @seealso See \code{\link{OBV}}, \code{\link{chaikinAD}}, and #' \code{\link{ATR}}. #' @references The following site(s) were used to code/document this #' indicator:\cr #' \url{https://www.fmlabs.com/reference/WilliamsAD.htm}\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=125}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' ad <- williamsAD(ttrc[,c("High","Low","Close")]) #' "williamsAD" <- function(HLC) { # Williams Accumulation/Distribution HLC <- try.xts(HLC, error=as.matrix) # Calculate change in close, and true high/low dCl <- momentum(HLC[,3], 1) atr <- ATR(HLC) # Calculate AD ad <- HLC[,3] - ifelse( dCl > 0, atr[,"trueLow"], atr[,"trueHigh"] ) ad[ dCl == 0 ] <- 0 ad.na <- naCheck(ad) ad <- cumsum( ad[ad.na$nonNA] ) ad <- c( rep( NA, ad.na$NAs ), ad ) reclass(ad, HLC) } TTR/R/CMO.R0000644000176200001440000000432214531142730011666 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Chande Momentum Oscillator #' #' The Chande Momentum Oscillator (CMO) is a modified RSI. Developed by Tushar #' S. Chande. #' #' The CMO divides the total movement by the net movement ([up - down] / [up + #' down]), where RSI divides the upward movement by the net movement (up / [up + #' down]). #' #' @param x Price, volume, etc. series that is coercible to xts or matrix. #' @param n Number of periods to use. #' @return A object of the same class as \code{x} or a vector (if \code{try.xts} #' fails) containing Chande Momentum Oscillator values. #' @note There are several ways to interpret the CMO: #' \enumerate{ #' \item Values over/under +/- 50 indicate overbought/oversold conditions. #' \item High CMO values indicate strong trends. #' \item When the CMO crosses above/below a moving average of the CMO, #' it is a buy/sell signal. #' } #' @author Joshua Ulrich #' @seealso See \code{\link{RSI}}. #' @references The following site(s) were used to code/document this #' indicator:\cr \url{https://www.fmlabs.com/reference/CMO.htm}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' cmo <- CMO(ttrc[,"Close"]) #' "CMO" <- function(x, n=14) { # Chande Momentum Oscillator x <- try.xts(x, error=as.matrix) up <- momentum(x, n=1) dn <- ifelse(up<0, abs(up), 0) up <- ifelse(up>0, up , 0) up <- runSum(up, n) dn <- runSum(dn, n) cmo <- 100 * (up-dn)/(up+dn) if (!is.null(dim(cmo)) && ncol(cmo) == 1L) { colnames(cmo) <- "cmo" } reclass( cmo, x ) } TTR/R/rollFun.R0000644000176200001440000000413514531142730012673 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Analysis of Running/Rolling/Moving Windows #' #' Various functions to analyze data over a moving window of periods. #' #' #' @aliases rollFun rollSFM #' @param Ra Object coercible to xts or matrix, containing the excess #' return for an individual security #' @param Rb Object coercible to xts or matrix, containing the market #' / benchmark return #' @param n Number of periods to use in the window #' #' @return A object of the same class as \code{Ra} (and \code{Rb}?) or a vector #' (if \code{try.xts} fails). #' \describe{ #' \item{rollSFM}{returns single-factor model parameters and R-squared #' over a n-period moving window.} #' } #' #' @author Joshua Ulrich #' @references The following site(s) were used to code/document this #' indicator: #' \url{https://en.wikipedia.org/wiki/Simple_linear_regression}\cr #' @keywords ts #' @rdname rollFun rollSFM <- function(Ra, Rb, n = 60) { # Calculate a rolling single-factor model # stopifnot(is.xts(Ra) && is.xts(Rb)) # calculate beta beta <- runCov(Ra, Rb, n) / runVar(Rb, n=n) # calculate alpha alpha <- runMean(Ra, n) - beta * runMean(Rb, n) # calculate R-squared se.resid <- 1/(n*(n-2)) * (n*runSum(Ra^2,n)-runSum(Ra,n)^2 - beta^2 * (n*runSum(Rb^2,n)-runSum(Rb,n)^2)) se.Ra <- runVar(Ra, n=n) * (n-1)/(n-2) r.squared <- 1 - se.resid / se.Ra result <- merge(alpha, beta, r.squared) return(result) } TTR/R/VHF.R0000644000176200001440000000535614531142730011703 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Vertical Horizontal Filter #' #' The Vertical Horizontal Filter (VHF) attempts to identify starting and ending #' trends. Developed by Adam White. #' #' The VHF is calculated by subtracting the \code{n}-period lowest low from the #' \code{n}-period highest high and dividing that result by the \code{n}-period #' rolling sum of the close price changes. #' #' @param price Object that is coercible to xts or matrix and contains a Close #' price series, or a High-Low-Close price series. #' @param n Number of periods to use. #' @return A object of the same class as \code{price} or a vector (if #' \code{try.xts} fails) containing the VHF values. #' @note If Close prices are given, the function calculates the max/min using #' only those prices (the default). If HLC prices are given, the function #' calculates the max/min using the high/low prices (added for flexibility). #' @author Joshua Ulrich #' @seealso See \code{\link{aroon}}, \code{\link{CCI}}, \code{\link{ADX}}, #' \code{\link{TDI}}, \code{\link{GMMA}} for other indicators that measure trend #' direction/strength. #' @references The following site(s) were used to code/document this #' indicator:\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=119}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' vhf.close <- VHF(ttrc[,"Close"]) #' vhf.hilow <- VHF(ttrc[,c("High","Low","Close")]) #' "VHF" <- function(price, n=28) { # Vertical Horizontal Filter price <- try.xts(price, error=as.matrix) # Calculation if price series is given if(NCOL(price)==1) { high <- price low <- price close <- price } else # Calculation if HLC series is given if(NCOL(price)==3) { high <- price[,1] low <- price[,2] close <- price[,3] } else stop("Price series must be either Close, or High-Low-Close") # Find highest max, and lowest min of price series hmax <- runMax( high, n) lmin <- runMin( low, n) denom <- abs( momentum(close, n=1, na.pad=TRUE) ) VHF <- ( hmax - lmin ) / runSum(denom, n) reclass(VHF, price) } TTR/R/chaikinAD.R0000644000176200001440000000523014531142730013062 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Chaikin Accumulation / Distribution #' #' The Chaikin Accumulation / Distribution (AD) line is a measure of the money #' flowing into or out of a security. It is similar to On Balance Volume (OBV). #' Developed by Marc Chaikin. #' #' The AD line is similar to OBV; the difference is that OBV sums volume #' multiplied by +/- 1 if the close is higher/lower than the previous close, #' while the AD line multiplies volume by the close location value (CLV). #' #' @param HLC Object that is coercible to xts or matrix and contains #' High-Low-Close prices. #' @param volume Vector or matrix of volume observations corresponding to the #' \code{HLC} object. #' @return A object of the same class as \code{HLC} and \code{volume} or a #' vector (if \code{try.xts} fails) containing the accumulation / distribution #' values. #' @note The Accumulation/Distribution Line is interpreted by looking for a #' divergence in the direction of the indicator relative to price. #' @author Joshua Ulrich #' @seealso See \code{\link{OBV}}, and \code{\link{CLV}}. #' @references The following site(s) were used to code/document this #' indicator:\cr \url{https://www.fmlabs.com/reference/AccumDist.htm}\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=27}\cr #' \url{https://www.linnsoft.com/techind/accumulation-distribution}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:accumulation_distribution_line}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' ad <- chaikinAD(ttrc[,c("High","Low","Close")], ttrc[,"Volume"]) #' "chaikinAD" <- function(HLC, volume) { # Chaikin Accumulation / Distribution HLC <- try.xts(HLC, error=as.matrix) volume <- try.xts(volume, error=as.matrix) if(!(is.xts(HLC) && is.xts(volume))) { HLC <- as.matrix(HLC) volume <- as.matrix(volume) } ad <- CLV(HLC) * volume ad.na <- naCheck(ad) ad <- cumsum( ad[ad.na$nonNA] ) ad <- c( rep( NA, ad.na$NAs ), ad ) reclass(ad, HLC) } TTR/R/WebData.R0000644000176200001440000004321114531142730012557 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Fetch Internet Data #' #' Get investment data from the internet. #' #' \code{getYahooData} fetches individual stock data from the Yahoo! Finance #' website. It also adjusts price for splits and dividends, and volume for #' splits. See the Warning section, and note that it is deprecated in favor #' of getSymbols in the quantmod package. #' #' \code{stockSymbols} fetches instrument symbols from the nasdaq.com website, #' and adjusts the symbols to be compatible with the Yahoo! Finance website. #' #' @aliases WebData getYahooData stockSymbols #' @param symbol Yahoo! Finance instrument symbol. #' @param start Numeric; first date of desired data, in YYYYMMDD format. #' Default is first date of series. #' @param end Numeric; last date of desired data, in YYYYMMDD format. Default #' is last date of series. #' @param freq Desired data frequency. One of \code{"daily"}, \code{"weekly"}, #' \code{"monthly"}. #' @param type Type of data to return. One of \code{"price"}, or #' \code{"split"}. \code{type="split"} will return both split and dividend #' data. #' @param adjust Logical; if \code{TRUE}, the Open, High, Low, and Close prices #' will be adjusted for dividends and splits, and Volume will be adjusted for #' dividends. #' @param quiet Logical; if \code{TRUE}, status messages will be printed to the #' console. #' @param exchange Character vector of exchange names on which desired #' instrument symbols are traded. #' @param sort.by Character vector of columns by which returned data will be #' sorted. Must be one or more of \code{"Name"}, \code{"Symbol"}, #' \code{"Market.Cap"}, or \code{"Exchange"}. #' @return \code{getYahooData} returns an xts object containing the columns: #' #' \code{stockSymbols} returns a character vector containing all the listed #' symbols for the given exchanges. #' \describe{ #' \item{ Date }{ Trade date, in CCYYMMDD format. } #' \item{ Open }{ Open price. } #' \item{ High }{ High price. } #' \item{ Low }{ Low price. } #' \item{ Close }{ Close price. } #' \item{ Volume }{ Volume. } #' } #' @note The symbols returned by \code{stockSymbols} may not be in the format #' necessary to retrieve data using \code{getYahooData}. #' #' \code{getYahooData} has only been tested on daily data. It isn't known if #' the function correctly adjusts data for any other frequency. #' @author Joshua Ulrich #' @keywords ts #' @examples #' #' ### Note: you must have a working internet #' ### connection for these examples to work! #' if (interactive()) { #' ge <- getYahooData("GE", 19990404, 20050607, adjust = FALSE) #' #' nyse.symbols <- stockSymbols("NYSE") #' } #' #' @section Warning: #' As of TTR 0.23-2, \code{getYahooData} has been patched to work with changes #' to Yahoo Finance, which also included the following changes to the raw data: #' \itemize{ #' \item The adjusted close column appears to no longer include dividend adjustments #' \item The open, high, and low columns are adjusted for splits, and #' \item The raw data may contain missing values. #' \item The raw data may contain errors. #' } #' #' As of TTR 0.24.2, \code{stockSymbols} began using data from NASDAQ's FTP #' site because the data from the original site is no longer available. This #' new file does not contain data for the columns: LastSale, MarketCap, #' IPOyear, Sector, and Industry. All the columns still appear in the results,#' but all the values in the columns are set to \code{NA}. #' #' @references #' #' \itemize{ #' \item \href{https://quant.stackexchange.com/questions/1640/where-to-download-list-of-all-common-stocks-traded-on-nyse-nasdaq-and-amex/1862}{Quant StackExchange: Download list of all stock symbols?} #' \item \href{https://www.nasdaqtrader.com/trader.aspx?id=CQSsymbolconvention}{CQS symbol convention} #' \item \href{https://web.archive.org/web/20111023221931/http://help.yahoo.com/l/us/yahoo/finance/quotes/quote-02.html}{Yahoo Finance symbol conventions} #' } #' #' @rdname WebData "stockSymbols" <- function(exchange = c("AMEX", "NASDAQ", "NYSE", "ARCA", "BATS", "IEX"), sort.by = c("Exchange", "Symbol"), quiet = FALSE) { # Many thanks to Ion Georgiadis for helpful suggestions and testing. # See "NYSE "behind the dot" or Nasdaq 5th-letter codes and other special # codes" here: # http://en.wikipedia.org/wiki/Ticker_symbol # # AMEX / NYSE Mappings (NASDAQ doesn't need transformation?): # Exchanges -> Yahoo # /WS -> -WT # /U -> -U # .[A-Z] -> NA (special notes/bonds - IG) # :[AP] -> NA (after-hours / pre-market) # ^ -> -P # / -> - # $ -> NA (NYSE Only) # ~ -> NA (NYSE Only) symbols.colnames <- c("Symbol","Name","LastSale","MarketCap","IPOyear","Sector","Industry", "Exchange", "Test.Issue", "Round.Lot.Size", "ETF", "Market.Category", "Financial.Status", "Next.Shares", "ACT.Symbol", "CQS.Symbol") exchange <- match.arg(exchange, several.ok=TRUE) sort.by <- match.arg(sort.by, symbols.colnames, several.ok=TRUE) ### nasdaqlisted.txt ##nasdaq.colnames <- ## c("Symbol", ## "Security.Name", ## "Market.Category", ## "Test.Issue", ## "Financial.Status", ## "Round.Lot.Size", ## "ETF", ## "NextShares") .market.category <- c(Q = "NASDAQ Global Select MarketSM", G = "NASDAQ Global MarketSM", S = "NASDAQ Capital Market") ### otherlisted.txt ##other.colnames <- ## c("ACT.Symbol", ## "Security.Name", ## "Exchange", ## "CQS.Symbol", ## "ETF", ## "Round.Lot.Size", ## "Test.Issue", ## "NASDAQ.Symbol") .exchange <- c(A = "AMEX", N = "NYSE", P = "ARCA", Z = "BATS", V = "IEX") .financial.status <- c(D = "Deficient", E = "Delinquent", Q = "Bankrupt", N = "Normal (Default)", G = "Deficient and Bankrupt", H = "Deficient and Delinquent", J = "Delinquent and Bankrupt", K = "Deficient, Delinquent, and Bankrupt") tmp <- tempfile() base.url <- "ftp://ftp.nasdaqtrader.com/SymbolDirectory/" nasdaq.url <- paste0(base.url, "nasdaqlisted.txt") other.url <- paste0(base.url, "otherlisted.txt") nasdaq <- NULL if ("NASDAQ" %in% exchange) { if (!quiet) { message("Fetching NASDAQ symbols...") flush.console() } curl::curl_download(nasdaq.url, destfile = tmp) nasdaq <- read.table(tmp, header = TRUE, sep = "|", quote = "", fill = TRUE, na.strings = NULL) # add symbols columns not in file nasdaq$Name <- nasdaq$Security.Name nasdaq$Exchange <- "NASDAQ" nasdaq[, setdiff(symbols.colnames, colnames(nasdaq))] <- NA # order columns nasdaq <- nasdaq[, symbols.colnames] # convert market category code to name nasdaq$Market.Category <- .market.category[nasdaq$Market.Category] # convert financial status code to name nasdaq$Financial.Status <- .financial.status[nasdaq$Financial.Status] } other <- NULL if (length(exchange) > 1L) { if (!quiet) { message("Fetching non-NASDAQ symbols...") flush.console() } curl::curl_download(other.url, destfile = tmp) other <- read.table(tmp, header = TRUE, sep = "|", quote = "", fill = TRUE, na.strings = NULL) # remove last row (File creation time) other <- other[-nrow(other),] # add symbols columns not in file other$Name <- other$Security.Name other$Symbol <- other$NASDAQ.Symbol other[, setdiff(symbols.colnames, colnames(other))] <- NA # convert exchange code to name other$Exchange <- .exchange[other$Exchange] # order columns other <- other[, symbols.colnames] } # Append data from all exchanges symbols <- rbind(nasdaq, other) # Convert symbol from NASDAQ to Yahoo format # symbols[grep("[-.*$+!@%^=#].?$", symbols$NASDAQ.Symbol),c("Symbol", "NASDAQ.Symbol")] symbols$NASDAQ.Symbol <- symbols$Symbol # preferreds symbols$Symbol <- sub("-(.?)$", "-P\\1", symbols$Symbol) # classes symbols$Symbol <- sub("\\.(.?)$", "-\\1", symbols$Symbol) # warrants symbols$Symbol <- sub("\\+(.?)$", "-WT\\1", symbols$Symbol) # units symbols$Symbol <- sub("\\=$", "-UN", symbols$Symbol) # rights symbols$Symbol <- sub("\\^$", "-R", symbols$Symbol) # convert ETF and Test.Issue to logical symbols$ETF <- ("Y" == symbols$ETF) symbols$Test.Issue <- ("Y" == symbols$Test.Issue) # Sort symbols <- symbols[do.call("order", symbols[,sort.by]),] # Pretty rownames rownames(symbols) <- NULL return(symbols) } #-------------------------------------------------------------------------# #' @rdname WebData "getYahooData" <- function(symbol, start, end, freq="daily", type="price", adjust=TRUE, quiet=FALSE) { warn.Deprecated <- function() { .Deprecated("quantmod::getSymbols", package = "TTR", paste("TTR::getYahooData is deprecated and will be removed in a", "future release.\nPlease use quantmod::getSymbols instead."), old = "getYahooData") } callingFun <- sys.call(-1L)[[1]] if(is.null(callingFun)) { # Called from top level warn.Deprecated() } else { if(is.call(callingFun) && any(deparse(callingFun[[1]]) == c("::", ":::"))) { if("getYahooData" != as.character(callingFun[[3]])) warn.Deprecated() } else { if("getYahooData" != deparse(callingFun)) warn.Deprecated() } } # Thank you to Giorgio Beltrame for the URL to download dividends _and_ # splits, and for his correct adjustment procedure. # Many thanks to Ion Georgiadis for helpful suggestions and testing. # symbol: Character, instrument symbol # start: Numeric, starting date, in ISO-8601 format as ccyymmdd (default # is series' first date) # end: Numeric, ending date, in ISO-8601 format as ccyymmdd (default is today) # freq: Character, frequency of data # either 'daily', 'weekly', 'monthly' # type: Character, either 'price' or 'split' # adjust: Logical, adjusts the Open, High, Low, and Close prices for # dividends and splits, and adjusts Volume for dividends. # # http://help.yahoo.com/l/us/yahoo/finance/quotes/quote-12.html # http://ichart.finance.yahoo.com/x?s=MSFT&g=d&y=0&z=30000 # # Requires R-2.4.1 # Check dates if (missing(start)) { beg <- .dateToUNIX(as.Date("1900-01-01")) } else { beg <- .dateToUNIX(as.Date(as.character(start), "%Y%m%d")) } if (missing(end)) { end <- .dateToUNIX(Sys.Date()) } else { end <- .dateToUNIX(as.Date(as.character(end), "%Y%m%d")) } if( beg > end ) stop("Start date must be before end date.") if (beg > .dateToUNIX(Sys.Date())) stop("Start date is after today's date.") # Get frequency and type parameters intervals <- c(daily = "1d", weekly = "1wk", monthly = "1mo") freq <- match.arg( freq, names(intervals) ) interval <- intervals[freq] type <- match.arg( type, c("price","split") ) if(type!="price") { if(freq!="daily" & !quiet) message("Only freq=\"daily\" data available for type=\"split\".\n", "Setting freq=\"daily\"...") } tmp <- tempfile() on.exit(unlink(tmp), add = TRUE) flush.console() if(type=="price") { if(adjust) { if(freq=="daily") { # Get price, dividend, and split data from 'beg' to present ohlc <- getYahooData(symbol, start, freq="daily", type="price", adjust=FALSE, quiet=TRUE) divspl <- getYahooData(symbol, start, freq="daily", type="split", adjust=FALSE, quiet=TRUE) ohlc <- merge(ohlc, divspl, all=TRUE) # If there are no div/spl, then ohlc is a zero-width xts object if(NROW(divspl) != 0) { adj <- adjRatios(ohlc[,'Split'],ohlc[,'Div'],ohlc[,'Close']) s.ratio <- adj[,1] d.ratio <- adj[,2] # Adjust OHLC and volume cn <- colnames(ohlc) ohlc <- cbind(ohlc,ohlc[,'Close']) colnames(ohlc) <- c(cn,'Unadj.Close') #ohlc[,'Unadj.Close'] <- ohlc[,'Close'] ohlc[,'Open'] <- ohlc[,'Open'] * d.ratio * s.ratio ohlc[,'High'] <- ohlc[,'High'] * d.ratio * s.ratio ohlc[,'Low'] <- ohlc[,'Low'] * d.ratio * s.ratio ohlc[,'Close'] <- ohlc[,'Close'] * d.ratio * s.ratio ohlc[,'Volume'] <- ohlc[,'Volume'] * ( 1 / d.ratio ) # Order columns #ohlc <- ohlc[,c("Date","Open","High","Low","Close","Volume", ohlc <- ohlc[,c("Open","High","Low","Close","Volume", "Unadj.Close","Div","Split","Adj.Div")] } } else stop("Only freq=\"daily\" adjusted data is currently supported.") # For other frequencies, get daily data and use a routine to # aggregate to desired frequency. } else { handle <- .getHandle() # Construct URL for 'beg' to 'end' url <- .yahooURL(symbol, beg, end, interval, "history", handle) # Fetch data curl::curl_download(url, destfile=tmp, quiet=quiet, handle=handle$ch) # Read data ohlc <- read.csv(tmp, na.strings="null") # Re-order and set column names cnames <- c("Date", "Open", "High", "Low", "Close", "Volume", "Adjusted") corder <- pmatch(substr(cnames, 1, 3), colnames(ohlc)) ohlc <- ohlc[,corder] colnames(ohlc) <- cnames ohlc[,'Adjusted'] <- NULL ohlc <- ohlc[order(ohlc[,"Date"]),] ohlc <- xts(ohlc[,-1], as.Date(as.character(ohlc[,1]))) } } else { if(!quiet) message("Unadjusted and adjusted dividend data are always returned.") handle <- .getHandle() # Split data url <- .yahooURL(symbol, beg, end, "1d", "split", handle) curl::curl_download(url, destfile=tmp, quiet=quiet, handle=handle$ch) spl <- read.csv(tmp, as.is=TRUE) if(NROW(spl)==0) { spl <- NA } else { spl$V3 <- 1 / sapply(parse(text=spl[,2]), eval) spl <- xts(spl$V3, as.Date(spl[,1], "%Y-%m-%d")) colnames(spl) <- NULL } # Dividend data url <- .yahooURL(symbol, beg, end, "1d", "div", handle) curl::curl_download(url, destfile=tmp, quiet=quiet, handle=handle$ch) div <- read.csv(tmp, as.is=TRUE) div <- xts(div[,2],as.Date(div[,1])) colnames(div) <- NULL ohlc <- merge(Adj.Div = div, Split = spl) # Return (empty) data if(NROW(ohlc)==0) return(ohlc) if( all(is.na(ohlc[,'Split'])) ) { s.ratio <- rep(1,NROW(ohlc)) } else { s.ratio <- adjRatios(splits=ohlc[,'Split'])[,1] } # Un-adjust dividends for Splits ohlc <- cbind(ohlc,ohlc[,"Adj.Div"] * ( 1 / s.ratio )) colnames(ohlc)[3] <- "Div" ohlc[,'Split'] <- as.numeric(ohlc[,'Split']) # Order data columns ohlc <- ohlc[,c("Div","Split","Adj.Div")] } # Only return requested data dateRange <- paste(as.Date(.POSIXct(beg, tz = "UTC")), as.Date(.POSIXct(end, tz = "UTC")), sep = "/") ohlc <- ohlc[dateRange] ### Check to see if supplied dates occur in data set # if( max(ohlc[,'Date']) != as.Date(end) ) { # if(!quiet) message("End date out of range, " , max(ohlc[,'Date']), " is last available date.") # } # if( min(ohlc[,'Date']) != as.Date(beg) ) { # if(!quiet) message("Start date out of range, ", min(ohlc[,'Date']), " is first available date.") # } return(ohlc) } .getHandle <- function(force.new = FALSE) { h <- if (exists("_handle_", .env)) get("_handle_", .env) else NULL if (is.null(h) || force.new) { # create 'h' if it doesn't exist yet if (!force.new) { h <- list() } # establish session new.session <- function(h) { tmp <- tempfile() on.exit(unlink(tmp)) for (i in 1:5) { h <- curl::new_handle() # random query to avoid cache ru <- paste(sample(c(letters, 0:9), 4), collapse = "") cu <- paste0("https://finance.yahoo.com?", ru) curl::curl_download(cu, tmp, handle = h) if (NROW(curl::handle_cookies(h)) > 0) break; Sys.sleep(0.1) } if (NROW(curl::handle_cookies(h)) == 0) stop("Could not establish session after 5 attempts.") return(h) } h$ch <- new.session() n <- if (unclass(Sys.time()) %% 1L >= 0.5) 1L else 2L query.srv <- paste0("https://query", n, ".finance.yahoo.com/", "v1/test/getcrumb") cres <- curl::curl_fetch_memory(query.srv, handle = h$ch) h$cb <- rawToChar(cres$content) assign("_handle_", h, .env) } return(h) } .yahooURL <- function(symbol, from, to, period, type, handle) { p <- match.arg(period, c("1d", "1wk", "1mo")) e <- match.arg(type, c("history", "div", "split")) n <- if (unclass(Sys.time()) %% 1L >= 0.5) 1L else 2L u <- paste0("https://query", n, ".finance.yahoo.com/v7/finance/download/", symbol, "?period1=", from, "&period2=", to, "&interval=", p, "&events=", e, "&crumb=", handle$cb) return(u) } .dateToUNIX <- function(Date) { posixct <- as.POSIXct(as.Date(Date, origin = "1970-01-01")) trunc(as.numeric(posixct)) } TTR/R/runFun.R0000644000176200001440000002431414531142730012530 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Analysis of Running/Rolling/Moving Windows #' #' Various functions to analyze data over a moving window of periods. #' #' #' @aliases runFun runSum runMin runMax runMean runMedian runCov runCor runVar #' runSD runMAD wilderSum #' @param x Object coercible to xts or matrix. #' @param y Object coercible to xts or matrix. #' @param n Number of periods to use in the window or, if #' \code{cumulative=TRUE}, the number of observations to use before the first #' result is returned. Must be between 1 and \code{nrow(x)}, inclusive. #' @param cumulative Logical, use from-inception calculation? #' @param sample Logical, sample covariance if \code{TRUE} (denominator of #' \code{n-1}) #' @param use Only \code{"all.obs"} currently implemented. #' @param non.unique One of 'mean', 'max', or 'min'; which compute their #' respective statistics for the two middle values of even-sized samples. #' @param center The values to use as the measure of central tendency, around #' which to calculate deviations. The default (\code{NULL}) uses the median. #' @param stat Statistic to calculate, one of 'median' or 'mean' (e.g. median #' absolute deviation or mean absolute deviation, respectively.) #' @param constant Scale factor applied to approximate the standard deviation. #' @return A object of the same class as \code{x} and \code{y} or a vector (if #' \code{try.xts} fails). #' \describe{ #' \item{runSum}{returns sums over a n-period moving window.} #' \item{runMin}{returns minimums over a n-period moving window.} #' \item{runMax}{returns maximums over a n-period moving window.} #' \item{runMean}{returns means over a n-period moving window.} #' \item{runMedian}{returns medians over a n-period moving window.} #' \item{runCov}{returns covariances over a n-period moving window.} #' \item{runCor}{returns correlations over a n-period moving window.} #' \item{runVar}{returns variances over a n-period moving window.} #' \item{runSD}{returns standard deviations over a n-period moving window.} #' \item{runMAD}{returns median/mean absolute deviations over a n-period moving window.} #' \item{wilderSum}{retuns a Welles Wilder style weighted sum over a n-period moving window.} #' } #' #' @author Joshua Ulrich #' @keywords ts #' @rdname runFun "runSum" <- function(x, n=10, cumulative=FALSE) { x <- try.xts(x, error=as.matrix) if( n < 1 || n > NROW(x) ) stop(sprintf("n = %d is outside valid range: [1, %d]", n, NROW(x))) if(NCOL(x) > 1) { stop("ncol(x) > 1. runSum only supports univariate 'x'") } if(cumulative) { # Count NAs, ensure they're only at beginning of data. NAs <- sum(is.na(x)) if( NAs > 0 ) { if( any( is.na(x[-(1:NAs)]) ) ) stop("Series contains non-leading NAs") if( NAs + n > NROW(x) ) stop("not enough non-NA values") } beg <- 1 + NAs # Initialize result vector result <- double(NROW(x)) result[beg:NROW(x)] <- cumsum(x[beg:NROW(x)]) # Replace 1:(n-1) with NAs is.na(result) <- seq_len(n-1+NAs) } else { # Call C routine result <- .Call(C_runsum, x, n) } # Convert back to original class reclass(result, x) } #-------------------------------------------------------------------------# #' @rdname runFun "runMin" <- function(x, n=10, cumulative=FALSE) { x <- try.xts(x, error=as.matrix) if( n < 1 || n > NROW(x) ) stop(sprintf("n = %d is outside valid range: [1, %d]", n, NROW(x))) if(NCOL(x) > 1) { stop("ncol(x) > 1. runMin only supports univariate 'x'") } if(cumulative) { # Count NAs, ensure they're only at beginning of data, then remove. NAs <- sum( is.na(x) ) if( NAs > 0 ) { if( any( is.na(x[-(1:NAs)]) ) ) stop("Series contains non-leading NAs") if( NAs + n > NROW(x) ) stop("not enough non-NA values") } beg <- 1 + NAs # Initialize result vector result <- double(NROW(x)) result[beg:NROW(x)] <- cummin(x[beg:NROW(x)]) # Replace 1:(n-1) with NAs is.na(result) <- seq_len(n-1+NAs) } else { # Call C routine result <- .Call(C_runmin, x, n) } # Convert back to original class reclass(result, x) } #-------------------------------------------------------------------------# #' @rdname runFun "runMax" <- function(x, n=10, cumulative=FALSE) { x <- try.xts(x, error=as.matrix) if( n < 1 || n > NROW(x) ) stop(sprintf("n = %d is outside valid range: [1, %d]", n, NROW(x))) if(NCOL(x) > 1) { stop("ncol(x) > 1. runMax only supports univariate 'x'") } if(cumulative) { # Count NAs, ensure they're only at beginning of data, then remove. NAs <- sum( is.na(x) ) if( NAs > 0 ) { if( any( is.na(x[-(1:NAs)]) ) ) stop("Series contains non-leading NAs") if( NAs + n > NROW(x) ) stop("not enough non-NA values") } beg <- 1 + NAs if(NCOL(x) > 1) { stop("ncol(x) > 1. runMax only supports univariate 'x'") } # Initialize result vector result <- double(NROW(x)) result[beg:NROW(x)] <- cummax(x[beg:NROW(x)]) # Replace 1:(n-1) with NAs and prepend NAs from original data is.na(result) <- seq_len(n-1+NAs) } else { # Call C routine result <- .Call(C_runmax, x, n) } # Convert back to original class reclass(result, x) } #-------------------------------------------------------------------------# #' @rdname runFun "runMean" <- function(x, n=10, cumulative=FALSE) { if(cumulative) { x.na <- sum(is.na(x)) denom <- c(rep(NA_real_, x.na), seq_len(NROW(x)-x.na)) result <- runSum(x, n, cumulative) / denom } else { result <- runSum(x, n) / n } return(result) } #-------------------------------------------------------------------------# #' @rdname runFun "runMedian" <- function(x, n=10, non.unique="mean", cumulative=FALSE) { x <- try.xts(x, error=as.matrix) if( n < 1 || n > NROW(x) ) stop(sprintf("n = %d is outside valid range: [1, %d]", n, NROW(x))) if(NCOL(x) > 1) { stop("ncol(x) > 1. runMedian only supports univariate 'x'") } # Non-unique median non.unique <- match.arg(non.unique, c('mean','max','min')) non.unique <- switch(non.unique, mean=0L, max=1L, min=-1L) # Call C routine result <- .Call(C_runmedian, x, n, non.unique, cumulative) # Convert back to original class reclass(result, x) } #-------------------------------------------------------------------------# #' @rdname runFun "runCov" <- function(x, y, n=10, use="all.obs", sample=TRUE, cumulative=FALSE) { x <- try.xts(x, error=as.matrix) y <- try.xts(y, error=as.matrix) if(is.xts(x) && is.xts(y)) { xy <- cbind(x,y) } else { xy <- cbind( as.vector(x), as.vector(y) ) } if( n < 1 || n > NROW(x) ) stop(sprintf("n = %d is outside valid range: [1, %d]", n, NROW(x))) if(NCOL(x) > 1 || NCOL(y) > 1) { stop("ncol(x) > 1 or ncol(y) > 1.", " runCov only supports univariate 'x' and 'y'") } # "all.obs", "complete.obs", "pairwise.complete.obs" # Call C routine result <- .Call(C_runcov, xy[,1], xy[,2], n, sample, cumulative) # Convert back to original class # Should the attributes of *both* x and y be retained? reclass(result, x) } #-------------------------------------------------------------------------# #' @rdname runFun "runCor" <- function(x, y, n=10, use="all.obs", sample=TRUE, cumulative=FALSE) { result <- runCov(x, y, n, use=use, sample=sample, cumulative) / ( runSD(x, n, sample=sample, cumulative) * runSD(y, n, sample=sample, cumulative) ) return( result ) } #-------------------------------------------------------------------------# #' @rdname runFun "runVar" <- function(x, y=NULL, n=10, sample=TRUE, cumulative=FALSE) { if(is.null(y)) y <- x result <- runCov(x, y, n, use="all.obs", sample=sample, cumulative) return( result ) } #-------------------------------------------------------------------------# #' @rdname runFun "runSD" <- function(x, n=10, sample=TRUE, cumulative=FALSE) { result <- sqrt( runCov(x, x, n, use="all.obs", sample=sample, cumulative) ) return( result ) } #-------------------------------------------------------------------------# #' @rdname runFun "runMAD" <- function(x, n=10, center=NULL, stat="median", constant=1.4826, non.unique="mean", cumulative=FALSE) { x <- try.xts(x, error=as.matrix) if( n < 1 || n > NROW(x) ) stop(sprintf("n = %d is outside valid range: [1, %d]", n, NROW(x))) if(NCOL(x) > 1) { stop("ncol(x) > 1. runMAD only supports univariate 'x'") } if(is.null(center)) { center <- runMedian(x, n, cumulative=cumulative) } # Mean or Median absolute deviation? median <- match.arg(stat, c("mean","median")) median <- switch( stat, median=TRUE, mean=FALSE ) # Non-unique median non.unique <- match.arg(non.unique, c('mean','max','min')) non.unique <- switch( non.unique, mean=0, max=1, min=-1 ) # Call C routine result <- .Call(C_runmad, x, center, n, median, non.unique, cumulative) if( median ) result <- result * constant # Convert back to original class reclass(result, x) } #-------------------------------------------------------------------------# #' @rdname runFun "wilderSum" <- function(x, n=10) { x <- try.xts(x, error=as.matrix) if( n < 1 || n > NROW(x) ) stop(sprintf("n = %d is outside valid range: [1, %d]", n, NROW(x))) if(NCOL(x) > 1) { stop("ncol(x) > 1. wilderSum only supports univariate 'x'") } # Check for non-leading NAs # Leading NAs are handled in the C code naCheck(x, n) # called for error handling side-effect # Call C routine result <- .Call(C_wilderSum, x, n) # Convert back to original class reclass(result, x) } TTR/R/SAR.R0000644000176200001440000000620514531142730011677 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Parabolic Stop-and-Reverse #' #' The Parabolic Stop-and-Reverse calculates a trailing stop. Developed by J. #' Welles Wilder. #' #' The calculation for the SAR is quite complex. See the URLs in the references #' section for calculation notes. #' #' The SAR assumes that you are always in the market, and calculates the Stop #' And Reverse point when you would close a long position and open a short #' position or vice versa. #' #' @param HL Object that is coercible to xts or matrix and contains High-Low #' prices. #' @param accel accel[1]: Acceleration factor.\cr accel[2]: Maximum acceleration #' factor. #' @return A object of the same class as \code{HL} or a vector (if #' \code{try.xts} fails) containing the Parabolic Stop and Reverse values. #' @author Joshua Ulrich #' @seealso See \code{\link{ATR}} and \code{\link{ADX}}, which were also #' developed by Welles Wilder. #' @references The following site(s) were used to code/document this #' indicator:\cr #' \url{https://www.linnsoft.com/techind/parabolic-sar-sar}\cr #' \url{https://www.fmlabs.com/reference/SAR.htm}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:parabolic_sar}\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=87} #' @keywords ts #' @examples #' #' data(ttrc) #' sar <- SAR(ttrc[,c("High","Low")]) #' "SAR" <- function(HL, accel=c(.02,.2)) { # Parabolic Stop-and-Reverse (SAR) # ---------------------------------------------- # HL = HL vector, matrix, or dataframe # accel[1] = acceleration factor # accel[2] = maximum acceleration factor # WISHLIST: # Determine signal based on DM+/DM- for first bar # If sig[1]==1, then ep[1]==high; if sig[1]==-1, then ep[1]==low # The first SAR value should be the opposite (high/low) of ep # The first acceleration factor is based on the first signal # Since I've already lost one bar, do what TA-lib does and use that bar to # determine the inital signal value. Also try to incorporate different # accel factors for long/short. # accel = c( long = c( 0.02, 0.2 ), short = long ) HL <- try.xts(HL, error=as.matrix) # Check for non-leading NAs # Leading NAs are handled in the C code naCheck(HL, 0) # called for error handling side-effect # Gap for inital SAR initGap <- sd(drop(coredata(HL[,1] - HL[,2])), na.rm=TRUE) # Call C routine sar <- .Call(C_sar, HL[,1], HL[,2], accel, initGap) colnames(sar) <- "sar" reclass( sar, HL ) } TTR/R/OBV.R0000644000176200001440000000507314531142730011702 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' On Balance Volume (OBV) #' #' On Balance Volume (OBV) is a measure of the money flowing into or out of a #' security. It is similar to Chaikin Accumulation / Distribution. #' #' OBV is calculated by adding (subtracting) each day's volume to a running #' cumulative total when the security's price closes higher (lower). #' #' @param price Price series that is coercible to xts or matrix. #' @param volume Volume series that is coercible to xts or matrix, that #' corresponds to price object. #' @return A object of the same class as \code{price} and \code{volume} or a #' vector (if \code{try.xts} fails) containing the OBV values. #' @note OBV is usually compared with the price chart of the underlying security #' to look for divergences/confirmation. #' @author Joshua Ulrich #' @seealso See \code{\link{chaikinAD}}. #' @references The following site(s) were used to code/document this #' indicator:\cr \url{https://www.fmlabs.com/reference/OBV.htm}\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=82}\cr #' \url{https://www.linnsoft.com/techind/balance-open-interest}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:on_balance_volume_obv}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' obv <- OBV(ttrc[,"Close"], ttrc[,"Volume"]) #' "OBV" <- function(price, volume) { # On Balance Volume price <- try.xts(price, error=as.matrix) volume <- try.xts(volume, error=as.matrix) if(!(is.xts(price) && is.xts(volume))) { price <- as.vector(price) volume <- as.vector(volume) } prChg <- ROC(price) obv <- c( volume[1], ifelse( prChg > 0, volume, -volume )[-1] ) # OBV[t] = OBV[t-1] if price change is equal to zero obv[abs(prChg) < sqrt(.Machine$double.eps)] <- 0 obv <- cumsum( obv ) if(is.xts(obv)) { obv <- xts(obv,index(price)) colnames(obv) <- 'obv' } reclass( obv, price ) } TTR/R/WPR.R0000644000176200001440000000560014531142730011720 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' William's \%R #' #' William's \% R. #' #' If an High-Low-Close series is provided, the indicator is calculated using #' the high/low values. If a vector is provided, the calculation only uses that #' series. #' #' @param HLC Object that is coercible to xts or matrix and contains #' High-Low-Close prices. If only a univariate series is given, it will be #' used. See details. #' @param n Number of periods to use. #' @return A object of the same class as \code{HLC} or a vector (if #' \code{try.xts} fails) containing the William's \%R values. #' @note The William's \%R calculation is similar to stochastics' fast \%K. #' #' The value for William's \%R will be 0.5 whenever the highest high and #' lowest low are the same over the last \code{n} periods. #' @author Joshua Ulrich #' @seealso See \code{\link{stoch}}. #' @references The following site(s) were used to code/document this #' indicator:\cr #' \url{https://www.fmlabs.com/reference/WilliamsR.htm}\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=126}\cr #' \url{https://www.linnsoft.com/techind/williams-r-wpr}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:williams_r}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' stochOsc <- stoch(ttrc[,c("High","Low","Close")]) #' stochWPR<- WPR(ttrc[,c("High","Low","Close")]) #' #' plot(tail(stochOsc[,"fastK"], 100), type="l", #' main="Fast %K and Williams %R", ylab="", #' ylim=range(cbind(stochOsc, stochWPR), na.rm=TRUE) ) #' lines(tail(stochWPR, 100), col="blue") #' lines(tail(1-stochWPR, 100), col="red", lty="dashed") #' "WPR" <- function(HLC, n=14) { # William's Percent R (similar to Stochastics' fast %K) HLC <- try.xts(HLC, error=as.matrix) # Calculation if HLC series is given if(NCOL(HLC)==3) { high <- HLC[,1] low <- HLC[,2] close <- HLC[,3] } else # Calculation if price vector is given if(NCOL(HLC)==1) { high <- HLC low <- HLC close <- HLC } else stop("Price series must be either High-Low-Close, or Close") hmax <- runMax(high, n) lmin <- runMin( low, n) pctR <- (hmax - close) / (hmax - lmin) pctR[is.nan(pctR)] <- 0.5 reclass( pctR, HLC ) } TTR/R/ATR.R0000644000176200001440000000736014531142730011703 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' True Range / Average True Range #' #' True range (TR) is a measure of volatility of a High-Low-Close series; #' average true range (ATR) is a Welles Wilder's style moving average of the TR. #' Developed by J. Welles Wilder in 1978. #' #' TR incorporates yesterday's close in the calculation (high minus low). E.g. #' if yesterday's close was higher than today's high, then the TR would equal #' yesterday's close minus today's low. #' #' The ATR is a component of the Welles Wilder Directional Movement Index #' (\code{DX}, \code{ADX}). #' #' @aliases ATR TR #' @param HLC Object that is coercible to xts or matrix and contains #' High-Low-Close prices. #' @param n Number of periods for moving average. #' @param maType A function or a string naming the function to be called. #' @param \dots Other arguments to be passed to the \code{maType} function. #' @return A object of the same class as \code{HLC} or a matrix (if #' \code{try.xts} fails) containing the columns: #' \describe{ #' \item{ tr }{ The true range of the series. } #' \item{ atr }{ The average (as specified by \code{ma}) true range of the series. } #' \item{ trueHigh }{ The true high of the series. } #' \item{ trueLow }{ The true low of the series. } #' } #' @author Joshua Ulrich #' @seealso See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average #' options; and note Warning section. See \code{\link{DX}}, which uses true #' range. See \code{\link{chaikinVolatility}} for another volatility measure. #' @references The following site(s) were used to code/document this #' indicator:\cr \url{https://www.fmlabs.com/reference/TR.htm}\cr #' \url{https://www.fmlabs.com/reference/ATR.htm}\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=35}\cr #' \url{https://www.linnsoft.com/techind/true-range-tr}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:average_true_range_atr}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' tr <- TR(ttrc[,c("High","Low","Close")]) #' atr <- ATR(ttrc[,c("High","Low","Close")], n=14) #' #' @rdname ATR "TR" <- function(HLC) { # True Range HLC <- try.xts(HLC, error=as.matrix) if(is.xts(HLC)) { closeLag <- lag.xts(HLC[,3]) } else { closeLag <- c( NA, HLC[-NROW(HLC),3] ) } trueHigh <- pmax( HLC[,1], closeLag, na.rm=FALSE ) trueLow <- pmin( HLC[,2], closeLag, na.rm=FALSE ) tr <- trueHigh - trueLow result <- cbind(tr, trueHigh, trueLow ) colnames(result) <- c('tr','trueHigh','trueLow') reclass( result, HLC ) } #' @rdname ATR "ATR" <- function(HLC, n=14, maType, ...) { # Average True Range / True Range HLC <- try.xts(HLC, error=as.matrix) tr <- TR(HLC) maArgs <- list(n=n, ...) # Default Welles Wilder EMA if(missing(maType)) { maType <- 'EMA' if(is.null(maArgs$wilder)) { # do not overwrite user-provided value maArgs$wilder <- TRUE } } atr <- do.call( maType, c( list(tr[,1]), maArgs ) ) result <- cbind( tr[,1], atr, tr[,2:3]) colnames(result) <- c('tr','atr','trueHigh','trueLow') reclass( result, HLC ) } TTR/R/EMV.R0000644000176200001440000000647514531142730011712 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Arms' Ease of Movement Value #' #' Arms' Ease of Movement Value (EMV) emphasizes days where the security moves #' easily and minimizes days where the security does not move easily. Developed #' by Richard W. Arms, Jr. #' #' The EMV is calculated by dividing the midpoint ([high + low]/2) move by the #' 'Box Ratio' (volume divided by the high minus low). #' #' @param HL Object that is coercible to xts or matrix and contains High-Low #' prices. #' @param volume Vector or matrix of volume observations corresponding to the #' \code{HL} object. #' @param n Number of periods for moving average. #' @param maType A function or a string naming the function to be called. #' @param vol.divisor An increment to make the results larger and easier to work #' with. #' @param \dots Other arguments to be passed to the \code{maType} function. #' @return A object of the same class as \code{HL} and \code{volume} or a matrix #' (if \code{try.xts} fails) containing the columns: #' \describe{ #' \item{ emv }{ The ease of movement values. } #' \item{ maEMV }{ The smoothed (as specified by \code{ma}) ease of movement values. } #' } #' @note A buy/sell signal is generated when the EMV crosses above/below zero. #' When the EMV hovers around zero, there are small price movements and/or high #' volume, and the price is not moving easily. #' @author Joshua Ulrich #' @seealso See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average #' options; and note Warning section. #' @references The following site(s) were used to code/document this #' indicator:\cr \url{https://www.fmlabs.com/reference/ArmsEMV.htm}\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=51}\cr #' \url{https://www.linnsoft.com/techind/arms-ease-movement}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' emv <- EMV(ttrc[,c("High","Low")], ttrc[,"Volume"]) #' "EMV" <- function(HL, volume, n=9, maType, vol.divisor=10000, ...) { # Arms' Ease of Movement Value if( missing(HL) | missing(volume) ) stop("High-Low matrix (HL) and volume vector must be specified.") HL <- try.xts(HL, error=as.matrix) volume <- try.xts(volume, error=as.matrix) if(!(is.xts(HL) && is.xts(volume))) { HL <- as.matrix(HL) volume <- as.matrix(volume) } mid <- ( HL[,1] + HL[,2] ) / 2 volume <- volume / vol.divisor emv <- momentum(mid, n=1, na.pad=TRUE) / ( volume / ( HL[,1] - HL[,2] ) ) maArgs <- list(n=n, ...) # Default MA if(missing(maType)) { maType <- 'SMA' } maEMV <- do.call( maType, c( list(emv), maArgs ) ) result <- cbind(emv,maEMV) colnames(result) <- c('emv','maEMV') reclass( result, HL ) } TTR/R/CCI.R0000644000176200001440000000701014531142730011643 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Commodity Channel Index #' #' The Commodity Channel Index (CCI) attempts to identify starting and ending #' trends. #' #' CCI relates the current price and the average of price over \code{n} periods. #' The CCI usually falls in a channel of -100 to 100. A basic CCI trading system #' is: Buy (sell) if CCI rises above 100 (falls below -100) and sell (buy) when #' it falls below 100 (rises above -100). #' #' CCI is usually calculated using the typical price, but if a univariate series #' (e.g. Close, Weighted Close, Median Price, etc.) is provided, it will be used #' instead. #' #' @param HLC Object that is coercible to xts or matrix and contains #' High-Low-Close prices. If only a univariate series is given, it will be #' used. See details. #' @param n Number of periods for moving average. #' @param maType A function or a string naming the function to be called. #' @param c Constant to apply to the mean deviation. #' @param \dots Other arguments to be passed to the \code{maType} function. #' @return A object of the same class as \code{HLC} or a vector (if #' \code{try.xts} fails) containing the CCI values. #' @note If \code{HLC} is a High-Low-Close matrix, then typical price will be #' calculated. If \code{HLC} is a vector, then those values will be used #' instead of the typical price. #' @author Joshua Ulrich #' @seealso See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average #' options; and note Warning section. See \code{\link{aroon}}, #' \code{\link{ADX}}, \code{\link{TDI}}, \code{\link{VHF}}, \code{\link{GMMA}} #' for other indicators that measure trend direction/strength. #' @references The following site(s) were used to code/document this #' indicator:\cr \url{https://www.fmlabs.com/reference/CCI.htm}\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=42}\cr #' \url{https://www.linnsoft.com/techind/cci-commodity-channel-index}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:commodity_channel_index_cci}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' cci <- CCI(ttrc[,c("High","Low","Close")]) #' "CCI" <- function(HLC, n=20, maType, c=0.015, ...) { # Commodity Channel Index HLC <- try.xts(HLC, error=as.matrix) if(NCOL(HLC)==3) { if(is.xts(HLC)) { xa <- xcoredata(HLC) HLC <- xts(apply(HLC, 1, mean),index(HLC)) xcoredata(HLC) <- xa } else { HLC <- apply(HLC, 1, mean) } } else if(NCOL(HLC)!=1) { stop("Price series must be either High-Low-Close, or Close/univariate.") } maArgs <- list(n=n, ...) # Default MA if(missing(maType)) { maType <- 'SMA' } mavg <- do.call( maType, c( list(HLC), maArgs ) ) meanDev <- runMAD( HLC, n, center=mavg, stat="mean" ) cci <- ( HLC - mavg ) / ( c * meanDev ) if(is.xts(cci)) { colnames(cci) <- "cci" } reclass(cci, HLC) } TTR/R/ADX.R0000644000176200001440000000761014531142730011667 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Welles Wilder's Directional Movement Index #' #' Directional Movement Index; developed by J. Welles Wilder. #' #' The \code{DIp}/\code{DIn} (positive/negative) is the percentage of the true #' range that is up/down. #' #' @aliases ADX DI DX #' @param HLC Object that is coercible to xts or matrix and contains #' High-Low-Close prices. #' @param n Number of periods to use for DX calculation (not ADX calculation). #' @param maType A function or a string naming the function to be called. #' @param \dots Other arguments to be passed to the \code{maType} function. #' @return A object of the same class as \code{HLC} or a matrix (if #' \code{try.xts} fails) containing the columns: #' \describe{ #' \item{ DIp }{ The positive Direction Index. } #' \item{ DIn }{ The negative Direction Index. } #' \item{ DX }{ The Direction Index. } #' \item{ ADX }{ The Average Direction Index (trend strength). } #' } #' @note A buy/sell signal is generated when the +/-DI crosses up over the #' -/+DI, when the DX/ADX signals a strong trend. A high/low DX signals a #' strong/weak trend. DX is usually smoothed with a moving average (i.e. the #' ADX). #' @author Joshua Ulrich #' @seealso See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average #' options; and note Warning section. The DX calculation uses #' \code{\link{ATR}}. See \code{\link{aroon}}, \code{\link{CCI}}, #' \code{\link{TDI}}, \code{\link{VHF}}, \code{\link{GMMA}} for other indicators #' that measure trend direction/strength. #' @references The following site(s) were used to code/document this #' indicator:\cr \url{https://www.fmlabs.com/reference/DI.htm}\cr #' \url{https://www.fmlabs.com/reference/DX.htm}\cr #' \url{https://www.fmlabs.com/reference/ADX.htm}\cr #' \url{https://www.fmlabs.com/reference/ADXR.htm}\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/?p=49}\cr #' \url{https://www.linnsoft.com/techind/directional-indicator-diplus-diminus}\cr #' \url{https://www.linnsoft.com/techind/adx-avg-directional-movement}\cr #' \url{https://www.linnsoft.com/techind/adxr-avg-directional-movement-rating}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:average_directional_index_adx}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' dmi.adx <- ADX(ttrc[,c("High","Low","Close")]) #' "ADX" <- function(HLC, n=14, maType, ...) { # Welles Wilder's Directional Movement Index HLC <- try.xts(HLC, error=as.matrix) dH <- momentum(HLC[,1]) dL <- -momentum(HLC[,2]) DMIp <- ifelse( dH==dL | (dH< 0 & dL< 0), 0, ifelse( dH >dL, dH, 0 ) ) DMIn <- ifelse( dH==dL | (dH< 0 & dL< 0), 0, ifelse( dH . # #' De-Trended Price Oscillator #' #' The Detrended Price Oscillator (DPO) removes the trend in prices - or other #' series - by subtracting a moving average of the price from the price. #' #' The Detrended Price shows cycles and overbought / oversold conditions. #' #' @param x Price, volume, etc. series that is coercible to xts or matrix. #' @param n Number of periods for moving average. #' @param maType A function or a string naming the function to be called. #' @param shift The number of periods to shift the moving average. #' @param percent logical; if \code{TRUE}, the percentage difference between the #' slow and fast moving averages is returned, otherwise the difference between #' the respective averages is returned. #' @param \dots Other arguments to be passed to the \code{maType} function. #' @return A object of the same class as \code{x} or a vector (if \code{try.xts} #' fails) containing the DPO values. #' @note #' DPO does not extend to the last date because it is based on a displaced moving #' average. The calculation shifts the results \code{shift} periods, so the last #' \code{shift} periods will be zero.\cr #' As stated above, the DPO can be used on any univariate series, not just price. #' @section Warning: The detrended price oscillator removes the trend in the #' series by centering the moving average. Centering the moving average causes it #' to include future data. Therefore, even though this indicator looks like a #' classic oscillator, it should not be used for trading rule signals. #' @author Joshua Ulrich #' @seealso See \code{\link{EMA}}, \code{\link{SMA}}, etc. for moving average #' options; and note Warning section. See \code{\link{MACD}} for a general #' oscillator. #' @references The following site(s) were used to code/document this #' indicator:\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators:detrended_price_osci}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' priceDPO <- DPO(ttrc[,"Close"]) #' volumeDPO <- DPO(ttrc[,"Volume"]) #' "DPO" <- function(x, n=10, maType, shift=n/2+1, percent=FALSE, ...) { # De-Trended Price Oscillator x <- try.xts(x, error=as.matrix) maArgs <- list(n=n, ...) # Default MA if(missing(maType)) { maType <- 'SMA' } mavg <- do.call( maType, c( list(x), maArgs ) ) mavg <- lag.xts(mavg, -shift) if(percent) { DPO <- 100 * ( x[,1] / mavg - 1 ) } else { DPO <- x[,1] - mavg } reclass( DPO, x ) } TTR/R/GMMA.R0000644000176200001440000000505114531142730011771 0ustar liggesusers# # TTR: Technical Trading Rules # # Copyright (C) 2007-2013 Joshua M. Ulrich # # This program 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. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # #' Guppy Multiple Moving Averages #' #' Calculate the Guppy Multiple Moving Average of a series. #' #' The Guppy Multiple Moving Average signals a changing trend when the #' \code{short} and \code{long} groups of moving averages intersect. An up/down #' trend exists when the short/long-term moving averages are greater than the #' long/short-term averages. #' #' @aliases GMMA Guppy guppy #' @param x Price, volume, etc. series that is coercible to xts or matrix. #' @param short Vector of short-term periods. #' @param long Vector of long-term periods. #' @param maType Either: #' \enumerate{ #' \item A function or a string naming the function to be called. #' \item A \emph{list} with the first component like (1) above, and #' additional parameters specified as \emph{named} components. #' See Examples. #' } #' @return A object of the same class as \code{x} or \code{price} or a vector #' (if \code{try.xts} fails) containing the Guppy Multiple Moving Average. #' @author Joshua Ulrich #' @seealso See \code{\link{aroon}}, \code{\link{CCI}}, \code{\link{ADX}}, #' \code{\link{VHF}}, \code{\link{TDI}} for other indicators that measure trend #' direction/strength. #' @references The following site(s) were used to code/document this #' indicator:\cr #' \url{https://www.investopedia.com/terms/g/guppy-multiple-moving-average.asp}\cr #' @keywords ts #' @examples #' #' data(ttrc) #' gmma <- GMMA(ttrc[,"Close"]) #' "GMMA" <- function(x, short=c(3,5,8,10,12,15), long=c(30,35,40,45,50,60), maType) { # Guppy Multiple Moving Average x <- try.xts(x, error=as.matrix) # Default MA if(missing(maType)) { maType <- 'EMA' } fn <- function(g) { do.call(maType, list(x,n=g)) } gmma <- do.call(cbind, lapply(c(short,long), fn)) colnames(gmma) <- c(paste('short lag',short),paste('long lag',long)) reclass(gmma, x) } TTR/R/TTR-package.R0000644000176200001440000000524214531142730013314 0ustar liggesusers#' Technical Trading Rule Composite data #' #' Historical Open, High, Low, Close, and Volume data for the periods January 2, #' 1985 to December 31, 2006. Randomly generated. #' #' These data do not represent an actual security. They are provided so #' examples do not necessitate an internet connection. #' #' @name ttrc #' @docType data #' @format The format is: \tabular{lll}{ Date: \tab Class 'Date' \tab 5480 5481 #' 5482 5485 5486 ...\cr Open: \tab num \tab 3.18 3.09 3.11 3.09 3.10 ...\cr #' High: \tab num \tab 3.18 3.15 3.12 3.12 3.12 ...\cr Low: \tab num \tab 3.08 #' 3.09 3.08 3.07 3.08 ...\cr Close: \tab num \tab 3.08 3.11 3.09 3.10 3.11 #' ...\cr Volume: \tab num \tab 1870906 3099506 2274157 2086758 2166348 ...\cr } #' @source Randomly generated. #' @keywords datasets #' @examples #' #' data(ttrc) #' plot(tail(ttrc[,"Close"],100), type="l") #' @rdname ttrc NULL #' Functions to create Technical Trading Rules (TTR) #' #' This package contains many of the most popular technical analysis functions, #' as well as functions to retrieve U.S. stock symbols, and data from Yahoo #' Finance. #' #' Users will probably be most interested in the following functions:\cr #' \code{\link{ADX}}\cr \code{\link{BBands}}\cr \code{\link{changes}}\cr #' \code{\link{MovingAverages}}\cr \code{\link{MACD}}\cr \code{\link{RSI}}\cr #' \code{\link{runFun}}\cr \code{\link{stoch}}\cr \code{\link{VWAP}}\cr #' \code{\link{WebData}}\cr #' #' @name TTR #' @docType package #' @aliases TTR-package #' @author Joshua Ulrich #' #' Maintainer: Joshua Ulrich #' @references The following sites were used to code/document this package:\cr #' \url{https://www.fmlabs.com/reference/default.htm}\cr #' \url{https://www.metastock.com/Customer/Resources/TAAZ/}\cr #' \url{https://www.linnsoft.com/indicators}\cr #' \url{https://school.stockcharts.com/doku.php?id=technical_indicators}\cr #' @keywords package #' @examples #' #' data(ttrc) #' #' # Bollinger Bands #' bbands <- BBands( ttrc[,c("High","Low","Close")] ) #' #' # Directional Movement Index #' adx <- ADX(ttrc[,c("High","Low","Close")]) #' #' # Moving Averages #' ema <- EMA(ttrc[,"Close"], n=20) #' sma <- SMA(ttrc[,"Close"], n=20) #' #' # MACD #' macd <- MACD( ttrc[,"Close"] ) #' #' # RSI #' rsi <- RSI(ttrc[,"Close"]) #' #' # Stochastics #' stochOsc <- stoch(ttrc[,c("High","Low","Close")]) #' #' ### Note: you must have a working internet connection #' ### for the examples below to work! #' if (interactive()) { #' # Fetch U.S. symbols from the internet #' nyseSymbols <- stockSymbols("NYSE") #' #' # Fetch Yahoo! Finance data from the internet #' ge <- getYahooData("GE", 19990404, 20050607, adjust = FALSE) #' } #' #' @rdname TTR NULL TTR/NEWS.md0000644000176200001440000004332714531225355012037 0ustar liggesusers# Changes in 0.24.4 * Added Ethan B. Smith as a contributor. Thanks Ethan! ### NEW FEATURES - Added a `TR()` function to calculate the true high, true low, and true range. Refactored `ATR()` to use the `TR()` function. Thanks to @openbmsjsc and Steve Bronder for the reports, and Ethan B. Smith for the PR. (#18, #114, #124) ### BUG FIXES * Fix `stockSymbols()` for ticker "NA". `read.table()` converts the string "NA" to a missing value (NA) because `na.strings = "NA"` by default. This causes an issue because there's actually a company with "NA" for the ticker. (#128) - `CTI()` did not pad its result with leading NA when the input was not coerced to an xts object. This was different from other TTR functions (e.g. `SMA()`, `RSI()`, `ROC()`). (#127) - Removed the `VMA()` function, which was never correct because the results made no sense. - Check that the `wma()` C function has enough non-NA values and throw an error if it doesn't. This could cause the `WMA()` function to crash the user's R session. (#126) - `runMean(..., cumulative = TRUE)` didn't account for leading NA in the denominator. (#122) - `runSD(x, cumulative = TRUE)` returned all NA when `x` had any leading NA. Thanks to Ethan B. Smith for the report. (#121) - The `TRIX()` signal line did not use `nSig` unless `maType` was provided. Thanks to @SatoshiReport for the... report. (#120) ### MISCELLANEOUS - Use symbols for native routine entry points to make them explicit and unable to be found accidentally. (#123) # Changes in 0.24.3 ### SIGNIFICANT USER-VISIBLE CHANGES - Significant improvement to `ALMA()` calculation speed. Thanks to Ethan B. Smith for the report and suggested fix. (#117) ### NEW FEATURES - Added Keltner Channels. Thanks to Nick Procyk for the patch and docs (#106) ### BUG FIXES - `runPercentRank()` would segfault if `x` had fewer non-NA observations than the value for `n`. Thanks to Ian Fellows for the report. (#112) - `run*(x, n = 1, cumulative = TRUE)` functions would return NA for the first value. Thanks to Ethan B. Smith for the report and PR! (#111, #108, #88) - Fix NA check off-by-one error in `aroon()` that caused it to fail if there were exactly enough non-NA values. (#102) # Changes in 0.24.2 ### BUG FIXES - Check for `ratio > 0` before calculating `n` in `zlema()` C code. The prior code could result in division by 0, which was flagged by clang-UBSAN. Thanks to Prof Brian Ripley for the report. (#100) # Changes in 0.24.1 ### BUG FIXES - Fix leading NA accounting in `wma()` C code. The prior code caused invalid reads under valgrind. Thanks to Prof Brian Ripley for the report. (#99) - Check for `ratio > 0` before calculating `n` `n ema()` C code. The prior code could result in division by 0, which was flagged by UBSAN. Thanks to Prof Brian Ripley for the report. (#100) - Make `ALMA()` output length equal input length when the input can not be converted to xts. This was caused by the difference between `rollapply.default()` and `rollapply.xts()`. Thanks to GitHub user @marksimmonds for the report. (#29) - Fix `stoch()` in very rare cases where `fastK = Inf`. I could only reproduce this if the Close is > High and High and Low are equal, but that is a data error. I fixed anyway because there may be other cases I don't anticipate. Thanks to GitHub user @cjuncosa for the report. (#52) - Fix `MFI()` when money flow is always zero or positive. The denominator of the money ratio will be zero if there is no negative money flow for `n` consecutive observations (e.g. during a strong up-trend), which causes the money flow index to be Inf. Set the money flow index to 100 in this case. And the money ratio will be NaN if there's no money flow for `n` consecutive observations (e.g. if there are no trades), which causes the money flow index to be NaN. Set the money flow index to 50 in this case. Thanks to GitHub user @jgehw for the report, reproducible example, and suggested patch. (#81) # Changes in 0.24.0 ### SIGNIFICANT USER-VISIBLE CHANGES - Updated `stockSymbols()` to use the NASDAQ FTP site instead of downloading the CSV from the NASDAQ stock screener page. Some columns are no longer populated because they are not provided in the FTP file: LastSale ,MarketCap, IPOyear, Sector, Industry These columns will be removed in a future version. (#98, #5, #97) - `runPercentRank(x, n, cumulative = TRUE)` now sets observations in the initialization period to NA. This is consistent with the other running/rolling functions in TTR. If you want the previous behavior, you should use `runPercentRank(x, n = 1, cumulative = TRUE)`. Thanks to GitHub user @httassadar for the report. (#73) ### NEW FEATURES - Add Ehler's Correlation Trend Indicator. Thanks to Evelyn Mitchell for the suggestion, and for Ethan B. Smith for the initial implementation. (#92) ### BUG FIXES - `runMAD()` returned incorrect values when `cumulative = TRUE` and the input contained leading NA. Thanks to GitHub user @stellathecat for the report. This also affected `runMedian()`. (#93) - `ZLEMA()` would crash when `ratio = 0.0` and `n` was not specified. Thanks to GitHub user @yogat3ch for the report! (#95) - `WMA()` did not return an xts object when passed an xts object for `x` that had leading NA, with the default `wts = 1:n`. Thanks to Cory Fletcher for reporting this issue via email. (#96) - `stoch()` was wrong when `bounded = FALSE`. Thanks to GitHub user @rfinfun for the report and patch. (#74) - `HMA()` threw an error when `n` was an odd number. This was because the first call to `WMA()` used `n = n / 2` which caused `n` to not be an integer. Thanks to GitHub user @dragie for the report. (#76) # Changes in 0.23.0 ### SIGNIFICANT USER-VISIBLE CHANGES - Update `DVI()` to use `runPercentRank()`. Thanks to Ivan Popivanov for the patch. - `getYahooData()` now returns an xts object with Date index (not POSIXct). - Column names for moving average function outputs are no longer based on the input column names. ### NEW FEATURES - Add `HMA()` and `ALMA()` functions/docs. Thanks to Ivan Popivanov. - Add Ultimate Oscillator function/docs/tests. Thanks to Ivan Popivanov. ### BUG FIXES - `run*()` functions now error if there are not enough non-NA values. - Change all instances of `lag()` to `lag.xts()` in case `x` is a matrix. Thanks to Ivan Popivanov for the report. - Correct output column names in `ATR()` docs. - `CLV()` now sets NaN and Inf values to 0, instead of only NaN values. - Fix `OBV()` so `OBV[t] = OBV[t-1]` when `Close[t] == Close[t-1]`. - Fix dead links in documentation. # Changes in 0.22.0 ### SIGNIFICANT USER-VISIBLE CHANGES - `CCI()` now returns an object with column names ("cci"). - All moving average functions now attempt to set column names. - Added clarification on the displaced nature of `DPO()`. - `SAR()` now sets the initial gap based on the standard deviation of the high-low range instead of hard-coding it at 0.01. ### NEW FEATURES - Added `rollSFM()` function that calculates alpha, beta, and R-squared for a single-factor model. Thanks to James Toll for the prototype. - Added `runPercentRank()` function. Thanks to Charlie Friedemann. - Moved slowest portion of `aroon()` to C. - `DonchianChannel()` gains an `include.lag = FALSE` argument, which includes the current period's data in the calculation. Setting it to `TRUE` replicates the original calculation. Thanks to Garrett See and John Bollinger. - The Stochastic Oscillator and Williams' %R now return 0.5 (instead of NaN) when a securities' price doesn't change over a sufficient period. - All moving average functions gain `...`. - Users can now change alpha in Yang Zhang volatility calculation. ### BUG FIXES - Fixed `MACD()` when `maType` is a list. Now `mavg.slow = maType[[2]]` and `mavg.fast = maType[[1]]`, as users expected based on the order of the `nFast` and `nSlow` arguments. Thanks to Phani Nukala and Jonathan Roy. - Fixed bug in `lags()`. Thanks to Michael Weylandt. - Corrected error in Yang Zhang volatility calculation. Thanks to several people for identifying this error. - Correction to `SAR()` extreme point calculations. Thanks to Vamsi Galigutta. - `adjRatios()` now ensures all inputs are univariate. Thanks to Garrett See. - `EMA()` and `EVWMA()` now ensure `n` is less than the number of non-NA values. Thanks to Roger Bos. - Fix to `BBands()` docs. Thanks to Evelyn Mitchell. # Changes in 0.21.1 ### BUG FIXES - Fixed `stockSymbols()` for nasdaq.com changes (again), and attempted to make `stockSymbols()` more robust to nasdaq.com changes. - Corrected final calculation in Yang-Zhang volatility. Thanks to Shal Patel. - Corrected `k` in Yang-Zhang volatility. Thanks to Ian Rayner. - Corrected `s2o` and `s2c` in Yang-Zhang volatility. Thanks to Ian Rayner. - Corrected `KST()` when input is xts (result is now * 100). Thanks to Yuanwei. # Changes in 0.21.0 ### NEW FEATURES - Added variable moving average function, `VMA()`. - Added Brian Peterson's price bands function, `PBands()`. - Added David Varadi's `DVI()` indicator. - Added `wilder` and `ratio` arguments to `DEMA`. Thanks to Matthew Fornari for the suggestion. ### BUG FIXES - Changed `wilderSum()` to seed initial value with raw sum. This matches Wilder's original calculations. Thanks to Mahesh Bp for the report. - The `BBands()` standard deviation calculation now uses the population instead of sample statistic. This is consistent with Bollinger Band literature. Thanks to Jeff Ryan for the patch. - Fixed `stockSymbols()` for nasdaq.com changes. - Fixed `ZLEMA()` default ratio by changing it from `2/(n-1)` to `2/(n+1)`. This makes it consistent with `EMA()`. Thanks to Dirk Eddelbuettel. - Corrected close-to-close volatility. Thanks to James Toll for the report. - `adjRatios()` failed (spectacularly) if there were missing close prices. Thanks to Garrett See for the report. # Changes in 0.20.2 ### NEW FEATURES - Added `VWAP()` and `VWMA()`. Thanks to Brian Peterson. - Added v-factor generalization to `DEMA()`. Thanks to John Gavin. - Updated `volatility()` to handle univariate case of `calc = "close"`. Thanks to Cedrick Johnson. - Moved `EMA()`, `SAR()`, and `wilderSum ()`from .Fortran to `.Call ()`and used `xts:::naCheck()` instead of TTR's NA check mechanism. - `RSI ()`up/down momentum is now faster with xts. Thanks to Jeff Ryan. - If `ratio` is specified in `EMA ()`but `n` is missing, the traditional value of `n` is approximated and returned as the first non-NA value. ### BUG FIXES - Fix to `stoch()` when `maType` is a list and `n` is not set in the list's 3rd element. Thanks to Wind Me. - Fixed `fastK` in `stoch()` when `smooth != 1`. - Fixed segfault in `EMA ()`when `n < NROW(x)`. Thanks to Douglas Hobbs. - `test.EMA.wilder()` failed under R-devel. Thanks to Prof Brian Ripley. # Changes in 0.20.1 ### NEW FEATURES - Updated `CMO()`, `DPO()`, `DonchianChannel()`, `RSI()`, and `TDI ()` to *explicitly* use xts internally. ### BUG FIXES - Fixed bug in `WMA()`, `EVWMA()`, `ZLEMA()`, and `GMMA()`; results were not being `reclass()`ed back to their original class. - Set column names after `cbind ()` call in the following functions: - `ADX()` - `aroon()` - `ATR()` - `BBands()` - `DonchianChannel()` - `EMV()` - `KST()` - `MACD()` - `stoch()` - `SMI()` - `TDI()` - `TRIX()` - Fixed bug in `VHF()`; missing `abs()` calculation in the denominator. Thanks to Jürgen Wurzer for the report! # Changes in 0.20.0 - Fixed version number; 0.20-0 is now > 0.14-0 (rookie mistake). ### SIGNIFICANT USER-VISIBLE CHANGES - `getYahooData()` now returns an xts object. - Added column names to output for `ADX()`, `EMV()`, and `CLV ()` (for xts). - `momentum()` in `CMO()` no longer sets `na = 100`. - Replaced `na` argument in `momentum()` and `ROC()` with `na.pad`. - Moved `maType` argument default values from function formals to function body for the following functions: - `ADX()` - `ATR()` - `CCI()` - `DPO()` - `EMV()` - `KST()` - `MACD()` - `RSI()` - `TRIX()` - `BBands()` - `chaikinVolatility()` - `stoch()` - `SMI()` ### NEW FEATURES - `adjRatios()` creates split and/or dividend adjustment ratio series via C code. - `GMMA()` calculates the Guppy Multiple Moving Average. - `volatility()` now has Yang Zhang, and Garman-Klass (Yang Zhang) calculations. - The functions below now have cumulative argument. This allows the calculation of "from inception" running series. - `runSum()`, `runMin()`, `runMax()` - `runMean()`, `runMedian()` - `runCov()`, `runCor()`, `runVar()`, `runSD()`, `runMAD()` - Added internal smoothing to `FastK` in `stoch()` via `smooth` argument. Thanks to Stanley Neo. - `getYahooData()` now uses `adjRatios(),` which yields significant speed improvements for larger data sets. - All functions now use xts internally, adding support for all major time series classes. If `try.xts()` fails on the input object(s), they will be converted to a matrix and a matrix object will be returned. - Added `bounded` arg to `stoch()` and `SMI()`, which includes the current period in the calculation. - Added the zig zag indicator: `ZigZag()`. - Added volatility estimators/indicators: `volatility()`, with the following calculations: - Close-to-Close - Garman Klass - Parkinson - Rogers Satchell - Added Money Flow Index: `MFI()`. - Added Donchian channel: `DonchianChannel()`. - Added `multiple` argument to `TDI()`, allowing more user control. - Added `naCheck()` and implemented it in the moving average functions. ### BUG FIXES - Fixed bug when `maType` was a list and `n` was not specified in `maType`. This affected: `stoch()`, `SMI()`, `RSI()`, `KST()`, `MACD()`, `TRIX()`. - Corrected NaN replacement in `CLV()`. - Corrected `williamsAD()`: the result is 0 if C(t) = C(t-1). - Corrected `runMedian()` and `runMAD()`. The argument controlling which type of median to calculate for even-numbered samples wasn't being passed to the Fortran routine. - `aroon()` calculation starts at period `n+1`, instead of `n`. - Added NA to first element of `closeLag` of `ATR()`. - Corrected `BBands()` and `CCI()` for `rowMeans()` use on xts objects. - Made changes to Rd files to pass R CMD check on R-devel (2.9.0). # Changes in 0.14.0 ### SIGNIFICANT USER-VISIBLE CHANGES - Changed default `type` of `ROC()` to `continuous`. - Changed `BBands()` %B output value from `pct.b` to `pctB`. - Changed `WPR()` output value from `pct.R` to `pctR`. - Changed `WPR()` MA output value from `ma.emv` to `emvMA`. - Changed `aroon()` output values from `aroon.xx` to `aroonXx`. - Renamed: - `chaikinMF()` to `CMF()` - `stochastic()` to `stoch()` - `bollingerBands()` to `BBands()` - Set `na = NA` for `momentum()` and `ROC()` functions in files KST.R, RSI.R, and TDI.R, and changed `ROC()` to use `type = "discrete"` in chaikinVolatility.R. - Made the following changes to the `ZLEMA()` function: - Add `ratio = NULL` argument. - Non-integer lags are a weighted mean of the two nearest observations, based on their proximity to the lag value. - Change 'lag = ratio^(-1)' to fully support `ratio` argument. - Changed the `BBands()` function's `sd` argument from a list that allows other dispersion functions to simply indicate the number of standard deviations to use. ### NEW FEATURES - Changed `maType` arguments and updated documentation for: - `RSIm()` - `ADX()` - `ATR()` - `CCI()` - `DPO()` - `EMV()` - `RSI()` - `BBands()` - `chaikinVolatility()` - `stoch()` - `SMI()` - `TRIX()` - `MACD()` - `KST()` - Added Stochastic Momentum Index `SMI()` and `williamsAD()` functions and documentation. - Added Fortran implementations of - `SMA()` - `EMA()` - `WMA()` - `EVWMA()` - `ZLEMA()` - `PSAR()` - Added NA checking/handling for many functions. - Added `ratio = NULL` argument to `EMA()`. - Changed all usage of `roll*()` to their respective Fortran implementations and removed the `rollFun()` function. Added Fortran based functions are: - `runSum()` - `wilderSum()` - `runMin()` - `runMax()` - `runMean()` - `runCov()` - `runCor()` - `runVar()` - `runSD()` - `runMedian()` - `runMAD()` - Changed `CCI()` to use `runMAD()` internally. ### DEPRECATED & DEFUNCT - Removed `oscillator()` function and transferred functionality to `MACD()` function. - Removed `chaikinOscillator()`, since it can be created via `MACD(chaikinAD(...))`. ### BUG FIXES - `match.arg(type)` in `ROC()` changed to simple subsetting of type. - Changed trailing zeros to trailing NAs in `DPO()`. - Fixed `WMA()` bug that allowed `x` and `wts` vectors to have different length if either series had leading NAs (similar to `EVWMA()` function). - Fixed `runCov()` bug that allowed `x` and `y` vectors to have different length if either series had leading NAs (similar to `EVWMA()` function). - Corrected `EVWMA()` to start at period `n` instead of `n-1`. - Removed `message` function from CCI.R, VHF.R, WPR.R, aroon.R bollingerBands.R, and stochastics.R. # Changes in 0.13.2 ### SIGNIFICANT USER-VISIBLE CHANGES - Changed order of `oscillator()` arguments from `ma.slow`, `ma.fast`, `ma.sig` to the traditional `ma.fast`, `ma.slow`, `ma.sig`. Thanks to Jeff Ryan. - The arguments to the `chaikinOscillator()` function were changed as above. - Changed `EVWMA()` so period `n` contains the value for periods `(i-n+1):n` and so periods `1:(n-2)` will be NA. - Changed `EMA()` so periods `1:n` will be NA. # Changes in 0.13.1 ### SIGNIFICANT USER-VISIBLE CHANGES - Changed `bbands()` to `bollingerBands()`. - Changed `DX()` to `ADX()`. - Changed `stoch()` to `stochastic()`. ### BUG FIXES - Corrected mis-spellings in documentation. TTR/MD50000644000176200001440000001373214531274225011246 0ustar liggesusers6daf9a9be3246de22da817b24aaa2504 *DESCRIPTION 33e693f69dd611d4db28cb578c872121 *NAMESPACE eb0297ac72ce03be8ad014116308bc3f *NEWS.md fe04030f0d44aab35a2b71f7e92cac68 *R/ADX.R 64758621ecb81c1934c5af6f820cbbbf *R/ATR.R 181fb0e7b7b186bcf24b93a85f2cc976 *R/CCI.R 2a701a41e6651712081fe10dea253ac8 *R/CLV.R e359f45653062ad07b36373fca6413d4 *R/CMF.R 01731498f1424ede0df5296259ed9939 *R/CMO.R 3e2372ade8b348c53d6cb297fe999818 *R/CTI.R db8e0690a98e3ae0f171b5efd231a3a7 *R/DPO.R eccb3908fdc3562954e15b443fe4f8cc *R/DVI.R b33860539bdeb3942958d00e853aed26 *R/DonchianChannel.R 0ece941384481dc1a73086582eac10a2 *R/EMV.R 90d9c794626bdf6b6a6ec7713a66af19 *R/GMMA.R c40564856c74078c14784b236691e45f *R/KST.R fc3cf17e2cefce4d11db032a81defec1 *R/MACD.R e7e2578fd0df0c31deadc3226860c2de *R/MFI.R c88656cdbb17594efccbe659fca2cf52 *R/MovingAverages.R 5cfd5388c38ee2fa6e63756debd64e84 *R/OBV.R fb803b5a1209d218df782f6b18addc28 *R/RSI.R 843418f6742bb977d0092d816fe42bba *R/SAR.R 14d34f405d6bbf617edae55fa847e06b *R/SNR.R 3c2a749433010c4e47a50a9031544f35 *R/TDI.R ea84bd4b1231717356acb4804008a45c *R/TRIX.R b8bd2903fb541f70c7505774df26afcf *R/TTR-package.R a1708d11ffe9c4a4f81e8db2412cc901 *R/TTRtools.R 22b4e9feab334656a9d5ff330034d6a1 *R/VHF.R 4d0256e152c3fc43b763accbc497d126 *R/WPR.R 4bcd1d557479136a3cde9a8d7c86dcf7 *R/WebData.R fbc8ff107e32079dd11a152f7ecf935c *R/ZigZag.R 8e5166dd8dff1c172d8d600218000c3b *R/adjRatios.R 5764718efff5897b4da8144963c1a83c *R/aroon.R e7fccdb2c56ab958a17c526756204c22 *R/bollingerBands.R b1551c5a33ab7351c8d998703a1b6ef1 *R/chaikinAD.R c228edfcae5ba5f5a3a49a78ee8d61b4 *R/chaikinVolatility.R c67679189aa23f8667d3db574a6a5482 *R/changes.R 2fee6556a7a26c32a5a421e25a8fc92c *R/keltnerChannels.R 477b6a6c3f66af36ecee074d3fab026a *R/percentRank.R e400a47c6d7fe58a3964d7109b4c6270 *R/priceBands.R e6b86bf16bc40819c1513e657e8e7370 *R/rollFun.R db756373ca593fb29d5de7229a34a8c0 *R/runFun.R c9e6f69a4b4a3e05a003acedd389999a *R/stochastics.R 599b501bf9be58bc4b3f1521cc2765a9 *R/ultimateOscillator.R 08b19aa327a335869f5060dbba02c885 *R/volatility.R 5a98cbf12094c96f5f2dfb50d1466a8b *R/williamsAD.R 55f464d5b42ae9ec4db73f2e284180e2 *R/zzz.R a212f905677273e63fb5d4f446221a7a *README.md b1c8cbf5900675293703086a0ef1f6b4 *THANKS 87ea4a9a2345d378b6078ac2b113a4a5 *data/ttrc.rda 9fd9d95de07300305cd03043f5deb78e *inst/unitTests/output.MA.rda 2b069196541112fb347327484e7f7c65 *inst/unitTests/output.Oscillators.rda 8adfcbe30d3945415a806bb702c23705 *inst/unitTests/output.misc.rda 559e27421f85a7cb6aec1d3b3ed11359 *inst/unitTests/output.overlays.rda 503d4b12d9aed8e29d9ee9f6d8c7b042 *inst/unitTests/output.runFun.rda d915468b754088dde08ed66d4c14df67 *inst/unitTests/output.trend.rda 7eeabaf711fb54d77e5adee740bb9991 *inst/unitTests/output.volatility.rda a733627e9696f857173f03255607997a *inst/unitTests/output.volume.rda 2241426f086252acf482b0e92cb28472 *inst/unitTests/runit.TTR.DVI.R c0363c2ab458d6ac4c4442c50e5b1f21 *inst/unitTests/runit.TTR.Misc.R c1d6281c9ed1ad929f630f3661e6c41f *inst/unitTests/runit.TTR.MovingAverages.R 979fa570e8851d9bf675d11ad6c06f1d *inst/unitTests/runit.TTR.Oscillators.R d10487a07e9489bb5d138dd25168f912 *inst/unitTests/runit.TTR.Overlays.R 26d3020e63f889c038e950a906f5d5af *inst/unitTests/runit.TTR.Trend.R 23af9d7dd64933d82f90f39d4d9b3e09 *inst/unitTests/runit.TTR.Volatility.R e44ce1bd3ed063db4e53dbd71d2d4556 *inst/unitTests/runit.TTR.Volume.R 9328e4fce907ec7726f2e1125372adf0 *inst/unitTests/runit.TTR.runFun.R a178fecb04047833aff9a22db7259ed1 *man/ADX.Rd bac3718cd875adc8dab607ca5c93855a *man/ATR.Rd 818b132a12972901f2c4556351f5937b *man/CCI.Rd bd8f0c5aad31120300dfc7dd8735bbc1 *man/CLV.Rd 959f51eac1922f78131f58aa5439e73b *man/CMF.Rd 89553f70cd2a4331e63ebb36c9925b9e *man/CMO.Rd c3d9e2901bb8c7b4972ddcbb525eddf6 *man/CTI.Rd ebc97dcaff64b52db8e8ad7d00c68938 *man/DPO.Rd c918150a188706b5d616509505b7b9c8 *man/DVI.Rd 362925b46e91b35a086d25aab25ad488 *man/DonchianChannel.Rd 2d5a49e6178257c35b09563395b89961 *man/EMV.Rd b43069983760cb40742e130b534829d5 *man/GMMA.Rd 2a4b406da2c12ca61b1092127a62b394 *man/KST.Rd a8cb4396fcd4a1cc9b48320c2a4ca30f *man/MACD.Rd bde31e7093e3b2ca3a20a4563067a225 *man/MFI.Rd 5312b2345eb3c70e7c5588dcd8a9be47 *man/MovingAverages.Rd 720f0db7ba2b79114df6ca48886583c4 *man/OBV.Rd bc35a8fd9676877f97d8f705d3d7c5e3 *man/RSI.Rd 05bfd70ac33d93b54cef2f3bce5c5af2 *man/SAR.Rd 9e3fbde1a874ed1d33de38817d256710 *man/SNR.Rd 19120589a857a780912f3c071cca2295 *man/TDI.Rd ac206eab08410517c1052165787edb40 *man/TRIX.Rd 42cf34ca997a23c2b2e41fb2e76bc4ed *man/TTR.Rd 4111fb0a6445697720bfdd6c52fff091 *man/TTRtools.Rd f705c5e8ed9856109445eb509ee63db8 *man/VHF.Rd 3962a97f48a88970e7ef74791b7795ff *man/WPR.Rd 80066b99e9679bc978c97f2ff3f75874 *man/WebData.Rd d50423da4c9adeddbbd78602cd401d16 *man/ZigZag.Rd 8bcaaa9ab40fc5c99de653e74008fd12 *man/adjRatios.Rd a6ff98e81dd6a1f7c5530e69787bd9de *man/aroon.Rd 58cd8c30b90a647e9bd5aaeff80267b0 *man/bollingerBands.Rd 8ecef6c95628a76fb26e1542f4b1a241 *man/chaikinAD.Rd a19e0da92a233a6fdb431c513e58cf57 *man/chaikinVolatility.Rd 7186fa980f198dd49c1228158b801784 *man/changes.Rd 50653924ec559e38f2b3fe6e783ec5cb *man/keltnerChannels.Rd 7c1d44f527ce04ea10b5ad37e3b8cd1c *man/priceBands.Rd 74bfdb3165af5bb9345e83bc57b1e11f *man/rollFun.Rd 581b1da86328bf703c2be915e9946c4a *man/runFun.Rd 74f8f65a557e644fdf15b01a21830ebb *man/runPercentRank.Rd 33401a58f235933b5f211174993d77b6 *man/stochastics.Rd 244405c4c111cf177be1144214a1b81d *man/ttrc.Rd a66b577d78b3c39ebc1255c6a3eb9bd9 *man/ultimateOscillator.Rd 5045b57cdcb3222b3a8488355e097e01 *man/volatility.Rd 2fea3b2705547ef4c3e3e34d225837e4 *man/williamsAD.Rd 5395f9c744f3a30dfe9d6dd894df0de9 *src/adjRatios.c d45985b3aff376ea5b6cfa72d0d9222e *src/aroon.c ba1dd058ca8b89e79f10153941efe55f *src/init.c 8bb973ab0e238449aafbb438bd0478cc *src/moving_averages.c 78284b6333b75d481b1264aec408444f *src/percent_rank.c b691e894d2153adb5da19312b9b3d7d5 *src/runfun.c 10a1303730f1347afd27796d865fefb9 *src/sar.c 3a76fa12f543b76e919aa763e4683306 *src/ttr.h 6031151e14acaa35135efe0955d05d70 *src/wilderSum.c 5967b495255002a0209d171ba200f952 *src/zigzag.c 5a0829eae4b658df818c959ef8178567 *tests/doRUnit.R TTR/inst/0000755000176200001440000000000013130160523011672 5ustar liggesusersTTR/inst/unitTests/0000755000176200001440000000000014531142730013702 5ustar liggesusersTTR/inst/unitTests/runit.TTR.Overlays.R0000644000176200001440000000365514450607776017472 0ustar liggesusers# # RUnit tests TTR moving averages # # test reclass works and throws error # test xtsAttributes, both CLASS and USER # test all.equal(CLASS) and !all.equal(CLASS) cases # Create input data data(ttrc) rownames(ttrc) <- ttrc$Date ttrc$Date <- NULL input <- list( all=ttrc[1:250,], top=ttrc[1:250,], mid=ttrc[1:250,] ) input$top[1:10,] <- NA input$mid[9:20,] <- NA # Load output data load(system.file("unitTests/output.overlays.rda", package="TTR")) ################################################# # Bollinger Bands test.BBands <- function() { ia <- input$all[,c('High','Low','Close')] it <- input$top[,c('High','Low','Close')] im <- input$mid[,c('High','Low')] rownames(ia) <- rownames(it) <- NULL oa <- BBands(ia) ot <- BBands(it) rownames(oa) <- rownames(ot) <- rownames(input$all) checkEqualsNumeric( oa, output$allBBands ) checkEquals( attributes(oa), attributes(output$allBBands) ) checkEqualsNumeric( ot, output$topBBands ) checkEquals( attributes(ot), attributes(output$topBBands) ) checkException( BBands(im) ) } # SAR test.SAR <- function() { ia <- input$all[,c('High','Low')] it <- input$top[,c('High','Low')] im <- input$mid[,c('High','Low')] rownames(ia) <- rownames(it) <- rownames(im) <- NULL checkEqualsNumeric( SAR(ia), output$allSAR ) checkEquals( attributes(SAR(ia)), attributes(output$allSAR) ) checkEqualsNumeric( SAR(it), output$topSAR ) checkEquals( attributes(SAR(it)), attributes(output$topSAR) ) checkException( SAR(im) ) } # Zig Zag test.ZigZag <- function() { ia <- input$all[,c('High','Low')] it <- input$top[,c('High','Low')] im <- input$mid[,c('High','Low')] rownames(ia) <- rownames(it) <- rownames(im) <- NULL checkEqualsNumeric( ZigZag(ia), output$allZZ ) checkEquals( attributes(ZigZag(ia)), attributes(output$allZZ) ) checkEqualsNumeric( ZigZag(it), output$topZZ ) checkEquals( attributes(ZigZag(it)), attributes(output$topZZ) ) checkException( ZigZag(im) ) } TTR/inst/unitTests/runit.TTR.Volume.R0000644000176200001440000000641414450607776017131 0ustar liggesusers# # RUnit tests TTR moving averages # # test reclass works and throws error # test xtsAttributes, both CLASS and USER # test all.equal(CLASS) and !all.equal(CLASS) cases # Create input data data(ttrc) rownames(ttrc) <- ttrc$Date ttrc$Date <- NULL #input <- list( all=ttrc[1:250,], top=ttrc[1:250,], mid=ttrc[1:250,] ) #input$top[1:10,] <- NA #input$mid[9:20,] <- NA #iAll <- as.matrix(ttrc[1:250,]) iAll <- ttrc[1:250,] iTop <- iAll; iTop[1:10,] <- NA iMid <- iAll; iMid[9:20,] <- NA hl <- c('High','Low') hlc <- c('High','Low','Close') cl <- 'Close' # Load output data load(system.file("unitTests/output.volume.rda", package="TTR")) ################################################# # On Balance Volume test.OBV <- function() { checkEqualsNumeric( OBV(iAll$Close, iAll$Volume), output$allOBV ) #checkEqualsNumeric( OBV(iTop[,cl], iTop[,'Volume']), output$topOBV ) #checkException( OBV(iMid[,cl], iMid[,'Volume']) ) #checkException( OBV(iAll[,cl], iMid[,'Volume']) ) #checkException( OBV(iMid[,cl], iAll[,'Volume']) ) } # Chaikin Accumulation / Distribution test.chaikinAD <- function() { checkEqualsNumeric( chaikinAD(iAll[,hlc], iAll[,'Volume']), output$allChaikinAD ) #checkEqualsNumeric( chaikinAD(iTop[,hlc], iTop[,'Volume']), output$topChaikinAD ) #checkException( chaikinAD(iMid[,hlc], iMid[,'Volume']) ) #checkException( chaikinAD(iAll[,hlc], iMid[,'Volume']) ) #checkException( chaikinAD(iMid[,hlc], iAll[,'Volume']) ) } # Chaikin Money Flow test.CMF <- function() { ia <- iAll[,hlc]; rownames(ia) <- NULL it <- iTop[,hlc]; rownames(it) <- NULL checkEqualsNumeric( CMF(ia, iAll[,'Volume']), output$allCMF ) checkEqualsNumeric( CMF(it, iTop[,'Volume']), output$topCMF ) checkException( CMF(iMid[,hlc], iMid[,'Volume']) ) checkException( CMF(iAll[,hlc], iMid[,'Volume']) ) checkException( CMF(iMid[,hlc], iAll[,'Volume']) ) } # Money Flow Index test.MFI <- function() { ia <- iAll[,hlc]; rownames(ia) <- NULL it <- iTop[,hlc]; rownames(it) <- NULL checkEqualsNumeric( MFI(ia, iAll[,'Volume']), output$allMFI ) checkEqualsNumeric( MFI(it, iTop[,'Volume']), output$topMFI ) checkException( MFI(iMid[,hlc], iMid[,'Volume']) ) checkException( MFI(iAll[,hlc], iMid[,'Volume']) ) checkException( MFI(iMid[,hlc], iAll[,'Volume']) ) } test.MFI.when.volume.does.not.change <- function() { x <- structure(c(6284.19, 6284.19, 6284.19, 6284.19, 6284.19, 6285.22, 6285.96, 6287.54, 6287.84, 6287.89, 6288.95, 6284.19, 6284.19, 6284.19, 6284.19, 6284.19, 6283.98, 6284.20, 6285.54, 6286.71, 6286.58, 6286.75, 6284.19, 6284.19, 6284.19, 6284.19, 6284.19, 6284.46, 6285.54, 6287.47, 6286.92, 6286.82, 6288.95, 9171293400, 9171293400, 9171293400, 9171293400, 9171293400, 1650189487, 1796244384, 1864666606, 1845475611, 1831082797, 1918533018), .Dim = c(11L, 4L)) o <- c(NA, NA, NA, 50, 50, 100, 100, 100, 100, 66.95494, 67.27551) m <- MFI(x[,-4], x[,4], n = 3) checkEqualsNumeric(m, o) } # Williams' Accumulation / Distribution test.williamsAD <- function() { # non-xts ia <- iAll[,hlc] it <- iTop[,hlc] im <- iMid[,hlc] rownames(ia) <- rownames(it) <- rownames(im) <- NULL checkEqualsNumeric( williamsAD(ia), output$allWilliamsAD ) #checkEqualsNumeric( williamsAD(iTop[,hlc]), output$topWilliamsAD ) #checkException( williamsAD(iMid[,hlc]) ) } TTR/inst/unitTests/runit.TTR.Oscillators.R0000644000176200001440000001475314450607776020165 0ustar liggesusers# # RUnit tests TTR moving averages # # test reclass works and throws error # test xtsAttributes, both CLASS and USER # test all.equal(CLASS) and !all.equal(CLASS) cases # Create input data data(ttrc) rownames(ttrc) <- ttrc$Date ttrc$Date <- NULL input <- list( all=ttrc[1:250,], top=ttrc[1:250,], mid=ttrc[1:250,] ) input$top[1:10,] <- NA input$mid[9:20,] <- NA # Load output data load(system.file("unitTests/output.Oscillators.rda", package="TTR")) ################################################# # MACD test.MACD <- function() { checkEqualsNumeric( MACD(input$all$Close), output$allMACD ) checkEquals( attributes(MACD(input$all$Close)), attributes(output$allMACD) ) checkEqualsNumeric( MACD(input$top$Close), output$topMACD ) checkEquals( attributes(MACD(input$top$Close)), attributes(output$topMACD) ) checkException( MACD(input$mid$Close) ) } # Stochastics test.stoch <- function() { # This mess is because data.frames' attributes don't come through reclass() well ia <- as.matrix(input$all[,c('High','Low','Close')]) it <- as.matrix(input$top[,c('High','Low','Close')]) #rn <- rownames(ia) #rownames(ia) <- rownames(it) <- NULL oa <- stoch(ia); #rownames(oa) <- rn ot <- stoch(it); #rownames(ot) <- rn # End: mess checkEqualsNumeric( oa, output$allStoch ) checkEquals( attributes(oa), attributes(output$allStoch) ) checkEqualsNumeric( ot, output$topStoch ) checkEquals( attributes(ot), attributes(output$topStoch) ) checkException( stoch(input$mid[,c('High','Low','Close')]) ) } test.stoch.for.Inf.fastK <- function() { a <- c(53.99, 54.69, rep(55.55, 3), rep(52.5, 13), rep(51.77, 2)) idx <- structure(1446422400 + cumsum(c(0, rep(86400, 4), 259200, rep(86400, 4), 259200, rep(86400,4), 259200, rep(86400, 2), 172800, 259200)), tzone = "UTC", tclass = "Date") X <- structure(c(a, a, a+0.1), .Dim = c(20L, 3L), class = c("xts", "zoo"), index = idx, .Dimnames = list(NULL, c("High", "Low", "Close"))) o <- structure(c(rep(NA, 9), rep(0.0327868852459021, 5), rep(0.5, 4), rep(0.136986301369856, 2), rep(NA, 11), rep(0.0327868852459021, 3), 0.188524590163935, 0.344262295081967, 0.5, 0.5, 0.378995433789952, 0.257990867579904, rep(NA, 13), 0.0327868852459021, 0.084699453551913, 0.188524590163935, 0.344262295081967, 0.448087431693989, 0.459665144596651, 0.378995433789952), .Dim = c(20L, 3L), .Dimnames = list(NULL, c("fastK", "fastD", "slowD")), index = idx, class = c("xts", "zoo")) s <- TTR::stoch(X, 10, 3) checkEqualsNumeric(s, o) # TODO: delete line above after xts is released w/fix for #322 #checkEquals(s, o } # Stochastic Momentum Index test.SMI <- function() { checkEqualsNumeric( SMI(input$all[,c('High','Low','Close')]), output$allSMI ) checkEquals( attributes(SMI(input$all[,c('High','Low','Close')])), attributes(output$allSMI) ) checkEqualsNumeric( SMI(input$top[,c('High','Low','Close')]), output$topSMI ) checkEquals( attributes(SMI(input$top[,c('High','Low','Close')])), attributes(output$topSMI) ) checkException( SMI(input$mid[,c('High','Low','Close')]) ) } # Relative Strength Index test.RSI <- function() { checkEqualsNumeric( RSI(input$all$Close), output$allRSI ) checkEquals( attributes(RSI(input$all$Close)), attributes(output$allRSI) ) checkEqualsNumeric( RSI(input$top$Close), output$topRSI ) checkEquals( attributes(RSI(input$top$Close)), attributes(output$topRSI) ) checkException( RSI(input$mid$Close) ) } test.RSI.does.not.overwrite.maArgs <- function() { wilder.and.matype <- RSI(input$all$Close, maType = "EMA", wilder = FALSE) wilder.only <- RSI(input$all$Close, wilder = FALSE) checkEqualsNumeric( wilder.and.matype, wilder.only ) } # Chande Momentum Oscillator test.CMO <- function() { checkEqualsNumeric( CMO(input$all$Close), output$allCMO ) checkEquals( attributes(CMO(input$all$Close)), attributes(output$allCMO) ) checkEqualsNumeric( CMO(input$top$Close), output$topCMO ) checkEquals( attributes(CMO(input$top$Close)), attributes(output$topCMO) ) checkException( CMO(input$mid$Close) ) } # De-trended Price Oscillator test.DPO <- function() { checkEqualsNumeric( DPO(input$all$Close), output$allDPO ) checkEquals( attributes(DPO(input$all$Close)), attributes(output$allDPO) ) checkEqualsNumeric( DPO(input$top$Close), output$topDPO ) checkEquals( attributes(DPO(input$top$Close)), attributes(output$topDPO) ) checkException( DPO(input$mid$Close) ) } # TRIX test.TRIX <- function() { checkEqualsNumeric( TRIX(input$all$Close), output$allTRIX ) checkEquals( attributes(TRIX(input$all$Close)), attributes(output$allTRIX) ) checkEqualsNumeric( TRIX(input$top$Close), output$topTRIX ) checkEquals( attributes(TRIX(input$top$Close)), attributes(output$topTRIX) ) checkException( TRIX(input$mid$Close) ) } # Willams' Percent R test.WPR <- function() { # This mess is because data.frames' attributes don't come through reclass() well ia <- input$all[,c('High','Low','Close')] it <- input$top[,c('High','Low','Close')] rn <- rownames(ia) rownames(ia) <- rownames(it) <- NULL oa <- WPR(ia); names(oa) <- rn ot <- WPR(it); names(ot) <- rn # End: mess checkEqualsNumeric( oa, output$allWPR ) checkEquals( attributes(oa), attributes(output$allWPR) ) checkEqualsNumeric( ot, output$topWPR ) checkEquals( attributes(ot), attributes(output$topWPR) ) checkException( WPR(input$mid$Close) ) } # Ultimate Oscillator test.ultimateOscillator <- function() { # This mess is because data.frames' attributes don't come through reclass() well ia <- input$all[,c('High','Low','Close')] it <- input$top[,c('High','Low','Close')] rn <- rownames(ia) rownames(ia) <- rownames(it) <- NULL oa <- ultimateOscillator(ia); names(oa) <- rn ot <- ultimateOscillator(it); names(ot) <- rn # End: mess checkEqualsNumeric( oa, output$allUltOsc ) checkEquals( attributes(oa), attributes(output$allUltOsc) ) checkEqualsNumeric( ot, output$topUltOsc ) checkEquals( attributes(ot), attributes(output$topUltOsc) ) checkException( ultimateOscillator(input$mid$Close) ) } test.ultimateOscillator.monthly.xts <- function() { stopifnot(requireNamespace("xts")) # Ultimate Oscillator on non-xts monthly data iam <- xts::to.monthly(input$all, name=NULL)[,c('High','Low','Close')] rn <- rownames(iam) rownames(iam) <- NULL oam <- ultimateOscillator(iam, c(2,5,8)) # Ultimate Oscillator on xts monthly data xia <- xts::as.xts(input$all) xiam <- xts::to.monthly(xia, name=NULL)[,c('High','Low','Close')] xoam <- ultimateOscillator(xiam, c(2,5,8)) checkEqualsNumeric( oam, xoam ) } TTR/inst/unitTests/output.volume.rda0000644000176200001440000002115514450607776017264 0ustar liggesusers{PI5"0E 0 E1"s!'Q0ADQŀŌa^n߭Ny;<}}-Jǖ&f+&$$$,4\pޏ" nGHޟ?zջ:ɿsa7lhNU|,o𸜏&G' 7>-lSjCnwj<cS >ħ1"+7g^6neg3nG 1`7.+Ohqco '7Ү7q+&^ w :9xG1J,~BKE31 d;oR˵uz>m8$ҟ10_%9gS>7 1 \y׭!uO'^ ˢ#v`_,KLTgL(xyo7)/!g;Wtk7M</Gçx8E=,C][b٧ty_Ȗ܏"W>xhKb><㶨`3.hvk|.ܱwcL:dL\#8&|Kquc_v]"e6wT`NQ_ѵxY]11?eI>9)^/v%8yxq}`^SEaܦ0 +Dmx =66.\:]0mo'D[ V3 d~Gc^6 ;<9ukSJ$m\7iZTyJPfܮY9"mnt#lF}ކ}h%!mIE ȋF/[|Nn.u7z(WJQa&kѫses;;n&y/Rը3qEއ9g!F4'uP\^\F>M֋5 &^};<{پn%(fپ)(Hʦ֣#MhiO=QpQA*O] uư \ǫF.eA 30QwG-}-c[# pFjL kSQ"֙>r{s g;؊@lPxژo/}G!r艇;A2#icr vcXmfw^@a%{Sϣ1OԽCOF@aU2uQX2Ojش(?g (Aa_͌Ӝy.g}@= #FrPHUf"wf>yf{!_EĵA1Fe1p} C^Sz Q_PSo8e@kv|c(tl`5zq q Qz<` q- s{^ǀyyG~k>NqޫC;9e"?K` J uAv%g{y#{/9e|hrD0sX$م|$O1 E7,D#er6 7l[(X{3n($'d!)[cϷ08>u3#7 8'3uxӑq=I(̸ŏbc' t /i'RYPh{o*3}&b FlE~wͺWK7tSZ&JZ-]"lf8GENK pjP r }͆0iXP4ݺhY(?96pJ;oj!K[3<\K}Zȑb8On6/ɝ'*(b,VTZH#"DNDTF!RR!" "BDC#֢{{Ј|hZޕ+ɇ :Q!" "JDC#CEhDD /)b<"NiNB`U`U`U`U`U`U`U`U`U`U`Uг22222224"wC%%:;,?BDDD0F24T2!Za ѼD*w'awX%!yVxU"aboJ[-?B5T;~*DE0_lFf_CPhrno@SiP{I ~oJ( 쟟 \ި1Id|Gcq Az#g_({< /} .bΐ|+._|X?TL<OPa*#Zjj5 Υ&(i֞{lp#g 0f p~_< lu[zϳ%]g6zNuYn/ؽji=m \z'{f^?7#O9>!;W2eeDcel#&q}~s9;,礮Y'(pgkJ}U6in[gGL=/9k?OK=^ MT\trPP,!"䋺LIGK.qݷEk㼉b$1'onss_.ڷRc[b.-%r~U'g֏7 Sc\%~i)tX hO8^?3g ϭ0pŠ|ǩϠ\7SsK&)dg~Դ{T~t/ m/3mfqA^4hhpܰz+ )Z9 P.z JzlҊ@X?ܰ߷~O+W῏+Dw=:#? ?{PI] rwSz ȟ/..#]6"7"4Tg8—T)HS8N)ڵ5eSレ,KkH BinN3ޗnN-Iu}ۍdAmV_$+%PRKAECÕ=֠Ԃe|-p}_U7puG߯9~32W_TW+W 6U gFI6Jۧrc@>SM#rpvmlQ7!ac1&7@Qn]1,'ϔڒc_wjԐ("ZtX5]A@ߤZi0-|ukz#5Q?~5TE5w,W,+5YK2LAӰۇu@CL-PX^m]P'4q%Şw.YzYj۟o uf!_H͚ hK/[ A_;y=>:k^o[ϏjW̞zD=muf_KTkPsx;nmʏO-[(́fwWNUyezA]O^"vhzfhV}zШ k$͖fq'zx+T_l.uk'>-τ:iic ӓG㄄m@ec۠+BC BáIEcAݫ6MluvCKǴ퇡Uёՠ՗f}*(v;h10*ն[ [Ʃe\[B@"U}:xq6d%x2hPl7=ZhS\3\{s&Z8Zx Z\r hur|pʹ\gg<2Qʆַ뀖%+amցyhWuEf-;z- ͩ/s;WU  gZ}i{9}v.ε_m+?m2+GMZy|C !UB'J;[hɀ/>hjäBËZiuP^c5 P?zǭp1{Amo8ђ>+PΥU'^hh k"R_eh^ oV0. Z=~84cGBC5;!CgXxAj,LCԍݰǠk(S(5v ܘV2ꚇgC4v𗌃HiVPiA`M4Z9Tph\:0[w>?m fBH)gOn~Ccv6ul>qwpYI A8fZpSP73i6A=uy 7B9P[&!wmU^x GG`Ռ{3BYyP39JOS#tz޳*Y Le'> Xw悦4ԖXuMɵD꿴[LmY B,/-؊m߮hJZ͠?iR{m; qZW{h#h'4wX\[5WZ)E.ꑜmghm*ӵl;V4h6#4w¯ F0hRٙ U L-Ѝ6v%Aurw/Ci=Z֋UBK %qƳja>N=h<__ _ __锯__!^O5(_]C|_|^oA|]˅(_W|]?FS΢|=!>z_|dW _/|=y)_oᆴᔯ'PnG׫)_/|}떔|݇u(_O_zѿ7}C_k~\WS@z)|}/|_z_/범S^ _ _w|}<;)_7|_;~(_7D{W׳)_뫆Vם~#M_뱔+_饖=!ʅ{" pu?+an?Yp2q»|p׻ԲTvz&v pW4wr&Fl S@ N;]&-h @B#ȿ~}(_O=X}`@o)Qzҡ͠tHyA/<ė߱%>/yx#j~gW>A?[`;al:{E~~xAW05 NM S |_c8>߶HݫX q^9^χ0 tҩʀQJi;CmAl[5C xy/mJWI鯋=nקt_POpN /:'QptBI>xC@ kxo)y |3:^~(eP7!oIvm̵VP[#zh}oyp{fgӳqg+l۶՝7WaUITTR/inst/unitTests/runit.TTR.Volatility.R0000644000176200001440000000457314450607776020026 0ustar liggesusers# # RUnit tests TTR moving averages # # test reclass works and throws error # test xtsAttributes, both CLASS and USER # test all.equal(CLASS) and !all.equal(CLASS) cases # Create input data data(ttrc) rownames(ttrc) <- ttrc$Date ttrc$Date <- NULL input <- list( all=ttrc[1:250,], top=ttrc[1:250,], mid=ttrc[1:250,] ) input$top[1:10,] <- NA input$mid[9:20,] <- NA # Load output data load(system.file("unitTests/output.volatility.rda", package="TTR")) ################################################# # Close test.Close <- function() { # Why does the last two checks fail if they're first??? #checkEqualsNumeric( volatility(input$all[,c('Open','High','Low','Close')],calc='close'), output$allClose ) #checkEqualsNumeric( volatility(input$top[,c('Open','High','Low','Close')],calc='close'), output$topClose ) checkException( volatility(input$mid[,c('Open','High','Low','Close')],calc='close') ) } # Garman Klass test.garman.klass <- function() { ohlc <- c('Open','High','Low','Close') checkEqualsNumeric( volatility(input$all[,ohlc],calc='garman.klass')[["x"]], output$allGK[["x"]] ) checkEqualsNumeric( volatility(input$top[,ohlc],calc='garman.klass')[["x"]], output$topGK[["x"]] ) checkException( volatility(input$mid[,ohlc],calc='garman.klass') ) } # Parkinson test.parkinson <- function() { ohlc <- c('Open','High','Low','Close') checkEqualsNumeric( volatility(input$all[,ohlc],calc='parkinson')[["x"]], output$allParkinson[["x"]] ) checkEqualsNumeric( volatility(input$top[,ohlc],calc='parkinson')[["x"]], output$topParkinson[["x"]] ) checkException( volatility(input$mid[,ohlc],calc='parkinson') ) } # Rogers Satchell test.rogers.satchell <- function() { ohlc <- c('Open','High','Low','Close') checkEqualsNumeric( volatility(input$all[,ohlc],calc='rogers.satchell')[["x"]], output$allRS[["x"]] ) checkEqualsNumeric( volatility(input$top[,ohlc],calc='rogers.satchell')[["x"]], output$topRS[["x"]] ) checkException( volatility(input$mid[,ohlc],calc='rogers.satchell') ) } # Chaikin Volatility test.chaikin <- function() { ia <- as.matrix(input$all) rownames(ia) <- NULL checkEqualsNumeric( chaikinVolatility(ia[,c('High','Low')]), output$allChaikin ) #checkEqualsNumeric( chaikinVolatility(input$top[,c('Open','High','Low','Close')],calc='rogers.satchell'), output$topRS ) #checkException( volatility(input$mid[,c('Open','High','Low','Close')],calc='rogers.satchell') ) } TTR/inst/unitTests/output.Oscillators.rda0000644000176200001440000010474514531142730020242 0ustar liggesusersXM6. A% # K0 f%(fHHsNYls?gw_ʩYkMwUuռXhYk1Ba01`gDYIfg'Gg' l˰nK"b{QȼgrHd޺R LQ-̋$RTkAՕne/* dV1퐩'Z1d<"0.ϹRRoFѽ`",{-5)q=x{ߔ%{z 6=|Yt0\6-!«hf}w=%d|y,W|L>"%CF)bH½HyMEH}=%(R7%muw|m)ҺԖUƜy#6C]+Bw"CՐQ8d<[6ik~d.VuS7 P7p*@ܼ5nFF8*#ZHGk. 6K7o?{7Vwj,Hʷa(y+gmB$ o]g8E]eVh q{CL=(7wtl ꗖ89Fb`%Q_"mz0U :'-%6Fpr #^˗aџ`8cyw˳ws2ۗ1Z.av՗`K1v0Qf09ѥ!roA;anYp܇L"Ȱk SoQH"dId^47Cs yo…)vÅlw:!0ro nпrY b(e%7臘>( Zwy5)/|[f)puɻ=KTjŗ@$# m;j+>v#UVwG]z؂h]rBYpBN4gl(ۄ|2]Oߍ%k]BZ>~ Si4/qD\燗 UMK ?#5o=Nfp-FV*w|TyJLY}fZQe1hm<|-zܚS ~zh ƻ4:Fh%yA=wi8} ~+_a6nnυ׷` `J.`S3]0xh(3 ^nZ#gӫ+Gܖ18oc XO/ڳU`gj\GguCC`pza{d|Ly O!E)‘|R+Sh )}=|S` ksG[G`"NV0DE֏!0Ƣ_ F7lN*#LlR%`8QdJ}U0lr30S=; 27WGe|B>:{_~ڄ\ʊA, EJ:v#zPơ7γ|=pq (9Sl9~},~~z ;^(Xk4> rBgW3Np^! ·9 37dHɩR@Bԗ}6PD~.kA~4nNDjdh! ۂ_jѐ& 2R[@da#-'7ҩ~<-=ҝ‡H* "'g:^.Ky!K}A\埈 RmGsЪ~dvΪ⵷[o! 7D#c .f}{cad=߄ 2|K,'|5;=|biHCvtO'퐖''w)3 A#+GoA*_F |<[?Zv'5Y"\:eg eA/|st@qp³i9ǀDhK^t'o'zOOS```So0N[=rXq  zLYAq`RhΊ[ӰWW O8z_fٽ`ڈS9`3+7NƁç_nIk/ӷ^~ QvA+1Q2~|)'  I9o!%ˍ?;[A񌇏S(?}ȩ'4;߳a:y🉁Ǐ:h?Y%^D&yV'~؄߻`2'w<:Z;+ \cMI =wK-Qfoٔ~ile\`pau`w*  <#άqc-ZÚ{[&෠OwoF?rv]`MO/qt _=@8ႮaTQ~p2a`jm.{Ϙݹ"YaII}I}tXFW=T0жvEt0xc)0Wxх'rD^}롳Ƞ%T4/AU/V~P/Am( ^Rgr\b Gv +K"^1RU Ƃ0;qI(~яě}[\2Jk4P#((xVdat4c*D>xl:Q,-9)v ' [ KYD#' !;i& kYKS} ʗ~r(E/؋ |;tU+[t7ayMr=r2/cn727h0goVJA&XXL1|Z>p P7޼2QI T6dꉹ!}]w,@-XfMHٽ}^OƑ ǏbrT/]!o2sdZ#'{'}u+\J |Rx->)ps,OxN#7'>L'>˗.F}߻q0PZ0O NyO lO |ZO \]O Dn'܅O \O /gv-ն':^'5~'bEuI N.|R=tl'\=N7俻nO`CAQ0vu VB/0W˯31ϲ@˃oɠ6bv?,ɷM4S\v!Y52 Gn>x !ү!T8&mx6 kZ^}?`f T{U^镌W&aw# X.F꟮} 60sE T9l/T<4uzSp3v4^jAAyʘV3HP3] <'|kl 8%{i!+&= In֋  %/^ނka9̼mxEM.7j h*λ_0]gv_ <5Hkh^}D})\wkRgϊmظ[%0#Ɠ+70FUc^`|W(_׳;eD$sO0~|lRD6TK![43RvשK7ke ?W .u_ ҝ+΀񼃮(rfl0fg!k,îd *lOL=`k_`21"y;0n|fok՗LWҠ#g }: 6! //fT"*NT[ǿ2P@Iۼ[AB@fMDG.kvr۱F鼗0q~ [ rAmGAN,S2 ֦Rqp=J[$D*=k$qy\G 7I igQҤ!C>i Fimr4GNvb7k%ǦUQrH#\JB"+$_BܘbD ~#9oo0!÷s z_"wǶDFe0mC\2FF_yZo0嚅 t̜F->NV!7'kyI7dzI+@z+>)_8 ('b* Xn!)@K>)p96O te/w'7O}'GI@3 2a!-!|RgO :StǷ`Oo+WJB6ڐiLt$~$m:w7УvY)}q<dx~}м[ihpq[9Y}j%hlO4AE{Ԧ{rIov9As2)t7xވy|Z@i4E vhР"th/?q tZkg6z?tY3sO μe h7)Ѐř׃U7_j:=,qo| EM3I??*܊V?A..b_YP D+/+dc@;j.kx${rYWߝ=- kЩ̫th7+Vb@;h,*KZ5=#WabIo@ozIzA80#Y[:z>Aۉ~bގqƠǑpy71ǒ"`#D 7[Y 5<])mⲃ5hE@nS&s?$],J3^Jqzdn|gwQ< 4GOꃎ^\M?) 磁h=]v5gJ]v9A?#H?_}RxQxP"|s|zܛd3gFT@t8t8Vxy@ "*yFo\~)@7=<6ѝo%+%qӺйNf|Xd6|8VNo!aE&B7?6vcI}kvytg,uCԍ;s菜g/A| o 46rA17~6dܡ>Uzl 0ck/ݙ =O.]4U.b%tm  1ݠ;~]W[f~n]~"h2=,Œ2 T  ƏW*ܬ\D۶ C@ctʾ$c+=kX '96,/ؠg[Tyul\?nDTt^yte;=WT>U;Ak}af>drЖ^ږøO9В\JN;PI{u#ys (hX {Dt z h<=eQj$h8w44<<3hӶ5h|Hc霬 *Vz+ 5?/Lҫa/fݗs7&w9e͆{&A'Ѯ/y/QA66)WgbWg|DdD4Qx@[X$QG7I}4cB*v6{n.#hvT1I\?*s/'@Ӌ~O/5A[@SGOŞɲ(;(;*}ܡC4÷Y/?@sw/QeAc m%<:,kCex|K#~hRou|XƋ-Oy ZUu~ۀ{w"4Qϥ0|eI,Ir^!^7;^3z9ہeD}wmOf,6 eiSUJ䵰,8FT{}K@^XbV.GEAQ|]y`ع';caеUصf-zr{TJtyծ2,-_ZT :b-ŭZeLûA)֒&I*:1 e;{{w y &zo[BF}o-kaн{z~oK9z.̵Kv:֞[ :3y30;\Nec*g;ިV̿!&mtoV`tlhy^Y 4*}V >7Wbu]xkiO$A]ҩ!16P64:2cc^t3#(ϗq oVGztp @le;X@ꅭz^ʥ#ે a"ҙ-T3$,ZW *-l (ꨏQAՄsP0I4aBE L.eLw# nOa" V=d\Jǝ gNUqU[j->>#Đ eN6w4 y7A_;ƏH֪ Oֻ V~m CVYUN-姠WPsKX1h, 4dnf:]tNߒza׹>g6ݑ==!ݵN]]|ҠG@?@gŠiYtֶS!^tO{^ӳފ͕EsiNk0ùStGP٬CT mh%(IzRBI$Lox(viP>%t}J3*O&m#Fi%6^]KMR[B@S#FB=h+-Mkˬ7% e$Mxv1V4h|O:JAo/(<{f#qʱ*(O\ W2;Ι "Ŋ;@L/|?}};}RP\.1nc fx~Wy8cp#n;GJv ۠>=s43B9F)E=SZ[D1_ QA;sL>.+}$h9lfw4+Nl;% M>]-fk :-CAksXM+@3Z0:ؽyQԻaj VGֳ$n0a[: h:f\>h[wjhD-q5hgtmKuй'.+ 訉.\/[_g @Dkj,?w-~:' 8@׍?VP@Ww۶.GRY2ItsJ׫ Z\qE]$Lϼî[xh^!mG|> aP~MJyL>1N?6;sXZ*/)%-)%CȒ4r$"IC%iHK4$ \$ICj4=2sɐ.C =2ȐE,GS4r$ݒ[^$rR[>&#tKn[%R[t2A& eAݲ[~'薮2[tKKnM-C eAC-A&[in[t4ny[tKynO-Qn[~ %;A'jA &[ e7At CҌ[t˗R[#ݲ[AN-eA'A%; e"A,"薥:A\H!n[2tKAn)K-tK*A$ݲ[$k A,'rAl&Ad!薖ᇏݒ['Vқ[ztR[FtKn)O-tKqnI-7tKan@-tKvn)N-tK+niI-otK*AJ-C eA%薶R[."A"薯 kn)J-t~nF-= ]n|n[tKIny[t|n)O-s !A,$薮rC)C}Cb{(RʞE+Aa^AePby 6X?J ?Ԡ|P48X!Ӡ'Cχe§jQP'}WqK&E#\p_拸4Xo%\ {C:Jߞbiyomhf1h8Djhz?Գ?+Zip8­kQ P!ϴtO5/nW[N[k=two$4Uw(U԰H9+*<T}.tw}j#ĺ̅BB΂4AXOmò"dVw\yK {\)7x6o kޞ X:` ӎhC lO p3[X[U9._Jn~w:A׉ ҳ ig>ix Pa[H%Mj.Ieтŝg$]Zc+igO)?[=|SW<O2ڶ/0-J^YPS#\Oa( LJ5܋I@EBOF~/G7+*PGF_+@e&:Qt* |Z*G_S#`̉gmu[}= *qygT|[@ȗ'ZqT|AMF.~ P^)(ϨHޣڢqpXUN\@u*)[e$T<,w)v}vE_.QxA6Psk_5uO""P×RSs4Ѕ_Il6ZKߟZ+V*G@G٘ PcDFU-=_()3šSSGBUK_A˚a]PitAmG P4F>PYŹJaYU!jǮ{ޝPϿBE 2p@g]A@Klz o1 uޯ@S`KNvϕ/UC`U: UYPeǣ/P;Pq>{dT(YwXwT D,PKB"@ \@˹ e3CmWmpsk/Ź& ʼnnru뜻'uAFzByMȼmH SJ*ICؓ^p i?U5\T"_JƠsl~.vUs;\7X _9h+C!Ik :pJ!QJRmZ·ZXWHۆ s./=n6r:&Y]y*g0vluTxj1Tt?6TfX9}}c!TYg;B]ˍnm~8{Uc\kOCγDs>+ЭU.bҾQ5{9+1"E PSQYﰸ]WQ)Xȯz5!9s)7 =6 ~O}ۈ,~i^&)pEͼRVCىo3(lI[EcN͂,BۋߟuΤ-<Rׄ*;߁j_=-߽;፣X럕+Ѧ;FՃyɡ )pP[P*dgeXLz!*v~tAwft-2%TVWU :.*zQP"$TE6vײBeΨzn/_Gk2Ivz5**l RG؋ĵ~*r -ĩ8 6ըF:t#o_ۄ]W(g 3(C҇`JcQ|by4s!ϕ wY%P=GAmP+H٧`F@{ &8p @0 iiCL٢*VUB?-A,$4 62"7<B?sq>zdm#dSI 1-"j?۠pfH^te YBu!5P5c[|ǠfdG PP_['jZ⮧7l5O}#5_5`Յr_,N9c j=jK^YICKwPաEך0 |p}˨+PZP *v*nrC3vP-Lv ](KU0G .4|biP4%ƀO& Y`>5X BԘr_V<`?9tt1/"3M9!g@H^9cz 7~L~Ee LPA>ӥI(%z7bЪL۳az]U W|w)€ 繨؇oOhbR~wc@8.K\^2`_eo?0DZ@B?N`?KP])H( '<$Gj} )W= IK`T ?Q1ZMu9b>AHŅP  P %6`̴b€W׷8 O(Ā6_ ?5'l0oD%{=t0ڐ [.ǀt1B̡Kfu-0mǀRni +Q6c?d_jj ?+ `k ɧMb#ܩ7Z1_dtXWX0Q$t?a_B#ƀсnL?€8Hǁj(s#mV/ŁԽ Wdg ǁT63c8>7ā9v8=N%qhTЁSp0H.3YWr ]:i:^D6tGkqE**!gT w\Zn]X6?jo‰x7=DJmd mπ/7톼ꈞ#0zфrVegp>}"*3*r *9S9e1>p߯w896(sqTxmVTU^B.g$[T. kBJCxtDrmT|>T<{}̨Ğok*DGVĝkPq§dPI(5.a P;_OA9+ն2@=GAΊ*JGk.^(qT\yf~v (.^N! s_\QO`]-χn Grڇ/=E7::Y95Pz8T)]lrVA|)($1J^Zl?BE+A9P̾ʴ3ċGuXdpP}I|Px[Pwߍ'Ǡ54)W櫷*ԌJXk{@-7PKI*]l{57(g@ B#~剩,7GI@naھPuCŁ @w+P喧^PYY6#QGC5TݵL_%f0oه'Ŋ0omFLb4!%rJ?~ _y'f 0T(:o% -!1$,=:,|R= 1௶<_l|'P;ZҎ_N+e q1S+ϰ 6sj|8GtŁn8ڀ_Ły p"%8/Ł~MeyāS87:_ 3qϘUƄ]Z:xC_ ҁ=dzMbp?00OY,u{hR3b4WBMAQƛ fگҝ!X]!$a147yB˂9Ra~2 ^8# s[SCOb J> C}E=qɋ[^vshju~ 4y\Y/=9iW~bhʓXMKV\8!4{./N|t]}wxj :7l*7zB폜-z{2ȖK ' @dYC{M]RarW}٘+:,.?.hC]u\AUWx0=q;~0~ u"`/NmsR[wԔsR:o=lWB=9!翡n @]dIlG>_uC!h WveiB@ ?yY<{+ |QЌ[ieh~kU7fAw!;NncC)Ermf h _qgf'۬rn{FKBsS&1asR׆MfB]lk$4OtIn6OMeBQ949\nzA4h0@Cz-ghJt!١./`˽P/5֋" JxEi?vU =))ӇX]~nuM46`uvcX]ED7)RǏaC!cu\uV׋a7ʜeVbz[}[#JX]buyuw3budu<>GV׃"zcd8l_eGuڰt߅^zQDHV]sUsP'zauq:hV(X;q+VקZh\q9"X]qeVsx}buwQX]/z|W au}%khX]T8W:zUi~WB>6Er_c<9Wt`P*ݙ7)"x]{| ^חO+cu]=w52z'[x]?UoKBX]Z;k5^E1uݎMP릞zZe~wNbun9^GuY ^k-v^׵MMeqwQu}q뺲zȆ;y&> ǷI-bjVw^xZ7?輌/ɒx]YxB2u]Au]ޖX]g: ۔}zY`:^m+E^ ԍr]x]w)II^iS*Qx]3uu{" 5]K8Bm: ~@-'Ƙt 70RoJJ]@Eap~5<' W 5Vf{?怲.?A$@p9(N \?GT?pX *{˷BbC=C<]9 lEU*EC"H6`05TMųW8. 5?hBo1Bvr)k #P T-l;EV"=.x&9-ʇ B%s*\OW̪lPu7|զ?/ UP]lQ-^Nh< 'Cp=ȥ Ipf#T4Ņ<B#e;H҄`?ECsԦ?pj*t;܇9u@="n!].% *пh{ka99ko9)Ex*oC(G[(lnm6mt;Ʈ/M^N&hJv4?v34TjУ Z @t*/o# 㗐7ϽvGCe1@y=4u%Fg,Ύ?qM}縷kG_3ȇ:}NwA!T?&TzvܣJvU?7# ݳze+s%Q?KK,6 gy \L_ٸ_ζC]vQsPuB~F9[|JٹAէ? 5?HUY&q'Qu0w8*\Uܾi,r+Po&zK椖ԩf]7[ޏs+hJ##g-Ɇ8*zv-ezeMg@N/Qz F ݁Csq;o`=~% ^u}>_i]G"O5Bbx;%Z#X7q@Ŵ'\( "t6Ag…Q8R}yF̾|.+Z "He;i[C== ťOIx+TPQk[) * 5VP ?{]馀 D{cKC[-Vu|]N^/ERqw B<{d9VHC^ EюESkyMWtma{FAv|/xB څ ps^ W{(Vrx7 i7(+}F 0?xOo/ ~e|4Pz|vk]4sy}4m6N)' Oeڬ?  ?m!d.$hܮeW,4 no@nq $ qĿL3"ξ9kOgoGi5|ޏ6xj)=h@> &36δz>N1zvjyV0ECvM'b|&e6)}\4Qflz]1Hgl^cv?| m( g~~6>Y,mY.!fqkl{foJCKZ}/Zi!S z,ig(nͯ'KD\Pz| $Ǹ&GADBӜ>`ʹքhy.f?=D ?t?-">Dc>A a6{xn]WRZ$~8!M?qX=7y2[7Ӱ8_!GSVW>_|]u}Yo(ME ظ[АMA{.+1U]⫵QD<[ԁM[VrOcEN{YkŌ"mWYecqlS!+Sd>ձ,ÁHaBHԺ6D" MH(Ϟ5Hm:y;H2@$|(PZ y@`;Ϫ/qzc }#D!zV{M@.36^J$]f>IR1 5I+JA}f}z»! #4$DQw5W_}Vjm +iI8χ)(kq}:VWDhǮUbh FNU:bS ?ov $>X=DwQWUVI4.83Aze.h \z[-d|xu_!7 2-ods)%zr0?růw}WAƾ{8u3rkJ%mW?QT^,gu,mp< dw+نS  9i[rM_X.<A~ ((Y U=JLطn[juE;t- bUQ@~ϝFA_ԃF %!ȣ. 更+KC) ;kQE?G!8ȌCM3ǯcVnG)gNE+5H^#J_7fQ@X/V}R 讗`7#nuBŸH_4q|ISl{PSJ&m \OXFЀ_o{C j{01ez<wlL:qv"Â(ymw*D"ޠhH |Gb& QKjWEBH†KҐWTbR>(I~!uO IS):SYkk=tօHڍB@$ͣUc8fx߲cHjRpk!?A2X !(5iH/l mۑԋ>[l55@*X>, b/s. [>a_uz~kB tC>?< 5^5AXܹp/ ޞ(ȍuOPV ,[_-i61\}%>t%?㵒r|KеxJDJhi,tDz0/%~=$1eH7E$*#˲s@B7>u܀1w>4@>qgL\@>'<`E|4_#<W߁D ;zA"@Nt$3ή) 2|p Z㏄'99i [kՕy!zhQK 1m/ҍ^#_\y,t_#q9E׹ҐOk" fN0" L9UH)49$pdIo$6d{Ɇf$:'HV*_O;z%r$ ٻe/#Oì_!n=gJK[Zŏ(K:U^ ڸ_V ,=@Ԯ \y 6(!b XeJrAbu Fǻ;u3;T RQ#< MdO~>G.eM >.Y! 4~+Ȃ V$>Ȑ1vxsdl9;2Jje~ ݉ 2ĊgFlz">c N]jR ٱI?@ΝSJ~ܙYN{ 9=堠=$; "G7=qa;3 }OqiQ@Ꮍ7Ɂe2~!moA]i@@nX~t}8f\sn29#z%-5L6R/T ()~s(5T$_p $Fd.3 ']=~kj._b݂/قX ,A@+% AݷgTR6>'tnYXiŵ̯oeg2K+{{ ;}GCė #' CEwPԽ݈όj]/2W`Ri3Hȃ؃C %뼑p +:#?fG5o@b]NZ$!qyB\Q. I }DpB{:3UU$g| HBIHʄGlԀ5CyktdESntB#^fHR (؈J$W^D? tk*BZ|JzoUyyo$ݱ*iS#@ XWAP91 mUyf]y=;$qDa@O)mw{3i}ULYO «~ٝk@n;/cZ PlAAe\Q>}VY#W O[#qa/ vΥC4]4$d.ѣ1@CU5Hiq ;t PfбFbvky|~GgGz$.Xk )04~Y$k:xle@ CHhfz$IX`0P}oe=wLrĶ@$FY]#DhH:\g A>qIy4=~.qv։G0 $~B @e6&TSS5H6lR0bZC>w1DՍ벫cH{+"l2"w,c'g[lpYvB~BL]3!Ot7;L dhV@yW1:V!wj뭇B wo C4| Sn"ϫ )(vPw5(Jg;|}S +3Q)C(VM? ]\{>5?qCq! sl0K\׿P@S%dg:aYCPC/ℛ0U+['u/!1dSPwC2Yig\L_E^G0J%I$7x!K__=FC]/bD(8G4 K=A1ʦc!}4 {B1d:3)rƑ?K& ǚSp!) s~C[iȋ`nM ; }O`-G)8/8!Ok1俑E1ĉu421&!5<8:(Cޫ 0V3 @1o<C^/=Zxc銔rv nLwO3<;+9?8`rC6NH>v-鼔!qbZa!M D k*mq ^_}r ּrY r !֐ـ!uwuqeUO6Ɛ=M)WxJyO׸b|XFo=b=マr=0t xeBŐ۽fGel;0ɾL!v%!#gs] W}eƐRb]/4Cί< o{1S صC>1&2XC@5b!ȌYtyHߪ2zG #_\U p 2q<.V؏ߣ з}YeoY/ {vn}{,A FPOn#ގ9ٌߚTy[fAĠ ~zBm {QlAn|; >÷\N?B{6oЅ-zqMiAݨxxqnB)(o*vg+ސ9B^nN'z{*$@PsPBPK'ysE }` {o9^JA<o?y;A~ro9O)E'$0'f.7H$A?q^=W=x @3?8UH_7@uOW{A7;6Rȡ߫GkֹIጹٸ2gkM Tv"m@џ?OCϿߟ_kvYN%R/YR]@a+`WvmJgz@y|8h79'.s ϶gٜT. JF%m99'6wF?JΥzBpp<<̍17S< ЇO1 :," B6qNwǑ>@O ՂvO|sW<u fy v^b<}=D?+кO$Πk~a&9Y*5prbnv9,z#~?I^lKm)۞Ho{"(45Zg)۞q =zng)һq Bdg۞d}6$ʒ*K,ɪ$ʒ*K,ɪ$ʒ*K,)eIv%YdgYeIv%YdgƼrl#G6r$ȑ,G-r"Gr$;ˑr)ȑ|!Gr"G-r$_ȑ|!_"O<$˓b^$_ȓ|!O<)I1/O<$_ȓb^$_ȓ|!O<)I/,oVW Y @ $;+b^ $_(|@)H1@ $;+b^ @")I1H"W$E"$+,HpER+,H"W$E"$+,HyER+bJ *TRSI1O%yJdy*)橤C%yJ<TRSIޡC%YJy*)$PIQ"ż)(|DJQDJ$_(|Di(FJ$_(DJQDҿV7q I#Kȑ4$ QW#Mj4=ҤsF!GҹdH}!]R{d"4;$ kIF<%iH;$ k$+M¹$ kH}!__Ȑb^$ +M°$ kH7IVaIאoː,OB$TkH7IVac/633333Cb N_[3f~oߚ5/k_̯_[3f~oߚ4/k_f~s MBy.&B&Qh64c5kf1 v"VCɏۢA}U;u_52GjCj ߡu[ӽ#H5hz>Qd h.„ rzEBwA}o^&zA3P[%9auz)mw&wPo9iɇ~PSPR ;V{@DM/1WPrǠn@]}288ɼ_K迄VQә.t~oj.H.qo4:RV$~4ޑh$L<4Yd?44#K+zȺ\5~ۅ5܉lNFG@{,?UXTY Ԓ7,oj7R&[JVBSG C7 a 5PsAWUԹΗ4(Z$  ЇY_*BCV)(7COh4)asMV>GC{w|c9pP hPtt44}}B_Rn 4MrH:umihPٹwyz/?0qEܰ;=ʸRI_BC1Þx߽#dh@Pf=483*V'm VAAoI\iڙ 4v[w}hE\@ChB" >%?BCVkAq3J|2@| V }6:AܽR_wASo]AR;/Cc[Wu3hZܮW}4 La!5Wuc_HGh@]{5 K;o&XZwnPGHdP+ko_{qp ձ`)uҔ}CDow]udZgk.%^+>p749UWf4 zB ˅#lV~o *5P!EK:݆wCW m=( _-u}eko} Ŏ _ZϛōsǗ,h"x'/\4ݹIy3q7@^d;,Рe6fܖͶzjՖFP9sKEHLZ8f f=//CY9c9ߚ_[3f~o_5/I3f~oߚ5/k_̯_{92222224/i_f~oߚ5/k_̯f~ߚ5/k_̯_[3$>rX]SϮ_QK'?_{1Mcӿ2]7xk~ vt_EرNgm(Äb:/5aCITTR/inst/unitTests/output.runFun.rda0000644000176200001440000003421714450607776017235 0ustar liggesusersy]ӣ|q<zukx\{U[;''@sA.^^P\͟|B'Nֱg|{ _kb%B !\ < !s1A(h!˻:J6PѼBq+ʮ5-GѬ2b qLIN dI\鏹̆ALCθc6.mшCt[0L9[& @L7b\zIA\'EL b )E(RҨD!T=Ey !D&B :P%>USɸ{dbz; a.x^o9@b s'n܉҄b*Eʜ1 R|&pd5bGL.3*vԫ`<ř?b"&iŽJi$b/GLI12O8rgFTZ"z;bX)vY9a="9j9`'ʳ\ HksJHzs_Ī#XdX>ν8R r:&_n=_T\"[*!{6Μy-ߢ[AHSDٕ~YD`8!V8'~YޜxfYL@,bp5Ǭфk0'YdXc953n|GLҎ1yd@ɝ@F{Ḧ́UJn~s\z?9%/%CZvj ĄUm\[+R)jX!TsWB*KD;@*Mz!9Ox@ $\w_!4&~ϰn-@gm97Iaܖb]1|W,rvr'b Z>>41%6tۅ9/գb*<BIe"sVٽQq)w1,1U+CL ;qES}G\,~⮴O{Ą@=%T3ȴ)bΨoHш2l5:bIB_u<qbJ Ԑ[{>B~6Z^CvV!jϷݹ<ۡbc'#ս 2s>N:/}QeRKGcNZPzE=:ˋƏ_xIojNi%zToc|Q쳅Hև^GrjTe!ddwn BG;qÈF=c.6!%Z|t20|<8!-# ,]{4![𸣆K/Bh95|nEl{>DsB͟Eab#_Cfv:c;6 lvyއ FL-k|_7c'JǜW.|{=0m>0hYĴ Y򶈅ɟBL;ltX!iR'.$ P WN2֍&y3T0*嶱s#q~l`\]<,"u~_T5W1LĬ,<ޏMfΞ1?_7 ۃ5.}]bK}ihwnĚevUeb ʒX{-1>!xφnGӴ>2[oO?/Bӽ`&};.oSǼgt];H@|º3V\6]y2wHdX҆W#A[Nc>kc1b?EUrtA? u`ܮU>anE'#)ŋ ۜKwz5}blk>|l;mZHs?os_f fXT/8ozU 8U_3> #w\bt?Ryإ2x?vKR<._W\<76η]6AQi]n:b~R @Ǟ|$> Lq5zؑkWѽRH=#WH{eeӞfr3:+bځt];="㴆n⟆Ѩ@tU.G>-=_4}"G?]]}^|=3B|#L'GgWb^OMRE LB|#U!2Hu@ z~6z" #^T_n FO /_[4 wHM2.ߓvI ]Ǽb2{7Rrpd>~G؏ X"TզZ"4h |)+Hc,ANֽƟ/q~2i$~}00|w(D"Y&6?yjϩ̯<Wb=| ~Rr!b.Ԁ۔.9MO10nTyą)r93t>E7I"y9K#C/kSsVք8߹P۽ }GsZo|s_u&MU+pu~>W!tḇ߇ Dlmx?~\/e,־!M;VփힿuӴ?Ϸ, -ՉI%Mu>g뇯/psۧi{%v s}*2oMx s}gE\_xU/gpߘ^#!}-?/઀ z9x`X +)>pΊbO7J) Y&1E'G\Wi/}s}GٲUr2`y p܉^G9\S1ץǾyOqw>_gql[SdZs욷1ק,Üv8(p ?{LѹvznuBf@1Q]_F0osS&JXຑwbf c']W&;bh3uв\_A"}M m1 lXAp]ݬGp= q$ו\ ~)#^Ds*g ospdZv\w9=zuS`=$1e7us\yjBp=^-z/co:џfw=~71stK G\q&.PKr]z!eI;;\wKrqƷb$'\'^7:kB!6$s?*\W%Jp kHBr}xfۤI+L!Br}$/V\ױ&^rExQ>tW"^]zoIr=iI $~(亡P"))Br}WB#YsI4\Q/i$WxZ\kAr]~iRJ$75\?}qڳ8\uK$ׇ'ud[Np} gƐ\TẠ5 8\$ח+q@r]Fu8\.9޳6|[s!sn*9qεiԹ= ʾT/ROJ9 t*ЩM"JGܼw)>/.Pɳ j}s's_oZGbTSRq"A'A3R#Ni?s\z?\_cj]w|ȍ'^'R#W~IrOZ<%A՗*7 jJP~s\z?1#3Eא[qW'.`Z$R3{ M^Aq?O=s٠g7 ZN:%KD+Zp4Fd3*Hl͸#QR<"Q{$Jv/D#f=#DAR}}R 6D/#QrHnn9$[8C~A(9OH#Ԏ#rbHHޖAHT=A<˝hT{:%+وG1ChȆ 7Mhurv4ts -ّV{9`%j$Foc$Fb,9#m$F71_8#qr=?Bd;&Hp$NS`# AGD8$H;EU%RH ߑ!J"y\z?~c\G"Թ5OQ4\FuګOsuY|rW%Q-<~rJ)}ɹW*5o9uyƵc_ߡᝇs:}8xs.iG^?qW}Gm{nNOʭ{Í3j"_sym|U'9oj{}~z\ON޹){l]kQ+{DT*ys'G/y:WJByI)³'{|t>Mم}70q}3ʏQNO[5{!n}I͏N)xqs\*'nS}B]q*oSSv N|+\@uűumVsN~s\z?) ۶3Z!fҎ[ bYfp~քT`3~Oz*0<ƙE')4'4ܠU+-|m ++u/zV-VArs@=WaV~RXLws'%d-aC;. ##F曂;Eh4r,XOtYCUNa­;`&7Q`sqƪ0l-{:pV/e+P1+XqaqP7 ^S}])QKbsOFH@`S-e58]^ :dg\ l{\8=fQe{+ʭLo kc8p:{Yݱ֦H b3E2{a ӱnJa?vU|ʌW既[ShRs/ N;n Xy*(?Dve[=c ò փN,HJw.tww>(QM{Q sgl~ {w@)Y51Wl mׯ,wWnDL4+χ5GߟW@14s}xmpM {lf!Jd;!`;]H "VMO W}R,-iC +XWnzQޙ `͂Jc]` C4O"{6 $d !/ Ôfx%8a+Y,S*2,Aj~2X=)ڛnк :7CfISe;oMdxyh]oO7$+Glk.%̈́5ӧZ&*h-Z<xYaWXTo^z?~sׁ"#o&eEnyZUlHV88)60;G۬" ~Mn6)J^ߡ)%mq'5BCVk s7Mط-/=Z; @By-:H IڡcpDdkJ^ɭݍG=ΡO&v|ޜWd+JE7«hsCKfᔧSuS<[O̠xh[^Xp5f7\vkx %cʢE!kvy>eTgh{P0hv!yhb6BJ7m<: hr-ZftŖ7l)bhwٮzlzWdL SC$eí,*`/t* ,A6_n6`~~?} ^qn䙹*v:Vp+; =VQL4>k{I\20FUx{]Ge$BBMT4=r[]ch-QOPR$4L?=&viC_Ş8'6ZEY-^jVE@GQX1w9|>netj%Rxq ݾo0%vSHlmОUٮtl tw%.Nq> :,{chf9Z<+WWE:|ܴXgLױvԋZ/*s{Vv&i6]s z g%koeNw+,,nv7`?P|=1<𸖞p[%Y$#3;pǪHV@KNŘyвCԬ=ndeh9G<^^z?~s!<+eƂ_!ԯ͔ kGb1sfX48/jV9= >5g9)m5 V_{,+4>2Ftc;wM[unPe 0˴AC*oA>@z$m蒱< bv|-K<fzRv]^%DC~Z.Y_.1Co>ӬG0UBhGgGJ[|_ {`*h}3WB8 X ؘjw+:Vؿ9}χ ]=E,`'6^-Vފ6?/clwM<:$$buVtjw ч?FkF`l>ub3e*XEw"W5 Z۳1{RgU--nc(+yx|7\6ܺ{6X-Z=J ،4,XWm,k{ypg<2]8)0 nLQY~/ci.=5ϫ`v8h@qKBa>R| ~KX[kit-p? nQ< %}i6Ӵ:`D։4йhN,&*د_"^lg ,VW=\F<3 vPћ+)i>/ {)?s_~s\z?1CQsv;8Zp6ZM 4|U[^O9#AF.ᐱWr-W7O*/fs5PT7יepZ.bDfBݡ/!}܋)!IÌpx+~p($%ptǖp£ZFn7dOrn=?EF  LiFē|}~=HvH qz4$[be It>.GLXs (d"IJMH˸.ϝ|{DZ㵢++V( Y3 BvĢ!"mNJ=ovCƺwGA7-BzGG8.&9H &{E74_&BZTdᲝnn VYH d|WX,q$R:6%o7DٌKW JEw>R3)F31Y)Z闥o3~3=\ *ʾ!On6:imQ E-4<N7-P!t <|-S%BUpz@nI(y)Φ =~>5**guu%W>N,r[@dEA*w yv{yT1cr>HkaCVt=}<5" Nd V 2O4Hv +򔇱 Krx8Jv;]HWٿ;ia/&&@I&v ͷK:QP]p9Cϣbg_d| fσz]GO,z׾~yg- i&%m7!K>dU6/y 2nWVtCv 1pGMI>$4Y9EԥݮhuPlB`>f4|2S3F&C^:]{Ȟ:d_S3Å"Fmpꥀ[ِgYWKLL>љ򶂺r^ˏSv='b@Nȹ;~ qmˎotGAhf~_դ RB>ޫZNWHCRl) Ɖ !qg\u;2GSޥ_M!k,:d5E9L[(dVYfR^ H-\&GL5,#WȽ}\O0 ȔՌ"= ( xW wشI=h$B+w A~ ۝2UF/p9$e Sv  ¹!݅UFq670NIP4ʃ1GciP:Ic/_9K!Eq#g!Ъِa6LN<٫ǐ5BGv TV;F=Us+BZ HB>MHythH]Έ p|idD]pٕa\m'RWpM7.}:93UI 'C ͒)Y#C yߧsS)8J՞g: 8:CZ[T $OQy8xj:rGxtK!7zMx+-j# 聥kNC~gHaM8%3`ydt%.%۾}jp|wdW|~VӞz?~s\Ǹg ?W|~A9(%\҉c"%" 꾘B P/|PD9;@0׼s}Gvm'mn5rƱWΤ?):"?G~;<.niqayp3? џOc}rwO4~}Ǎs"vzSoвr^orc|kno( ⬯}+}WT{yrs*s헫}W럻n`S]'ϯocw]}\v掟k3&ͦ'\n)}Y=~ܸ;?1'|ݸsڋS>)7n`Ѿ.{C]g'>8xje/8(?s\z?W :;Y{ S2wtr<]\{KBOE|"qOwT"|W"Zմ6w՟"U+?}@駶*pk?_- VP#<3!K߉i"TTR/inst/unitTests/runit.TTR.DVI.R0000644000176200001440000000050614450607776016300 0ustar liggesusers# # RUnit tests TTR DVI # # Create input data data(ttrc) rownames(ttrc) <- ttrc$Date ttrc$Date <- NULL ################################################# test.correct_column_names <- function() { dat <- setNames(ttrc$Close, rownames(ttrc)) dvi <- DVI(dat) checkEquals(colnames(dvi), c("dvi.mag", "dvi.str", "dvi")) } TTR/inst/unitTests/runit.TTR.Trend.R0000644000176200001440000001021314450607776016726 0ustar liggesusers# # RUnit tests TTR moving averages # # test reclass works and throws error # test xtsAttributes, both CLASS and USER # test all.equal(CLASS) and !all.equal(CLASS) cases # Create input data data(ttrc) rownames(ttrc) <- ttrc$Date ttrc$Date <- NULL iAll <- as.matrix(ttrc[1:250,]) iTop <- iAll; iTop[1:10,] <- NA iMid <- iAll; iMid[9:20,] <- NA hl <- c('High','Low') hlc <- c('High','Low','Close') cl <- 'Close' # Load output data load(system.file("unitTests/output.trend.rda", package="TTR")) ################################################# # ADX test.ADX <- function() { checkEqualsNumeric( ADX(iAll[,hlc]), output$allADX ) checkEquals( attributes(ADX(iAll[,hlc])), attributes(output$allADX) ) checkEqualsNumeric( ADX(iTop[,hlc]), output$topADX ) checkEquals( attributes(ADX(iTop[,hlc])), attributes(output$topADX) ) #checkException( ADX(iMid[,hlc]) ) } test.ADX.does.not.overwrite.maArgs <- function() { wilder.and.matype <- ADX(iAll[,hlc], maType = "EMA", wilder = FALSE) wilder.only <- ADX(iAll[,hlc], wilder = FALSE) checkEqualsNumeric( wilder.and.matype, wilder.only ) } # Aroon test.aroon.orig <- function() { # non-xts ia <- iAll[,hl] it <- iTop[,hl] im <- iMid[,hl] rownames(ia) <- rownames(it) <- rownames(im) <- NULL oa <- aroon(ia); rownames(oa) <- rownames(iAll) ot <- aroon(it); rownames(ot) <- rownames(iTop) checkEqualsNumeric( oa, output$allAroon ) checkEquals( attributes(oa), attributes(output$allAroon) ) checkEqualsNumeric( ot, output$topAroon ) checkEquals( attributes(ot), attributes(output$topAroon) ) #checkException( aroon(im) ) } test.aroon.xts <- function() { # xts checkEqualsNumeric( aroon(iAll[,hl]), output$allAroon ) checkEquals( attributes(aroon(iAll[,hl])), attributes(output$allAroon) ) checkEqualsNumeric( aroon(iTop[,hl]), output$topAroon ) checkEquals( attributes(aroon(iTop[,hl])), attributes(output$topAroon) ) #checkException( aroon(iMid[,hl]) ) } test.aroon.non.na.eq.n.does.not.error <- function() { # xts x <- c(NA, rnorm(10)) a <- aroon(x, 10) # error will prevent reaching here, failing test return(TRUE) } # Average True Range test.ATR.orig <- function() { # non-xts ia <- iAll[,hlc] it <- iTop[,hlc] im <- iMid[,hlc] rownames(ia) <- rownames(it) <- rownames(im) <- NULL aATR <- ATR(ia); rownames(aATR) <- rownames(iAll) tATR <- ATR(it); rownames(tATR) <- rownames(iTop) checkEqualsNumeric( aATR, output$allATR ) checkEquals( attributes(aATR), attributes(output$allATR) ) checkEqualsNumeric( tATR, output$topATR ) checkEquals( attributes(tATR), attributes(output$topATR) ) #checkException( ATR(im) ) } test.ATR.xts <- function() { # xts checkEqualsNumeric( ATR(iAll[,hlc]), output$allATR ) checkEquals( attributes(ATR(iAll[,hlc])), attributes(output$allATR) ) checkEqualsNumeric( ATR(iTop[,hlc]), output$topATR ) checkEquals( attributes(ATR(iTop[,hlc])), attributes(output$topATR) ) #checkException( ATR(iMid[,hlc]) ) } test.ATR.does.not.overwrite.maArgs <- function() { wilder.and.matype <- ATR(iAll[,hlc], maType = "EMA", wilder = FALSE) wilder.only <- ATR(iAll[,hlc], wilder = FALSE) checkEqualsNumeric( wilder.and.matype, wilder.only ) } # Commodity Channel Index test.CCI <- function() { checkEqualsNumeric( CCI(iAll[,hlc]), output$allCCI ) checkEquals( attributes(CCI(iAll[,hlc])), attributes(output$allCCI) ) checkEqualsNumeric( CCI(iTop[,hlc]), output$topCCI ) checkEquals( attributes(CCI(iTop[,hlc])), attributes(output$topCCI) ) #checkException( CCI(input$mid[,c('High','Low','Close')]) ) } # Trend Detection Index test.TDI <- function() { ia <- iAll[,cl] it <- iTop[,cl] names(ia) <- names(it) <- NULL checkEqualsNumeric( TDI(ia), output$allTDI ) checkEquals( attributes(TDI(ia)), attributes(output$allTDI) ) #checkEqualsNumeric( TDI(iTop[,cl]), output$topTDI ) #checkException( TDI(iMid[,cl]) ) } # Vertical Horizontal Filter test.VHF <- function() { ia <- iAll[,cl] it <- iTop[,cl] names(ia) <- names(it) <- NULL checkEqualsNumeric( VHF(ia), output$allVHF ) checkEquals( attributes(VHF(ia)), attributes(output$allVHF) ) #checkEqualsNumeric( VHF(iTop[,cl]), output$topVHF ) #checkException( VHF(iMid[,cl] ) } TTR/inst/unitTests/output.trend.rda0000644000176200001440000006514614450607776017101 0ustar liggesusersX.L"A0"9tN*`@P̨0E(t"b„ fxww=,Z;~7S=HR2Hq'M+peWqP㦸OJ ~MIȝOI? A.N5לbEO>(~vڃ$f|* 4>Ӷni@;^vWrPON '7.0 !?HCO8tQ 僫RY<J3P>x/̭~b,d/ݵuV3] m4ԗ͘1@1ÅHv/OY]4 6W9jn@}U%PU9 ㎤z@0rTW0wW.9$ `]0LTx Xۍ|GI2Z &k:4Ǎ մ"rP?:xbEt~?>d W}"榳NZzRkr5]`2A?i_Bodhm,?<4Ӱ X O2Ծ<6l?>nam} M}LPQ^W ֮ﲔ [b" Xç(k9vRb0ǜ;|v}=d!@3XߙSl'5f;(XVe>%Ѓve| oORO@S8eߦ ?%V|Ev`2qQbٲ۾ )#f k`vR^uX8`,[L4] XQ^7IЋF~jLj *XǮLc|{?`X{O8nuP`P8q۹jYѝ`h{'Ԣ]| ҁwyovβKni~}ӽHtQ4x7ԍ5( Syu@<hHU |>0|He#r%g=js[q`OG1hX @8gKGҕCa!7c3>%AFzy0[QOuY_sY:@-9v>3YɄ a󛞘G>f7Ny@{5u|y%h53Z)>KCW03rkћe<"y\`ZY8yזPOK}̇[@|m?PV3;>. ==7[]q9?hTr-@)iNZv 0OmvwZ@WPV Lv{f`*I Xs.@϶]=Xd s >*ɳ=Hå@3v>dgNlnQHO0怍1LqQhV<U)O0W ~h?nPJ!  tƄЕ`7]곶2X 0NI^`VT7 bMOkZ3*`)kX_\[i*[f?hXC [yħ܈h̝CXSP`pxѷ%o>t3gn cRGE^+ۄA+]1fxн8qñ`𚱁`n]( w9 LU΍] zd]K0?3M?5 o fn2k-356>_Y4+(;ci"O- nȮit bY˒L ,ڰs!zuZ&u@ESnKያ9j@?uXuEnY IX}(cؤΨ, D4 [i-:$졲E ֍90=xL{!5 .B?f[0^ۓΥ ͌bǗcmQ&y"-cş@6X򠏄G`LFM~yK0ggؑae;FOR"YՋCKAkH\%ng js\ˈ`nU,x/'kq6F-bWvJ1nl 惧{ UKi؏cj@';yOp(_d]H -WPckĥ!@oI튑Kڍչ=c;@N>? P4YMѴ<ݖOHÝ^(;N6?Tw`rPǕ⪭.?ˀ#QHSΤGmc.M ԢCgXnt{ V\SM3ռKjrj SO`Қi[hqzzpLe|:ji"Zہ)0M8iC }`'C5l lTAlX9?ϬT̍ڤZX^0X$^4eQd[2$?Ow__F\\;-1 ;@>fy9;?v$yXSote*ym/>| .(ùcK0*K4~fa[CŠcwi3|sAF HgmIٯcJǐOctʧ#@[m k `Nw0M+h: L`%F}s=Cq7/]o TLLt܀&yr"әƦ7Xc\C Cf\uQ}`,fQ`qlZ0|{\ra{O?]jGB|n0h"0OﴝI)ekpY*.\˕L;cIpȟ*w /m 6q?7R'o]w{L$qI v,F発|q;ߏo4eWگu;)2inx {<N=J]B齒ZUGb3N?AeVq9)5] { >u蔮5,F J@9)s8.s]1O-N:5rpr0y2 qqyH2;vt#5L[7Ŋqp,.py[^`2S\6UҘ<7pC]5w. rSy.':+Gzq@nʃWfr6 [!%S,nJ"#PTM2.@'M\[;LT߆2S$ wY=?~j_x&|ke=P܃mIhqBoy,XxV6z9w$X~CԴ׭ǁ<@G̙Kk0SGMfy"Gy@LJ@2vXETuಱ]IVkz$m+RPD94ygh\ҽ2v%=:zvIr;:7|KW@UkwuBZ6}ȂSmmwL8>ckp~#3N 015EV0*K:pܫyxz9/{csZ&{]* O PedTr8__YGlكN^3q\^VCR8%}_80ZVe\ 7_.Ok함|/@ 3\>up/\zqw;{O ld&/{v1;>6{.=@wWn[ lpEW@='J*#@ٟc؃m5gȈ1wPd僝'`rjP=R(wڏ;oεe غEu# KGrוsǡ):ܛ~Pv; yO1`u%'\:Qwa~h'jXC'3[&.o֥Ϸ˦|Pyø;Eg4H$Y{\+:뮲 z<2$^"ۆmsM(F|WY2ρ+AУ(n` یYBX4Wk >I^c-I 'ZLv͌@jj. ? r{'uD.(O-:r"=^u(QPes fr[9r'nO~Ɵ(*^L=rk9~sv\!Y~&Wo-Ob_T{tVJ{ $U/ly i@k^KgЮZ{n`hj*6@_1*G*+ƍ77P4jSz$-И'dKh<: h]t]VFxΥ%_4:s;0my#,7GL9 fK_`9/翃eX$e*_VgQ0wՍ x/l9Mb1]^ yU!'#~[~v`KnEbDUxYX5vgYO|fԇ6w9Mm{`K2D~p %8^kϞ;{ccf맴S[`p\~֔x*FTpd(]lA*aĨ!`1Kj> \cP^[S7QK/lՖrϿ0Tum6{wLgy0% F~n{\/,6iX2s9wkץa͙\,c23 ^Č|> }0I@^|Iat ybnqCӓ(gpIW ~qd=T6"0^Z O*>:}6Gx9{=|%)Yz; u {{8pW[@r~~:>-%h?&|jTH2o bFOjªJ`]uX6l-*W6@Κ_&-,^5z@?Pf\89߀Bݹj _q]0 x5?j|rf?;7 U\$ wޓkMFqҁSA1^`0%^z|~'x] ,7Dlop<eUԆR[Խy@-{dNB5ep?*xt6+Aǭ9mV\ ~u6ߓ7@]j$hec؟ǀ5~9XZ/˚4:8;o=`g/Nv՞H Y Jcm`H\]zѕ;;gUTbLՔ@4%D4d EDC0D4La !hD"RE44H}"!Ei;I$DC-KdC*E4 UDCE4 a,wDш. DZ* U"V%X,bUU"V%X,bUU"V%X,d;EL3Yd;EL3Y8)"6ц")"c Edl" )"c Edl" )"c Edl" ?B+jK@ aXK>17Tc X|F'0e:=ɮd7](GOM5-62yl79Q@>\% (^fY'ǻ`3 iJ/);N'0 ~7wNfWQ Lúc#?Xm :߼@ @kh^ طRmKiP E mٞ@] ~8Y j)h`#c"PJ3_r;0h O 9OM T ;2Pv}.y?eDБ#} ߮%dڛ]3@*&tpz`ne '/э_*S\Xt{*,\=~2 ^1_oոO!o[1>vn ,Z9vV2. Ӯ4kgl˨'p`1bu?h 8,m~[c2^voiW.`ۯ͖,ۤ-&x­UXt#Jz2R&P=khA` -k]oks~R@|e`\4[~Q?\9osY<ˢRX\>RV#g@H|8 )-s|CiJ|ӹ RXF Io=Z/#V" v l–Xuwwjƙ˖ȫgGȽI\z0s|#ӻOs;Oy{@z|8+,PK r\r Јaؼ@wμf{@-p>4k~'=DRKZ+2|&+Xe S^҃e>s߼ #ʍ`vӜ@ ݚ_QĄT@] n'~*ڦm/,2r^:gzNrɚ+@fyPkn^ozK[gytdø `1M>%G,^4ƱnNk=2a'PZ~Q _o"x{@`sknhE@]Pu,\a? X/ܚ( ϧO]~BI#P3ϼx^A@[vRfy"X,g<K$gٱk''<>bD:2'%XMvB8*M_ҎĢ@%@l<8#N̪bY$D|޳ x4&d%x|ˎ/`xWjND{U$ߝU^`~@ h@>7r-@2:lR +5nz]]uٴ 2Uw_f1%{`tcT0Ԯnͽ ,#={J@/LSo=螾|S1CVv?l@`I[@7Br0b_{z:ST:lHolmͥ/rO,OG0kaJ[O`p`xyeY`TvsrB/SS9`nMKf1w>(6WCB1< r2|>Wyj4\aC_ |-L6 G>PC5Kݯ@Z>&t"z~>rrMRl8fO?[m}dlFWovRa@ȉMsl }v 1WZv^{qX&cWdwjghю`,+BK s}խū&: ,5r-7kw`ȩVZ1\ X\y`h;m/z!굚>Xtw|y$g9wy%]z]1-UǮ9ǮMM]Q|aLIpyǮXs`]!5f{]e#_`:fZl!s*j!;vem'q+ݪJM*/cSL\Q‘Üp9:u``ph~> s|:`˹?רX;Br}ݜq'Up9e;lp `=;6ީi>N ]0XWD\&{-LJ!z$׃5n,\2,'UC7CַV@VڻpFP2kKZ@m8;'&98{t$8h&ǏeKռm}'JG_vڕ@f^=l(&`tlƮ|F X]ہjfӽH7x @y:{ wi`=Ӯhں]ef%$> dr V$~ NOkÄ3ūy-fLN<s,&>٣?'FW$IOUqV۩QVǹo0i70_Ѭ<G .F+YGۀŨh_Uӕo 2sbXsDH; Jke0;E!5^}$w?|gK:I 3ΰq^;K5'j q)goF_9X ֋ &qyL:iIXQ0VAa =gN4dҌbP=-Ḩ;Y;ڃQMkzqzc2RR[L0/zn2+=s0|~'7|=\ꂱCTSuX~=H?P ƭ u}`*{gGq}6mduOC")sZ ;ƼAm^!hnwc˃ɫ *-wj' #k[im N^atmhL" zc森ۗ(w+5N L픕TOd Շv.ɋqEtM*vxI9ŏ6=35+)Uƚ-f3Q34p{˩&`,q9XNs^0N,tXWz `[9F`i1/.9̃nVK1!V /NZQ`&K`;)#ZML!axy:wKr;M S%gS&Lk-2WN|DؚY-~l_@nw]bh=e v]˔/GO-84/ȃqҸ f`CplAϪ Cg,pF~'ع?;ŦwRuz@pl g%J$0x  1v$wNbF5 j}V qrE`ݳP @2pXn=Ӏ\tsP7 \j=w#GI.-,kR:@v>8k(jΒ$PbyU [t#8+EuofvP[=Wჵg`s0h{!۸js.轞n?L0\~e%Ƽ\yJH3 \`]@U~ăK_Lb\[k&N⷏@M³!R?&<~elެ=fR͒#@jaЦ4umˉ 3Vc%oZR7g|+XZont,k.)(#z2N]aom=~^Q ȸʻOݥvǮI,rNcWTq+uB?THb ULֈ)h1FLS(h1BW#PՈ)}5b E_BW#PՈ)}5b )t/)IAzz&{N7 ?wzI L\RpiK]\K-_!?z{W ߥg?kzYw_cO䟍_=Uwۿ_x67Q5ɸ?]m^_?zܟZ/; FOGA| 'xTIכW:R3P9x{{^ߒ7'/)OwUwz?x"qBX SPpߝBRRX;N Yeow-no)<҂럓3K ťCAwߍE o{Or)-r)ooE#rW#rW#rW#rG#rW#rF岯F岯F岯F岯F岯F岯F岯-9+WlT\j??.rSKI_g&wIKLYq~W=߶SO'P'Dvj0D; ۉ<9b{Gp_:'H? pyDoNg&#΢_#߫_ݧ_ "!_p~7S~_jǧ`Hz R /[_fR0vf a; ON~%U ߎ7p= ҂Zx~O_ǑG];?{kܥ[ZciA| gpS/8?퉲 ۸ "ʮʋ1cQLkC_*HG#ՍQU(0"ڨNZ_M~jlw^7e0[ՠeEG|eZʚqoPV馽(K;ķ(sS(S߂QF*.0I|JOiaA ;^$/"ZP1a7tt8"l3Jud3(Ø_2O .C鯟|5J/ut[4JAJeQ=wJ?rkJbn;%t^(c2Ə9(D&'eܑ8=~_ vzePCL뱲Q՚QF(c}k(#}ܹ(c(!q;s')HqEJ3}ڡ 5=ԅeSU5*9eu S}΅B[ҁ~̨(tPjujP\ڋRP*qy^kj!qjuf !E:ۭn6<&#vPJ(W ˋ/Z#f]=V@i)4Eiqmҟ 4QFB)l˹~lnxXS)v<LF& G&*>BE?UTE]җ i7E[wZə|>J]pۯSQJz`=(ˡ(}bŷGU("lߟ[߉3Q+e \ : ecEuEHlQ]Ӳ;6su'藝{>n+ 잟gjBgt݃^6gRgkNl~c'JFu\!JXx蹇,JuA~(ս|Ӊ(uvPU$J)c=> kҙ6Pi,9zpWb?G{sxk9PzJdu8eMφ$FYׅƫ'k򦣬6O5;PZF({\z(#缗$D"rQvf2 e9f: QVBb3s5a{/e| 3-7e:gB6,``J:Rq>[U⩺?O.{ZKN)A]U/Ye&-=7yC33nnUQҴPfIq붹(QcQftwQ+-[8a|~â (_sxs(sa|Fj'4Xe8մ- (fM' eSD82OJ9ͷT(s(3KquB%dWsQֈIN?/MPևVeƪP%Qe󗗻PVr˽(g׏Zo9cZhce({)ְ Pv}(GRsM؊DY/=$>n}?>PECO裬UQAѷt3(+=[*7quvڃ߉\.l^ϭgsOq_x1P:Cm*@YYw;|}JM o'lӰu6(gH&I\9YjrVE9y?3 ;&FE싙􏃹9Э(Ǜ{7.hfV0;O^묌rj nJխ(Q"(獶_zG'9y)Q_]U'32 _Dll!𘿀E7SH( zH%|-K^o%*dC8P[b@^yz x=)U^ȿ@9x:@cx{ɍ_]{ O ׎{N @/'^޴O)^)xpPa nW x;zP q)~m~<.{HAqW~Kq;KnzK *(G/~_0owo|N/o_{JAi !,#p\o z n9nۧ?竂QN_ ^~*=TUQ#p`I|.+zxy x{0.{[//EX0 }SoZx/`_=WCTОߴC0 %z{U&sGuSPPzH^xUs[WJco< @~uH/z7RWד8ě).}^QA o` xw>^nO#<yAB ϳq]`>K0OD7A= ABAo.; ßR~~ y7%B@uC 8[~!/7A #(.[{ ׋ĥB^{ (wuXo| ׋xZdۂy>w߂uyMc BF̣ֈy}5b/1F̣(j<>1F̣E#QՈy}5bE_GW#QՈy}5bE_[< TP OA[h1'\+K1%{\ Ay.W /OO1B̥s)\7#mV4D9~W.ݴr-rלq~dOe^ґ݃2gޭUBL9(d(96%Geʔmq iꛪvq_bڷ**P)JRH? ll{]_=* ~֒CR7)T@U5:N>n(uʩ[P~Lo֋(7ّ҃ ^s۷a%JGX ]f@=N?zsMJoTTh*Bbs@8X>cJc J?6Hj/ޤ9Xk)oPQJNtN/*|b\Fi&Պ_%K [FPZ\?JwaX|[LrwzfC|}Qxt^5JP2??prw::76w=W4Z2Vi{Oȡ}-@'fMqϜ[rnk^y&~n(J=K1J?~g(d/L48CQj~I-dNFiTƍbR]87;4Ptg[9'xR.: J{8DkwocQ:gdmpY)wN32De콶Ȱ4etH)/ej:\fe%NM8ZOYQ KKօJ{6$ʮN' ex0;2ǻe*.l2u}oRR)"NYFHV7}:Kǥx6ǥԡtY67iO;QVFwq)"ٍq)fK'7{IR|9+Kz(ǥxǥ.T q)d+q)N6<.Ÿ'QփQx\q<.E^w<.Ťy\E<.gx\mg=ǥxpRlۖǥ8UR^Tlq)߇,q)mq)4n"W!KA{1ʍZWRRx\X~x\Dl%RXTq)/6-q)V:;d[% [y\w7{x\ `Cq)8#y\ceFG74~q)j yV̥s)\ 1B̥E̥s)\|>s)\ 1B̥s)\ 1B̥s)~шh\1F̥s)j\>1K!s)j\1F̥s)j\16.D߽wؐޕ>sN3|^_ %_A `M5M`aPSCgŒ@Vc@ٗ0kgʙy0_v_aW~m=̮q4L;wZm#L~: \?(gݾukfGD 0>LV⹑9139vK8l,+ϙo'D'3"?oHc"+ip՝{p2Z2Z8 R 47;>x[]ķ8 =%/ri"Gr<w x8bqp%J H!rQ-im@S6rqC(ǧ4p6μ+woqm_մ3.m9':N%rF3XKLXvr|'с`LaN$}tR9n = oCn SHNuLַv^=8[C/̿c:̉7}]yx>K S*Գ*Wް(yβJ_O!2K KFnν`#1,+hL 2Vf)z+[$=keNUl"2`[x9OV'`ssA39! m`'`'eqVry,8ns'\QH&raw󟣰?ٝ_^`&>~_cCk^b#s̷Hnmw'X*㷧 =4BX9_ xH d? 2؂ ] /o4H$I $v~;ߎ3_푎Z +=? {6 |gcq,+?]ֱ]7el/;ACBz5|;@x}P;3}q ï؉Rw4% aF_n4^2;ױr$Y8r|4s[8؉aDR2\3_D,evBj)_#8Ia8ɑRy\`HqoKȲ"^?_'V+6mQ?3{X||B= 7}n혉_ <<@'f?w,w~=_̟?|?GX4uEOI2__`7֟z1?8|?UdķGo>ۉ=>6Mj~η9S8:T rrA?~X}A?M?)Mk?}kn}Bx<#lkI B''O;T<{TV璘[x3q?" |ItZ7|7D:>.دdcX s1.)TV~|\N>G a'rdp4? ?ll:=Ư+^_:G~{|{sl[؟uzl齏ͷy|E|_ߡz/f?fٍ8'|4" atʿ a%>{c<ް#'9ꍷ}D?N@Xp""vk ?I8??YY?q~P|9?v Z2ǂ4?}~t8lO K=qh~>'>, 8N?{^DI < ?i7 ҈'~g[WEX*Fqr _#|݋u}l\"~6ఱu+@fcUpvg?n׫X<^bNe'Od|.{_' |//)ϓ8 zܬQ&fvkv1|]|[$9Ic6?sd"su5֫JXƷWxF}f#%n !lO@?ꉯ]|p 8̚|ځT'''a5?u|R3PǦN2hMlM~{07c l^ Mԗ|.?%OU]QM[gP}N;86y AXPC:jGT߇jN8I;j<_\rQ}dU{TͿZcP±'Pvf'G~:J bWуsGj#d_Y)`DfTqw%j-ܟ&xA͚9GW/C ID|z[UF،a*z4mmos*F]4 U*xj8WV }k**;=*Ul^s34=l%] =tx4G q)~nqx+oF]Br{]?׍n>H5D8^莒|l3*u*JZ*혈*8N[ȕ ?%o7UiZ~@y?ԣ*TMGVe+o {FN/G~G5c}tLj^(̿1ɦϒM乡rjL!9Q߿Pk# )smOd<┏Tjo6 VQkv^q= *׉ZeX]A g v?F; ݰ fѣ _EU7QE/1}QUo9z,#Yz©Q=]Bw =mj 5_ 5d <-$j~fA7|{1?.KG[ͦpCεj8tok/T=)O$} Xyn&{}S2Z{p)<=7};Л=]a3lt%%薊^=V@7n'.{$%SkPqeЬ>vQFwGڝIMbɵ~ ݇)C?ljilҸUoRZQ_W2~Ce7﷡tϏxWfW؛~8Ex:!BU^6[B&z_!5Q U޻G\~AfPWMC^* I5v=ГT4d2zPXC=/SE%G%>g{jC^=Gq#a?zȏw|P*ΊuFx=Q w،jc.]>) ʞ){b.]˝^֠* i8P.x~:^wLZ@=\j,Oy7'M'[%M7P3MՃMF?N=Ye%:)?jkj2W?&5DOZ-yAGMDQ7Ѽs)/gUj@WV \r ͻ'wڔ޳^4ȏiØBdTTR/inst/unitTests/output.overlays.rda0000644000176200001440000003415314450607776017623 0ustar liggesusersyXM8T93$y0;Ch@e")21E$CR" E)*f,s~z\˹{9뜳Zks^5m,=j%###+#'/'#+G(/KNF^F@Zk=\z7t?#PFFvWLCS_M]c@+=@U(nѧ 'ۀ`kbٯ *~v-Nq… N;Sa75-@p` |w/Oʥl| }iq Pݶ= CZeKy2%?)yg Z~,M+'hH~>_ ^-hVlt/z-[ھ@}4b1?ẽ/@9; 3&e7vnj Ku<԰W电 s]%U1F(YED_oj»η2y72P\jtjfVb Pʅ{˓AP (tO<^i3<oF\T΁y4D\^/Cژ\4 J|r8 N\ u7 wAk -+;˂vK%# xPgآWZfƿe>g@1UP|{‚0؅1XGKi+'bl)()W cA1eŠxexף@񒱇˷P>)2 /LZ]B;o(>: o*A`}^GZط έ68M3că;uĉwه8)CYwIcXwqj?kx @LvX55vd@ߖI1 BUf@xa#IFG~(]~~ζlo:֋HkRZ`nޣu!p)!_v}NڈA@szow ޟ09Б]d_}:} I 0fv+-`ho\:"B`ffd) ~L䵃'lup U`{5֞/Z5u.K2_z_,+vY}+QP zYGa\ i__4y4`Ik?|mř?ʯku mRI:ߴeGs9X3$rrOΧ $=#w]]8}[srp6`w>(*@v_\$'اdSeG`9K7oֽCí׏,5ӐcwXFo(gZ]uW0>$M*a ʠ޴@ $EΫϲ=-^q7#&#y ~6Ճ$?O>襝z~Κ k#WKHnqf=&3^ds;3C|YH{(WQ~7Y;-^,7ЉV)?EkXR_ݍ}4Z&уFNHVJ6?FU5n= w;'o`27LfskrZ`6-QkN !ٳSԋdl;b;lrE[Rw׭BX{04RWzM] ZV[wwEgH=}:'+4/1%]ͻVOvm+M%R{O]`W:mB95݄ ߂гgx- PW)eGl#3wؙy&oZ `_링y[8sW |2:3گ T$2bY j hKn=AZ@o=hTH\%{&zhUp2n?S9֚{[,W}ѐ@!q98ɻj"KR 'S]'Ž/*j%ۮk|uƀ\]<+&ĐqlH r:XE9z;VLJ@[="2dw2\!Ygv6֜7j<̧. @.JXui!@7e3.PĻI|ⵄ3ړ>\:d~:=|`47[uh}OCIv|?€ !A##w>ޱG+YWPPͬN'F.RA#Hb5غrW6s1P¨'YJ z5c69lNy2vq<)A%i/#DvP Fl-@<(R _uYnCY= 8קdC$g$m[p1Gtv"yKo46cSRwt8B#X TUt(IÐ+fdg,:9DX`2qfs}fD*Kif/.mg0UuD"5Xq6zQXV(k5`zڝqXrvL'[`_75؏Ʌ:؟-%j o~K2늌c<E@h~),~HZ/$.3+Q=# @r$ H_ q\.y. l_ 'VVaqx=%{<)e#a;dٔlqAB|Jfפ/c~|5`Cq̛+0$ G(&[մ%g`V+[<< -ysZFr]/游$s0u;$2׀Y/~q|#e/sQlRx޶@߷<Ìd's40IBzd%Z=F+.x'x3W`2o 咴Xɑ+H|% lx1Xijːh rvz} Bɼ {J =JG:rrN 78DzRx_"'r)W|a _L@$k{PyNc3dAI9u3@I{$vGv>KV.Oi "B+V)&)zel4Ptk;d*qd*M2ɺ+.}בVs<QRVRCMz0;fmAqdr]80S9-ݕ io݆Nd\xgY`v3/ƐFIzc.+9Ojkô~*FL@w lrMtkȺ+Ĩ`Yxb}d]jGw%L\Ku% :<|]3w/}*j@'\:ܐ\C|]+I>˃+|s?{w" Q&7 S{*[M{ݤ.|#Z-(߉̗O'6&ۮ9i"09[:{wh?3 Ӿ?$d^P$32~9_ ̽-HW6|__`TN׋gύ'㜨׸r{]D6%V"!ɺ*>*wɩүCf1`˟v'l"ܝ"H " 0 ,)G}pLGWdvv^ X uD]?]9aA1 2ۗnzxgZKҕ /?n@d;1/lG_ҺMDӕ "J @˙uȸk WϘ}WVnE2*t jV{09NY5V |+x2?ߧOK7G _V; &+.S (mkoh8v1_1nٝd{,@ our\JQ r`Z%_q\if=^C;_MP9 |#3jͺ% VgSq1?aIǀpPu\vuF Dqai1]4AkIt`]أC' /On銞v>tѿ1֍:!w}\>@D%*/#m}*zpad2mnl?\7ݫ,Kl_K%CI]څVݚlg߁}U-mLU|ج[d)!͙7xaLn{H^,zo/8o*%ͮHeU R}yL&q7kd'Zw&>z_/{iAPr{js( ?n>(Qz](W=WecT.RM#T+a9B֪]XjI7x)IB9A)f򮠔wzZM;jGv=eWSᄦ>W0\Ek}4)?;7hx0ɡ\Ơ+qM :qo{^;ijrĮǷxxgǼ+ٟJs5≥S?Gp&l^{/̝_\N6*l1+7hS_R'Q2s;:apNq?\ͥ<^.8|ѥ%Ho1;SS($&.^̺g?>ryr%+ܹMdjr.fp#Ye;, lszTWqmuK<5,lW|_.r-/"F-˅/{:X.R5Js=Q{4Wf_Qۋ{a*NN}#1C5DpetSLjhUȅ$*wƄ+ wO#3{e=({!W[q}F13sy~5=97mujxej e>ښ0(<=/Zw߱ΥY׾0.&K~R=KNw:g]urV#j˳rKo^*Nn\N-XjlI5άOM>~q;U9=нUǙlrKWA*cK'fde*]3gs7*6ދv;'mWxfdk/U /=-UgrG/qUizpU]5UpTVMpɽZmW},9:OΗ[tww}mrՕ{=Wy/]'QsLwVxrsT\"ՎzͣfoTKŞ#>ߟ5osq/~޽*޼t9r޷N)ܛ Gr5~;U*|ArUǻ$TrQS3SRY5>OqӭAWѕ[>d˄^\_SɭW\i_.o~\wg7p&&/ʮ٩j~U%\t+.OV+M޼$d٥|;gLΠ+ŭ^ Yn:cGzsOE^u*n;?ard9J.K1-eLRjo4\O/e3%J StC>q^d]pG-/ߜU:&+9x3aG1isS/kRccr|R7zU?ӍrM.'gqY{,"ݞq_q9U[_L1Fk5Oz5^>>d\Ȉ܋E-^xP30rѱ8E|xD=5Yx t:wXæ515yzB.|5qy< 4^x4=+yUq8{61j*NhU:*qZpjzei8G<̺1ǾpU FQqf:/ pCf\2 Zr=;=kIKpktZbn5H6pi40iܻ~K-5inUoČV.וsDZ\c/ݹ]19uk̓k-n՞goZo;so}H"vPjn=ʽzv٥rݧC795oN)wD9Eğ5h>F/i)=vӞs\]W}t\]}Z(=|?4IƥɯrϺk:oo/]?]n iX?|#EU \?w)I+}551z x=Ƽ^=:]^o_#^xtyǣۗx;=;w}޹q/8ϋ>/&ּ/ƀ7col1-\raol1-\raol1-\raobȋ!/jސW\ra˅! y5o˅!/\jސW\ra˅! y77sT7وWFLj #^.xq6ռx0ˆg#^jވ #^.xq6ռx/;Ƽ7ռ1/Ƽ*ܘWƼ"ő1yn̋1/Ƽ*ܘWƼ"ő1y5o̫y^.Lx0EބW&7eDŽ^Mx5o«y^vLx1EބW&7eDŽ^Mx5o«y^vLx1ռ)o1” S^MyW)*0” S^MyW)*0” S^MyW)*0ϨY=^>ǀc1٣;]G{x=o_zs㝻xxǣcew+1zy=&y?k^ܣϟÊ{Luy\]=wzs3z<Vw˻gauy{Xqo_ּ/Z]]?kw+݌<"hIe]^W'1WS+WX!b+ W"E^qy+W+ B^qyuWWF^1yEPOW|C^"yS+BW+ ByE ?+X+n!b#+. HF^ᇼb"+F!"y;WG^ф3  +"0E^b9+z!+>#(B^ypW@^y+BQy+#y$+W"xmWDV&3W$ B^ab ]"dZ A^qy;+WtA^1yEwV+!`WP+#؅y^WLC^y}WB^y%+W$#* !+#Xb 3ߐW2+W#G^1yLWE^1yE* W @^QyW\E^b+tW}WD^ф" y.y+WLE^ьy%ېWOϳkW"p@^" yE_+JW""y[%$WW#D^By_$08+~"h3+W D^yt+ B^yaa+ґW (D^y'cW"0A^"y->+WG^qy+ D^qyE%e+ (F^1y'+#hb W+W B^QByE K7W|C^ᇼ+ uˑW!hF^ayE N+!pC^yE n+W"H@^ ycW!xy> }ӐWB^ab+W8 yE3Auj+#8B^"9Om%"@+"@^yDP[+*Z "yŲIxE'n+RW!XJxE5 GWd b> +#B^qyp;W"8++!@^ჼ" yW A^0+6 HG6 yEIx^-+W B^qyE+yE1+"(@^b+WE^ yE\X=W"胼y}W,A^abbW#Xb W#y<6KyE$U+W@^1yE.+"W4 C^yE(M+!"yE7+& C^ᏼ"yE +Hy 7+\W+JW"D^Qy{/Wd!8" yE,+#PE^ylːW@^ByE_+#D^ay>v+ܑWd#؆b"0WX#HD^1yE !+#@^ByE7>+ W"w+ ߭WlB^1yEO W!Xy!V+&!臼HW\D^"yE=+!X0 {W,F^A!@^y\+WF^1yE8+ @^Q=+ PyE[+(ÐWX!ByE5+v#B^"y^KWC^qyE~+W+WF^!D^By6C+lWF^yE: EWW#0D^a+!hOϳk\C+fIyE+"Xb2=+䥼bN= 5W HB^)fOWtf^a29[+{IyE )x/5R^d-!wbW|?WHyER sW8"PA^y,)xR" 뤼⃙W} )+Zߥb[WẄ+,- ])l@^qyR)8*G"Wܿ&C"rWe+WLG^1yj)yP+D^*IyEW f+ ByEW"y 5+ґW C^1y+n ؉b:)+#!)yW,ER^b5+U~^ӂ +Jy1_a+Ky+W C)U+h)x4W+V? &WɛHF+tD^ByEw)xPbW 򊰟R^qdW/Wh#% D^ yEW|kD^1y@+2Wx"W<@^y/ @^qy!+"x*+WLF^b0+Hy֗+W" i+WtG^b) ++¤"#C+n"脼ByUWI/k* _Cg_C_z5k(P篡g_C_z5k(P篡g_CϞ= @gU@P\{(z7ŭ6(;l悢jFP !Cώ2kcO-;D|htR'hk߱{&M@b3V ؿH[\;A;?BA67I?n&PTEztmj~:,kPz?'[k6ߘUg+|:ȢP<߭Qm&lx'R].{=Aeɉ[f\kZoff{3|]"`Nvy9,|j17=9@L-¶V] 2rPJVX8tI]F+PjQEE@O:1":yr t&g.kU[ׁʪ_w;;0cR5nM ckP#Y6vŶj`N'Xxc.<("e8Td _o DtD" qk+JYG@?|t#1,vX㌂h`U`Z*s y>3:eJ: 52OyN+PGZA) w@|S5~ XǢ)*@q;eC4颪ǝ}`#UgM&qJL̏?և\̀)9P`$5ww&$]vR;`XC1:fMzmuzy>SV&T˝S[z@O1VdEݝZs e9*o]sAˏ@ ~U[cvQal*0= Lc}€9qmQ.s^\/FUӁU{]w`44+ s].D1 ;!JSg-{ Bű A5i4Nu] 盕;M&}HTd DC;OUޔ=P)Ҩtʀ֩\ɗANMstA\n2P \&to:ͿĵKEdV:qv)@;ډL-8e]]]]]]]XH@)HTn Ŵ ~ Hsd )-/>KH"B%gԒH f%1@IpebV%SDK"܀4+(wh :Ylh19)Z(P)Yd({LS@RJMm=6^w`%tM+㚿l^$)FƺqtO`Fmӻf S}YHldM*xEzMdjit@_4.uY@דݳL5BzQ:GVTf 4|bQ^f2BS&ܦjB _ )dPjFN?[*\%݋pf1}#9n@Y*:9O}?Pi+%ޚ3e}/HcߏǬ/@fAJa7 (gy<] ᄑ$¯Lr0"M!Kq>y]I ؞J3W.A?n[HA >S+@z9 P<@0N@Qݬ 8-QuNkSz%8=U/i$N[.VjTƇd)9bSX1 ]FD3|(y3b=]$_p:A#@_?.<:J /5elD[ kݔ3#@΍[½[ܪẃ;<VY~@h4YՂPݨ3 yFY2dIв~/C*Ubb؜Z}ҳ=;np'``-ǿ"SV]چoyN۰w`G} t/vmz<`w\̯u9Sr婗d1q KwnY7^[A{!'mTjwz2SQNf2iu-ç;ۦ攠W*1@weU&CT=IMm;Sh*Oζ eɸ8Gec`j#c1}ԧr:[j[ETQLZ/d[%},]_c*11cYOy YCWk[y6 ;?^W"u4DF2E;煮i_0Z[[k 2FA$j]/~ "KѺlRo CuOQBKB ƏNv^ڠq֥@I݆|r=(Z(] c?fV=K+ml2׈2JTM(%x׼?$b(1ddbI%b܂KD*%/h,?CF%Kc@KMo?f%В'715䀑3^#lV`$r>w^;cׯ+``ʕc,X_]Kyٴ=#/=kO^y"nl@7TTR/inst/unitTests/output.misc.rda0000644000176200001440000003072114450607776016707 0ustar liggesusers 8U}QJ"(^2FYTʜ8$)IO)deN+MB:o\\>׺׽}u^RL1CPX)h߲ҾP(\v1W.W;Z<ڟ 1W G"vgWݏ7SͅcfE¢ȷ|M\,vʖbQwzwl}N\YwW߷z-,[UgX7b:sMY,m_kH=ϔXl_sx1& 8nY܅{U3y]Yc=*qudgN;(Q}fݶ7~ID1iֺ l'.ܛR*} c3&s,ܖ/KV_)M۹$H0G"#yan妧GvuV3>J"<?ON&N,xֆů [4p[ )^DþDgmccXǻ[w'unD$ ".jr%¿.;9{o_b" ˉ Ŋe-_0l-٨()b:o]u.~,^Uf C}dZ.1G#C~3HȖn pAY*h.4)s|ZRzpC쐣.]7cg'`1O誔v&Q<<.c3bP7/Of½2e@HwVxodssCe,ڲ"rIaY#<]8s YPx ;<_#ޅ{ML0ֲyܞ[mJ%SY;οV2 !.˷j˞&Bn݌Qo;m!v)WĦ[Z^x7KG uq(zQ\1 g]~ & ;^(A4jKcD7{O 6Ӧa~n4qٿTc*[!͠X3{L1J_3xUcZLA\.V[ʖ@Z~YH|o>/. ۡ-g^P6'˴6-UM%zL]NdD9'I&0 VN,wn1H1zXHZƨccސ4}-=BT=*x.z.ʹ[2!kFՄM'1` bcQy!UM+NbMbAǬ^j⨜ bX c(*\j&'+ݱb.`V-8dn!—+>U.qKݗŃNg e&{L/", IX~)ewf%X`nI"g<,|@˿`{j(;?=SA%9S1z[z(KJ v-()a/rvPMbR {9|k-)EFI"^vʒ  *H_{}A;GÓ,@#=L~^0/총B9/{ ,TE@YyRg/V`A,IT\Z{(m#24;<)۶^;$;u$VoONgԣU],,-ǏJNۡٝ_BMrS1۩)"Xs;I1S<==;,ߩDGoN /#[H#HC*q5z$<ɳ/γBMCBD+nN??o,:x=>WLbvWIZ~мVIaȈxaD !ҷY vq4 a3zi~_#GYih--qAh^ag(dH[ G!C~.gT"hc645IDLJD)< nb^犗QKX~Eu^iZޛXДNr04f‚@Pol E%;&Z~KV/=';MO3:#l~ #.>Lm1 'q)TvnJ;iFӯJE4R#ŊxOOݳvrQ0)7uQH5٠G w;on{:j%%]rw.JWuZ_{b٭wQ1v.*q]MT-KOď+fM4O HzMgwrK%I,D/_ oo/ ;؏^WBذ!nk;ltJ\@(IC"}GU'bG;=Bh@tE 2=31?KbB Z;O"p&a$B5BдicT 'aU"k~d9m}(.s?E~vYl)Dz΄4-MSVm jR!-,̱39MGQ֦aӭ5]إ# UI2gݦ]M['cF..`ΥKKܦ{B 1˯! sLް|Q&Lz*/z*i˃6D855e;\I͌ue͢/|8ܮE͌ rjsVKV敥_iXx,YmY۰x"zhmz,OȮےbɒ(#9Gs=0[BXPJ~Dk`ivw팾J{ߍrx΃*,S\:v.MEڅVݹ6uXt?!//2獮z\BT [F|0cL`>Ť:_臩u[;/f-3F|q.s0QW:109ň蚾ʧܹ5u`o_9er_˼7G#M!?331bp`1D|ߵ%؛nW4{ƚ}kIڵsez| z?)4/}ې߁t LϟX7n<ɨCzq8͆ފ d?m)oD<ׁd[S/܋p7s73uD+ }dne~î>ZHu'S6QTiޭrxMn57>,҆ k7 Dm_ y t)O}y'bLJ#ַC)t ӛs  =$g1(we1N&2/l0af}<:"]V|8 jX} C͆Gnϴ&Jx5gԱ,!_)y84 x](/^aH<#Ow7;NHw{Ǹc>Wm\Ac[> ]xOC:/Gd@̈́l_wԾJɻߵ}n>wg?sXg|h<3ok?x2T;-jj> }[ .ۗ?1L*XJs|R0];j~Rſ^ϤLN|^:~&xnWRn$Qg<~o+{^~eJ*)%)Y[KT4>\og3x[i O ՜L_.8%T>mvJv,+Jik͠|U㴷E~E*_يAnīhwɕ`ޒ f'urcf= K[;ބo۞M'[At_`ĀwBY~p$,j5=zVޙV@ܴ2{gm,:$~@|ͽlnХ~$喳{iy ?wX2x+E"Va|Aܵ_A|ިsMdt q~rD.}kS~Id2Cj^<9H'U!TWk"W/‹ҟVKG_kcx߉w>,|">~kƜ 8})gS⬏.=Sݿfa|l#1N |i$)"r7 +kZ8)(&W>NvmW 􎄍vCx.+ ^+)dmM*w3`/>~ز#iSo4 LyQvC#'5SdI;OxޘaC/^rxuQɛx's~SZ3sbz}?5aa$/[Ë6g*ݭw u}112Bc\mm(E:n]j- =gto  } ( u"GvV{\mg#@RBkN)E5T%)_}!kdj WPA-WP_A^S%}F>AGN˗ ˒[Wf\A#w+f qFkG H.L.,eߝ/5Y*oIPآt=˥>=V;X=\~ }^ ϙru6.BAEXPxWXP.sx g!lpq/f_sXsw6Xn^w:zV =VVPy =My ui0""αB]xxɃ,xɮ828ݤT& y\M M >.M wr8&Zm Ń{dU夊T~Gm>^ѮR|w&^f1' 6;/Xs-KL+~jE6j,6]!^[<=E4xJVd5+c@moVxohDw4gsPq\f9xx {$ w'dொ$l9Moik-Ҭ&l z 6^EL*^rJ;0(FokL-_W{4E=Oټx' 7ؗ} sK9-Q;ts>w>|o(uc[ ^)\N3 -i>T .6o݌Wto/Q:{_v͎U[ҭ,+{'Z30O̴tu9jd=i~ow3Nn[v' 3};-T$4#fٮ|asuPA/np0/bpsO۪u>pcbּ'>#I-Yf2TKn7\!R@,F^jWL.V8l "AJᑷJIx8 >#<;$(vM˕ $wXr)h*PL4ZIJ= ny=JڐCn^9Dnz6zj5=Q~**@8?ԙ{9bM,~6X^H.+j)`B-1V3utݪIpw؎wΥ_zS1 xΝPmpP)T[ŊOL, ?Y?܀Vh~nK4#+_1? ܻE_@uC-ߡ:0&P]21C-\" ՟ĵc# c}z!PGdf;׋z,=uΧB=sG$;~6m54(W=ᾯNT+>@RzXC ,w&?4\'5؆Pi UTnL)*uTrmZα"T3PGľ (!ݺJoW~ ʢuPRy3Y7npݩ "SFG!E_JpQӁpq.[\!o/6$)2As̏R@a)K:9e'@||g2@\ǻu}9v}׬U=e}"r[ohp4äNtùR: [,ՑpH>R<}/R9+ TϤy2|CUgrrw9)ƑOV(%kr#}?P5r;_|R<ǹǣH\?ȕ ^y)$aP"]W>NϳswD˴j=M=O ͽHT1޻>q,Tw`K]ΤT7ݝ7q@-xC\t^C]4UjsxG!CχZ 'ٚfݎ9%^Pd軎;PsW}OPj3v.huc`Wv.j'^\HX`*ZRrTxx/־msnj'~}%R:};,SmuX>(^j+Z9=|$zl{򃅡ת2bQq{N:G}{c#O"Pn! >͇[Ѧ} xs+>9>+T]rF">5{qWK"/TUCذ* -ӁF@Ǐ*ۧ?ec|?%y>Cנp&9֗ 7h9 E*tÕk~l4r\}&^n5cujRوv #İr:R,+1j;LR|^t6%P#pO5f<~\$I +-[r\uc^lzG { ^o ,-ђ_BJZ85 Kac>[H跟HpVWP~{IRP/ ,gt D7Zܥ6oJOFR;ً7R-NM8NpkN/V*R/5N%ՖۜXs,T]Y휟x{,}Em$T|м?ě2{IW/_2L9jxym$%\I,iE.zM//?g d叅vCuWY4W|Aܧxq`_ĵ$V Tn<8eZ U'+CZ1vyKÖ$ѹy~QԼٱ#n/uwֱo@m;vB^<{C#p6Ae;þ =;06 CgG !Wuabp`Y(44wR;mx*  (<+kfx`#']I{ۣ-=/#?7_D?-O D7BfO#B?M!D?"G#Ei}/G 7#A_$%!_!8ǘ d210cm@6_ i~50)_C(:W!_?D>Z΀+B :O{!B__#@{W 7A.#@OA_/3"@??!euw 0 UK ߁ *g!7E"&&YB_L Y0L<bӿDo?bg!D{@?X{"D/ Zg#߁!l"G߅_ .G_^J]A߈?/8A}{#_9U G??T~!_*C;L!D@"_?  "ODߏ??1!O"OA_ ?7  gC T!?_C@-u!Cொ6?#Gs7 Eߌ_O#AOEύ -s mo!@9N!e?ohǜNYk/En9}7۲XXTTR/inst/unitTests/runit.TTR.MovingAverages.R0000644000176200001440000001355414450607776020602 0ustar liggesusers# # RUnit tests TTR moving averages # # Create input data data(ttrc) rownames(ttrc) <- ttrc$Date ttrc$Date <- NULL input <- list( all=ttrc[1:250,], top=ttrc[1:250,], mid=ttrc[1:250,] ) input$top[1:10,] <- NA input$mid[9:20,] <- NA # Load output data load(system.file("unitTests/output.MA.rda", package="TTR")) ################################################# # ALMA test.ALMA.output.length.eq.input.length <- function() { v <- 1:10 x <- xts::.xts(v, seq_along(v)) av <- ALMA(v) ax <- ALMA(x) checkEquals(NROW(av), NROW(ax)) } # Simple Moving Average test.SMA <- function() { checkEqualsNumeric( SMA(input$all$Close), output$allSMA ) checkEquals( attributes(SMA(input$all$Close)), attributes(output$allSMA) ) checkEqualsNumeric( SMA(input$top$Close), output$topSMA ) checkEquals( attributes(SMA(input$top$Close)), attributes(output$topSMA) ) checkException( SMA(input$mid$Close) ) checkException( SMA(input$all[,1:2]) ) } # Exponential Moving Average test.EMA <- function() { checkEqualsNumeric( EMA(input$all$Close), output$allEMA ) checkEquals( attributes(EMA(input$all$Close)), attributes(output$allEMA) ) checkEqualsNumeric( EMA(input$top$Close), output$topEMA ) checkEquals( attributes(EMA(input$top$Close)), attributes(output$topEMA) ) checkException( EMA(input$mid$Close) ) checkException( EMA(input$all[,1:2]) ) checkException( EMA(input$all$Close, n = -1) ) checkException( EMA(input$all$Close, n = NROW(input$all) + 1) ) } test.EMA.n.ratio <- function() { out <- 0:9 * 1.0 is.na(out) <- 1:2 checkEqualsNumeric(EMA(1:10, ratio = 0.5), out) checkEqualsNumeric(EMA(1:10, n = 3), out) checkEqualsNumeric(EMA(1:10, n = 3, ratio = 0.5), out) } test.EMA.ratio.eq.0 <- function() { checkException(EMA(1:10, ratio = 0.0)) } # Exponential Moving Average, Wilder ratio test.EMA.wilder <- function() { checkEqualsNumeric( EMA(input$all$Close, wilder=TRUE), output$allEMAwilder ) checkEquals( attributes(EMA(input$all$Close, wilder=TRUE)), attributes(output$allEMAwilder) ) checkEqualsNumeric( EMA(input$top$Close, wilder=TRUE), output$topEMAwilder ) checkEquals( attributes(EMA(input$top$Close, wilder=TRUE)), attributes(output$topEMAwilder) ) checkException( EMA(input$mid$Close, wilder=TRUE) ) } # Double-Exponential Moving Average test.DEMA <- function() { checkEqualsNumeric( DEMA(input$all$Close), output$allDEMA ) checkEquals( attributes(DEMA(input$all$Close)), attributes(output$allDEMA) ) checkEqualsNumeric( DEMA(input$top$Close), output$topDEMA ) checkEquals( attributes(DEMA(input$top$Close)), attributes(output$topDEMA) ) checkException( DEMA(input$mid$Close) ) checkException( DEMA(input$all[,1:2]) ) } # Hull Moving Average test.HMA <- function() { hma <- HMA(1:10, 2) checkEqualsNumeric(hma, c(NA, 2:10 + 1/3)) } test.HMA.odd.n <- function() { hma <- HMA(1:10, 3) checkEqualsNumeric(hma, c(rep(NA, 2), 3:10 + 2/3)) } # Weighted Moving Average, 1:n test.WMA <- function() { checkEqualsNumeric( WMA(input$all$Close), output$allWMA ) checkEquals( attributes(WMA(input$all$Close)), attributes(output$allWMA) ) checkEqualsNumeric( WMA(input$top$Close), output$topWMA ) checkEquals( attributes(WMA(input$top$Close)), attributes(output$topWMA) ) checkException( WMA(input$mid$Close) ) checkException( WMA(input$all$Close, wts=1) ) checkException( WMA(input$all[,1:2]) ) checkException( WMA(input$all$Close, n = -1) ) checkException( WMA(input$all$Close, n = NROW(input$all) + 1) ) } # Weighted Moving Average, Volume test.WMAvol <- function() { checkEqualsNumeric( WMA(input$all$Close, wts=input$all$Volume), output$allWMAvol ) checkEquals( attributes(WMA(input$all$Close, wts=input$all$Volume)), attributes(output$allWMAvol) ) checkEqualsNumeric( WMA(input$top$Close, wts=input$top$Volume), output$topWMAvol ) checkEquals( attributes(WMA(input$top$Close, wts=input$top$Volume)), attributes(output$topWMAvol) ) checkException( WMA(input$all$Close, wts=input$mid$Volume) ) checkException( WMA(input$all[,1:2], wts=input$all$Volume) ) checkException( WMA(input$all$Close, wts=input$all[,1:2]) ) } test.WMA_returns_xts <- function() { x <- xts::.xts(x = c(NA, 1:3), 1:4) wma <- WMA(x, 2) checkTrue(inherits(wma, "xts")) } # Exponential, Volume-Weighted Moving Average test.EVWMA <- function() { checkEqualsNumeric( EVWMA(input$all$Close, input$all$Volume), output$allEVWMA ) checkEquals( attributes(EVWMA(input$all$Close, input$all$Volume)), attributes(output$allEVWMA) ) checkEqualsNumeric( EVWMA(input$top$Close, input$top$Volume), output$topEVWMA ) checkEquals( attributes(EVWMA(input$top$Close, input$top$Volume)), attributes(output$topEVWMA) ) checkException( EVWMA(input$mid$Close, input$mid$Volume) ) checkException( EVWMA(input$all$Close) ) checkException( EVWMA(input$all[,1:2], input$all$Volume) ) checkException( EVWMA(input$all$Close, input$all[,1:2]) ) checkException( EVWMA(input$all$Close, n = -1) ) checkException( EVWMA(input$all$Close, n = NROW(input$all) + 1) ) } # Zero-Lag Exponential Moving Average test.ZLEMA <- function() { checkEqualsNumeric( ZLEMA(input$all$Close), output$allZLEMA ) checkEquals( attributes(ZLEMA(input$all$Close)), attributes(output$allZLEMA) ) checkEqualsNumeric( ZLEMA(input$top$Close), output$topZLEMA ) checkEquals( attributes(ZLEMA(input$top$Close)), attributes(output$topZLEMA) ) checkException( ZLEMA(input$mid$Close) ) checkException( ZLEMA(input$all[,1:2]) ) } test.ZLEMA.n.ratio <- function() { out <- c(rep(NA, 6), 4.0, 6.0, 7.75, 9.3125) checkEqualsNumeric(ZLEMA(1:10, ratio = 0.25), out) checkEqualsNumeric(ZLEMA(1:10, n = 7), out) checkEqualsNumeric(ZLEMA(1:10, n = 7, ratio = 0.25), out) } test.ZLEMA.ratio.eq.0 <- function() { checkException(ZLEMA(1:10, ratio = 0.0)) } test.EMA.non.na.eq.n.does.not.error <- function() { x <- c(NA, rnorm(10)) e <- EMA(x, 10) z <- ZLEMA(x, 10) # error will prevent reaching here, failing test return(TRUE) } TTR/inst/unitTests/runit.TTR.Misc.R0000644000176200001440000000602614531142730016534 0ustar liggesusers# # RUnit tests TTR moving averages # # test reclass works and throws error # test xtsAttributes, both CLASS and USER # test all.equal(CLASS) and !all.equal(CLASS) cases # Create input data data(ttrc) rownames(ttrc) <- ttrc$Date ttrc$Date <- NULL input <- list( all=ttrc[1:250,], top=ttrc[1:250,], mid=ttrc[1:250,] ) input$top[1:10,] <- NA input$mid[9:20,] <- NA #iAll <- as.matrix(ttrc[1:250,]) iAll <- ttrc[1:250,] iTop <- iAll; iTop[1:10,] <- NA iMid <- iAll; iMid[9:20,] <- NA hl <- c('High','Low') hlc <- c('High','Low','Close') cl <- 'Close' # Load output data load(system.file("unitTests/output.misc.rda", package="TTR")) ################################################# # Rate-of-Change test.ROC.continuous <- function() { roc <- ROC(iAll[,cl], type='continuous') checkEqualsNumeric( roc, output$allROCc ) checkEquals( attributes(roc), attributes(output$allROCc) ) #checkEqualsNumeric( ROC(input$top$Close, type='continuous'), output$topROCc ) #checkException( ROC(input$mid$Close) ) } test.ROC.discrete <- function() { roc <- ROC(input$all$Close, type='discrete') checkEqualsNumeric( roc, output$allROCd ) checkEquals( attributes(roc), attributes(output$allROCd) ) #checkEqualsNumeric( ROC(input$top$Close, type='discrete'), output$topROCd ) } # Momentum test.momentum <- function() { mom <- momentum(input$all$Close) checkEqualsNumeric( mom, output$allMom ) checkEquals( attributes(mom), attributes(output$allMom) ) #checkEqualsNumeric( momentum(input$top$Close), output$topMom ) #checkException( momentum(input$mid$Close) ) } # Close Location Value test.CLV <- function() { ia <- iAll[,hlc]; rownames(ia) <- NULL it <- iTop[,hlc]; rownames(it) <- NULL oa <- as.data.frame(output$allCLV); rownames(oa) <- rownames(ia) ot <- as.data.frame(output$topCLV); rownames(ot) <- rownames(it) checkEqualsNumeric( CLV(ia), output$allCLV ) checkEquals( attributes(CLV(ia)), attributes(output$allCLV) ) checkEqualsNumeric( CLV(it), output$topCLV ) checkEquals( attributes(CLV(it)), attributes(output$topCLV) ) } # Arms' Ease of Movement test.EMV <- function() { ia <- iAll[,hl]; rownames(ia) <- NULL emv.all <- EMV(ia, input$all$Volume) checkEqualsNumeric( emv.all, output$allEMV ) checkEquals( attributes(emv.all), attributes(output$allEMV) ) #emv.top<- EMV(input$top[,c('High','Low')], input$top$Volume) #checkEqualsNumeric( emv.top, output$topEMV ) #checkEquals( attributes(emv.top), attributes(output$topEMV) ) #checkException( EMV(input$mid[,c('High','Low')], input$mid$Volume) ) #checkException( EMV(input$all[,c('High','Low')], input$mid$Volume) ) #checkException( EMV(input$mid[,c('High','Low')], input$all$Volume) ) } # Know Sure Thing test.KST <- function() { checkEqualsNumeric( KST(input$all$Close), output$allKST ) checkEquals( attributes(KST(input$all$Close)), attributes(output$allKST) ) #checkEqualsNumeric( KST(input$top$Close), output$topKST ) #checkException( KST(input$mid$Close) ) } # CTI test.CTI <- function() { checkEquals(length(input$all$Close), length(CTI(input$all$Close))) } TTR/inst/unitTests/runit.TTR.runFun.R0000644000176200001440000003212314531142730017113 0ustar liggesusers# # RUnit tests TTR running/rolling functions # # Create input data data(ttrc) rownames(ttrc) <- ttrc$Date ttrc$Date <- NULL input <- list( all=ttrc[1:250,], top=ttrc[1:250,], mid=ttrc[1:250,] ) input$top[1:10,] <- NA input$mid[9:20,] <- NA # Load output data load(system.file("unitTests/output.runFun.rda", package="TTR")) ################################################# # Sum test.runSum <- function() { checkEqualsNumeric( runSum(input$all$Close), output$allSum ) checkEquals( attributes(runSum(input$all$Close)), attributes(output$allSum) ) checkEqualsNumeric( runSum(input$top$Close), output$topSum ) checkEquals( attributes(runSum(input$top$Close)), attributes(output$topSum) ) checkException( runSum(input$mid$Close) ) checkException( runSum(input$all[,1:2]) ) checkEqualsNumeric( tail(runSum(input$all$Close,250),1), sum(input$all$Close) ) checkException( runSum(input$all$Close, n = -1) ) checkException( runSum(input$all$Close, n = NROW(input$all) + 1) ) } # Wilder Sum test.wilderSum <- function() { checkEqualsNumeric( wilderSum(input$all$Close), output$allwSum ) checkEquals( attributes(wilderSum(input$all$Close)), attributes(output$allwSum) ) checkEqualsNumeric( wilderSum(input$top$Close), output$topwSum ) checkEquals( attributes(wilderSum(input$top$Close)), attributes(output$topwSum) ) checkException( wilderSum(input$mid$Close) ) checkException( wilderSum(input$all[,1:2]) ) checkException( wilderSum(input$all$Close, n = -1) ) checkException( wilderSum(input$all$Close, n = NROW(input$all) + 1) ) } # Min test.runMin <- function() { checkEqualsNumeric( runMin(input$all$Close), output$allMin ) checkEquals( attributes(runMin(input$all$Close)), attributes(output$allMin) ) checkEqualsNumeric( runMin(input$top$Close), output$topMin ) checkEquals( attributes(runMin(input$top$Close)), attributes(output$topMin) ) checkException( runMin(input$mid$Close) ) checkException( runMin(input$all[,1:2]) ) checkException( runMin(input$all$Close, n = -1) ) checkException( runMin(input$all$Close, n = NROW(input$all) + 1) ) checkEqualsNumeric( tail(runMin(input$all$Close,250),1), min(input$all$Close) ) } test.runMin.cumulative <- function() { ttr <- runMin(input$all$Close, 1, TRUE) base <- cummin(input$all$Close) checkEqualsNumeric(base, ttr) } # Max test.runMax <- function() { checkEqualsNumeric( runMax(input$all$Close), output$allMax ) checkEquals( attributes(runMax(input$all$Close)), attributes(output$allMax) ) checkEqualsNumeric( runMax(input$top$Close), output$topMax ) checkEquals( attributes(runMax(input$top$Close)), attributes(output$topMax) ) checkException( runMax(input$mid$Close) ) checkException( runMax(input$all[,1:2]) ) checkException( runMax(input$all$Close, n = -1) ) checkException( runMax(input$all$Close, n = NROW(input$all) + 1) ) checkEqualsNumeric( tail(runMax(input$all$Close,250),1), max(input$all$Close) ) } test.runMax.cumulative <- function() { ttr <- runMax(input$all$Close, 1, TRUE) base <- cummax(input$all$Close) checkEqualsNumeric(base, ttr) } # Mean test.runMean <- function() { checkEqualsNumeric( runMean(input$all$Close), output$allMean ) checkEquals( attributes(runMean(input$all$Close)), attributes(output$allMean) ) checkEqualsNumeric( runMean(input$top$Close), output$topMean ) checkEquals( attributes(runMean(input$top$Close)), attributes(output$topMean) ) checkException( runMean(input$mid$Close) ) checkException( runMean(input$all[,1:2]) ) checkException( runMean(input$all$Close, n = -1) ) checkException( runMean(input$all$Close, n = NROW(input$all) + 1) ) checkEqualsNumeric( tail(runMean(input$all$Close,250),1), mean(input$all$Close) ) } test.runMean.cumulative <- function() { ttr <- runMean(input$all$Close, 5, TRUE) base <- cumsum(input$all$Close) / seq_along(input$all$Close) is.na(base) <- 1:4 checkEqualsNumeric(base, ttr) } test.runMean.cumulative.n.equals.1 <- function() { n.1.cum <- runMean(1, n = 1, cumulative = TRUE) n.1.noncum <- runMean(1, n = 1, cumulative = FALSE) checkEqualsNumeric(n.1.cum, n.1.noncum) } test.runMean.cumulative.accounts.for.leading.NA <- function() { x <- c(rep(NA_real_, 5), 1:5) target <- c(rep(NA_real_, 5), cumsum(1:5) / 1:5) result <- runMean(x, n = 1, cumulative = TRUE) checkEqualsNumeric(target, result) } # Median test.runMedian <- function() { checkEqualsNumeric( runMedian(input$all$Close), output$allMedian ) checkEquals( attributes(runMedian(input$all$Close)), attributes(output$allMedian) ) checkEqualsNumeric( runMedian(input$top$Close), output$topMedian ) checkEquals( attributes(runMedian(input$top$Close)), attributes(output$topMedian) ) checkException( runMedian(input$mid$Close) ) checkException( runMedian(input$all[,1:2]) ) checkException( runMedian(input$all$Close, n = -1) ) checkException( runMedian(input$all$Close, n = NROW(input$all) + 1) ) checkEqualsNumeric( tail(runMedian(input$all$Close,250),1), median(input$all$Close) ) } test.runMedian.cumulative <- function() { cummedian <- compiler::cmpfun( function(x) { med <- x * NA_real_ for (i in seq_along(x)) { med[i] <- median(x[1:i]) } med } ) base <- cummedian(input$all$Close) is.na(base) <- 1:4 ttr <- runMedian(input$all$Close, 5, "mean", TRUE) checkEqualsNumeric(base, ttr) is.na(base) <- 1:5 ttr <- runMedian(input$all$Close, 6, "mean", TRUE) checkEqualsNumeric(base, ttr) } test.runMedian.cumulative.leading.NA <- function() { na <- rep(NA, 10) x <- input$all$Close xmed <- runMedian(x, 1, "mean", TRUE) y <- c(na, input$all$Close) ymed <- runMedian(y, 1, "mean", TRUE) checkEqualsNumeric(ymed, c(na, xmed)) } test.runMedian.cumulative.n.equals.1 <- function() { n.1.cum <- runMedian(1, n = 1, cumulative = TRUE) n.1.noncum <- runMedian(1, n = 1, cumulative = FALSE) checkEqualsNumeric(n.1.cum, n.1.noncum) } # Covariance test.runCov <- function() { checkEqualsNumeric( runCov(input$all$High, input$all$Low), output$allCov ) checkEquals( attributes(runCov(input$all$High, input$all$Low)), attributes(output$allCov) ) checkEqualsNumeric( runCov(input$top$High, input$top$Low), output$topCov ) checkEquals( attributes(runCov(input$top$High, input$top$Low)), attributes(output$topCov) ) checkException( runCov(input$mid$High, input$mid$Low) ) checkException( runCov(input$all$High) ) checkException( runCov(input$all[,1:2], input$all$Low) ) checkException( runCov(input$all$Close, n = -1) ) checkException( runCov(input$all$Close, n = NROW(input$all) + 1) ) checkEqualsNumeric( tail(runCov(input$all$High, input$all$Low, 250),1), cov(input$all$High, input$all$Low) ) # x argument as xts object checkEqualsNumeric( runCov(xts::as.xts(input$all)$High, input$all$Low), output$allCov ) # x and y arguments as xts objects checkEqualsNumeric( runCov(xts::as.xts(input$all)$High, xts::as.xts(input$all)$Low), output$allCov ) } test.runCov.xts.nonleading.na <- function() { top <- input$top$Close mid <- input$mid$Close checkException(runCov(top, mid)) } test.runCov.n.1.and.cumulative.FALSE.warns <- function() { op <- options("warn") options(warn = 2) on.exit(options(warn = op$warn)) checkException(runCov(1:10, 1:10, n = 1, cumulative = FALSE)) } test.runCov.cumulative <- function() { cumcov <- compiler::cmpfun( function(x) { cov <- x * NA_real_ for (i in seq_along(x)) { y <- x[1:i] cov[i] <- cov(y, y) } cov } ) x <- input$all$Close base <- cumcov(x) is.na(base) <- 1 ttr <- runCov(x, x, 1, "all.obs", TRUE, TRUE) checkEqualsNumeric(base, ttr) is.na(base) <- 1:4 ttr <- runCov(x, x, 5, "all.obs", TRUE, TRUE) checkEqualsNumeric(base, ttr) is.na(base) <- 1:5 ttr <- runCov(x, x, 6, "all.obs", TRUE, TRUE) checkEqualsNumeric(base, ttr) } # Correlation test.runCor <- function() { checkEqualsNumeric( runCor(input$all$High, input$all$Low), output$allCor ) checkEquals( attributes(runCor(input$all$High, input$all$Low)), attributes(output$allCor) ) checkEqualsNumeric( runCor(input$top$High, input$top$Low), output$topCor ) checkEquals( attributes(runCor(input$top$High, input$top$Low)), attributes(output$topCor) ) checkException( runCor(input$mid$High, input$mid$Low) ) checkException( runCor(input$all$High) ) checkException( runCor(input$all[,1:2], input$all$Low) ) checkException( runCor(input$all$Close, n = -1) ) checkException( runCor(input$all$Close, n = NROW(input$all) + 1) ) checkEqualsNumeric( tail(runCor(input$all$High, input$all$Low, 250),1), cor(input$all$High, input$all$Low) ) } # Variance test.runVar <- function() { checkEqualsNumeric( runVar(input$all$Close), output$allVar ) checkEquals( attributes(runVar(input$all$Close)), attributes(output$allVar) ) checkEqualsNumeric( runVar(input$top$Close), output$topVar ) checkEquals( attributes(runVar(input$top$Close)), attributes(output$topVar) ) checkException( runVar(input$mid$Close) ) checkException( runVar(input$all[,1:2], input$all$Low) ) checkException( runVar(input$all$Close, n = -1) ) checkException( runVar(input$all$Close, n = NROW(input$all) + 1) ) checkEqualsNumeric( tail(runVar(input$all$Close,n=250),1), var(input$all$Close) ) } # Standard Deviation test.runSD <- function() { checkEqualsNumeric( runSD(input$all$Close), output$allSD ) checkEquals( attributes(runSD(input$all$Close)), attributes(output$allSD) ) checkEqualsNumeric( runSD(input$top$Close), output$topSD ) checkEquals( attributes(runSD(input$top$Close)), attributes(output$topSD) ) checkException( runSD(input$mid$Close) ) checkException( runSD(input$all[,1:2]) ) checkException( runSD(input$all$Close, n = -1) ) checkException( runSD(input$all$Close, n = NROW(input$all) + 1) ) checkEqualsNumeric( tail(runSD(input$all$Close,250),1), sd(input$all$Close) ) } test.runSD.cumulative.with.leading.NA <- function() { x <- c(rep(NA_real_, 5), 1:5) target <- sapply(1:5, function(i) sd(seq_len(i))) target <- c(rep(NA, 5), target) result <- runSD(x, n = 1, cumulative = TRUE) checkEqualsNumeric(target, result) } # Absolute deviation test.runMAD <- function() { checkEqualsNumeric( runMAD(input$all$Close), output$allMAD ) checkEquals( attributes(runMAD(input$all$Close)), attributes(output$allMAD) ) checkEqualsNumeric( runMAD(input$top$Close), output$topMAD ) checkEquals( attributes(runMAD(input$top$Close)), attributes(output$topMAD) ) checkException( runMAD(input$mid$Close) ) checkException( runMAD(input$all[,1:2]) ) checkException( runMAD(input$all$Close, n = -1) ) checkException( runMAD(input$all$Close, n = NROW(input$all) + 1) ) checkEqualsNumeric( tail(runMAD(input$all$Close,250),1), mad(input$all$Close) ) } test.runMAD.cumulative <- function() { cummad <- compiler::cmpfun( function(x) { mad <- x * NA_real_ for (i in seq_along(x)) { y <- x[1:i] mad[i] <- mad(y) } mad } ) x <- input$all$Close base <- cummad(x) is.na(base) <- 1:4 ttr <- runMAD(x, 5, cumulative = TRUE) checkEqualsNumeric(base, ttr) is.na(base) <- 1:5 ttr <- runMAD(x, 6, cumulative = TRUE) checkEqualsNumeric(base, ttr) } test.runMAD.cumulative.leading.NA <- function() { na <- rep(NA, 10) x <- input$all$Close xmed <- runMAD(x, 1, cumulative = TRUE) y <- c(na, input$all$Close) ymed <- runMAD(y, 1, cumulative = TRUE) checkEqualsNumeric(ymed, c(na, xmed)) } # Percent Rank test.runPercentRank_exact.multiplier_bounds <- function() { x <- input$all$Close checkException( runPercentRank(x, 10, exact.multiplier = -0.1) ) checkException( runPercentRank(x, 10, exact.multiplier = 1.1) ) } xdata <- c(7.9, 5.2, 17.5, -12.7, 22, 4.3, -15.7, -9.3, 0.6, 0, -22.8, 7.6, -5.5, 1.7, 5.6, 15.1, 6.6, 11.2, -7.8, -4.3) xrank10_1 <- c(NA, NA, NA, NA, NA, NA, NA, NA, NA, 0.4, 0.1, 0.8, 0.5, 0.7, 0.9, 1, 0.8, 0.9, 0.2, 0.4) xrank10_0 <- c(NA, NA, NA, NA, NA, NA, NA, NA, NA, 0.3, 0, 0.7, 0.4, 0.6, 0.8, 0.9, 0.7, 0.8, 0.1, 0.3) test.runPercentRank_exact.multiplier_eq0 <- function() { xrank <- round(xrank10_0, 2) checkIdentical(xrank, runPercentRank(xdata, 10, FALSE, 0)) } test.runPercentRank_exact.multiplier_eq0.5 <- function() { xrank <- round(xrank10_0 + 0.05, 2) checkIdentical(xrank, runPercentRank(xdata, 10, FALSE, 0.5)) } test.runPercentRank_exact.multiplier_eq1 <- function() { xrank <- round(xrank10_0 + 0.1, 2) checkIdentical(xrank, runPercentRank(xdata, 10, FALSE, 1)) } test.runPercentRank_cumulTRUE_exact.multiplier_eq0 <- function() { xrank <- c(0, 0, 2, 0, 4, 1, 0, 2, 3, 3, 0, 8, 4, 7, 10, 13, 11, 14, 4, 6) / 1:20 xrank[1:9] <- NA xrank[10] <- 0 checkIdentical(xrank, runPercentRank(xdata, 10, TRUE, 0)) } test.runPercentRank_cumulTRUE_exact.multiplier_eq0.5 <- function() { xrank <- (c(0, 0, 2, 0, 4, 1, 0, 2, 3, 3, 0, 8, 4, 7, 10, 13, 11, 14, 4, 6) + 0.5) / 1:20 xrank[1:9] <- NA xrank[10] <- 0.5 checkIdentical(xrank, runPercentRank(xdata, 10, TRUE, 0.5)) } test.runPercentRank_cumulTRUE_exact.multiplier_eq1 <- function() { xrank <- (c(0, 0, 2, 0, 4, 1, 0, 2, 3, 3, 0, 8, 4, 7, 10, 13, 11, 14, 4, 6) + 1) / 1:20 xrank[1:9] <- NA xrank[10] <- 1 checkIdentical(xrank, runPercentRank(xdata, 10, TRUE, 1)) } TTR/inst/unitTests/output.volatility.rda0000644000176200001440000003011414450607776020150 0ustar liggesusersyX?𑲄di#ʾ$Z4ƬeC%*Nb~xA6!aE6Dmjk!sqfNj?*::<,`!jQh,Zv kNjt=?~pz6Fq9wUb?ܑ@mBC CcP,'L5t[]L o/,yLn aGBmp7% .'҆B_{';8d&X >(6"c e]+ @(˘Q6A(HJoiHGA`-aЅ>(8v={8wEq)[CքQ3ow. "y j^n>|w$?!PjR^oGI.a#!~$GdD:@(aJtٖ G~}<^T]RGuߦ#nt]ba|Wu@?2Ag;nr1e" na{i"dN+<{}9̟{%Cmhz'Od1)0t,zR3R&5OVm?n~B䔒5֬bOI,9CN~9;u?c.9ne>'q׬(pLz(d5_E;}(Ȳ~ QӬgo\PU#u&'Em p[no %tbخ޺x2 ~4 n25xC>xاI v?*")91X>hҁe=[~l)!4SpNm1#^\=)PM#"b.u{Nӻܪcn5\_ɶ)c1>t] ʡCWCm]Q!8臢C4$xק-qX,1^1hKE .i4,,? އ_h2Cɒ9DſVny׃Ct`'42m`ZQjC!vqQJbdF>8ou;y-p {{b?e+,2DP~3AzvtX}gu=|s9sf_^;at}#^=煿*Z—:tEb3f?F(6(8X`/ƒgָȷeS# ;]`~8G}&nd&X遲\U(0ݹ%oVY/Ac-|&@t`-ZaPYA[Z満;2gI 7,|om7zgfcAz>?H# {'U-/X%|NKp$~ aj+kUx 5q >Cظ^ 5xH/͌k:҅rܥ c)3)ǁ?'|C%:iW-lò0+[p8Zۼ'\Χ;7CX;fa%Y^CޠD7 ek =;[\t-a*$a P%9|s,w܋v^^C޶)ܬ .n켕!;8e/p8 ޼Kܖ`+P_΀7o{Ve.p1sT+xm2oa̎ Y_ rUVd̅'=i[rnd 5󫋇!|bzϚ>+J&܊2Nڮnx'Q[zk!^jA0])VBYMHd@T<S+e.q~{dDoJMhmK<ȸCroCepUuw]"W]!8rS~p}Rj+\V>fD5~~`9ܛ[M:}`5ps˪h+H^z?ѡʰm+_\hM=/Y #35L~}ɮk}.Jy>6UEics?^868wSk65B2}k\kq$ O#B8+ q%3NB8h9ҁp <"SN !لp  Lg$!p;FB8"3NӟVB8Vp>9Clj#B8pt &ցp2;:!ip~‰@8 xyL7!pDp‰ Mga;!pdpGG؁p‰'sN_B8c ¹K'JB8B8NpyCǨ#SAg'!KpCGE4!yp"$yIǙNOB8لpB $#%MI'N!!"B8!p$Up$s%%(&JQL( G1QB$H( G1Qb$DI8p%(&J{$ɿ$@\e0MV.>(=ۨnRYVfAv{9jz&зBSzlgiȢ;!nw m:5RO fyA,Kn8/i0oċ!Z}US{fLU7o+! (}<iic;𷑷[(DC|?C8rvCwz [c::Ύs}m8ՊvBq`xVMHz'LN@41N3x>WYb^Boe t<߂'O Qޢ7В; +-!3#{&߰{q'WN0v_;N2SYM$ny߶_g"E&oUU<;%i͓Qt.K87Cы/'%xWZO`+o;y{QsuC }3~'qoօEv ;qN/15qR^ рHYG&>51lX'Oȷ#}krx$`;s cseb;by?yQ{sgsv/EvE-Z钝=л-@xqVW񬐪6:~7{(N|[a[mءi&:S-{5w -NSb/ LɜN&u)prrUeq`Lz ;akRc}P,q@6oKl 7?v{ |b:6NDNZkBuҼXGm,x|8D>lٷ^Kޤ|h╓Z]/?zp:&JQL( G1Qb$DI8p%(&J{$p%(&JQL( G!Qοȧp3N!p^!LǓ&!لp 0 ,'@LjB8 p'Lg&!#B8Fp&™B5!KB8g ‰&"sN;!Մp,!cHg.!XB8 !Bg+!B8΄pJ E'!p"Cg5!Apl &cKǏ&! pr I"B8 $‘7±fYI'N! B8 l#OqB8p^YA !opIǎ)!ՄpYFg!фpOLJ+!VB8K&3\'3hB8g $3N ! B8p DL7!%p L$J!Kp!B8%pn &# G!DŽpT "SDg"!=B8p>©$3N>!ۄpBG!B8pp%J!+B8g I SD!pMGN$!B8GGǗ&B8=L cH'NB8:pF@!p”1Qb$DI8p%(&JQL( G1Q%tH( G1Qb$DI8 p>#\RD#LuPw]AY$q//׌]!(ﶣ)­xO!&Hu m{h]=?tul kdmM(yҾb[9[eT*3Ǫ̼B$ b.I !bbQp}œfκk :o\ʳ_~ )wq N˕{W`ѲGƳ=u˨+B: m!?Q-|NDa! 9C7"^%5_A8}/)DMU۬[ 2)>?-@2Pb9C l { =APTMg4˶=Ë*׃yu[4xOW-%-M?2 h;ulz6u9'6EUנwڠ(>-\Mac6$: t>~7b˦-\-d>o}+IbL3uŴ/H^kѫL+4GzcݖCRC 4aBB$-eow^ 6n;ϳyݔ#n;ir "(4y {'O?竮4U t_ߺln0 X \{#n|:e p4m o~e0++wXvÍneTTH e@ҧ?LtVm-6"-p͛s9ۏ>/X?_;%"SQr)q/l"JW[dn^g:FcdѫWR p\p'/[`Kn^ 5]-˂Bl?懭?z >~9 aMB{%ߖݺE͘iPrNu޼~!5r3S sXPm \f@ qFe6a9U߹S~X{C|\,m{|𵵊ulYMkr@ Wmy] @bxk RϾ]k[X WZ!8h@\|eo{, fαG[Y0y"Wz74]JxPWnد^.?tG>-'Ԇ`xJŮ(7$ev[J=Cw utL^har.'!|qN>?nw&"ÎsL!y'k&@tMdD2j7|{%:iC Zu'KzK݀!(絤 eüM7}EN ?svdQo x_@5̌\keNcDUHԩ># 9bP%]DI톴V<к{JP:ˠbS@d6@]k8s߱B2q,w aUNDI8p%(&JQL( G1Qb$DI8O!Qb$DI8p%($Jp$%( GI8JQp:$JQL( %(&JQL( G1Qb$DI8 p!Qb$DI8p4ny}uY Lh~< 3nj*vZH4a˨ *®0}nz_>U=u/fV )U{ԅ.c??fյ)a *k@-TpaHJwjlmV\J)1ѧ8V+T#R"zRK-.ȧ/9\" QMݷ d4䢩wY6Ap?6 hg*#ѫ\),ӜB!:#>17~=Fݣqooa 8h6-sgC02#'8u]N6|bWJ2)ܾRQ/W.7+nOdP BIlzx@eqf #fEc>*ycC5W)U^)t}AUaJpE|6D}ץVC)~?^̲ѤB[;yr3餷6g[>~{*jMey'6"* ΚpgNU#'ۃ.9R,>Ф>:> 'w *3) *O@|OI_\He \;oy+%|!7U|ޕwjN J2rUzMS>T";B!'ɳ3k ?WWeBzGɡfq;a2D}^K'9x+VWS ;1U:պ`y%-^M {x9QyQ~ҍY\fDQ$z}R>:1 azhjdcVuQy0 #GC*i`t[*Wѿt!8/< `_h;T2n >&T9&'QM9jziE榹xP~AC.ѝǃ󡙫ܜWcr/޻"9dk--*Oai(1wa0)p-2󳮴R't[1tmQwAeuۙGܓF rYe)|M~XPedD.ytrҧr6o^r:m\sL[0Y9 &#S/nLwTzzPڪϦR9u:yÏc LhnF+Jӫ:)ueoYTW;Ck;z&.|]y >OjCzvi\<"um. qz`<~ܪsCbs.^=E鸽i}OdƏ]^yŹC- ﶡ8iJ#MT+@ᬝ '\[)pm{MnK|ɓ(!EU'OV]N} ܬVi]+m+,ב7Jf]3F\v@}4gz=΃ɈrVEȏ+H3N4v"N5ai{"`쀕.&Dl1*7UTnߪ1ב&rU?yzZk{{ڻwlɄ!&&&!&AA8/ [m݂o 5bW]lpw e~F?^ۧd6< ˷Yr C w@'aģHHYK'ݵ@G4y:*_b C@@pis{C|O]G@qD̤qmx|vTo^nS<G9y-u@[W^M`"3xSjM`va]6D2{DiM ;--@dL x;oqx x(;;qW_DsHh\2Tf=4?\XҊ+@ @9H\Rt?$~.8n5Q)l@ŝ)PyRYJeZP\XŹPP\g^uPܸPmN N&b(n7ņxc@sТ롹c hnLƷO/0<)#pq w^Y".׹Z w^|_-`Kُ``y) `8y|Mg>Nbgæ<chW6ܮТ:{Z:`yg*0lh\vl͆\|4F itTgOy8wJ7FŦRO؟2P\wIw>%QQGP<(~3]Q9s9w='nx 7xk/hvC 4w-Zh.0lڠ08#:p>=Np%>Q-[]7sssps@ %|]0 i= 8{ `V녾ppa%y=?i纨_/Ifi0;^\Т^\4#=_ra)>Xl=RW@X$ l:ن҉aAGQw5}cˀs˘R" ǔ-p F^lKE7vx- =: r@޲{l';WFwn*bz'$YS~2 %z+5: dy!"k˄~  'DC[ ;NqESAj #w7 j j5@4%Ʃj#ϗ.Y)o=DkDbm vWLK>I.KA=O,~I\/"y'y!we ō4!wTCocv@}pZd8{l;6YDȌ-X/M3U ľ/fVMs85G+(:?hoo#b͞=ؒX\Zqtkb՛83jH"`StjS!:;qxh,^ы=Vl/^š^vk$uYR:`ݐc8~ ~+DiDZN*b-x ܪS('*|]W>I >{䜱/:,ot/:2an j!E8Z4O?o; AZ@jݬJc\o6O:1:3mnYϿJqn_ۀYټ`|܄y}B/u3̧g+?eߩmz вexa==pfVvHn^@_qba??dFŖlϦO}Z ]j{=+ekwV^)yy@_zS _Buf|ֲp͗,<.nZR }̂C:l>,x]!ί0ewf\?#3rSx\ۗzbXo2㋜!krxv!0&q-^Gp)UYɿ~(rf_̈`uG9B 9wʕ笆L_!z0>w0!ûq|: y|P{h/خϵ@PKlcO\.҉z~b@kto.{vc||b=PK O+kwix:vgH\6}_띹I*~LPSt6b\u7EKa֟@OΈyXur. V^ԥ5IN7 -@5\_U6 󑣲ɫBJ??.o`#+ I]~#U?9 À 5pf8,x=e>عqM,}a\d?wZf eR@~WI P[ye _r6 ̿yxO@=qrxTZpVM*W4i8jI'n" 4轙/7 suhxƺY}W)]nYT@ȧ[ukq?.x埍g{eMVnh@G`DH3>OjTF .eG/BfWX-Dsuww_tQb o2*EG߶={>̎yK=0[?c]/~a ;ݿ! ڡR/W؞*sf'mb]Q0u}\AzН|t;}|a:~4n{ tTi!+p;j*/y)ƺNdºc OƳ߬Ⱥ5oFFzXu#GW[Yw)Ra]κn0͈x?lX n_̺^3ћum8eǹ ƹ1ϥ9ׇ\7ݬȹ| z^1ΙGsQĹ~sYm!sHʭ9?'s\?s'm[9Ͻ\\zJ-zV/J9שo #t;ޟ&'n4s}p1B/]o(.)t]a9s_Msmׅ8 ]?.t=WzMu{Bpgޑ+tB$\_'r "G ],r=TpA"uD;\%r}uBD\>C亻q"ח\.r=KEK\_/r] r=S] ׃=x#9^xmW??>}]8ЈU> 繵p6T?1\y}99oOeցdm˛z@V|a`7Ǘb +_~낶YXge:?o) g5viE6ϟ1w2YicEȪ @`vt仇c&%Gy&o9N1o|2~N]H 7"w"y{@F^PddնaӀ۰ݣ eUSx}ert/ Uf-eʩ 23 ğIRݠJWc)9ہ^S֫%to/ ObG\e]/u>Dn;˓FR$ '3ἤo@n"1Iv8nvr%XѮwHwep{ lnhꙇ`:~ &͚%t}Wpm9y-. A1ny-@ȧ?y"sY/ 2>zuC5@ׅ&"hܯwkO -?z[ii_zqڑM4_90H.s4301kB o*oS V1/dFʕlJqU QFcɠKc"֓'(=|q PkGVjWX/mjY<[ޮIkVm@GGkbߪ 3uJ'~2w@EXp9'wqH:L+e͘W\s!薾m֯3`~dz^_*~6mlk./w ob~g1*~.cy=u3>nߎjw=QKf,luz\0ߏlzm}` |4'UOkF`BW p6RKa1뛑iϞH߯ =}-ɗ\lpaKН| w~(L:~W16Z tVDc?}:&u. S'`]3Gv*г] <9E=xhS"Ǩ|n;|!-9"?vAD; eNu5嗯o` r>8Nz0V)@j~qLͺ!z\s@QHF/p=z3^]W CzwF e^[x1p&XA ?hG?xjd̓V8ߝC3Zu*κ]g6q(Ӊ(#KCכN~KBT y?m`>)J5>f]Jds<6exKqUfgN LA#wfKĦjcq>mf{FmNc]O?^w]/p:^"vEם\va\L^LND_D+W'"8E7H(TkFD_yp4xx^9l8v"Ο3p[M,yuj?],9?/{5ʷuJt=x_cnYUi&Qz̫KXׯIuǽ8q뫜fpnZŹ>}1@Ks}uu'M+:9ן8c]'q)su^q[Vpa.\?Hq\Zsu8yvqGs\ωzù{s"'g\Ϛj¹nvsR w&ݜv~ tF)s+?N\'̹^V1s Q8ו\ ]o#tEz[8/~BCZ3yB׿~wM78#?\(t}k;Y ]o!t B ] UjUׁݑ/^nMryWQі?屟9`ms2n[t@f d_oپ`@m4gNb. yIv@X\P!\ ʾYɍ ĸ~H|2}-ћ0 Z:(2:ug;ͧ:s̋r׆|[?/_Fi'^֤ HaW2ѳ<%}zeGn],+]p_ dDVRA" CEYDv@]`Ӂuϊu/׿0܆κ^"uؗ,;23&@t=Ē?=bǙ]׀GUnj"}l}K-úᬲ\;@D?y=+(6g9Et~dož9J{ RJ7/6 +zF/`ƛ<3D{ tyZ pcsgx쳍M<+b !+[sμ>yhH2t8GbXw'Ǜ1z3Ox /p {h lU]Ǭ|_?߄<ُ'Ϯ1}ɧu{p4i1F>/J_ PVα/YK\ Iݢ@}:-Pfϔ#7sslx@yXt 6Jw]*qu9'c4G-Y2B\#tHC;wOtچn)GZ)-Rtة9IGm؇tK|f%'˙~kyQq!.gotgQ,MŠ#+ޒGr0Vs| _z~;0?}L}>E {LREpo[VDUW0ƧO-=t3ˬnk`Ċ+~%q|-hq蛸6dvV:;ziy?nk _.X̜ؖ;|z|[V%=5yeY!03nl,{y6㸟30sfQlSbG@g t>k4\rT}G =Z&mjh%뫫=dc,Ҙ^m)XoYSN '}L;uA f9Iٺ1c7 Wh$YY?9Բa>9{mnub7|`2 c0Nk N7UGU{Zhnt5~WU4D4У@ЙoZ\"$wI,֗cw8c}ҿhGצ9L'f%X,gy ~Nۺ<aSUo}`y]o^菮V-Ae&|G׍WnXNGJVB?lߍ(AחFkSԚToIz{HC`=ux{-Xt=]qWhg5WZ~v֨c]u=R#xިQ/SX׋tf f]?j7`únź§uzY¤Y- `]7xzK25g]OXu)xz۷FqI_%{жe]e)M%Zi7f*ng]w/uqb]z+tz9=kY׃<\{fc 9ח<\Ŝ.JqQ9׳]Xݜ&n`]>Ϲ^^缢9s{%97wO\~o!:[\O}>ȹ>z[gq;?ιqn#\Ogh.tgB׳ ]_RĹ>kB ]o~Y躩Z7 ]n/t%B躇E焮Wh ]_)t]Vz\#$t4)Bף҄W ]OG#" ]9Rz"DoLJ'D-r}u}D&r}U"E}QslVJ6@_٫?/zj^Cf~4e y@MX{n.T"7" Rb]Or8QejǗ:^0ȥdQ沕xGT{4UٿN(8#J@Ig!#m޹@6Q)oB?<ƾ%`u>-_} )s<{;cϴG(-,4C/~uVU2T9 /lR8Oq;x<ԗ<~(;p8˿Jx9bg;NYuQ{zF {,gkW g#x4P!iU_FOy*o=_{WrV軗^=t9@D&nD #)7-=8kܭPl> z凯1#:հuxinkm}.*" +neK8:@F|bE@16٨'u$dJb6c:x6@:^JoZeL4y;|1bJsmcN&{Ǐa@@82Jïi}sB&@u.J`LPz܀cis5!PJ21,󶥸 :P w fbck'-*}Zf4N@?V-aí?GW)t`̉}*.Wa6 naws>>>s 79!Xc RPgWt5"`f>¼w|u'C0(~]]uNzwʆq.`K6oJP_+Vp7s ج?Xd_ 5o-sxj#/^ߜQ .cv푋>j ts/g8pa2m#̓/g==q9@K}׾];;y@5\蹧01`g( +4`d;=~îşd6i-8渭~O|kOb(lԪ?OuB {P\>z((cZ}1Pʁ\[v/I_'>3<Q/N m&@7ze!@_iE1xЂYOS֣?3B|YN6z@Ϙp6}E Uw_`# :"X3W-5lѦEOA :< `G+ǧ!D ޟN<_-,|lNڝ :$q&nG@ /]]]]sx7eoި*雽m wk0_KJ QBnF]ƚ5@L]"70ˁX(aZ 6UEo`?kDESJ z.& {@Z$\T_H=/mT_* WVIyZUC =yM ȇjr^<ͽgYLY?cT3ՀKY%(|W:N?Ťi~>֢ȯoFrd [#_iY= #>FJ˷]Mٯ]kςQThDO.Q&o*Μ!@\WGJ/>Q$Zi| -q躂kb x{@W̌~&ʓ HuXT bߡ@W^=|CcU}rH/l bT >r 6:. 0 I@DHuEVENQ3 >:y 729{tF-)S |Aԗ7W4sĂ `G+q/;LbI N[8o^_TKN*0]9:?Fp- ^Z3-ۺiIk czWa~uu@2,r8* 䧹Z1ʬl RV{bV՗Ge@}i4i?2#iRW 4ZζYU{m.+z`꟭5RN̏*]O;(0 .& J[? X琝ٻs\00;\;qW0{Nu̲`,Ίu0S^,s8h|06󌇵>Ԩ0[ vv`>%8X?qj~N09pdb`@#\itAJHw< zoXu7;o`xzW%3bWd`H?]ɎzσLJzs_ۋN ~Mq0YzT?n:eԚ@dazqEsdĖt`;eWSwZ*E._X9{~YOّ^S1@ܮ l8(.I= Xܛhn5 ܉q+9D,r]zA?wQ^+Nע'&Tbf 3]$Yo+w4aS c= 6hg>!$~M bYgrF=8 @R/T&On`]|8w58(qIO2k!^gM+H>?[g5.zdm-o; ę7i< Y8g/ VDb˻Ƒ8g%s3uB'NzbIW{d 4zSZE4_B q=I"xnk{z;C5}}}<8Cf'_Ι\k=Zq5M%qe;jDbE@fdžCr1>X/ u9a@,˴[ 8M ;ŀ|{l7nc/++˳->} f-= 3WmuJUy{F\.`O^J=jG|TNk{gl Jt s';JU-3Oo{b_x]U|sFn-(M@7NN!;{Ƀd2`,XIF`sUJ`贎칲h_ φc^?[0R/vwb'ӟ- ~KSLg^^|u `_S|KmWE/z?Z[0^Mce< R`&p-7uƜf.m]n`}j6i`13Q䡊}9,P}Lc9l`.)[+;u|b"1n}Ykqv"A =fgWrWlx# h¢@Tdm@G>'_6v+p>R-^9Y+}zV`CtϤf|}h1ՠ@WU@q( ºc`۸tXQ >fn:?P#hU'P xGtw/Z_q|{1aM&3es7~=MEo{V9։}~ >e/w}#^e2.7WSRAa',8m~㓳8S񞙫[%kv@E9)?A0\"dsn|WHN^1?߯ HȘc;aH5|}t7<ҹHwݤ4̟kw}T;  -LSo; ȫI=7@OoVRK%}|Wˑgk0pzؗ7+Љ+<;*tA~Νy6vz_UMmBt\ XYOsT,9(!:Ni.úE|)iO;.BG`C@[eo#] y+,u|>_%V>Fu@8xs>~ݪxĹ~D~k}qԻ{_c}vY玠%$@tyVv]슮gNu"~k5~c.̼̇': _bX|*c`oO|"RX%uR>{vz2wCubt[Ms e~HܽXח}B ?~˰$zZrƬṛYד^z|~ n(:@ W>Rdz{~Ǻc]Xuܳm[e];Gu}a;c땍聆d]_^T̺W?d]Of]_;=8z]륉W`]?Vú2IuqլcuN7`}KX-- gY׃7OͺozZ#ziʟleb!8\.Ǻn뙫X׍L%9}N\wuzWus8s/Ko9׻N\7ɹf\=뇬9YP8!9K{r߻^¹߮ϹbTϹs׸ ű6~ yP!n!c_n?!<ObЯL)_l h^9}9xؗO 5KL]ߪ0>w .9ӃӰo'skOCBgzk7`?r@>ҵ b%4ȋ1:zc*|"- 22eWr. Ӯ~V7[ t?~n] F!@ݕ@,0?QS@dpF/o~:{0|a?ozw/&p1rPz'@.,:Ww` w,t13^oA@Hipp]t:XKaPH@w>cykAc~3DOoمs t09F@疋+hOeiw:t^2qFSnf~r60& ` G|zږ,`fFf{(ʀNi z<}Lϋ0>Nkԙտ_rΦzY%jf6f+ 7wߴ_{UДnƈ7_3zMsğf-B/VbVtNN7@{Won<0 }fZlgĭo)_}}.rq1G6!nj.l=f߸cx\@+DV/sH)˃aŒ-HhbCI$p{FOmWW* 2y3շ*;Kw0q}x|,Υ+&Ho Y`#7 G 琄"N rKq%蟭Y1\$\t}[ kn}E-\WZjF ptp@\/0Rոy_6LWgzyi;!ph8iy\x0[7d&>Ap]B ?y\ ifluk|:{O\_O!=*ˈ]zue*!uK8zq9q=!/"$~:zU(q8u^E]RA\WPׇ 7˩OMuc*wyG7u|uu&kuYF]9@]w`;P׷3sf˙u9sc s\`3m1Bzs݌~.d\~z sݜsW\_veqQ_/fY \%',浨"2*q>GG,8O4C +^.2x|u #u3 cx-&pC!~