Showing preview only (432K chars total). Download the full file or copy to clipboard to get everything.
Repository: joshuaulrich/TTR
Branch: master
Commit: 76e5618e4a71
Files: 132
Total size: 403.1 KB
Directory structure:
gitextract_yqsyaveo/
├── .Rbuildignore
├── .github/
│ ├── FUNDING.yml
│ ├── issue_template.md
│ ├── pull_request_template.md
│ ├── security.md
│ └── workflows/
│ └── ci.yaml
├── .gitignore
├── DESCRIPTION
├── LICENSE
├── Makefile
├── NAMESPACE
├── NEWS.md
├── R/
│ ├── ADX.R
│ ├── ATR.R
│ ├── CCI.R
│ ├── CLV.R
│ ├── CMF.R
│ ├── CMO.R
│ ├── CTI.R
│ ├── DPO.R
│ ├── DVI.R
│ ├── DonchianChannel.R
│ ├── EMV.R
│ ├── GMMA.R
│ ├── KST.R
│ ├── MACD.R
│ ├── MFI.R
│ ├── MovingAverages.R
│ ├── OBV.R
│ ├── RSI.R
│ ├── SAR.R
│ ├── SNR.R
│ ├── TDI.R
│ ├── TRIX.R
│ ├── TTR-package.R
│ ├── TTRtools.R
│ ├── VHF.R
│ ├── WPR.R
│ ├── WebData.R
│ ├── ZigZag.R
│ ├── adjRatios.R
│ ├── aroon.R
│ ├── bollingerBands.R
│ ├── chaikinAD.R
│ ├── chaikinVolatility.R
│ ├── changes.R
│ ├── keltnerChannels.R
│ ├── percentRank.R
│ ├── pivots.R
│ ├── priceBands.R
│ ├── rollFun.R
│ ├── runFun.R
│ ├── stochastics.R
│ ├── ultimateOscillator.R
│ ├── volatility.R
│ ├── williamsAD.R
│ └── zzz.R
├── README.md
├── THANKS
├── data/
│ └── ttrc.rda
├── inst/
│ └── tinytest/
│ ├── output/
│ │ ├── misc.rda
│ │ ├── moving-averages.rda
│ │ ├── oscillators.rda
│ │ ├── overlays.rda
│ │ ├── running-functions.rda
│ │ ├── trend.rda
│ │ ├── volatility.rda
│ │ └── volume.rda
│ ├── test-dvi.R
│ ├── test-misc.R
│ ├── test-moving-averages.R
│ ├── test-oscillators.R
│ ├── test-overlays.R
│ ├── test-runfun.R
│ ├── test-trend.R
│ ├── test-volatility.R
│ └── test-volume.R
├── man/
│ ├── ADX.Rd
│ ├── ATR.Rd
│ ├── CCI.Rd
│ ├── CLV.Rd
│ ├── CMF.Rd
│ ├── CMO.Rd
│ ├── CTI.Rd
│ ├── DPO.Rd
│ ├── DVI.Rd
│ ├── DonchianChannel.Rd
│ ├── EMV.Rd
│ ├── GMMA.Rd
│ ├── KST.Rd
│ ├── MACD.Rd
│ ├── MFI.Rd
│ ├── MovingAverages.Rd
│ ├── OBV.Rd
│ ├── RSI.Rd
│ ├── SAR.Rd
│ ├── SNR.Rd
│ ├── TDI.Rd
│ ├── TRIX.Rd
│ ├── TTR.Rd
│ ├── TTRtools.Rd
│ ├── VHF.Rd
│ ├── WPR.Rd
│ ├── WebData.Rd
│ ├── ZigZag.Rd
│ ├── adjRatios.Rd
│ ├── aroon.Rd
│ ├── bollingerBands.Rd
│ ├── chaikinAD.Rd
│ ├── chaikinVolatility.Rd
│ ├── changes.Rd
│ ├── keltnerChannels.Rd
│ ├── priceBands.Rd
│ ├── rollFun.Rd
│ ├── runFun.Rd
│ ├── runPercentRank.Rd
│ ├── stochastics.Rd
│ ├── ttrc.Rd
│ ├── ultimateOscillator.Rd
│ ├── volatility.Rd
│ └── williamsAD.Rd
├── src/
│ ├── adjRatios.c
│ ├── aroon.c
│ ├── init.c
│ ├── moving_averages.c
│ ├── percent_rank.c
│ ├── runfun.c
│ ├── sar.c
│ ├── ttr.h
│ ├── wilderSum.c
│ └── zigzag.c
└── tests/
└── tinytest.R
================================================
FILE CONTENTS
================================================
================================================
FILE: .Rbuildignore
================================================
R/pivots.R
LICENSE
WISHLIST
^.*\.Rproj$
^\.Rproj\.user$
\.git
\.gitignore
^.*\.orig$
^.*\.sw.
.travis.yml
^0.*\.patch$
^.*\.tar.gz$
Makefile
================================================
FILE: .github/FUNDING.yml
================================================
github: [joshuaulrich]
================================================
FILE: .github/issue_template.md
================================================
### Description
[Describe the issue]
### Expected behavior
[Describe the behavior/output you expected]
### Minimal, reproducible example
```r
[Insert sample data and code]
```
### Session Info
```r
[Insert your sessionInfo() output]
```
================================================
FILE: .github/pull_request_template.md
================================================
Please review the [contributing guide](CONTRIBUTING.md) before submitting your pull request. Please pay special attention to the [pull request](CONTRIBUTING.md#want-to-submit-a-pull-request) and [commit message](CONTRIBUTING.md#commit-messages) sections. Thanks for your contribution and interest in the project!
================================================
FILE: .github/security.md
================================================
# Security Policy
## Supported Versions
As with most R packages, only the latest package version is supported with bug
fixes, features, etc. This also applies to security updates.
## Reporting a Vulnerability
To report a security vulnerability, please use the
[Tidelift security contact](https://tidelift.com/security).
Tidelift will coordinate the fix and disclosure.
================================================
FILE: .github/workflows/ci.yaml
================================================
# Run CI for R using https://eddelbuettel.github.io/r-ci/
name: ci
on:
push:
pull_request:
env:
USE_BSPM: "true"
_R_CHECK_FORCE_SUGGESTS_: "false"
_R_CHECK_CRAN_INCOMING_ : "false"
_R_S3_METHOD_LOOKUP_BASEENV_AFTER_GLOBALENV_: "true"
_R_CHECK_CODETOOLS_PROFILE_: "suppressLocalUnused=false"
_R_CHECK_LENGTH_1_CONDITION_: "true"
_R_CHECK_LENGTH_1_LOGIC2_: "true"
_R_CHECK_UNDOC_USE_ALL_NAMES_: "true"
jobs:
build:
strategy:
matrix:
config:
#- {os: macOS-latest}
- {os: ubuntu-latest}
runs-on: ${{ matrix.config.os }}
steps:
- uses: actions/checkout@v3
- name: Bootstrap
run: |
curl -OLs https://eddelbuettel.github.io/r-ci/run.sh
chmod 0755 run.sh
./run.sh bootstrap
- name: Dependencies
run: ./run.sh install_all
- name: Test
run: ./run.sh run_tests
================================================
FILE: .gitignore
================================================
# History and data files
.Rhistory
.Rapp.history
.RData
# RStudio files
.Rproj.user/
# produced vignettes
vignettes/*.html
vignettes/*.pdf
# knitr and R markdown
/*_cache/
/cache/
*.utf8.md
*.knit.md
# object and shared objects
*.o
*.so
# vim
*.swp
*.swo
*~
# R package build/check
*.tar.gz
*.Rcheck/
# miscellaneous
0*.patch
*.bak
*.orig
================================================
FILE: DESCRIPTION
================================================
Package: TTR
Type: Package
Title: Technical Trading Rules
Version: 0.24.4.1
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: tinytest
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
================================================
FILE: LICENSE
================================================
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
================================================
FILE: Makefile
================================================
#https://stackoverflow.com/questions/34603415/makefile-automatic-target-generation
#https://www.gnu.org/software/make/manual/make.html#Static-Pattern
#https://stackoverflow.com/questions/2826029/passing-additional-variables-from-command-line-to-make
#https://stackoverflow.com/questions/2214575/passing-arguments-to-make-run
R_HOME = /usr
PKG_PATH = ${PWD}
TOP = ${PWD}/..
PKG_DESC = ${PKG_PATH}/DESCRIPTION
PKG_NAME = $(shell sed -ne "s/^Package: //p" ${PKG_DESC} | tr -d '\n')
PKG_VER = $(shell sed -ne "s/^Version: \(.*\)/\1/p" ${PKG_DESC} | tr -d '\n')
PKG_TARGZ = $(PKG_NAME)_$(PKG_VER).tar.gz
PKG_BUILD_OPTS ?= --no-build-vignettes
R_LIB ?= $(shell Rscript -e 'cat(.libPaths()[1L])')
PKG_INST_FILE = $(R_LIB)/${PKG_NAME}/DESCRIPTION
PKG_R_FILES := $(wildcard ${PKG_PATH}/R/*.R)
PKG_RD_FILES := $(wildcard ${PKG_PATH}/man/*.Rd)
PKG_SRC_FILES := $(wildcard ${PKG_PATH}/src/*)
PKG_HEADER_FILES := $(wildcard ${PKG_PATH}/inst/include/*h)
PKG_ALL_FILES := ${PKG_PATH}/DESCRIPTION ${PKG_PATH}/NAMESPACE ${PKG_HEADER_FILES} \
$(PKG_R_FILES) $(PKG_RD_FILES) $(PKG_SRC_FILES) ${PKG_PATH}/.Rbuildignore
HTML_FILES := $(patsubst %.Rmd, %.html, $(wildcard *.Rmd)) \
$(patsubst %.md, %.html, $(wildcard *.md))
UNIT_TEST_SUITE = ${PKG_PATH}/tests/tinytest.R
UNIT_TEST_FILES = $(wildcard ${PKG_PATH}/inst/tinytest/test-*.R)
BENCHMARK_FILE = ${PKG_PATH}/inst/benchmarks/benchmark.subset.R
.PHONY: docs build install check tests test clean
all: cran
#man/*.Rd depend on R/*.R files
print:
@echo 'path: $(PKG_PATH) \
inst_file: $(PKG_INST_FILE) \
tar.gz: $(PKG_TARGZ)'
# Build package
build: $(PKG_TARGZ)
$(PKG_TARGZ): $(PKG_ALL_FILES) $(UNIT_TEST_FILES) $(UNIT_TEST_SUITE)
@${R_HOME}/bin/R CMD build ${PKG_BUILD_OPTS} ${PKG_PATH} --no-build-vignettes
# Install package
install: build $(PKG_INST_FILE)
$(PKG_INST_FILE): $(PKG_TARGZ)
@${R_HOME}/bin/R CMD INSTALL ${PKG_TARGZ} --no-byte-compile
# Run R CMD check
check: docs build
@_R_CHECK_CRAN_INCOMING_=false \
_PKG_TINYTEST_VERBOSE_=1 _PKG_TINYTEST_COLOR_=FALSE \
${R_HOME}/bin/R CMD check ${PKG_TARGZ} --no-vignettes
docs: ${PKG_R_FILES}
@${R_HOME}/bin/Rscript -e "roxygen2::roxygenize(roclets='rd')" \
&& sed -i '/^RoxygenNote/d' ${PKG_PATH}/DESCRIPTION \
&& /bin/rm --force ${PKG_PATH}/src/*.o \
&& /bin/rm --force ${PKG_PATH}/src/*.so
# Check for CRAN
cran:
@${R_HOME}/bin/R CMD build ${PKG_PATH} && \
_PKG_TINYTEST_VERBOSE_=1 _PKG_TINYTEST_COLOR_=FALSE \
_R_CHECK_CRAN_INCOMING_=false ${R_HOME}/bin/R CMD check ${PKG_TARGZ} --as-cran
# Run unit test suite
tests: install ${UNIT_TEST_FILES}
@_PKG_TINYTEST_VERBOSE_=2 _PKG_TINYTEST_COLOR_=TRUE \
${R_HOME}/bin/Rscript ${UNIT_TEST_SUITE}
html: $(HTML_FILES)
%.html: %.Rmd
R --slave -e "set.seed(100);rmarkdown::render('$<')"
%.html: %.md
R --slave -e "set.seed(100);rmarkdown::render('$<')"
clean:
/bin/rm --force $(HTML_FILES) ${PKG_PATH}/src/*.o ${PKG_PATH}/src/*.so
================================================
FILE: NAMESPACE
================================================
export(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(runRange)
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_")
================================================
FILE: NEWS.md
================================================
# 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.
================================================
FILE: R/ADX.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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 <dL, dL, 0 ) )
tr <- TR(HLC)[,"tr"]
TRsum <- wilderSum(tr, n=n)
DIp <- 100 * wilderSum(DMIp, n=n) / TRsum
DIn <- 100 * wilderSum(DMIn, n=n) / TRsum
DX <- 100 * ( abs(DIp - DIn) / (DIp + DIn) )
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
}
}
ADX <- do.call( maType, c( list(DX), maArgs ) )
result <- cbind( DIp, DIn, DX, ADX )
colnames(result) <- c( "DIp", "DIn", "DX", "ADX" )
reclass(result, HLC)
}
================================================
FILE: R/ATR.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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 )
}
================================================
FILE: R/CCI.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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)
}
================================================
FILE: R/CLV.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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 )
}
================================================
FILE: R/CMF.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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)
}
================================================
FILE: R/CMO.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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 )
}
================================================
FILE: R/CTI.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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)
}
================================================
FILE: R/DPO.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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 )
}
================================================
FILE: R/DVI.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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)
}
================================================
FILE: R/DonchianChannel.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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)
}
================================================
FILE: R/EMV.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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 )
}
================================================
FILE: R/GMMA.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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)
}
================================================
FILE: R/KST.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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 )
}
================================================
FILE: R/MACD.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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 )
}
================================================
FILE: R/MFI.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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 )
}
================================================
FILE: R/MovingAverages.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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
# Convert back to original class
ma <- reclass(ma,x)
if(!is.null(dim(ma))) {
colnames(ma) <- "WMA"
}
return(ma)
}
#-------------------------------------------------------------------------#
#' @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)
# Convert back to original class
ma <- reclass(ma, price)
if(!is.null(dim(ma))) {
colnames(ma) <- "EVWMA"
}
return(ma)
}
#-------------------------------------------------------------------------#
#' @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)
# Convert back to original class
ma <- reclass(ma,x)
if(!is.null(dim(ma))) {
colnames(ma) <- "ZLEMA"
}
return(ma)
}
#-------------------------------------------------------------------------#
#' @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)), ...)
if(!is.null(dim(hma))) {
colnames(hma) <- "HMA"
}
return(hma)
}
#-------------------------------------------------------------------------#
#' @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)
}
if(!is.null(dim(alma))) {
colnames(alma) <- "ALMA"
}
reclass(alma, x)
}
================================================
FILE: R/OBV.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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 )
}
================================================
FILE: R/RSI.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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 )
}
================================================
FILE: R/SAR.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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
# Call C routine
sar <- .Call(C_sar, HL[,1], HL[,2], accel)
colnames(sar) <- "sar"
reclass( sar, HL )
}
================================================
FILE: R/SNR.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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))
}
================================================
FILE: R/TDI.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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 )
}
================================================
FILE: R/TRIX.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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 )
}
================================================
FILE: R/TTR-package.R
================================================
#' 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
#' @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
"_PACKAGE"
================================================
FILE: R/TTRtools.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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)
}
================================================
FILE: R/VHF.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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)
}
================================================
FILE: R/WPR.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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.
#' @param scale Scale the result to be between 0 and -100.
#' @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,
#' and the result of \code{WPR} is equal to \code{1-fastK}.
#'
#' 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.
#'
#' William's \%R is usually scaled to be between 0 and -100, which is not what
#' \code{WPR} returns by default. Set \code{scale = TRUE} to return the result
#' with the usual scaling.
#'
#' @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)
#' hlc <- ttrc[,c("High","Low","Close")]
#' stochOsc <- stoch(hlc)
#' stochWPR <- WPR(hlc)
#'
#' # WPR is a transformation of stochastics' fastK
#' all.equal(stochWPR, 1-stochOsc[,'fastK']) # TRUE
#'
#' # WPR converted to the usual scaling between 0 and -100
#' scaledWPR <- WPR(hlc, scale=TRUE)
#'
#' 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, scale=FALSE) {
# 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
if(isTRUE(scale)) {
pctR <- -100 * pctR
}
reclass( pctR, HLC )
}
================================================
FILE: R/WebData.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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))
}
================================================
FILE: R/ZigZag.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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 )
}
================================================
FILE: R/adjRatios.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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)
}
================================================
FILE: R/aroon.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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 )
}
================================================
FILE: R/bollingerBands.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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)
}
================================================
FILE: R/chaikinAD.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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)
}
================================================
FILE: R/chaikinVolatility.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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)
}
================================================
FILE: R/changes.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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)
}
================================================
FILE: R/keltnerChannels.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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)
}
================================================
FILE: R/percentRank.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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)
}
================================================
FILE: R/pivots.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
"pivots" <-
function(data, lagts=TRUE) {
# Author: Brian G. Peterson
# http://www.investopedia.com/articles/forex/05/FXpivots.asp
# http://www.investopedia.com/articles/technical/04/041404.asp
# CentralPivot Point (P) = (High + Low + Close) / 3
center <- xts(rowSums(HLC(data))/3,order.by=index(data))
R1 <- (2*center)-Lo(data) # First Resistance (R1) = (2*P) - Low
S1 <- (2*center)-Hi(data) # First Support (S1) = (2*P) - High
R2 <- center + (R1 - S1) # Second Resistance (R2) = P + (R1-S1)
S2 <- center - (R1 - S1) # Second Support (S2) = P - (R1- S1)
ret <- cbind(center,R1,R2,S1,S2)
colnames(ret) <- c('center','R1','R2','S1','S2')
if(lagts){
newrow <- xts(t(rep(NA,5)), order.by=last(index(data))+1)
ret <- rbind(ret,newrow)
ret <- lag.xts(ret)
}
return(ret)
}
================================================
FILE: R/priceBands.R
================================================
#
# 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 <http://www.gnu.org/licenses/>.
#
#' 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-fre
gitextract_yqsyaveo/
├── .Rbuildignore
├── .github/
│ ├── FUNDING.yml
│ ├── issue_template.md
│ ├── pull_request_template.md
│ ├── security.md
│ └── workflows/
│ └── ci.yaml
├── .gitignore
├── DESCRIPTION
├── LICENSE
├── Makefile
├── NAMESPACE
├── NEWS.md
├── R/
│ ├── ADX.R
│ ├── ATR.R
│ ├── CCI.R
│ ├── CLV.R
│ ├── CMF.R
│ ├── CMO.R
│ ├── CTI.R
│ ├── DPO.R
│ ├── DVI.R
│ ├── DonchianChannel.R
│ ├── EMV.R
│ ├── GMMA.R
│ ├── KST.R
│ ├── MACD.R
│ ├── MFI.R
│ ├── MovingAverages.R
│ ├── OBV.R
│ ├── RSI.R
│ ├── SAR.R
│ ├── SNR.R
│ ├── TDI.R
│ ├── TRIX.R
│ ├── TTR-package.R
│ ├── TTRtools.R
│ ├── VHF.R
│ ├── WPR.R
│ ├── WebData.R
│ ├── ZigZag.R
│ ├── adjRatios.R
│ ├── aroon.R
│ ├── bollingerBands.R
│ ├── chaikinAD.R
│ ├── chaikinVolatility.R
│ ├── changes.R
│ ├── keltnerChannels.R
│ ├── percentRank.R
│ ├── pivots.R
│ ├── priceBands.R
│ ├── rollFun.R
│ ├── runFun.R
│ ├── stochastics.R
│ ├── ultimateOscillator.R
│ ├── volatility.R
│ ├── williamsAD.R
│ └── zzz.R
├── README.md
├── THANKS
├── data/
│ └── ttrc.rda
├── inst/
│ └── tinytest/
│ ├── output/
│ │ ├── misc.rda
│ │ ├── moving-averages.rda
│ │ ├── oscillators.rda
│ │ ├── overlays.rda
│ │ ├── running-functions.rda
│ │ ├── trend.rda
│ │ ├── volatility.rda
│ │ └── volume.rda
│ ├── test-dvi.R
│ ├── test-misc.R
│ ├── test-moving-averages.R
│ ├── test-oscillators.R
│ ├── test-overlays.R
│ ├── test-runfun.R
│ ├── test-trend.R
│ ├── test-volatility.R
│ └── test-volume.R
├── man/
│ ├── ADX.Rd
│ ├── ATR.Rd
│ ├── CCI.Rd
│ ├── CLV.Rd
│ ├── CMF.Rd
│ ├── CMO.Rd
│ ├── CTI.Rd
│ ├── DPO.Rd
│ ├── DVI.Rd
│ ├── DonchianChannel.Rd
│ ├── EMV.Rd
│ ├── GMMA.Rd
│ ├── KST.Rd
│ ├── MACD.Rd
│ ├── MFI.Rd
│ ├── MovingAverages.Rd
│ ├── OBV.Rd
│ ├── RSI.Rd
│ ├── SAR.Rd
│ ├── SNR.Rd
│ ├── TDI.Rd
│ ├── TRIX.Rd
│ ├── TTR.Rd
│ ├── TTRtools.Rd
│ ├── VHF.Rd
│ ├── WPR.Rd
│ ├── WebData.Rd
│ ├── ZigZag.Rd
│ ├── adjRatios.Rd
│ ├── aroon.Rd
│ ├── bollingerBands.Rd
│ ├── chaikinAD.Rd
│ ├── chaikinVolatility.Rd
│ ├── changes.Rd
│ ├── keltnerChannels.Rd
│ ├── priceBands.Rd
│ ├── rollFun.Rd
│ ├── runFun.Rd
│ ├── runPercentRank.Rd
│ ├── stochastics.Rd
│ ├── ttrc.Rd
│ ├── ultimateOscillator.Rd
│ ├── volatility.Rd
│ └── williamsAD.Rd
├── src/
│ ├── adjRatios.c
│ ├── aroon.c
│ ├── init.c
│ ├── moving_averages.c
│ ├── percent_rank.c
│ ├── runfun.c
│ ├── sar.c
│ ├── ttr.h
│ ├── wilderSum.c
│ └── zigzag.c
└── tests/
└── tinytest.R
SYMBOL INDEX (23 symbols across 9 files)
FILE: src/adjRatios.c
function SEXP (line 23) | SEXP adjRatios (SEXP split, SEXP div, SEXP close) {
FILE: src/aroon.c
function SEXP (line 22) | SEXP aroon_max (SEXP x, SEXP n) {
FILE: src/init.c
function R_init_TTR (line 51) | void R_init_TTR(DllInfo *dll)
FILE: src/moving_averages.c
function SEXP (line 22) | SEXP ema (SEXP x, SEXP n, SEXP ratio, SEXP wilder) {
function SEXP (line 97) | SEXP evwma (SEXP pr, SEXP vo, SEXP n) {
function SEXP (line 164) | SEXP wma (SEXP x, SEXP w, SEXP n) {
function SEXP (line 228) | SEXP zlema (SEXP x, SEXP n, SEXP ratio) {
FILE: src/percent_rank.c
function calc_n_less (line 23) | double calc_n_less(double* x, double mult, int i, int j1)
function SEXP (line 40) | SEXP ttr_rollPercentRank(SEXP _x, SEXP _n, SEXP _cumul, SEXP _mult)
FILE: src/runfun.c
function SEXP (line 23) | SEXP runsum(SEXP _x, SEXP _n)
function SEXP (line 71) | SEXP runrange(SEXP _x, SEXP _n)
function tiebreaker_lt (line 133) | static inline double
function tiebreaker_gt (line 138) | static inline double
function tiebreaker_eq (line 143) | static inline double
function ttr_median (line 149) | static inline double
function SEXP (line 162) | SEXP runmedian(SEXP _x, SEXP _n, SEXP _tiebreak, SEXP _cumulative)
function ttr_mean (line 231) | static inline double
function SEXP (line 242) | SEXP runmad(SEXP _x, SEXP _center, SEXP _n, SEXP _type,
function SEXP (line 344) | SEXP runcov(SEXP _x, SEXP _y, SEXP _n, SEXP _sample, SEXP _cumulative)
FILE: src/sar.c
function SEXP (line 24) | SEXP sar (SEXP hi, SEXP lo, SEXP xl) {
FILE: src/wilderSum.c
function SEXP (line 23) | SEXP wilderSum (SEXP x, SEXP n) {
FILE: src/zigzag.c
type price_and_index (line 24) | typedef struct {
function SEXP (line 29) | SEXP ttr_zigzag
Condensed preview — 132 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (436K chars).
[
{
"path": ".Rbuildignore",
"chars": 141,
"preview": "R/pivots.R\nLICENSE\nWISHLIST\n^.*\\.Rproj$\n^\\.Rproj\\.user$\n\\.git\n\\.gitignore\n^.*\\.orig$\n^.*\\.sw.\n.travis.yml\n^0.*\\.patch$\n^"
},
{
"path": ".github/FUNDING.yml",
"chars": 23,
"preview": "github: [joshuaulrich]\n"
},
{
"path": ".github/issue_template.md",
"chars": 245,
"preview": "### Description\n\n[Describe the issue]\n\n### Expected behavior\n\n[Describe the behavior/output you expected]\n\n### Minimal, "
},
{
"path": ".github/pull_request_template.md",
"chars": 313,
"preview": "Please review the [contributing guide](CONTRIBUTING.md) before submitting your pull request. Please pay special attentio"
},
{
"path": ".github/security.md",
"chars": 374,
"preview": "# Security Policy\n\n## Supported Versions\n\nAs with most R packages, only the latest package version is supported with bug"
},
{
"path": ".github/workflows/ci.yaml",
"chars": 907,
"preview": "# Run CI for R using https://eddelbuettel.github.io/r-ci/\n\nname: ci\n\non:\n push:\n pull_request:\n\nenv:\n USE_BSPM: \"true"
},
{
"path": ".gitignore",
"chars": 346,
"preview": "# History and data files\n.Rhistory\n.Rapp.history\n.RData\n\n# RStudio files\n.Rproj.user/\n\n# produced vignettes\nvignettes/*."
},
{
"path": "DESCRIPTION",
"chars": 672,
"preview": "Package: TTR\nType: Package\nTitle: Technical Trading Rules\nVersion: 0.24.4.1\nAuthors@R: c(\n person(given=\"Joshua\", famil"
},
{
"path": "LICENSE",
"chars": 18092,
"preview": " GNU GENERAL PUBLIC LICENSE\n Version 2, June 1991\n\n Copyright (C) 1989, 1991 Fr"
},
{
"path": "Makefile",
"chars": 2925,
"preview": "#https://stackoverflow.com/questions/34603415/makefile-automatic-target-generation\n#https://www.gnu.org/software/make/ma"
},
{
"path": "NAMESPACE",
"chars": 1350,
"preview": "export(ADX)\nexport(ALMA)\nexport(ATR)\nexport(BBands)\nexport(CCI)\nexport(CLV)\nexport(CMF)\nexport(CMO)\nexport(CTI)\nexport(D"
},
{
"path": "NEWS.md",
"chars": 18134,
"preview": "# Changes in 0.24.4\n\n* Added Ethan B. Smith as a contributor. Thanks Ethan!\n\n### NEW FEATURES\n\n- Added a `TR()` function"
},
{
"path": "R/ADX.R",
"chars": 3976,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/ATR.R",
"chars": 3824,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/CCI.R",
"chars": 3592,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/CLV.R",
"chars": 1948,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/CMF.R",
"chars": 2631,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/CMO.R",
"chars": 2258,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/CTI.R",
"chars": 2590,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2020 Joshua M. Ulrich\n#\n# This program is free software: you c"
},
{
"path": "R/DPO.R",
"chars": 3202,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/DVI.R",
"chars": 3297,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/DonchianChannel.R",
"chars": 3762,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/EMV.R",
"chars": 3390,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/GMMA.R",
"chars": 2601,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/KST.R",
"chars": 5664,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/MACD.R",
"chars": 5872,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/MFI.R",
"chars": 3502,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/MovingAverages.R",
"chars": 13361,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/OBV.R",
"chars": 2619,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/RSI.R",
"chars": 5014,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/SAR.R",
"chars": 3111,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/SNR.R",
"chars": 2070,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2016 Peter Carl, Joshua M. Ulrich\n#\n# This program is free sof"
},
{
"path": "R/TDI.R",
"chars": 2943,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/TRIX.R",
"chars": 4887,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/TTR-package.R",
"chars": 2708,
"preview": "#' Technical Trading Rule Composite data\n#'\n#' Historical Open, High, Low, Close, and Volume data for the periods Januar"
},
{
"path": "R/TTRtools.R",
"chars": 3259,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/VHF.R",
"chars": 2798,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/WPR.R",
"chars": 3519,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/WebData.R",
"chars": 18058,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/ZigZag.R",
"chars": 3654,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/adjRatios.R",
"chars": 2922,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/aroon.R",
"chars": 3595,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/bollingerBands.R",
"chars": 4262,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/chaikinAD.R",
"chars": 2712,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/chaikinVolatility.R",
"chars": 2456,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/changes.R",
"chars": 2994,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/keltnerChannels.R",
"chars": 4008,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2020 Joshua M. Ulrich\n#\n# This program is free software: you c"
},
{
"path": "R/percentRank.R",
"chars": 3796,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/pivots.R",
"chars": 1558,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/priceBands.R",
"chars": 4022,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/rollFun.R",
"chars": 2141,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/runFun.R",
"chars": 10100,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/stochastics.R",
"chars": 11514,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/ultimateOscillator.R",
"chars": 2187,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/volatility.R",
"chars": 10263,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/williamsAD.R",
"chars": 2264,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2007-2013 Joshua M. Ulrich\n#\n# This program is free software: "
},
{
"path": "R/zzz.R",
"chars": 829,
"preview": "#\n# TTR: Technical Trading Rules\n#\n# Copyright (C) 2017 Joshua M. Ulrich\n#\n# This program is free software: you c"
},
{
"path": "README.md",
"chars": 3015,
"preview": "### About\n\nTTR is an [R](https://www.r-project.org) package that provides the most popular\ntechnical analysis functions "
},
{
"path": "THANKS",
"chars": 344,
"preview": "In no particular order:\n\n- I can't thank Jeff Ryan enough for all his help with TTR via:\n motivation to submit TTR to C"
},
{
"path": "inst/tinytest/test-dvi.R",
"chars": 210,
"preview": "# Create input data\ndata(ttrc)\nrownames(ttrc) <- ttrc$Date\nttrc$Date <- NULL\n\n# Run test\ndat <- setNames(ttrc$Close, row"
},
{
"path": "inst/tinytest/test-misc.R",
"chars": 2559,
"preview": "# Create input data\ndata(ttrc)\nrownames(ttrc) <- ttrc$Date\nttrc$Date <- NULL\n\ninput <- list( all=ttrc[1:250,], top=ttrc["
},
{
"path": "inst/tinytest/test-moving-averages.R",
"chars": 5721,
"preview": "# Create input data\ndata(ttrc)\nrownames(ttrc) <- ttrc$Date\nttrc$Date <- NULL\n\ninput <- list( all=ttrc[1:250,], top=ttrc["
},
{
"path": "inst/tinytest/test-oscillators.R",
"chars": 5767,
"preview": "# Create input data\ndata(ttrc)\nrownames(ttrc) <- ttrc$Date\nttrc$Date <- NULL\n\ninput <- list( all=ttrc[1:250,], top=ttrc["
},
{
"path": "inst/tinytest/test-overlays.R",
"chars": 1608,
"preview": "# Create input data\ndata(ttrc)\nrownames(ttrc) <- ttrc$Date\nttrc$Date <- NULL\n\ninput <- list( all=ttrc[1:250,], top=ttrc["
},
{
"path": "inst/tinytest/test-runfun.R",
"chars": 11589,
"preview": "# Create input data\ndata(ttrc)\nrownames(ttrc) <- ttrc$Date\nttrc$Date <- NULL\n\ninput <- list( all=ttrc[1:250,], top=ttrc["
},
{
"path": "inst/tinytest/test-trend.R",
"chars": 3475,
"preview": "# Create input data\ndata(ttrc)\nrownames(ttrc) <- ttrc$Date\nttrc$Date <- NULL\n\niAll <- as.matrix(ttrc[1:250,])\niTop <- iA"
},
{
"path": "inst/tinytest/test-volatility.R",
"chars": 1977,
"preview": "# Create input data\ndata(ttrc)\nrownames(ttrc) <- ttrc$Date\nttrc$Date <- NULL\n\ninput <- list( all=ttrc[1:250,], top=ttrc["
},
{
"path": "inst/tinytest/test-volume.R",
"chars": 2877,
"preview": "# Create input data\ndata(ttrc)\nrownames(ttrc) <- ttrc$Date\nttrc$Date <- NULL\n\n#input <- list( all=ttrc[1:250,], top=ttrc"
},
{
"path": "man/ADX.Rd",
"chars": 2401,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/ADX.R\n\\name{ADX}\n\\alias{ADX}\n\\alias{DI}\n\\a"
},
{
"path": "man/ATR.Rd",
"chars": 2151,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/ATR.R\n\\name{TR}\n\\alias{TR}\n\\alias{ATR}\n\\ti"
},
{
"path": "man/CCI.Rd",
"chars": 2210,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/CCI.R\n\\name{CCI}\n\\alias{CCI}\n\\title{Commod"
},
{
"path": "man/CLV.Rd",
"chars": 1035,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/CLV.R\n\\name{CLV}\n\\alias{CLV}\n\\title{Close "
},
{
"path": "man/CMF.Rd",
"chars": 1659,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/CMF.R\n\\name{CMF}\n\\alias{CMF}\n\\title{Chaiki"
},
{
"path": "man/CMO.Rd",
"chars": 1262,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/CMO.R\n\\name{CMO}\n\\alias{CMO}\n\\title{Chande"
},
{
"path": "man/CTI.Rd",
"chars": 1636,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/CTI.R\n\\name{CTI}\n\\alias{CTI}\n\\title{Ehler'"
},
{
"path": "man/DPO.Rd",
"chars": 2174,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/DPO.R\n\\name{DPO}\n\\alias{DPO}\n\\title{De-Tre"
},
{
"path": "man/DVI.Rd",
"chars": 1626,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/DVI.R\n\\name{DVI}\n\\alias{DVI}\n\\title{DV Int"
},
{
"path": "man/DonchianChannel.Rd",
"chars": 1922,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/DonchianChannel.R\n\\name{DonchianChannel}\n\\"
},
{
"path": "man/EMV.Rd",
"chars": 1992,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/EMV.R\n\\name{EMV}\n\\alias{EMV}\n\\title{Arms' "
},
{
"path": "man/GMMA.Rd",
"chars": 1617,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/GMMA.R\n\\name{GMMA}\n\\alias{GMMA}\n\\alias{Gup"
},
{
"path": "man/KST.Rd",
"chars": 2624,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/KST.R\n\\name{KST}\n\\alias{KST}\n\\title{Know S"
},
{
"path": "man/MACD.Rd",
"chars": 3299,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/MACD.R\n\\name{MACD}\n\\alias{MACD}\n\\title{MAC"
},
{
"path": "man/MFI.Rd",
"chars": 1796,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/MFI.R\n\\name{MFI}\n\\alias{MFI}\n\\alias{moneyF"
},
{
"path": "man/MovingAverages.Rd",
"chars": 6660,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/MovingAverages.R\n\\name{SMA}\n\\alias{SMA}\n\\a"
},
{
"path": "man/OBV.Rd",
"chars": 1415,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/OBV.R\n\\name{OBV}\n\\alias{OBV}\n\\title{On Bal"
},
{
"path": "man/RSI.Rd",
"chars": 2641,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/RSI.R\n\\name{RSI}\n\\alias{RSI}\n\\title{Relati"
},
{
"path": "man/SAR.Rd",
"chars": 1449,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/SAR.R\n\\name{SAR}\n\\alias{SAR}\n\\title{Parabo"
},
{
"path": "man/SNR.Rd",
"chars": 1266,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/SNR.R\n\\name{SNR}\n\\alias{SNR}\n\\title{Signal"
},
{
"path": "man/TDI.Rd",
"chars": 1847,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/TDI.R\n\\name{TDI}\n\\alias{TDI}\n\\title{Trend "
},
{
"path": "man/TRIX.Rd",
"chars": 2265,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/TRIX.R\n\\name{TRIX}\n\\alias{TRIX}\n\\title{Tri"
},
{
"path": "man/TTR.Rd",
"chars": 1968,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/TTR-package.R\n\\docType{package}\n\\name{TTR}"
},
{
"path": "man/TTRtools.Rd",
"chars": 1222,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/TTRtools.R\n\\name{lags}\n\\alias{lags}\n\\alias"
},
{
"path": "man/VHF.Rd",
"chars": 1494,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/VHF.R\n\\name{VHF}\n\\alias{VHF}\n\\title{Vertic"
},
{
"path": "man/WPR.Rd",
"chars": 2183,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/WPR.R\n\\name{WPR}\n\\alias{WPR}\n\\title{Willia"
},
{
"path": "man/WebData.Rd",
"chars": 4211,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/WebData.R\n\\name{stockSymbols}\n\\alias{stock"
},
{
"path": "man/ZigZag.Rd",
"chars": 2168,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/ZigZag.R\n\\name{ZigZag}\n\\alias{ZigZag}\n\\ali"
},
{
"path": "man/adjRatios.Rd",
"chars": 1064,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/adjRatios.R\n\\name{adjRatios}\n\\alias{adjRat"
},
{
"path": "man/aroon.Rd",
"chars": 2268,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/aroon.R\n\\name{aroon}\n\\alias{aroon}\n\\title{"
},
{
"path": "man/bollingerBands.Rd",
"chars": 2699,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/bollingerBands.R\n\\name{BBands}\n\\alias{BBan"
},
{
"path": "man/chaikinAD.Rd",
"chars": 1689,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/chaikinAD.R\n\\name{chaikinAD}\n\\alias{chaiki"
},
{
"path": "man/chaikinVolatility.Rd",
"chars": 1551,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/chaikinVolatility.R\n\\name{chaikinVolatilit"
},
{
"path": "man/changes.Rd",
"chars": 1186,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/changes.R\n\\name{ROC}\n\\alias{ROC}\n\\alias{ch"
},
{
"path": "man/keltnerChannels.Rd",
"chars": 2547,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/keltnerChannels.R\n\\name{keltnerChannels}\n\\"
},
{
"path": "man/priceBands.Rd",
"chars": 2303,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/priceBands.R\n\\name{PBands}\n\\alias{PBands}\n"
},
{
"path": "man/rollFun.Rd",
"chars": 966,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/rollFun.R\n\\name{rollSFM}\n\\alias{rollSFM}\n\\"
},
{
"path": "man/runFun.Rd",
"chars": 3176,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/runFun.R\n\\name{runSum}\n\\alias{runSum}\n\\ali"
},
{
"path": "man/runPercentRank.Rd",
"chars": 2445,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/percentRank.R\n\\name{runPercentRank}\n\\alias"
},
{
"path": "man/stochastics.Rd",
"chars": 5162,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/stochastics.R\n\\name{stoch}\n\\alias{stoch}\n\\"
},
{
"path": "man/ttrc.Rd",
"chars": 952,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/TTR-package.R\n\\docType{data}\n\\name{ttrc}\n\\"
},
{
"path": "man/ultimateOscillator.Rd",
"chars": 970,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/ultimateOscillator.R\n\\name{ultimateOscilla"
},
{
"path": "man/volatility.Rd",
"chars": 6374,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/volatility.R\n\\name{volatility}\n\\alias{vola"
},
{
"path": "man/williamsAD.Rd",
"chars": 1226,
"preview": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/williamsAD.R\n\\name{williamsAD}\n\\alias{will"
},
{
"path": "src/adjRatios.c",
"chars": 2466,
"preview": "/*\n * TTR: Technical Trading Rules\n *\n * Copyright (C) 2007-2013 Joshua M. Ulrich\n *\n * This program is free softwar"
},
{
"path": "src/aroon.c",
"chars": 2627,
"preview": "/*\n * TTR: Technical Trading Rules\n *\n * Copyright (C) 2007-2013 Joshua M. Ulrich\n *\n * This program is free softwar"
},
{
"path": "src/init.c",
"chars": 1936,
"preview": "/*\n * TTR: Technical Trading Rules\n *\n * Copyright (C) 2007-2017 Joshua M. Ulrich\n *\n * This program is free softwar"
},
{
"path": "src/moving_averages.c",
"chars": 8693,
"preview": "/*\n * TTR: Technical Trading Rules\n *\n * Copyright (C) 2007-2013 Joshua M. Ulrich\n *\n * This program is free softwar"
},
{
"path": "src/percent_rank.c",
"chars": 2502,
"preview": "/*\n * TTR: Technical Trading Rules\n *\n * Copyright (C) 2012-2017 Charlie Friedemann, Joshua M. Ulrich\n *\n * This pro"
},
{
"path": "src/runfun.c",
"chars": 11596,
"preview": "/*\n * TTR: Technical Trading Rules\n *\n * Copyright (C) 2007-2018 Joshua M. Ulrich\n *\n * This program is free softwar"
},
{
"path": "src/sar.c",
"chars": 4084,
"preview": "/*\n * TTR: Technical Trading Rules\n *\n * Copyright (C) 2007-2013 Joshua M. Ulrich\n *\n * This program is free softwar"
},
{
"path": "src/ttr.h",
"chars": 703,
"preview": "#ifndef _TTR_H_\n#define _TTR_H_\n\n#include <Rinternals.h>\n\n/* declare functions called via .Call() */\nSEXP adjRatios(SEXP"
},
{
"path": "src/wilderSum.c",
"chars": 2068,
"preview": "/*\n * TTR: Technical Trading Rules\n *\n * Copyright (C) 2007-2013 Joshua M. Ulrich\n *\n * This program is free softwar"
},
{
"path": "src/zigzag.c",
"chars": 4529,
"preview": "/*\n * TTR: Technical Trading Rules\n *\n * Copyright (C) 2007-2017 Joshua M. Ulrich\n *\n * This program is free softwar"
},
{
"path": "tests/tinytest.R",
"chars": 442,
"preview": "# run package unit tests\nif (requireNamespace(\"tinytest\", quietly = TRUE)) {\n suppressPackageStartupMessages(library("
}
]
// ... and 9 more files (download for full content)
About this extraction
This page contains the full source code of the joshuaulrich/TTR GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 132 files (403.1 KB), approximately 127.2k tokens, and a symbol index with 23 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.