├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── bug_report.md │ ├── custom.md │ └── feature_request.md ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── PULL_REQUEST_TEMPLATE.md ├── README.md ├── docs ├── README.pdf ├── a_sane_and_simple_bitcoin_savings_plan_(sss).html ├── dollar_cost_averaging_discount_dcad.html ├── example-1-plot.html ├── example-10-df-numpy-pandas.html ├── example-11-basic-usage.html ├── example-2-plot.html ├── example-3-plot.html ├── example-4-plot-quandl.html ├── example-5-plot-quandl.html ├── example-6-plot-quandl.html ├── example-7-quandl-2-df.html ├── example-8-alphavantage-2-df.html ├── example-9-cryptocompare-2-df.html ├── index.html ├── jupyter.sh ├── pandoc.css ├── pandoc.md ├── pandoc.sh └── recession_probability.html ├── example ├── data.csv ├── example-1-plot.ipynb ├── example-1-plot.py ├── example-10-df-numpy-pandas.ipynb ├── example-11-basic-usage.ipynb ├── example-2-plot.ipynb ├── example-2-plot.py ├── example-3-plot.ipynb ├── example-3-plot.py ├── example-4-plot-quandl.ipynb ├── example-4-plot-quandl.py ├── example-5-plot-quandl.ipynb ├── example-5-plot-quandl.py ├── example-6-plot-quandl.ipynb ├── example-6-plot-quandl.py ├── example-7-quandl-2-df.ipynb ├── example-7-quandl-2-df.py ├── example-8-alphavantage-2-df.ipynb ├── example-8-alphavantage-2-df.py ├── example-9-cryptocompare-2-df.ipynb └── example-9-cryptocompare-2-df.py ├── jhtalib ├── __init__.py ├── behavioral_techniques │ ├── __init__.py │ └── behavioral_techniques.py ├── candlestick │ ├── __init__.py │ └── candlestick.py ├── cycle_indicators │ ├── __init__.py │ └── cycle_indicators.py ├── data │ ├── __init__.py │ └── data.py ├── decorators.py ├── derivatives │ ├── __init__.py │ └── derivatives.py ├── event_driven │ ├── __init__.py │ └── event_driven.py ├── example.py ├── experimental │ ├── __init__.py │ └── experimental.py ├── general │ ├── __init__.py │ └── general.py ├── helpers.py ├── information │ ├── __init__.py │ └── information.py ├── math_functions │ ├── __init__.py │ └── math_functions.py ├── momentum_indicators │ ├── __init__.py │ └── momentum_indicators.py ├── money_management │ ├── __init__.py │ └── money_management.py ├── overlap_studies │ ├── __init__.py │ └── overlap_studies.py ├── pattern_recognition │ ├── __init__.py │ └── pattern_recognition.py ├── price_transform │ ├── __init__.py │ └── price_transform.py ├── statistic_functions │ ├── __init__.py │ └── statistic_functions.py ├── uncategorised │ ├── __init__.py │ └── uncategorised.py ├── volatility_indicators │ ├── __init__.py │ └── volatility_indicators.py └── volume_indicators │ ├── __init__.py │ └── volume_indicators.py ├── notebook ├── a_sane_and_simple_bitcoin_savings_plan_(sss).ipynb ├── dollar_cost_averaging_discount_dcad.ipynb └── recession_probability.ipynb ├── setup.py └── test ├── data.csv ├── run-test.py └── test.py /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: 'https://github.com/joosthoeks/jhTAlib/blob/master/README.md#donation-and-funding' # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | 5 | --- 6 | 7 | **Describe the bug** 8 | A clear and concise description of what the bug is. 9 | 10 | **To Reproduce** 11 | Steps to reproduce the behavior: 12 | 1. Go to '...' 13 | 2. Click on '....' 14 | 3. Scroll down to '....' 15 | 4. See error 16 | 17 | **Expected behavior** 18 | A clear and concise description of what you expected to happen. 19 | 20 | **Screenshots** 21 | If applicable, add screenshots to help explain your problem. 22 | 23 | **Desktop (please complete the following information):** 24 | - OS: [e.g. iOS] 25 | - Browser [e.g. chrome, safari] 26 | - Version [e.g. 22] 27 | 28 | **Smartphone (please complete the following information):** 29 | - Device: [e.g. iPhone6] 30 | - OS: [e.g. iOS8.1] 31 | - Browser [e.g. stock browser, safari] 32 | - Version [e.g. 22] 33 | 34 | **Additional context** 35 | Add any other context about the problem here. 36 | 37 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/custom.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Custom issue template 3 | about: Describe this issue template's purpose here. 4 | 5 | --- 6 | 7 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | 5 | --- 6 | 7 | **Is your feature request related to a problem? Please describe.** 8 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 9 | 10 | **Describe the solution you'd like** 11 | A clear and concise description of what you want to happen. 12 | 13 | **Describe alternatives you've considered** 14 | A clear and concise description of any alternative solutions or features you've considered. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | env/ 12 | build/ 13 | develop-eggs/ 14 | dist/ 15 | downloads/ 16 | eggs/ 17 | .eggs/ 18 | lib/ 19 | lib64/ 20 | parts/ 21 | sdist/ 22 | var/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | 27 | # PyInstaller 28 | # Usually these files are written by a python script from a template 29 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 30 | *.manifest 31 | *.spec 32 | 33 | # Installer logs 34 | pip-log.txt 35 | pip-delete-this-directory.txt 36 | 37 | # Unit test / coverage reports 38 | htmlcov/ 39 | .tox/ 40 | .coverage 41 | .coverage.* 42 | .cache 43 | nosetests.xml 44 | coverage.xml 45 | *,cover 46 | .hypothesis/ 47 | 48 | # Translations 49 | *.mo 50 | *.pot 51 | 52 | # Django stuff: 53 | *.log 54 | local_settings.py 55 | 56 | # Flask stuff: 57 | instance/ 58 | .webassets-cache 59 | 60 | # Scrapy stuff: 61 | .scrapy 62 | 63 | # Sphinx documentation 64 | docs/_build/ 65 | 66 | # PyBuilder 67 | target/ 68 | 69 | # IPython Notebook 70 | .ipynb_checkpoints 71 | 72 | # pyenv 73 | .python-version 74 | 75 | # celery beat schedule file 76 | celerybeat-schedule 77 | 78 | # dotenv 79 | .env 80 | 81 | # virtualenv 82 | venv/ 83 | ENV/ 84 | 85 | # Spyder project settings 86 | .spyderproject 87 | 88 | # Rope project settings 89 | .ropeproject 90 | 91 | # Project 92 | *~ 93 | *.swp 94 | 95 | 96 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at joosthoeks@gmail.com. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | 48 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | ## How can I contribute? 2 | 1. fork the [repository](https://github.com/joosthoeks/jhTAlib) 3 | 2. make your changes 4 | 3. create a pull request 5 | 6 | We follow the methodology as described on the github help pages on [fork a repo](https://help.github.com/articles/fork-a-repo/) and [syncing a fork](https://help.github.com/articles/syncing-a-fork/) 7 | 8 | ## What work needs to be done? 9 | We use the [github issue queue](https://github.com/joosthoeks/jhTAlib/issues), so you can have a look at it to see what the current issues are. 10 | 11 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3 2 | 3 | WORKDIR /usr/src/app 4 | 5 | RUN apt-get update && apt-get install git 6 | 7 | RUN git clone https://github.com/joosthoeks/jhTAlib.git 8 | 9 | RUN cd jhTAlib/ && pip3 install -e . 10 | 11 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: jhTAlib 3 | author: Joost Hoeks 4 | date: 2024-09-02 5 | --- 6 | 7 | # jhTAlib 8 | 9 | Technical Analysis Library Time-Series 10 | 11 | You can use and import it for your: 12 | 13 | - Technical Analysis Software 14 | 15 | - Charting Software 16 | 17 | - Backtest Software 18 | 19 | - Trading Robot Software 20 | 21 | - Trading Software in general 22 | 23 | Work in progress... 24 | 25 | --- 26 | 27 | ## Depends only on 28 | 29 | - [The Python Standard Library](https://docs.python.org/3/library/index.html) 30 | 31 | --- 32 | 33 | ## Install 34 | 35 | From [source](https://github.com/joosthoeks/jhTAlib) - [source mirror 1](https://gitlab.com/joosthoeks/jhtalib) - [source mirror 2](https://bitbucket.org/joosthoeks/jhtalib): 36 | 37 | ```bash 38 | $ git clone https://github.com/joosthoeks/jhTAlib.git 39 | $ cd jhTAlib 40 | $ [sudo] pip3 install -e . 41 | ``` 42 | 43 | --- 44 | 45 | ## Update 46 | 47 | From [source](https://github.com/joosthoeks/jhTAlib) - [source mirror 1](https://gitlab.com/joosthoeks/jhtalib) - [source mirror 2](https://bitbucket.org/joosthoeks/jhtalib): 48 | 49 | ```bash 50 | $ cd jhTAlib 51 | $ git pull [upstream master] 52 | ``` 53 | 54 | --- 55 | 56 | ## In Docker 57 | 58 | From [DockerHub](https://hub.docker.com/r/joosthoeks/jhtalib): 59 | 60 | ```bash 61 | $ docker pull joosthoeks/jhtalib 62 | $ docker run -it joosthoeks/jhtalib /bin/bash 63 | /usr/src/app# python3 64 | >>> import jhtalib as jhta 65 | ``` 66 | 67 | From [source](https://github.com/joosthoeks/jhTAlib) - [source mirror 1](https://gitlab.com/joosthoeks/jhtalib) - [source mirror 2](https://bitbucket.org/joosthoeks/jhtalib): 68 | 69 | ```bash 70 | $ git clone https://github.com/joosthoeks/jhTAlib.git 71 | $ cd jhTAlib 72 | $ docker build -f Dockerfile -t jhtalib . 73 | $ docker run -it jhtalib /bin/bash 74 | /usr/src/app# python3 75 | >>> import jhtalib as jhta 76 | ``` 77 | 78 | --- 79 | 80 | ## In Jupyter 81 | 82 | From [source](https://github.com/joosthoeks/jhTAlib) - [source mirror 1](https://gitlab.com/joosthoeks/jhtalib) - [source mirror 2](https://bitbucket.org/joosthoeks/jhtalib): 83 | 84 | ```bash 85 | !git clone [-b branch-name] https://github.com/joosthoeks/jhTAlib.git 86 | %cd 'jhTAlib/' 87 | import jhtalib as jhta 88 | %cd '../' 89 | !rm -rf ./jhTAlib/ 90 | ``` 91 | 92 | --- 93 | 94 | ## Basic Usage 95 | 96 | ```python 97 | """""" 98 | # Import Built-Ins: 99 | from pprint import pprint as pp 100 | 101 | # Import Third-Party: 102 | 103 | # Import Homebrew: 104 | import jhtalib as jhta 105 | 106 | 107 | # df is DataFeed: 108 | df = { 109 | 'datetime': ('20151217', '20151218', '20151221', '20151222', '20151223', '20151224', '20151228', '20151229', '20151230', '20151231'), 110 | 'Open': (235.8, 232.3, 234.1, 232.2, 232.7, 235.4, 236.9, 234.85, 236.45, 235.0), 111 | 'High': (238.05, 236.9, 237.3, 232.4, 235.2, 236.15, 236.9, 237.6, 238.3, 237.25), 112 | 'Low': (234.55, 230.6, 230.2, 226.8, 231.5, 233.85, 233.05, 234.6, 234.55, 234.4), 113 | 'Close': (234.6, 233.6, 230.2, 230.05, 234.15, 236.15, 233.25, 237.6, 235.75, 234.4), 114 | 'Volume': (448294, 629039, 292528, 214170, 215545, 23548, 97574, 192908, 176839, 69347) 115 | } 116 | 117 | # basic usage: 118 | #pp (df) 119 | pp (jhta.SMA(df, 10)) 120 | #pp (jhta.BBANDS(df, 10)) 121 | ``` 122 | 123 | --- 124 | 125 | ## Help 126 | 127 | ```python 128 | $ python3 129 | >>> import jhtalib as jhta 130 | >>> dir(jhta) 131 | >>> help(jhta) 132 | >>> help(jhta.behavioral_techniques) 133 | >>> help(jhta.candlestick) 134 | >>> help(jhta.cycle_indicators) 135 | >>> help(jhta.data) 136 | >>> help(jhta.event_driven) 137 | >>> help(jhta.experimental) 138 | >>> help(jhta.general) 139 | >>> help(jhta.information) 140 | >>> help(jhta.math_functions) 141 | >>> help(jhta.momentum_indicators) 142 | >>> help(jhta.money_management) 143 | >>> help(jhta.overlap_studies) 144 | >>> help(jhta.pattern_recognition) 145 | >>> help(jhta.price_transform) 146 | >>> help(jhta.statistic_functions) 147 | >>> help(jhta.uncategorised) 148 | >>> help(jhta.volatility_indicators) 149 | >>> help(jhta.volume_indicators) 150 | >>> quit() 151 | ``` 152 | 153 | --- 154 | 155 | ## Check Installation 156 | 157 | ```python 158 | $ python3 159 | >>> import jhtalib as jhta 160 | >>> jhta.example() 161 | ``` 162 | 163 | If not errors then installation is correct. 164 | 165 | ```python 166 | >>> quit() 167 | ``` 168 | 169 | --- 170 | 171 | ## Examples 172 | 173 | - [https://joosthoeks.github.io/jhTAlib/example-1-plot.html](https://joosthoeks.github.io/jhTAlib/example-1-plot.html) 174 | 175 | - [https://joosthoeks.github.io/jhTAlib/example-2-plot.html](https://joosthoeks.github.io/jhTAlib/example-2-plot.html) 176 | 177 | - [https://joosthoeks.github.io/jhTAlib/example-3-plot.html](https://joosthoeks.github.io/jhTAlib/example-3-plot.html) 178 | 179 | - [https://joosthoeks.github.io/jhTAlib/example-4-plot-quandl.html](https://joosthoeks.github.io/jhTAlib/example-4-plot-quandl.html) 180 | 181 | - [https://joosthoeks.github.io/jhTAlib/example-5-plot-quandl.html](https://joosthoeks.github.io/jhTAlib/example-5-plot-quandl.html) 182 | 183 | - [https://joosthoeks.github.io/jhTAlib/example-6-plot-quandl.html](https://joosthoeks.github.io/jhTAlib/example-6-plot-quandl.html) 184 | 185 | - [https://joosthoeks.github.io/jhTAlib/example-7-quandl-2-df.html](https://joosthoeks.github.io/jhTAlib/example-7-quandl-2-df.html) 186 | 187 | - [https://joosthoeks.github.io/jhTAlib/example-8-alphavantage-2-df.html](https://joosthoeks.github.io/jhTAlib/example-8-alphavantage-2-df.html) 188 | 189 | - [https://joosthoeks.github.io/jhTAlib/example-9-cryptocompare-2-df.html](https://joosthoeks.github.io/jhTAlib/example-9-cryptocompare-2-df.html) 190 | 191 | - [https://joosthoeks.github.io/jhTAlib/example-10-df-numpy-pandas.html](https://joosthoeks.github.io/jhTAlib/example-10-df-numpy-pandas.html) 192 | 193 | - [https://joosthoeks.github.io/jhTAlib/example-11-basic-usage.html](https://joosthoeks.github.io/jhTAlib/example-11-basic-usage.html) 194 | 195 | --- 196 | 197 | ## Notebooks 198 | 199 | - [https://joosthoeks.github.io/jhTAlib/a_sane_and_simple_bitcoin_savings_plan_(sss).html](https://joosthoeks.github.io/jhTAlib/a_sane_and_simple_bitcoin_savings_plan_(sss).html) 200 | 201 | - [https://joosthoeks.github.io/jhTAlib/dollar_cost_averaging_discount_dcad.html](https://joosthoeks.github.io/jhTAlib/dollar_cost_averaging_discount_dcad.html) 202 | 203 | - [https://joosthoeks.github.io/jhTAlib/recession_probability.html](https://joosthoeks.github.io/jhTAlib/recession_probability.html) 204 | 205 | --- 206 | 207 | ## References 208 | 209 | ### Books 210 | 211 | - An Introduction to Algorithmic Trading 212 | 213 | - Computer Analysis of the Futures Markets 214 | 215 | - New Concepts in Technical Trading Systems 216 | 217 | - The New Technical Trader 218 | 219 | - Trading Systems and Methods 220 | 221 | ### Urls 222 | 223 | - [https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/overview](https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/overview) 224 | 225 | - [https://fintechprofessor.com/2017/12/02/log-vs-simple-returns-examples-and-comparisons/](https://fintechprofessor.com/2017/12/02/log-vs-simple-returns-examples-and-comparisons/) 226 | 227 | - [https://www.fmlabs.com/reference/default.htm](https://www.fmlabs.com/reference/default.htm) 228 | 229 | - [https://gannsecret.blogspot.com/p/pivot-point-definition.html](https://gannsecret.blogspot.com/p/pivot-point-definition.html) 230 | 231 | - [https://www.investopedia.com/terms/k/kellycriterion.asp](https://www.investopedia.com/terms/k/kellycriterion.asp) 232 | 233 | - [https://www.investopedia.com/terms/p/profit_loss_ratio.asp](https://www.investopedia.com/terms/p/profit_loss_ratio.asp) 234 | 235 | - [https://machinelearningmastery.com/implement-simple-linear-regression-scratch-python/](https://machinelearningmastery.com/implement-simple-linear-regression-scratch-python/) 236 | 237 | - [https://machinelearningmastery.com/normalize-standardize-time-series-data-python/](https://machinelearningmastery.com/normalize-standardize-time-series-data-python/) 238 | 239 | - [https://www.mathsisfun.com/data/least-squares-regression.html](https://www.mathsisfun.com/data/least-squares-regression.html) 240 | 241 | - [https://www.tadoc.org/index.htm](https://www.tadoc.org/index.htm) 242 | 243 | - [https://www.theinvestorspodcast.com/bitcoin-mayer-multiple/](https://www.theinvestorspodcast.com/bitcoin-mayer-multiple/) 244 | 245 | - [https://www.tradeciety.com/understand-candlesticks-patterns/](https://www.tradeciety.com/understand-candlesticks-patterns/) 246 | 247 | - [https://www.wallstreetmojo.com/statistics-guides/](https://www.wallstreetmojo.com/statistics-guides/) 248 | 249 | - [https://www.wallstreetmojo.com/investment-banking/corporate-finance/](https://www.wallstreetmojo.com/investment-banking/corporate-finance/) 250 | 251 | - [https://www.wikihow.com/Calculate-the-Standard-Error-of-Estimate](https://www.wikihow.com/Calculate-the-Standard-Error-of-Estimate) 252 | 253 | - [https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Covariance](https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Covariance) 254 | 255 | - [https://en.wikipedia.org/wiki/Amplitude](https://en.wikipedia.org/wiki/Amplitude) 256 | 257 | - [https://en.wikipedia.org/wiki/Beta_(finance)](https://en.wikipedia.org/wiki/Beta_(finance)) 258 | 259 | - [https://en.wikipedia.org/wiki/Expected_value](https://en.wikipedia.org/wiki/Expected_value) 260 | 261 | - [https://en.wikipedia.org/wiki/Julian_day](https://en.wikipedia.org/wiki/Julian_day) 262 | 263 | - [https://en.wikipedia.org/wiki/Monte_Carlo_method](https://en.wikipedia.org/wiki/Monte_Carlo_method) 264 | 265 | - [https://en.wikipedia.org/wiki/Pivot_point_(technical_analysis)](https://en.wikipedia.org/wiki/Pivot_point_(technical_analysis)) 266 | 267 | --- 268 | 269 | ## Donation and Funding 270 | 271 | - [https://github.com/joosthoeks/jhTAlib/stargazers](https://github.com/joosthoeks/jhTAlib/stargazers) 272 | 273 | --- 274 | -------------------------------------------------------------------------------- /docs/README.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joosthoeks/jhTAlib/b26f3ddacf4deedf8b66db2f8125f9ae88856e64/docs/README.pdf -------------------------------------------------------------------------------- /docs/jupyter.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | jupyter nbconvert --output-dir=docs --to html --template lab example/*.ipynb 3 | jupyter nbconvert --output-dir=docs --to html --template lab notebook/*.ipynb 4 | -------------------------------------------------------------------------------- /docs/pandoc.css: -------------------------------------------------------------------------------- 1 | code {background-color: lightgray;} 2 | table, th, td {border: 1px solid black;} 3 | table {border-collapse: collapse;} 4 | tr:hover {background-color: #f5f5f5;} 5 | tr:nth-child(even) {background-color: #f2f2f2;} 6 | th {background-color: #4caf50; color: white;} 7 | 8 | -------------------------------------------------------------------------------- /docs/pandoc.md: -------------------------------------------------------------------------------- 1 | Generate HTML5: 2 | 3 | ``` 4 | $ pandoc -s -t html5 --toc -c pandoc.css README.md -o docs/index.html 5 | ``` 6 | 7 | Generate EPUB ebook: 8 | 9 | ``` 10 | $ pandoc -s -t epub --toc README.md -o docs/README.epub 11 | ``` 12 | 13 | Generate JSON: 14 | 15 | ``` 16 | $ pandoc -s -t json --toc README.md -o docs/README.json 17 | ``` 18 | 19 | Generate ODT (OpenDocument Text, readable by LibreOffice): 20 | 21 | ``` 22 | $ pandoc -s -t odt --toc README.md -o docs/README.odt 23 | ``` 24 | 25 | Generate PDF: 26 | 27 | ``` 28 | $ pandoc -s -t latex --toc README.md -o docs/README.pdf 29 | ``` 30 | 31 | Generate reStructuredText: 32 | 33 | ``` 34 | $ pandoc -s -t rst --toc README.md -o docs/README.rst 35 | ``` 36 | 37 | Generate Rich text format (RTF): 38 | 39 | ``` 40 | $ pandoc -s -t rtf --toc README.md -o docs/README.rtf 41 | ``` 42 | 43 | Generate OpenDocument XML: 44 | 45 | ``` 46 | $ pandoc -s -t opendocument --toc README.md -o docs/README.xml 47 | ``` 48 | 49 | -------------------------------------------------------------------------------- /docs/pandoc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | pandoc -s -t html5 --toc -c pandoc.css README.md -o docs/index.html 3 | #pandoc -s -t epub --toc README.md -o docs/README.epub 4 | #pandoc -s -t json --toc README.md -o docs/README.json 5 | #pandoc -s -t odt --toc README.md -o docs/README.odt 6 | pandoc -s -t latex --toc README.md -o docs/README.pdf 7 | #pandoc -s -t rst --toc README.md -o docs/README.rst 8 | #pandoc -s -t rtf --toc README.md -o docs/README.rtf 9 | #pandoc -s -t opendocument --toc README.md -o docs/README.xml 10 | 11 | -------------------------------------------------------------------------------- /example/example-1-plot.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "example-1-plot.ipynb", 7 | "version": "0.3.2", 8 | "provenance": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "metadata": { 18 | "id": "p8kdzyG1Hs99", 19 | "colab_type": "code", 20 | "colab": {} 21 | }, 22 | "cell_type": "code", 23 | "source": [ 24 | "!pip install --upgrade jhtalib\n" 25 | ], 26 | "execution_count": 0, 27 | "outputs": [] 28 | }, 29 | { 30 | "metadata": { 31 | "id": "SIYmJmQQISmq", 32 | "colab_type": "code", 33 | "colab": {} 34 | }, 35 | "cell_type": "code", 36 | "source": [ 37 | "import requests\n", 38 | "import csv\n", 39 | "\n", 40 | "import jhtalib as jhta\n", 41 | "import matplotlib.pyplot as plt\n", 42 | "\n", 43 | "\n", 44 | "# download csv content:\n", 45 | "result = requests.get('https://raw.githubusercontent.com/joosthoeks/jhTAlib/master/example/data.csv')\n", 46 | "decoded = result.content.decode('utf-8')\n", 47 | "csv_reader = csv.reader(decoded.splitlines(), delimiter=',')\n", 48 | "\n", 49 | "# save csv content to csv file:\n", 50 | "with open('data.csv', 'w') as csv_file:\n", 51 | " csv_writer = csv.writer(csv_file)\n", 52 | " for row in csv_reader:\n", 53 | " csv_writer.writerow(row)\n", 54 | "\n", 55 | "# start example:\n", 56 | "df = jhta.CSV2DF('data.csv')\n", 57 | "x = df['datetime']\n", 58 | "\n", 59 | "plt.figure(1)\n", 60 | "\n", 61 | "plt.subplot(211)\n", 62 | "plt.title('Time / Price')\n", 63 | "plt.xlabel('Time')\n", 64 | "plt.ylabel('Price')\n", 65 | "plt.grid(True)\n", 66 | "plt.plot(x, df['Close'], color='blue')\n", 67 | "plt.plot(x, jhta.SMA(df, 200), color='red')\n", 68 | "plt.legend(['Close', 'SMA 200'], loc='upper left')\n", 69 | "\n", 70 | "plt.show()\n" 71 | ], 72 | "execution_count": 0, 73 | "outputs": [] 74 | } 75 | ] 76 | } -------------------------------------------------------------------------------- /example/example-1-plot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | import jhtalib as jhta 5 | import matplotlib.pyplot as plt 6 | 7 | 8 | def main(): 9 | df = jhta.CSV2DF('data.csv') 10 | x = df['datetime'] 11 | 12 | plt.figure(1) 13 | 14 | plt.subplot(211) 15 | plt.title('Time / Price') 16 | plt.xlabel('Time') 17 | plt.ylabel('Price') 18 | plt.grid(True) 19 | plt.plot(x, df['Close'], color='blue') 20 | plt.plot(x, jhta.SMA(df, 200), color='red') 21 | plt.legend(['Close', 'SMA 200'], loc='upper left') 22 | 23 | plt.show() 24 | 25 | 26 | if __name__ == '__main__': 27 | main() 28 | 29 | -------------------------------------------------------------------------------- /example/example-10-df-numpy-pandas.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "example-10-df-numpy-pandas.ipynb", 7 | "version": "0.3.2", 8 | "provenance": [], 9 | "collapsed_sections": [] 10 | }, 11 | "kernelspec": { 12 | "name": "python3", 13 | "display_name": "Python 3" 14 | }, 15 | "accelerator": "TPU" 16 | }, 17 | "cells": [ 18 | { 19 | "metadata": { 20 | "id": "JcXr2ZZ1kwSi", 21 | "colab_type": "code", 22 | "colab": {} 23 | }, 24 | "cell_type": "code", 25 | "source": [ 26 | "!pip install --upgrade jhtalib\n" 27 | ], 28 | "execution_count": 0, 29 | "outputs": [] 30 | }, 31 | { 32 | "metadata": { 33 | "id": "q7FIPHDfMtk-", 34 | "colab_type": "code", 35 | "colab": {} 36 | }, 37 | "cell_type": "code", 38 | "source": [ 39 | "import jhtalib as jhta\n", 40 | "from pprint import pprint as pp\n", 41 | "import numpy as np\n", 42 | "import pandas as pd\n", 43 | "\n", 44 | "\n", 45 | "def DF2NUMPY(df):\n", 46 | " \"\"\"\n", 47 | " DataFeed 2 NumPy DataFeed\n", 48 | " \"\"\"\n", 49 | " return {\n", 50 | " 'datetime': np.array(df['datetime']),\n", 51 | " 'Open': np.array(df['Open'], dtype=float),\n", 52 | " 'High': np.array(df['High'], dtype=float),\n", 53 | " 'Low': np.array(df['Low'], dtype=float),\n", 54 | " 'Close': np.array(df['Close'], dtype=float),\n", 55 | " 'Volume': np.array(df['Volume'], dtype=int)\n", 56 | " }\n", 57 | "\n", 58 | "def NUMPY2DF(df_np):\n", 59 | " \"\"\"\n", 60 | " NumPy DataFeed 2 DataFeed\n", 61 | " \"\"\"\n", 62 | " return {\n", 63 | " 'datetime': tuple(df_np['datetime']),\n", 64 | " 'Open': tuple(df_np['Open']),\n", 65 | " 'High': tuple(df_np['High']),\n", 66 | " 'Low': tuple(df_np['Low']),\n", 67 | " 'Close': tuple(df_np['Close']),\n", 68 | " 'Volume': tuple(df_np['Volume'])\n", 69 | " }\n", 70 | "\n", 71 | "def DF2PANDAS(df):\n", 72 | " \"\"\"\n", 73 | " DataFeed 2 Pandas DataFeed\n", 74 | " \"\"\"\n", 75 | " return pd.DataFrame({\n", 76 | " 'datetime': pd.Series(df['datetime']),\n", 77 | " 'Open': pd.Series(df['Open'], dtype=float),\n", 78 | " 'High': pd.Series(df['High'], dtype=float),\n", 79 | " 'Low': pd.Series(df['Low'], dtype=float),\n", 80 | " 'Close': pd.Series(df['Close'], dtype=float),\n", 81 | " 'Volume': pd.Series(df['Volume'], dtype=int),\n", 82 | " }, columns=['datetime', 'Open', 'High', 'Low', 'Close', 'Volume'])\n", 83 | "\n", 84 | "def PANDAS2DF(df_pd):\n", 85 | " \"\"\"\n", 86 | " Pandas DataFeed 2 DataFeed\n", 87 | " \"\"\"\n", 88 | " return {\n", 89 | " 'datetime': tuple(df_pd['datetime']),\n", 90 | " 'Open': tuple(df_pd['Open']),\n", 91 | " 'High': tuple(df_pd['High']),\n", 92 | " 'Low': tuple(df_pd['Low']),\n", 93 | " 'Close': tuple(df_pd['Close']),\n", 94 | " 'Volume': tuple(df_pd['Volume'])\n", 95 | " }\n", 96 | "\n", 97 | "\n", 98 | "df = jhta.CSVURL2DF('https://raw.githubusercontent.com/joosthoeks/jhTAlib/master/example/data.csv')\n", 99 | "pp (df)\n", 100 | "\n", 101 | "df_np = DF2NUMPY(df)\n", 102 | "pp (df_np)\n", 103 | "\n", 104 | "df = NUMPY2DF(df_np)\n", 105 | "pp (df)\n", 106 | "\n", 107 | "df_pd = DF2PANDAS(df)\n", 108 | "pp (df_pd)\n", 109 | "\n", 110 | "df = PANDAS2DF(df_pd)\n", 111 | "pp (df)\n" 112 | ], 113 | "execution_count": 0, 114 | "outputs": [] 115 | } 116 | ] 117 | } -------------------------------------------------------------------------------- /example/example-11-basic-usage.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "example-11-basic-usage.ipynb", 7 | "version": "0.3.2", 8 | "provenance": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | }, 14 | "accelerator": "TPU" 15 | }, 16 | "cells": [ 17 | { 18 | "cell_type": "code", 19 | "metadata": { 20 | "id": "BGm2HquKHz9B", 21 | "colab_type": "code", 22 | "colab": {} 23 | }, 24 | "source": [ 25 | "!pip install --upgrade jhtalib\n" 26 | ], 27 | "execution_count": 0, 28 | "outputs": [] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "metadata": { 33 | "id": "umhhLzw0I3ez", 34 | "colab_type": "code", 35 | "colab": {} 36 | }, 37 | "source": [ 38 | "import jhtalib as jhta\n", 39 | "from pprint import pprint as pp\n", 40 | "\n", 41 | "\n", 42 | "# df is DataFeed:\n", 43 | "df = {\n", 44 | " 'datetime': ('20151217', '20151218', '20151221', '20151222', '20151223', '20151224', '20151228', '20151229', '20151230', '20151231'),\n", 45 | " 'Open': (235.8, 232.3, 234.1, 232.2, 232.7, 235.4, 236.9, 234.85, 236.45, 235.0),\n", 46 | " 'High': (238.05, 236.9, 237.3, 232.4, 235.2, 236.15, 236.9, 237.6, 238.3, 237.25),\n", 47 | " 'Low': (234.55, 230.6, 230.2, 226.8, 231.5, 233.85, 233.05, 234.6, 234.55, 234.4),\n", 48 | " 'Close': (234.6, 233.6, 230.2, 230.05, 234.15, 236.15, 233.25, 237.6, 235.75, 234.4),\n", 49 | " 'Volume': (448294, 629039, 292528, 214170, 215545, 23548, 97574, 192908, 176839, 69347)\n", 50 | " }\n", 51 | "\n", 52 | "# basic usage:\n", 53 | "#pp (df)\n", 54 | "pp (jhta.SMA(df, 10))\n", 55 | "#pp (jhta.BBANDS(df, 10))\n" 56 | ], 57 | "execution_count": 0, 58 | "outputs": [] 59 | } 60 | ] 61 | } -------------------------------------------------------------------------------- /example/example-2-plot.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "example-2-plot.ipynb", 7 | "version": "0.3.2", 8 | "provenance": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "metadata": { 18 | "id": "69IpGclWooU_", 19 | "colab_type": "code", 20 | "colab": {} 21 | }, 22 | "cell_type": "code", 23 | "source": [ 24 | "!pip install --upgrade jhtalib" 25 | ], 26 | "execution_count": 0, 27 | "outputs": [] 28 | }, 29 | { 30 | "metadata": { 31 | "id": "MGFDS5K6pAvL", 32 | "colab_type": "code", 33 | "colab": {} 34 | }, 35 | "cell_type": "code", 36 | "source": [ 37 | "import requests\n", 38 | "import csv\n", 39 | "\n", 40 | "import jhtalib as jhta\n", 41 | "import matplotlib.pyplot as plt\n", 42 | "\n", 43 | "\n", 44 | "# download csv content:\n", 45 | "result = requests.get('https://raw.githubusercontent.com/joosthoeks/jhTAlib/master/example/data.csv')\n", 46 | "decoded = result.content.decode('utf-8')\n", 47 | "csv_reader = csv.reader(decoded.splitlines(), delimiter=',')\n", 48 | "\n", 49 | "# save csv content to csv file:\n", 50 | "with open('data.csv', 'w') as csv_file:\n", 51 | " csv_writer = csv.writer(csv_file)\n", 52 | " for row in csv_reader:\n", 53 | " csv_writer.writerow(row)\n", 54 | "\n", 55 | "# start example:\n", 56 | "df = jhta.CSV2DF('data.csv')\n", 57 | "x = df['datetime']\n", 58 | "bbands = jhta.BBANDS(df, 20)\n", 59 | "\n", 60 | "plt.figure(1)\n", 61 | "\n", 62 | "plt.subplot(211)\n", 63 | "plt.title('Time / Price')\n", 64 | "plt.xlabel('Time')\n", 65 | "plt.ylabel('Price')\n", 66 | "plt.grid(True)\n", 67 | "plt.plot(x, df['Close'], color='blue')\n", 68 | "plt.plot(x, bbands['midband'], color='red')\n", 69 | "plt.plot(x, bbands['upperband'], color='yellow')\n", 70 | "plt.plot(x, bbands['lowerband'], color='yellow')\n", 71 | "plt.legend(['Close', 'BBANDS midband', 'BBANDS upperband', 'BBANDS lowerband'], loc='upper left')\n", 72 | "\n", 73 | "plt.show()\n" 74 | ], 75 | "execution_count": 0, 76 | "outputs": [] 77 | } 78 | ] 79 | } -------------------------------------------------------------------------------- /example/example-2-plot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | import jhtalib as jhta 5 | import matplotlib.pyplot as plt 6 | 7 | 8 | def main(): 9 | df = jhta.CSV2DF('data.csv') 10 | x = df['datetime'] 11 | bbands = jhta.BBANDS(df, 20) 12 | 13 | plt.figure(1) 14 | 15 | plt.subplot(211) 16 | plt.title('Time / Price') 17 | plt.xlabel('Time') 18 | plt.ylabel('Price') 19 | plt.grid(True) 20 | plt.plot(x, df['Close'], color='blue') 21 | plt.plot(x, bbands['midband'], color='red') 22 | plt.plot(x, bbands['upperband'], color='yellow') 23 | plt.plot(x, bbands['lowerband'], color='yellow') 24 | plt.legend(['Close', 'BBANDS midband', 'BBANDS upperband', 'BBANDS lowerband'], loc='upper left') 25 | 26 | plt.show() 27 | 28 | 29 | if __name__ == '__main__': 30 | main() 31 | 32 | -------------------------------------------------------------------------------- /example/example-3-plot.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "example-3-plot.ipynb", 7 | "version": "0.3.2", 8 | "provenance": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "metadata": { 18 | "id": "OMNknpd42ebU", 19 | "colab_type": "code", 20 | "colab": {} 21 | }, 22 | "cell_type": "code", 23 | "source": [ 24 | "!pip install --upgrade jhtalib" 25 | ], 26 | "execution_count": 0, 27 | "outputs": [] 28 | }, 29 | { 30 | "metadata": { 31 | "id": "dutToad-2vwS", 32 | "colab_type": "code", 33 | "colab": {} 34 | }, 35 | "cell_type": "code", 36 | "source": [ 37 | "import requests\n", 38 | "import csv\n", 39 | "\n", 40 | "import jhtalib as jhta\n", 41 | "import matplotlib.pyplot as plt\n", 42 | "\n", 43 | "\n", 44 | "# download csv content:\n", 45 | "result = requests.get('https://raw.githubusercontent.com/joosthoeks/jhTAlib/master/example/data.csv')\n", 46 | "decoded = result.content.decode('utf-8')\n", 47 | "csv_reader = csv.reader(decoded.splitlines(), delimiter=',')\n", 48 | "\n", 49 | "# save csv content to csv file:\n", 50 | "with open('data.csv', 'w') as csv_file:\n", 51 | " csv_writer = csv.writer(csv_file)\n", 52 | " for row in csv_reader:\n", 53 | " csv_writer.writerow(row)\n", 54 | "\n", 55 | "# start example:\n", 56 | "df = jhta.CSV2DF('data.csv')\n", 57 | "x = df['datetime']\n", 58 | "\n", 59 | "plt.figure(1)\n", 60 | "\n", 61 | "plt.subplot(211)\n", 62 | "plt.title('Time / Price / Ratio')\n", 63 | "plt.xlabel('Time')\n", 64 | "plt.ylabel('Price')\n", 65 | "plt.grid(True)\n", 66 | "plt.plot(x, df['Close'], color='blue')\n", 67 | "plt.legend(['Close'], loc='upper left')\n", 68 | "\n", 69 | "plt.subplot(212)\n", 70 | "plt.xlabel('Time')\n", 71 | "plt.ylabel('Ratio')\n", 72 | "plt.grid(True)\n", 73 | "plt.plot(x, [0] * len(x))\n", 74 | "plt.plot(x, jhta.MOM(df, 10))\n", 75 | "plt.legend(['Price', 'MOM 10'], loc='upper left')\n", 76 | "\n", 77 | "plt.show()\n" 78 | ], 79 | "execution_count": 0, 80 | "outputs": [] 81 | } 82 | ] 83 | } -------------------------------------------------------------------------------- /example/example-3-plot.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | import jhtalib as jhta 5 | import matplotlib.pyplot as plt 6 | 7 | 8 | def main(): 9 | df = jhta.CSV2DF('data.csv') 10 | x = df['datetime'] 11 | 12 | plt.figure(1) 13 | 14 | plt.subplot(211) 15 | plt.title('Time / Price / Ratio') 16 | plt.xlabel('Time') 17 | plt.ylabel('Price') 18 | plt.grid(True) 19 | plt.plot(x, df['Close'], color='blue') 20 | plt.legend(['Close'], loc='upper left') 21 | 22 | plt.subplot(212) 23 | plt.xlabel('Time') 24 | plt.ylabel('Ratio') 25 | plt.grid(True) 26 | plt.plot(x, [0] * len(x)) 27 | plt.plot(x, jhta.MOM(df, 10)) 28 | plt.legend(['Price', 'MOM 10'], loc='upper left') 29 | 30 | plt.show() 31 | 32 | 33 | if __name__ == '__main__': 34 | main() 35 | 36 | -------------------------------------------------------------------------------- /example/example-4-plot-quandl.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "example-4-plot-quandl.ipynb", 7 | "version": "0.3.2", 8 | "provenance": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "metadata": { 18 | "id": "Mj7YX4fsIYm-", 19 | "colab_type": "code", 20 | "colab": {} 21 | }, 22 | "cell_type": "code", 23 | "source": [ 24 | "!pip install --upgrade quandl\n", 25 | "!pip install --upgrade jhtalib" 26 | ], 27 | "execution_count": 0, 28 | "outputs": [] 29 | }, 30 | { 31 | "metadata": { 32 | "id": "2rC37p9wIjUj", 33 | "colab_type": "code", 34 | "colab": {} 35 | }, 36 | "cell_type": "code", 37 | "source": [ 38 | "import quandl\n", 39 | "import jhtalib as jhta\n", 40 | "import matplotlib.pyplot as plt\n", 41 | "\n", 42 | "\n", 43 | "#quandl_data = quandl.get('BCHARTS/BITSTAMPUSD', start_date='2011-01-01', end_date='2018-11-01', order='asc', collapse='daily', returns='numpy', authtoken='YOUR_AUTH_TOKEN')\n", 44 | "quandl_data = quandl.get('BCHARTS/BITSTAMPUSD', start_date='2011-01-01', end_date='2018-11-01', order='asc', collapse='daily', returns='numpy')\n", 45 | "\n", 46 | "df = {'datetime': [], 'Open': [], 'High': [], 'Low': [], 'Close': [], 'Volume': []}\n", 47 | "i = 0\n", 48 | "while i < len(quandl_data['Close']):\n", 49 | " df['datetime'].append(str(quandl_data['Date'][i]))\n", 50 | " df['Open'].append(float(quandl_data['Open'][i]))\n", 51 | " df['High'].append(float(quandl_data['High'][i]))\n", 52 | " df['Low'].append(float(quandl_data['Low'][i]))\n", 53 | " df['Close'].append(float(quandl_data['Close'][i]))\n", 54 | " df['Volume'].append(int(quandl_data['Volume (BTC)'][i]))\n", 55 | " i += 1\n", 56 | "\n", 57 | "x = df['datetime']\n", 58 | "\n", 59 | "plt.figure(1, figsize=(20, 10))\n", 60 | "\n", 61 | "plt.subplot(211)\n", 62 | "plt.title('Time / Price')\n", 63 | "plt.xlabel('Time')\n", 64 | "plt.ylabel('Price')\n", 65 | "plt.grid(True)\n", 66 | "plt.plot(x, df['Close'], color='blue')\n", 67 | "plt.plot(x, df['High'], color='grey')\n", 68 | "plt.plot(x, df['Low'], color='grey')\n", 69 | "plt.plot(x, jhta.ATH(df)['ath'], color='red')\n", 70 | "plt.plot(x, jhta.LMC(df)['lmc'], color='green')\n", 71 | "plt.legend(['Close', 'High', 'Low', 'ATH', 'LMC'], loc='upper left')\n", 72 | "\n", 73 | "plt.show()\n" 74 | ], 75 | "execution_count": 0, 76 | "outputs": [] 77 | } 78 | ] 79 | } -------------------------------------------------------------------------------- /example/example-4-plot-quandl.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | import quandl 5 | import jhtalib as jhta 6 | import matplotlib.pyplot as plt 7 | 8 | 9 | def main(): 10 | # quandl_data = quandl.get('BCHARTS/BITSTAMPUSD', start_date='2011-01-01', end_date='2018-11-01', order='asc', collapse='daily', returns='numpy', authtoken='YOUR_AUTH_TOKEN') 11 | quandl_data = quandl.get('BCHARTS/BITSTAMPUSD', start_date='2011-01-01', end_date='2018-11-01', order='asc', collapse='daily', returns='numpy') 12 | 13 | df = {'datetime': [], 'Open': [], 'High': [], 'Low': [], 'Close': [], 'Volume': []} 14 | i = 0 15 | while i < len(quandl_data['Close']): 16 | df['datetime'].append(str(quandl_data['Date'][i])) 17 | df['Open'].append(float(quandl_data['Open'][i])) 18 | df['High'].append(float(quandl_data['High'][i])) 19 | df['Low'].append(float(quandl_data['Low'][i])) 20 | df['Close'].append(float(quandl_data['Close'][i])) 21 | df['Volume'].append(int(quandl_data['Volume (BTC)'][i])) 22 | i += 1 23 | 24 | x = df['datetime'] 25 | 26 | plt.figure(1) 27 | 28 | plt.subplot(211) 29 | plt.title('Time / Price') 30 | plt.xlabel('Time') 31 | plt.ylabel('Price') 32 | plt.grid(True) 33 | plt.plot(x, df['Close'], color='blue') 34 | plt.plot(x, df['High'], color='grey') 35 | plt.plot(x, df['Low'], color='grey') 36 | plt.plot(x, jhta.ATH(df)['ath'], color='red') 37 | plt.plot(x, jhta.LMC(df)['lmc'], color='green') 38 | plt.legend(['Close', 'High', 'Low', 'ATH', 'LMC'], loc='upper left') 39 | 40 | plt.show() 41 | 42 | 43 | if __name__ == '__main__': 44 | main() 45 | 46 | -------------------------------------------------------------------------------- /example/example-5-plot-quandl.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "example-5-plot-quandl.ipynb", 7 | "version": "0.3.2", 8 | "provenance": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "metadata": { 18 | "id": "mjLtnyOCVZI5", 19 | "colab_type": "code", 20 | "colab": {} 21 | }, 22 | "cell_type": "code", 23 | "source": [ 24 | "!pip install --upgrade quandl\n", 25 | "!pip install --upgrade jhtalib" 26 | ], 27 | "execution_count": 0, 28 | "outputs": [] 29 | }, 30 | { 31 | "metadata": { 32 | "id": "RCOFr0A_Vwdj", 33 | "colab_type": "code", 34 | "colab": {} 35 | }, 36 | "cell_type": "code", 37 | "source": [ 38 | "import quandl\n", 39 | "import jhtalib as jhta\n", 40 | "import matplotlib.pyplot as plt\n", 41 | "\n", 42 | "\n", 43 | "#quandl_data = quandl.get('BCHARTS/BITSTAMPUSD', start_date='2011-01-01', end_date='2018-11-01', order='asc', collapse='daily', returns='numpy', authtoken='YOUR_AUTH_TOKEN')\n", 44 | "quandl_data = quandl.get('BCHARTS/BITSTAMPUSD', start_date='2011-01-01', end_date='2018-11-01', order='asc', collapse='daily', returns='numpy')\n", 45 | "\n", 46 | "df = {'datetime': [], 'Open': [], 'High': [], 'Low': [], 'Close': [], 'Volume': []}\n", 47 | "i = 0\n", 48 | "while i < len(quandl_data['Close']):\n", 49 | " df['datetime'].append(str(quandl_data['Date'][i]))\n", 50 | " df['Open'].append(float(quandl_data['Open'][i]))\n", 51 | " df['High'].append(float(quandl_data['High'][i]))\n", 52 | " df['Low'].append(float(quandl_data['Low'][i]))\n", 53 | " df['Close'].append(float(quandl_data['Close'][i]))\n", 54 | " df['Volume'].append(int(quandl_data['Volume (BTC)'][i]))\n", 55 | " i += 1\n", 56 | "\n", 57 | "x = df['datetime']\n", 58 | "\n", 59 | "plt.figure(1, figsize=(20, 10))\n", 60 | "\n", 61 | "plt.subplot(211)\n", 62 | "plt.title('Time / Price / Ratio')\n", 63 | "plt.xlabel('Time')\n", 64 | "plt.ylabel('Price')\n", 65 | "plt.grid(True)\n", 66 | "plt.plot(x, df['Close'], color='blue')\n", 67 | "plt.plot(x, jhta.SMA(df, 200), color='red')\n", 68 | "plt.legend(['Close', 'SMA 200'], loc='upper left')\n", 69 | "\n", 70 | "plt.subplot(212)\n", 71 | "plt.xlabel('Time')\n", 72 | "plt.ylabel('Ratio')\n", 73 | "plt.grid(True)\n", 74 | "plt.plot(x, [1] * len(x))\n", 75 | "plt.plot(x, jhta.MMR(df))\n", 76 | "plt.legend(['SMA 200', 'MMR'], loc='upper left')\n", 77 | "\n", 78 | "plt.show()\n" 79 | ], 80 | "execution_count": 0, 81 | "outputs": [] 82 | } 83 | ] 84 | } -------------------------------------------------------------------------------- /example/example-5-plot-quandl.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | import quandl 5 | import jhtalib as jhta 6 | import matplotlib.pyplot as plt 7 | 8 | 9 | def main(): 10 | # quandl_data = quandl.get('BCHARTS/BITSTAMPUSD', start_date='2011-01-01', end_date='2018-11-01', order='asc', collapse='daily', returns='numpy', authtoken='YOUR_AUTH_TOKEN') 11 | quandl_data = quandl.get('BCHARTS/BITSTAMPUSD', start_date='2011-01-01', end_date='2018-11-01', order='asc', collapse='daily', returns='numpy') 12 | 13 | df = {'datetime': [], 'Open': [], 'High': [], 'Low': [], 'Close': [], 'Volume': []} 14 | i = 0 15 | while i < len(quandl_data['Close']): 16 | df['datetime'].append(str(quandl_data['Date'][i])) 17 | df['Open'].append(float(quandl_data['Open'][i])) 18 | df['High'].append(float(quandl_data['High'][i])) 19 | df['Low'].append(float(quandl_data['Low'][i])) 20 | df['Close'].append(float(quandl_data['Close'][i])) 21 | df['Volume'].append(int(quandl_data['Volume (BTC)'][i])) 22 | i += 1 23 | 24 | x = df['datetime'] 25 | 26 | plt.figure(1) 27 | 28 | plt.subplot(211) 29 | plt.title('Time / Price / Ratio') 30 | plt.xlabel('Time') 31 | plt.ylabel('Price') 32 | plt.grid(True) 33 | plt.plot(x, df['Close'], color='blue') 34 | plt.plot(x, jhta.SMA(df, 200), color='red') 35 | plt.legend(['Close', 'SMA 200'], loc='upper left') 36 | 37 | plt.subplot(212) 38 | plt.xlabel('Time') 39 | plt.ylabel('Ratio') 40 | plt.grid(True) 41 | plt.plot(x, [1] * len(x)) 42 | plt.plot(x, jhta.MMR(df)) 43 | plt.legend(['SMA 200', 'MMR'], loc='upper left') 44 | 45 | plt.show() 46 | 47 | 48 | if __name__ == '__main__': 49 | main() 50 | 51 | -------------------------------------------------------------------------------- /example/example-6-plot-quandl.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "example-6-plot-quandl.ipynb", 7 | "version": "0.3.2", 8 | "provenance": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "metadata": { 18 | "id": "pXKd3O7s0O5m", 19 | "colab_type": "code", 20 | "colab": {} 21 | }, 22 | "cell_type": "code", 23 | "source": [ 24 | "!pip install --upgrade quandl\n", 25 | "!pip install --upgrade jhtalib" 26 | ], 27 | "execution_count": 0, 28 | "outputs": [] 29 | }, 30 | { 31 | "metadata": { 32 | "id": "G_sguSfq0duq", 33 | "colab_type": "code", 34 | "colab": {} 35 | }, 36 | "cell_type": "code", 37 | "source": [ 38 | "import quandl\n", 39 | "import matplotlib.dates as mdates\n", 40 | "import matplotlib.pyplot as plt\n", 41 | "import jhtalib as jhta\n", 42 | "\n", 43 | "\n", 44 | "#quandl_data = quandl.get('BCHARTS/BITSTAMPUSD', order='asc', collapse='daily', returns='numpy', authtoken='YOUR_AUTH_TOKEN')\n", 45 | "quandl_data = quandl.get('BCHARTS/BITSTAMPUSD', order='asc', collapse='daily', returns='numpy')\n", 46 | "\n", 47 | "df = {'datetime': [], 'Open': [], 'High': [], 'Low': [], 'Close': [], 'Volume': []}\n", 48 | "i = 0\n", 49 | "while i < len(quandl_data['Close']):\n", 50 | "# df['datetime'].append(i)\n", 51 | " df['datetime'].append(quandl_data['Date'][i])\n", 52 | " df['Open'].append(float(quandl_data['Open'][i]))\n", 53 | " df['High'].append(float(quandl_data['High'][i]))\n", 54 | " df['Low'].append(float(quandl_data['Low'][i]))\n", 55 | " df['Close'].append(float(quandl_data['Close'][i]))\n", 56 | " df['Volume'].append(int(quandl_data['Volume (BTC)'][i]))\n", 57 | " i += 1\n", 58 | "\n", 59 | "x = df['datetime']\n", 60 | "\n", 61 | "sma_list = jhta.SMA(df, 200)\n", 62 | "mmr_list = jhta.MMR(df)\n", 63 | "mmr_mean_list = jhta.MEAN({'mmr': mmr_list}, len(mmr_list), 'mmr')\n", 64 | "mom_list = jhta.MOM(df, 365)\n", 65 | "mom_mean_list = jhta.MEAN({'mom': mom_list}, len(mom_list), 'mom')\n", 66 | "\n", 67 | "print ('Calculated from %i data points:' % len(x))\n", 68 | "print ('Last Close: %f' % df['Close'][-1])\n", 69 | "print ('Last SMA 200: %f' % sma_list[-1])\n", 70 | "print ('Last MMR: %f' % mmr_list[-1])\n", 71 | "print ('Last MEAN MMR: %f' % mmr_mean_list[-1])\n", 72 | "print ('Last MOM 365: %f' % mom_list[-1])\n", 73 | "print ('Last MEAN MOM 365: %f' % mom_mean_list[-1])\n", 74 | "\n", 75 | "#left = 365\n", 76 | "#right = len(x)\n", 77 | "\n", 78 | "#print ('Plot starts from %i until %i in Log scale:' % (left, right))\n", 79 | "\n", 80 | "plt.figure(1, figsize=(30, 10))\n", 81 | "\n", 82 | "plt.subplot(311)\n", 83 | "plt.title('Time / Price / Ratio')\n", 84 | "plt.xlabel('Time')\n", 85 | "plt.ylabel('Price')\n", 86 | "plt.grid(True)\n", 87 | "plt.plot(x, df['Close'], color='blue')\n", 88 | "plt.plot(x, sma_list, color='red')\n", 89 | "plt.legend(['Close', 'SMA 200'], loc='upper left')\n", 90 | "plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))\n", 91 | "plt.gca().xaxis.set_major_locator(mdates.YearLocator())\n", 92 | "plt.gcf().autofmt_xdate()\n", 93 | "#plt.xlim(left=left, right=right)\n", 94 | "plt.yscale('log')\n", 95 | "\n", 96 | "plt.subplot(312)\n", 97 | "plt.xlabel('Time')\n", 98 | "plt.ylabel('Ratio')\n", 99 | "plt.grid(True)\n", 100 | "plt.plot(x, [1] * len(x), color='red')\n", 101 | "plt.plot(x, mmr_list)\n", 102 | "plt.plot(x, mmr_mean_list)\n", 103 | "plt.plot(x, [2.4] * len(x))\n", 104 | "plt.legend(['SMA 200', 'MMR', 'MEAN MMR', 'THRESHOLD 2.4'], loc='upper left')\n", 105 | "plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))\n", 106 | "plt.gca().xaxis.set_major_locator(mdates.YearLocator())\n", 107 | "plt.gcf().autofmt_xdate()\n", 108 | "#plt.xlim(left=left, right=right)\n", 109 | "plt.yscale('log')\n", 110 | "\n", 111 | "plt.subplot(313)\n", 112 | "plt.xlabel('Time')\n", 113 | "plt.ylabel('Ratio')\n", 114 | "plt.grid(True)\n", 115 | "plt.plot(x, [0] * len(x), color='blue')\n", 116 | "plt.plot(x, mom_list)\n", 117 | "plt.plot(x, mom_mean_list)\n", 118 | "plt.legend(['Price', 'MOM 365', 'MEAN MOM 365'], loc='upper left')\n", 119 | "plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))\n", 120 | "plt.gca().xaxis.set_major_locator(mdates.YearLocator())\n", 121 | "plt.gcf().autofmt_xdate()\n", 122 | "#plt.xlim(left=left, right=right)\n", 123 | "plt.yscale('symlog')\n", 124 | "\n", 125 | "plt.show()\n" 126 | ], 127 | "execution_count": 0, 128 | "outputs": [] 129 | } 130 | ] 131 | } -------------------------------------------------------------------------------- /example/example-6-plot-quandl.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | import quandl 5 | import matplotlib.dates as mdates 6 | import matplotlib.pyplot as plt 7 | import jhtalib as jhta 8 | 9 | 10 | def main(): 11 | # quandl_data = quandl.get('BCHARTS/BITSTAMPUSD', order='asc', collapse='daily', returns='numpy', authtoken='YOUR_AUTH_TOKEN') 12 | quandl_data = quandl.get('BCHARTS/BITSTAMPUSD', order='asc', collapse='daily', returns='numpy') 13 | 14 | df = {'datetime': [], 'Open': [], 'High': [], 'Low': [], 'Close': [], 'Volume': []} 15 | i = 0 16 | while i < len(quandl_data['Close']): 17 | # df['datetime'].append(i) 18 | df['datetime'].append(quandl_data['Date'][i]) 19 | df['Open'].append(float(quandl_data['Open'][i])) 20 | df['High'].append(float(quandl_data['High'][i])) 21 | df['Low'].append(float(quandl_data['Low'][i])) 22 | df['Close'].append(float(quandl_data['Close'][i])) 23 | df['Volume'].append(int(quandl_data['Volume (BTC)'][i])) 24 | i += 1 25 | 26 | x = df['datetime'] 27 | 28 | sma_list = jhta.SMA(df, 200) 29 | mmr_list = jhta.MMR(df) 30 | mmr_mean_list = jhta.MEAN({'mmr': mmr_list}, len(mmr_list), 'mmr') 31 | mom_list = jhta.MOM(df, 365) 32 | mom_mean_list = jhta.MEAN({'mom': mom_list}, len(mom_list), 'mom') 33 | 34 | print ('Calculated from %i data points:' % len(x)) 35 | print ('Last Close: %f' % df['Close'][-1]) 36 | print ('Last SMA 200: %f' % sma_list[-1]) 37 | print ('Last MMR: %f' % mmr_list[-1]) 38 | print ('Last MEAN MMR: %f' % mmr_mean_list[-1]) 39 | print ('Last MOM 365: %f' % mom_list[-1]) 40 | print ('Last MEAN MOM 365: %f' % mom_mean_list[-1]) 41 | 42 | # left = 365 43 | # right = len(x) 44 | 45 | # print ('Plot starts from %i until %i in Log scale:' % (left, right)) 46 | 47 | plt.figure(1, (30, 10)) 48 | 49 | plt.subplot(311) 50 | plt.title('Time / Price / Ratio') 51 | plt.xlabel('Time') 52 | plt.ylabel('Price') 53 | plt.grid(True) 54 | plt.plot(x, df['Close'], color='blue') 55 | plt.plot(x, sma_list, color='red') 56 | plt.legend(['Close', 'SMA 200'], loc='upper left') 57 | plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d')) 58 | plt.gca().xaxis.set_major_locator(mdates.YearLocator()) 59 | plt.gcf().autofmt_xdate() 60 | # plt.xlim(left=left, right=right) 61 | plt.yscale('log') 62 | 63 | plt.subplot(312) 64 | plt.xlabel('Time') 65 | plt.ylabel('Ratio') 66 | plt.grid(True) 67 | plt.plot(x, [1] * len(x), color='red') 68 | plt.plot(x, mmr_list) 69 | plt.plot(x, mmr_mean_list) 70 | plt.plot(x, [2.4] * len(x)) 71 | plt.legend(['SMA 200', 'MMR', 'MEAN MMR', 'THRESHOLD 2.4'], loc='upper left') 72 | plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d')) 73 | plt.gca().xaxis.set_major_locator(mdates.YearLocator()) 74 | plt.gcf().autofmt_xdate() 75 | # plt.xlim(left=left, right=right) 76 | plt.yscale('log') 77 | 78 | plt.subplot(313) 79 | plt.xlabel('Time') 80 | plt.ylabel('Ratio') 81 | plt.grid(True) 82 | plt.plot(x, [0] * len(x), color='blue') 83 | plt.plot(x, mom_list) 84 | plt.plot(x, mom_mean_list) 85 | plt.legend(['Price', 'MOM 365', 'MEAN MOM 365'], loc='upper left') 86 | plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d')) 87 | plt.gca().xaxis.set_major_locator(mdates.YearLocator()) 88 | plt.gcf().autofmt_xdate() 89 | # plt.xlim(left=left, right=right) 90 | plt.yscale('symlog') 91 | 92 | plt.show() 93 | 94 | 95 | if __name__ == '__main__': 96 | main() 97 | 98 | -------------------------------------------------------------------------------- /example/example-7-quandl-2-df.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "example-7-quandl-2-df.ipynb", 7 | "version": "0.3.2", 8 | "provenance": [], 9 | "collapsed_sections": [] 10 | }, 11 | "kernelspec": { 12 | "name": "python3", 13 | "display_name": "Python 3" 14 | } 15 | }, 16 | "cells": [ 17 | { 18 | "metadata": { 19 | "id": "uCrOUsHiEkUV", 20 | "colab_type": "code", 21 | "colab": {} 22 | }, 23 | "cell_type": "code", 24 | "source": [ 25 | "import requests\n", 26 | "from datetime import datetime as dt\n", 27 | "from pprint import pprint as pp\n", 28 | "\n", 29 | "\n", 30 | "def request_quandl(endpoint, **kwargs):\n", 31 | " params = {'order': 'asc', 'returns': 'numpy', 'authtoken': 'YOUR_AUTH_TOKEN'}\n", 32 | " params.update(kwargs)\n", 33 | " r = requests.get('https://www.quandl.com/api/v3/datasets/%s/data.json' % endpoint, params=params).json()\n", 34 | " df = {'datetime': [], 'Open': [], 'High': [], 'Low': [], 'Close': [], 'Volume': []}\n", 35 | " i = 0\n", 36 | " while i < len(r['dataset_data']['data']):\n", 37 | "# df['datetime'].append(i)\n", 38 | "# df['datetime'].append(r['dataset_data']['data'][i][0])\n", 39 | " df['datetime'].append(dt.strptime(r['dataset_data']['data'][i][0], '%Y-%m-%d'))\n", 40 | " df['Open'].append(float(r['dataset_data']['data'][i][1]))\n", 41 | " df['High'].append(float(r['dataset_data']['data'][i][2]))\n", 42 | " df['Low'].append(float(r['dataset_data']['data'][i][3]))\n", 43 | " df['Close'].append(float(r['dataset_data']['data'][i][4]))\n", 44 | " df['Volume'].append(int(r['dataset_data']['data'][i][5]))\n", 45 | " i += 1\n", 46 | " return df\n", 47 | "\n", 48 | "\n", 49 | "df = request_quandl('BCHARTS/BITSTAMPUSD', collapse='daily')\n", 50 | "print (len(df['Close']))\n", 51 | "pp (df)\n" 52 | ], 53 | "execution_count": 0, 54 | "outputs": [] 55 | } 56 | ] 57 | } -------------------------------------------------------------------------------- /example/example-7-quandl-2-df.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | import requests 5 | from datetime import datetime as dt 6 | from pprint import pprint as pp 7 | 8 | 9 | def request_quandl(endpoint, **kwargs): 10 | params = { 11 | 'order': 'asc', 12 | 'returns': 'numpy', 13 | 'authtoken': 'YOUR_AUTH_TOKEN' 14 | } 15 | params.update(kwargs) 16 | r = requests.get('https://www.quandl.com/api/v3/datasets/%s/data.json' % endpoint, params=params).json() 17 | df = {'datetime': [], 'Open': [], 'High': [], 'Low': [], 'Close': [], 'Volume': []} 18 | i = 0 19 | while i < len(r['dataset_data']['data']): 20 | # df['datetime'].append(i) 21 | # df['datetime'].append(r['dataset_data']['data'][i][0]) 22 | df['datetime'].append(dt.strptime(r['dataset_data']['data'][i][0], '%Y-%m-%d')) 23 | df['Open'].append(float(r['dataset_data']['data'][i][1])) 24 | df['High'].append(float(r['dataset_data']['data'][i][2])) 25 | df['Low'].append(float(r['dataset_data']['data'][i][3])) 26 | df['Close'].append(float(r['dataset_data']['data'][i][4])) 27 | df['Volume'].append(int(r['dataset_data']['data'][i][5])) 28 | i += 1 29 | return df 30 | 31 | def main(): 32 | df = request_quandl('BCHARTS/BITSTAMPUSD', collapse='daily') 33 | print (len(df['Close'])) 34 | pp (df) 35 | 36 | 37 | if __name__ == '__main__': 38 | main() 39 | 40 | -------------------------------------------------------------------------------- /example/example-8-alphavantage-2-df.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "example-8-alphavantage-2-df.ipynb", 7 | "version": "0.3.2", 8 | "provenance": [] 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "metadata": { 18 | "id": "1Wx0bsmeHV6h", 19 | "colab_type": "code", 20 | "colab": {} 21 | }, 22 | "cell_type": "code", 23 | "source": [ 24 | "import requests\n", 25 | "from datetime import datetime as dt\n", 26 | "from pprint import pprint as pp\n", 27 | "\n", 28 | "\n", 29 | "def request_alphavantage(**kwargs):\n", 30 | " params = {'apikey': 'YOUR_API_KEY'}\n", 31 | " params.update(kwargs)\n", 32 | " return requests.get('https://www.alphavantage.co/query', params=params).json()\n", 33 | "\n", 34 | "\n", 35 | "def data2df_cur(data):\n", 36 | " '''\n", 37 | " currency data\n", 38 | " '''\n", 39 | " df = {'datetime': [], 'Open': [], 'High': [], 'Low': [], 'Close': [], 'Volume': []}\n", 40 | " for k, v in data.items():\n", 41 | "# df['datetime'].append(k)\n", 42 | " df['datetime'].append(dt.strptime(k, '%Y-%m-%d'))\n", 43 | " df['Open'].append(float(v['1b. open (USD)']))\n", 44 | " df['High'].append(float(v['2b. high (USD)']))\n", 45 | " df['Low'].append(float(v['3b. low (USD)']))\n", 46 | " df['Close'].append(float(v['4b. close (USD)']))\n", 47 | " df['Volume'].append(v['5. volume'])\n", 48 | " return df\n", 49 | "\n", 50 | "\n", 51 | "def data2df_stk(data):\n", 52 | " '''\n", 53 | " stock data\n", 54 | " '''\n", 55 | " df = {'datetime': [], 'Open': [], 'High': [], 'Low': [], 'Close': [], 'Volume': []}\n", 56 | " for k, v in data.items():\n", 57 | "# df['datetime'].append(k)\n", 58 | " df['datetime'].append(dt.strptime(k, '%Y-%m-%d'))\n", 59 | " df['Open'].append(float(v['1. open']))\n", 60 | " df['High'].append(float(v['2. high']))\n", 61 | " df['Low'].append(float(v['3. low']))\n", 62 | " df['Close'].append(float(v['4. close']))\n", 63 | " df['Volume'].append(v['5. volume'])\n", 64 | " return df\n", 65 | "\n", 66 | "\n", 67 | "def df2df_reversed(df):\n", 68 | " df_r = {'datetime': [], 'Open': [], 'High': [], 'Low': [], 'Close': [], 'Volume': []}\n", 69 | " i = len(df['Close'])-1\n", 70 | " while i > -1:\n", 71 | " df_r['datetime'].append(df['datetime'][i])\n", 72 | " df_r['Open'].append(df['Open'][i])\n", 73 | " df_r['High'].append(df['High'][i])\n", 74 | " df_r['Low'].append(df['Low'][i])\n", 75 | " df_r['Close'].append(df['Close'][i])\n", 76 | " df_r['Volume'].append(df['Volume'][i])\n", 77 | " i -= 1\n", 78 | " return df_r\n", 79 | "\n", 80 | "\n", 81 | "# search for symbol:\n", 82 | "#r = request_alphavantage(function='SYMBOL_SEARCH', keywords='bitcoin')\n", 83 | "#pp (r)\n", 84 | "\n", 85 | "# get symbol currency data:\n", 86 | "r = request_alphavantage(function='DIGITAL_CURRENCY_DAILY', symbol='BTC', market='EUR')\n", 87 | "#pp (r)\n", 88 | " \n", 89 | "data = r['Time Series (Digital Currency Daily)']\n", 90 | "print (len(data))\n", 91 | "\n", 92 | "df = data2df_cur(data)\n", 93 | "print (len(df['Close']))\n", 94 | "df_r = df2df_reversed(df)\n", 95 | "print (len(df_r['Close']))\n", 96 | "\n", 97 | "#pp (df['datetime']) # normal order.\n", 98 | "pp (df_r['datetime']) # reversed order.\n", 99 | "\n", 100 | "\n", 101 | "# get symbol stock data:\n", 102 | "#r = request_alphavantage(function='TIME_SERIES_DAILY', symbol='GBTC', outputsize='full')\n", 103 | "#pp (r)\n", 104 | "\n", 105 | "#data = r['Time Series (Daily)']\n", 106 | "#print (len(data))\n", 107 | "\n", 108 | "#df = data2df_stk(data)\n", 109 | "#print (len(df['Close']))\n", 110 | "#df_r = df2df_reversed(df)\n", 111 | "#print (len(df_r['Close']))\n", 112 | "\n", 113 | "#pp (df['datetime']) # normal order.\n", 114 | "#pp (df_r['datetime']) # reversed order.\n" 115 | ], 116 | "execution_count": 0, 117 | "outputs": [] 118 | } 119 | ] 120 | } -------------------------------------------------------------------------------- /example/example-8-alphavantage-2-df.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | import requests 5 | from datetime import datetime as dt 6 | from pprint import pprint as pp 7 | 8 | 9 | def request_alphavantage(**kwargs): 10 | params = {'apikey': 'YOUR_API_KEY'} 11 | params.update(kwargs) 12 | return requests.get('https://www.alphavantage.co/query', params=params).json() 13 | 14 | 15 | def data2df_cur(data): 16 | ''' 17 | currency data 18 | ''' 19 | df = {'datetime': [], 'Open': [], 'High': [], 'Low': [], 'Close': [], 'Volume': []} 20 | for k, v in data.items(): 21 | # df['datetime'].append(k) 22 | df['datetime'].append(dt.strptime(k, '%Y-%m-%d')) 23 | df['Open'].append(float(v['1b. open (USD)'])) 24 | df['High'].append(float(v['2b. high (USD)'])) 25 | df['Low'].append(float(v['3b. low (USD)'])) 26 | df['Close'].append(float(v['4b. close (USD)'])) 27 | df['Volume'].append(v['5. volume']) 28 | return df 29 | 30 | 31 | def data2df_stk(data): 32 | ''' 33 | stock data 34 | ''' 35 | df = {'datetime': [], 'Open': [], 'High': [], 'Low': [], 'Close': [], 'Volume': []} 36 | for k, v in data.items(): 37 | # df['datetime'].append(k) 38 | df['datetime'].append(dt.strptime(k, '%Y-%m-%d')) 39 | df['Open'].append(float(v['1. open'])) 40 | df['High'].append(float(v['2. high'])) 41 | df['Low'].append(float(v['3. low'])) 42 | df['Close'].append(float(v['4. close'])) 43 | df['Volume'].append(v['5. volume']) 44 | return df 45 | 46 | 47 | def df2df_reversed(df): 48 | df_r = {'datetime': [], 'Open': [], 'High': [], 'Low': [], 'Close': [], 'Volume': []} 49 | i = len(df['Close'])-1 50 | while i > -1: 51 | df_r['datetime'].append(df['datetime'][i]) 52 | df_r['Open'].append(df['Open'][i]) 53 | df_r['High'].append(df['High'][i]) 54 | df_r['Low'].append(df['Low'][i]) 55 | df_r['Close'].append(df['Close'][i]) 56 | df_r['Volume'].append(df['Volume'][i]) 57 | i -= 1 58 | return df_r 59 | 60 | 61 | def main(): 62 | # search for symbol: 63 | # r = request_alphavantage(function='SYMBOL_SEARCH', keywords='bitcoin') 64 | # pp (r) 65 | 66 | # get symbol currency data: 67 | r = request_alphavantage(function='DIGITAL_CURRENCY_DAILY', symbol='BTC', market='EUR') 68 | # pp (r) 69 | 70 | data = r['Time Series (Digital Currency Daily)'] 71 | print (len(data)) 72 | 73 | df = data2df_cur(data) 74 | print (len(df['Close'])) 75 | df_r = df2df_reversed(df) 76 | print (len(df_r['Close'])) 77 | 78 | # pp (df['datetime']) # normal order. 79 | pp (df_r['datetime']) # reversed order. 80 | 81 | 82 | # get symbol stock data: 83 | # r = request_alphavantage(function='TIME_SERIES_DAILY', symbol='GBTC', outputsize='full') 84 | # pp (r) 85 | 86 | # data = r['Time Series (Daily)'] 87 | # print (len(data)) 88 | 89 | # df = data2df_stk(data) 90 | # print (len(df['Close'])) 91 | # df_r = df2df_reversed(df) 92 | # print (len(df_r['Close'])) 93 | 94 | # pp (df['datetime']) # normal order. 95 | # pp (df_r['datetime']) # reversed order. 96 | 97 | 98 | if __name__ == '__main__': 99 | main() 100 | 101 | -------------------------------------------------------------------------------- /example/example-9-cryptocompare-2-df.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "example-9-cryptocompare-2-df.ipynb", 7 | "version": "0.3.2", 8 | "provenance": [], 9 | "collapsed_sections": [] 10 | }, 11 | "kernelspec": { 12 | "name": "python3", 13 | "display_name": "Python 3" 14 | } 15 | }, 16 | "cells": [ 17 | { 18 | "metadata": { 19 | "id": "rgArDkTD3vA9", 20 | "colab_type": "code", 21 | "colab": {} 22 | }, 23 | "cell_type": "code", 24 | "source": [ 25 | "import requests\n", 26 | "from datetime import datetime as dt\n", 27 | "from pprint import pprint as pp\n", 28 | "\n", 29 | "\n", 30 | "url = 'https://min-api.cryptocompare.com/data/histoday?fsym=ETH&tsym=BTC&allData=true'\n", 31 | "headers = {'authorization': 'Apikey YOUR_API_KEY'}\n", 32 | "r = requests.get(url, headers=headers).json()\n", 33 | "#print (len(r['Data']))\n", 34 | "#pp (r)\n", 35 | "\n", 36 | "df = {'datetime': [], 'Open': [], 'High': [], 'Low': [], 'Close': [], 'Volume': []}\n", 37 | "i = 0\n", 38 | "while i < len(r['Data']):\n", 39 | "# df['datetime'].append(r['Data'][i]['time'])\n", 40 | " df['datetime'].append(dt.fromtimestamp(r['Data'][i]['time']))\n", 41 | " df['Open'].append(float(r['Data'][i]['open']))\n", 42 | " df['High'].append(float(r['Data'][i]['high']))\n", 43 | " df['Low'].append(float(r['Data'][i]['low']))\n", 44 | " df['Close'].append(float(r['Data'][i]['close']))\n", 45 | " df['Volume'].append(int(r['Data'][i]['volumefrom']))\n", 46 | " i += 1\n", 47 | "\n", 48 | "print (len(df['Close']))\n", 49 | "pp (df)\n" 50 | ], 51 | "execution_count": 0, 52 | "outputs": [] 53 | } 54 | ] 55 | } -------------------------------------------------------------------------------- /example/example-9-cryptocompare-2-df.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | import requests 5 | from datetime import datetime as dt 6 | from pprint import pprint as pp 7 | 8 | 9 | def main(): 10 | url = 'https://min-api.cryptocompare.com/data/histoday?fsym=ETH&tsym=BTC&allData=true' 11 | headers = {'authorization': 'Apikey YOUR_API_KEY'} 12 | r = requests.get(url, headers=headers).json() 13 | # print (len(r['Data'])) 14 | # pp (r) 15 | 16 | df = {'datetime': [], 'Open': [], 'High': [], 'Low': [], 'Close': [], 'Volume': []} 17 | i = 0 18 | while i < len(r['Data']): 19 | # df['datetime'].append(r['Data'][i]['time']) 20 | df['datetime'].append(dt.fromtimestamp(r['Data'][i]['time'])) 21 | df['Open'].append(float(r['Data'][i]['open'])) 22 | df['High'].append(float(r['Data'][i]['high'])) 23 | df['Low'].append(float(r['Data'][i]['low'])) 24 | df['Close'].append(float(r['Data'][i]['close'])) 25 | df['Volume'].append(int(r['Data'][i]['volumefrom'])) 26 | i += 1 27 | 28 | print (len(df['Close'])) 29 | pp (df) 30 | 31 | if __name__ == '__main__': 32 | main() 33 | 34 | -------------------------------------------------------------------------------- /jhtalib/__init__.py: -------------------------------------------------------------------------------- 1 | """""" 2 | 3 | 4 | # Set Global Attributes: 5 | __name__ = 'jhTAlib' 6 | __version__ = '20240902.0' 7 | __description__ = 'Technical Analysis Library Time-Series' 8 | __url__ = 'https://github.com/joosthoeks/jhTAlib' 9 | __author__ = 'Joost Hoeks' 10 | __author_email__ = 'joosthoeks@gmail.com' 11 | 12 | 13 | # Import Built-Ins: 14 | 15 | # Import Third-Party: 16 | 17 | # Import Homebrew: 18 | from .decorators import * 19 | from .helpers import * 20 | 21 | 22 | from .behavioral_techniques import * 23 | from .candlestick import * 24 | from .cycle_indicators import * 25 | from .data import * 26 | from .derivatives import * 27 | from .event_driven import * 28 | from .experimental import * 29 | from .general import * 30 | from .information import * 31 | from .math_functions import * 32 | from .momentum_indicators import * 33 | from .money_management import * 34 | from .overlap_studies import * 35 | from .pattern_recognition import * 36 | from .price_transform import * 37 | from .statistic_functions import * 38 | from .uncategorised import * 39 | from .volatility_indicators import * 40 | from .volume_indicators import * 41 | 42 | 43 | from .example import * 44 | 45 | -------------------------------------------------------------------------------- /jhtalib/behavioral_techniques/__init__.py: -------------------------------------------------------------------------------- 1 | from .behavioral_techniques import * 2 | 3 | -------------------------------------------------------------------------------- /jhtalib/behavioral_techniques/behavioral_techniques.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | import math 4 | 5 | # Import Third-Party: 6 | 7 | # Import Homebrew: 8 | import jhtalib as jhta 9 | 10 | 11 | def ATH(df, price='High'): 12 | """ 13 | All Time High 14 | Returns: dict of lists of floats = jhta.ATH(df, price='High') 15 | """ 16 | ath_dict = {'ath': [], 'ath_index': []} 17 | for i in range(len(df[price])): 18 | df_part_list = df[price][0:i+1] 19 | ath = max(df_part_list) 20 | ath_dict['ath'].append(ath) 21 | ath_index = df_part_list.index(max(df_part_list)) 22 | ath_dict['ath_index'].append(ath_index) 23 | return ath_dict 24 | 25 | def ATL(df, price='Low'): 26 | """ 27 | All Time Low 28 | Returns: dict of lists of floats = jhta.ATL(df, price='Low') 29 | """ 30 | atl_dict = {'atl': [], 'atl_index': []} 31 | for i in range(len(df[price])): 32 | df_part_list = df[price][0:i+1] 33 | atl = min(df_part_list) 34 | atl_dict['atl'].append(atl) 35 | atl_index = df_part_list.index(min(df_part_list)) 36 | atl_dict['atl_index'].append(atl_index) 37 | return atl_dict 38 | 39 | def DDSATH(df, price='High'): 40 | """ 41 | DrawDown Since All Time High 42 | Returns: list of floats = jhta.DDSATH(df, price='High') 43 | """ 44 | ddsath_list = [] 45 | ath_list = jhta.ATH(df, price) 46 | for i in range(len(df[price])): 47 | ddsath = (ath_list['ath'][i] - df[price][i]) * -1 48 | ddsath_list.append(ddsath) 49 | return ddsath_list 50 | 51 | def EARTHC(df): 52 | """ 53 | Earth Cycle 54 | """ 55 | 56 | def FIBOPR(df, price='Close'): 57 | """ 58 | Fibonacci Price Retracements 59 | Returns: dict of lists of floats = jhta.FIBOPR(df, price='Close') 60 | Source: https://github.com/joosthoeks/jhTAlib/issues/15 61 | """ 62 | fibopr_dict = { 63 | '100': [], '61.8': [], '50.0': [], '38.1': [], '0': [], 64 | '-38.1': [], '-50.0': [], '-61.8': [], '-100': [] 65 | } 66 | p0618 = jhta.PHI() - 1 67 | p05 = .5 68 | p0381 = 1 - p0618 69 | ath = jhta.ATH(df, price)['ath'] 70 | atl = jhta.ATL(df, price)['atl'] 71 | for i in range(len(df[price])): 72 | diff = ath[i] - atl[i] 73 | fibopr_dict['100'].append(ath[i] + diff) 74 | fibopr_dict['61.8'].append(ath[i] + diff * p0618) 75 | fibopr_dict['50.0'].append(ath[i] + diff * p05) 76 | fibopr_dict['38.1'].append(ath[i] + diff * p0381) 77 | fibopr_dict['0'].append(ath[i]) 78 | fibopr_dict['-38.1'].append(ath[i] - diff * p0381) 79 | fibopr_dict['-50.0'].append(ath[i] - diff * p05) 80 | fibopr_dict['-61.8'].append(ath[i] - diff * p0618) 81 | fibopr_dict['-100'].append(ath[i] - diff) 82 | return fibopr_dict 83 | 84 | def FIBOTR(df, price='Close'): 85 | """ 86 | Fibonacci Time Retracements 87 | """ 88 | 89 | def GANNPR(df, price='Close'): 90 | """ 91 | W. D. Gann Price Retracements 92 | Returns: dict of lists of floats = jhta.GANNPR(df, price='Close') 93 | """ 94 | gannpr_dict = { 95 | '87.5': [], '75.0': [], '62.5': [], '50.0': [], 96 | '37.5': [], '25.0': [], '12.5': [], '0': [], 97 | '-12.5': [], '-25.0': [], '-37.5': [], '-50.0': [], 98 | '-62.5': [], '-75.0': [], '-87.5': [] 99 | } 100 | ath = jhta.ATH(df, price)['ath'] 101 | atl = jhta.ATL(df, price)['atl'] 102 | for i in range(len(df[price])): 103 | diff = ath[i] - atl[i] 104 | gannpr_dict['87.5'].append(ath[i] + diff * .875) 105 | gannpr_dict['75.0'].append(ath[i] + diff * .75) 106 | gannpr_dict['62.5'].append(ath[i] + diff * .625) 107 | gannpr_dict['50.0'].append(ath[i] + diff * .5) 108 | gannpr_dict['37.5'].append(ath[i] + diff * .375) 109 | gannpr_dict['25.0'].append(ath[i] + diff * .25) 110 | gannpr_dict['12.5'].append(ath[i] + diff * .125) 111 | gannpr_dict['0'].append(ath[i]) 112 | gannpr_dict['-12.5'].append(ath[i] - diff * .125) 113 | gannpr_dict['-25.0'].append(ath[i] - diff * .25) 114 | gannpr_dict['-37.5'].append(ath[i] - diff * .375) 115 | gannpr_dict['-50.0'].append(ath[i] - diff * .5) 116 | gannpr_dict['-62.5'].append(ath[i] - diff * .625) 117 | gannpr_dict['-75.0'].append(ath[i] - diff * .75) 118 | gannpr_dict['-87.5'].append(ath[i] - diff * .875) 119 | return gannpr_dict 120 | 121 | def GANNTR(df, price='Close'): 122 | """ 123 | W. D. Gann Time Retracements 124 | """ 125 | 126 | def GSLMC(df, price='Low', price_high='High'): 127 | """ 128 | Gain Since Last Major Correction 129 | Returns: list of floats = jhta.GSLMC(df, price='Low', price_high='High') 130 | """ 131 | gslmc_list = [] 132 | lmc_list = jhta.LMC(df, price, price_high) 133 | for i in range(len(df[price])): 134 | gslmc = df[price][i] - lmc_list['lmc'][i] 135 | gslmc_list.append(gslmc) 136 | return gslmc_list 137 | 138 | def JD(utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_second): 139 | """ 140 | Julian Date 141 | Returns: jd = jhta.JD(utc_year, utc_month, utc_day, utc_hour, utc_minute, utc_second) 142 | Source: https://en.wikipedia.org/wiki/Julian_day 143 | """ 144 | hour = int(utc_hour) 145 | minute = int(utc_minute) 146 | second = int(utc_second) 147 | 148 | jdn = JDN(utc_year, utc_month, utc_day) 149 | 150 | return jdn + ((hour-12)/24) + (minute/1440) + (second/86400) 151 | 152 | def JDN(utc_year, utc_month, utc_day): 153 | """ 154 | Julian Day Number 155 | Returns: jdn = jhta.JDN(utc_year, utc_month, utc_day) 156 | Source: https://en.wikipedia.org/wiki/Julian_day 157 | """ 158 | year = int(utc_year) 159 | month = int(utc_month) 160 | day = int(utc_day) 161 | 162 | a = math.floor((14-month)/12) 163 | y = year + 4800 - a 164 | m = month + (12*a) - 3 165 | 166 | return day + math.floor(((153*m)+2)/5) + (365*y) + math.floor(y/4) - math.floor(y/100) + math.floor(y/400) - 32045 167 | 168 | def JUPITERC(df): 169 | """ 170 | Jupiter Cycle 171 | """ 172 | 173 | def LMC(df, price='Low', price_high='High'): 174 | """ 175 | Last Major Correction 176 | Returns: dict of lists of floats = jhta.LMC(df, price='Low', price_high='High') 177 | """ 178 | lmc_dict = {'lmc': [], 'lmc_index': []} 179 | ath_dict = jhta.ATH(df, price_high) 180 | for i in range(len(df[price])): 181 | df_part_list = df[price][ath_dict['ath_index'][i]:i+1] 182 | lmc = min(df_part_list) 183 | lmc_dict['lmc'].append(lmc) 184 | # lmc_index = df_part_list.index(min(df_part_list)) 185 | lmc_index = len(df_part_list) - 1 - df_part_list[::-1].index(min(df_part_list)) 186 | lmc_dict['lmc_index'].append(lmc_index) 187 | return lmc_dict 188 | 189 | def MARSC(df): 190 | """ 191 | Mars Cycle 192 | """ 193 | 194 | def MERCURYC(df): 195 | """ 196 | Mercury Cycle 197 | """ 198 | 199 | def MOONC(df): 200 | """ 201 | Moon Cycle 202 | """ 203 | 204 | def NEPTUNEC(df): 205 | """ 206 | Neptune Cycle 207 | """ 208 | 209 | def PDDSATH(df, price='High'): 210 | """ 211 | %DrawDown Since All Time High 212 | Returns: list of floats = jhta.PDDSATH(df, price='High') 213 | """ 214 | pddsath_list = [] 215 | ath_list = jhta.ATH(df, price) 216 | ddsath_list = jhta.DDSATH(df, price) 217 | for i in range(len(df[price])): 218 | pddsath = ddsath_list[i] / ath_list['ath'][i] 219 | pddsath_list.append(pddsath) 220 | return pddsath_list 221 | 222 | def PGSLMC(df, price='Low', price_high='High'): 223 | """ 224 | %Gain Since Last Major Correction 225 | Returns: list of floats = jhta.PGSLMC(df, price='Low', price_high='High') 226 | """ 227 | pgslmc_list = [] 228 | lmc_list = jhta.LMC(df, price, price_high) 229 | gslmc_list = jhta.GSLMC(df, price, price_high) 230 | for i in range(len(df[price])): 231 | pgslmc = gslmc_list[i] / lmc_list['lmc'][i] 232 | pgslmc_list.append(pgslmc) 233 | return pgslmc_list 234 | 235 | def PLUTOC(df): 236 | """ 237 | Pluto Cycle 238 | """ 239 | 240 | def PP(df, high='High', low='Low', close='Close'): 241 | """ 242 | Pivot Point 243 | Returns: dict of lists of floats = jhta.PP(df, high='High', low='Low', close='Close') 244 | Source: https://en.wikipedia.org/wiki/Pivot_point_(technical_analysis) 245 | """ 246 | pp_dict = {'p': [], 'r1': [], 's1': [], 'r2': [], 's2': [], 'r3': [], 's3': []} 247 | for i in range(len(df[close])): 248 | if i < 1: 249 | p = float('NaN') 250 | r1 = float('NaN') 251 | s1 = float('NaN') 252 | r2 = float('NaN') 253 | s2 = float('NaN') 254 | r3 = float('NaN') 255 | s3 = float('NaN') 256 | else: 257 | p = (df[high][i - 1] + df[low][i - 1] + df[close][i - 1]) / 3 258 | r1 = p + (p - df[low][i - 1]) 259 | s1 = p - (df[high][i - 1] - p) 260 | r2 = p + (df[high][i - 1] - df[low][i - 1]) 261 | s2 = p - (df[high][i - 1] - df[low][i - 1]) 262 | r3 = r1 + (df[high][i - 1] - df[low][i - 1]) 263 | s3 = s1 - (df[high][i - 1] - df[low][i - 1]) 264 | pp_dict['p'].append(p) 265 | pp_dict['r1'].append(r1) 266 | pp_dict['s1'].append(s1) 267 | pp_dict['r2'].append(r2) 268 | pp_dict['s2'].append(s2) 269 | pp_dict['r3'].append(r3) 270 | pp_dict['s3'].append(s3) 271 | return pp_dict 272 | 273 | def PP_CAMARILLA(df, high='High', low='Low', close='Close'): 274 | """ 275 | Camarilla Pivot Points 276 | Returns: dict of lists of floats = jhta.PP_CAMARILLA(df, high='High', low='Low', close='Close') 277 | Source: https://gannsecret.blogspot.com/p/pivot-point-definition.html 278 | """ 279 | pp_dict = {'p': [], 'r1': [], 's1': [], 'r2': [], 's2': [], 'r3': [], 's3': [], 'r4': [], 's4': []} 280 | for i in range(len(df[close])): 281 | if i < 1: 282 | p = float('NaN') 283 | r1 = float('NaN') 284 | s1 = float('NaN') 285 | r2 = float('NaN') 286 | s2 = float('NaN') 287 | r3 = float('NaN') 288 | s3 = float('NaN') 289 | r4 = float('NaN') 290 | s4 = float('NaN') 291 | else: 292 | h = df[high][i - 1] 293 | l = df[low][i - 1] 294 | c = df[close][i - 1] 295 | p = (h + l + c) / 3 296 | r1 = c + (h - l) * 1.1 / 12 297 | s1 = c - (h - l) * 1.1 / 12 298 | r2 = c + (h - l) * 1.1 / 6 299 | s2 = c - (h - l) * 1.1 / 6 300 | r3 = c + (h - l) * 1.1 / 4 301 | s3 = c - (h - l) * 1.1 / 4 302 | r4 = c + (h - l) * 1.1 / 2 303 | s4 = c - (h - l) * 1.1 / 2 304 | pp_dict['p'].append(p) 305 | pp_dict['r1'].append(r1) 306 | pp_dict['s1'].append(s1) 307 | pp_dict['r2'].append(r2) 308 | pp_dict['s2'].append(s2) 309 | pp_dict['r3'].append(r3) 310 | pp_dict['s3'].append(s3) 311 | pp_dict['r4'].append(r4) 312 | pp_dict['s4'].append(s4) 313 | return pp_dict 314 | 315 | def PP_DEMARK(df, open='Open', high='High', low='Low', close='Close'): 316 | """ 317 | Demark Pivot Points 318 | Returns: dict of lists of floats = jhta.PP_DEMARK(df, open='Open', high='High', low='Low', close='Close') 319 | Source: https://gannsecret.blogspot.com/p/pivot-point-definition.html 320 | """ 321 | pp_dict = {'r1': [], 's1': []} 322 | for i in range(len(df[close])): 323 | if i < 1: 324 | r1 = float('NaN') 325 | s1 = float('NaN') 326 | else: 327 | o = df[open][i - 1] 328 | h = df[high][i - 1] 329 | l = df[low][i - 1] 330 | c = df[close][i - 1] 331 | x = h + l + 2 * c 332 | if c < o: 333 | x = h + 2 * l + c 334 | if c > o: 335 | x = 2 * h + l + c 336 | r1 = x / 2 - l 337 | s1 = x / 2 - h 338 | pp_dict['r1'].append(r1) 339 | pp_dict['s1'].append(s1) 340 | return pp_dict 341 | 342 | def PP_FIBO(df, high='High', low='Low', close='Close'): 343 | """ 344 | Fibonacci's Pivot Points 345 | Returns: dict of lists of floats = jhta.PP_FIBO(df, high='High', low='Low', close='Close') 346 | Source: https://gannsecret.blogspot.com/p/pivot-point-definition.html 347 | """ 348 | pp_dict = {'p': [], 'r1': [], 's1': [], 'r2': [], 's2': [], 'r3': [], 's3': []} 349 | for i in range(len(df[close])): 350 | if i < 1: 351 | p = float('NaN') 352 | r1 = float('NaN') 353 | s1 = float('NaN') 354 | r2 = float('NaN') 355 | s2 = float('NaN') 356 | r3 = float('NaN') 357 | s3 = float('NaN') 358 | else: 359 | h = df[high][i - 1] 360 | l = df[low][i - 1] 361 | c = df[close][i - 1] 362 | p = (h + l + c) / 3 363 | r1 = p + .382 * (h - l) 364 | s1 = p - .382 * (h - l) 365 | r2 = p + .618 * (h - l) 366 | s2 = p - .618 * (h - l) 367 | r3 = p + 1 * (h - l) 368 | s3 = p - 1 * (h - l) 369 | pp_dict['p'].append(p) 370 | pp_dict['r1'].append(r1) 371 | pp_dict['s1'].append(s1) 372 | pp_dict['r2'].append(r2) 373 | pp_dict['s2'].append(s2) 374 | pp_dict['r3'].append(r3) 375 | pp_dict['s3'].append(s3) 376 | return pp_dict 377 | 378 | def SATURNC(df): 379 | """ 380 | Saturn Cycle 381 | """ 382 | 383 | def SUNC(df): 384 | """ 385 | Sun Cycle 386 | """ 387 | 388 | def URANUSC(df): 389 | """ 390 | Uranus Cycle 391 | """ 392 | 393 | def VENUSC(df): 394 | """ 395 | Venus Cycle 396 | """ 397 | 398 | -------------------------------------------------------------------------------- /jhtalib/candlestick/__init__.py: -------------------------------------------------------------------------------- 1 | from .candlestick import * 2 | 3 | -------------------------------------------------------------------------------- /jhtalib/candlestick/candlestick.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | 4 | # Import Third-Party: 5 | 6 | # Import Homebrew: 7 | import jhtalib as jhta 8 | 9 | 10 | def CDLBODYM(df, n, open='Open', close='Close'): 11 | """ 12 | Candle Body Momentum 13 | Returns: list of floats = jhta.CDLBODYM(df, n, open='Open', close='Close') 14 | Source: book: Trading Systems and Methods 15 | """ 16 | cdl_list = [] 17 | for i in range(len(df[close])): 18 | if i + 1 < n: 19 | cdl = float('NaN') 20 | else: 21 | start = i + 1 - n 22 | end = i + 1 23 | cdlbodys = jhta.CDLBODYS(df, open, close)[start:end] 24 | upsum = 0 25 | downsum = 0 26 | for i2 in range(len(cdlbodys)): 27 | if cdlbodys[i2] > 0: 28 | upsum = upsum + 1 29 | else: 30 | downsum = downsum + 1 31 | cdl = upsum / (upsum + downsum) 32 | cdl_list.append(cdl) 33 | return cdl_list 34 | 35 | def CDLBODYP(df, open='Open', close='Close'): 36 | """ 37 | Candle Body Percent 38 | Returns: list of floats = jhta.CDLBODYP(df, open='Open', close='Close') 39 | """ 40 | return [(df[close][i] - df[open][i]) / df[open][i] for i in range(len(df[close]))] 41 | 42 | def CDLBODYS(df, open='Open', close='Close'): 43 | """ 44 | Candle Body Size 45 | Returns: list of floats = jhta.CDLBODYS(df, open='Open', close='Close') 46 | Source: https://www.tradeciety.com/understand-candlesticks-patterns/ 47 | """ 48 | return [df[close][i] - df[open][i] for i in range(len(df[close]))] 49 | 50 | def CDLLOWSHAS(df, open='Open', low='Low', close='Close'): 51 | """ 52 | Candle Lower Shadow Size 53 | Returns: list of floats = jhta.CDLLOWSHAS(df, open='Open', low='Low', close='Close') 54 | Source: https://www.tradeciety.com/understand-candlesticks-patterns/ 55 | """ 56 | cdl_list = [] 57 | for i in range(len(df[close])): 58 | body = df[close][i] - df[open][i] 59 | if body < 0: 60 | cdl = df[close][i] - df[low][i] 61 | else: 62 | cdl = df[open][i] - df[low][i] 63 | cdl_list.append(cdl) 64 | return cdl_list 65 | 66 | def CDLUPPSHAS(df, open='Open', high='High', close='Close'): 67 | """ 68 | Candle Upper Shadow Size 69 | Returns: list of floats = jhta.CDLUPPSHAS(df, open='Open', high='High', close='Close') 70 | Source: https://www.tradeciety.com/understand-candlesticks-patterns/ 71 | """ 72 | cdl_list = [] 73 | for i in range(len(df[close])): 74 | body = df[close][i] - df[open][i] 75 | if body < 0: 76 | cdl = df[high][i] - df[open][i] 77 | else: 78 | cdl = df[high][i] - df[close][i] 79 | cdl_list.append(cdl) 80 | return cdl_list 81 | 82 | def CDLWICKS(df, high='High', low='Low'): 83 | """ 84 | Candle Wick Size 85 | Returns: list of floats = jhta.CDLWICKS(df, high='High', low='Low') 86 | Source: https://www.tradeciety.com/understand-candlesticks-patterns/ 87 | """ 88 | return [df[high][i] - df[low][i] for i in range(len(df[low]))] 89 | 90 | def GAP(df, high='High', low='Low'): 91 | """ 92 | Gap 93 | Returns: list of floats = jhta.GAP(df, high='High', low='Low') 94 | """ 95 | gap_list = [] 96 | for i in range(len(df[low])): 97 | if i < 1: 98 | gap = float('NaN') 99 | else: 100 | gap = .0 101 | if df[low][i] > df[high][i - 1]: 102 | gap = df[low][i] - df[high][i - 1] 103 | if df[high][i] < df[low][i - 1]: 104 | gap = df[high][i] - df[low][i - 1] 105 | gap_list.append(gap) 106 | return gap_list 107 | 108 | def IMI(df, open='Open', close='Close'): 109 | """ 110 | Intraday Momentum Index 111 | Returns: list of floats = jhta.IMI(df, open='Open', close='Close') 112 | Source: https://www.fmlabs.com/reference/default.htm?url=IMI.htm 113 | """ 114 | imi_list = [] 115 | upsum = .0 116 | downsum = .0 117 | for i in range(len(df[close])): 118 | if df[close][i] > df[open][i]: 119 | upsum = upsum + (df[close][i] - df[open][i]) 120 | else: 121 | downsum = downsum + (df[open][i] - df[close][i]) 122 | imi = 100 * (upsum / (upsum + downsum)) 123 | imi_list.append(imi) 124 | return imi_list 125 | 126 | def INSBAR(df, high='High', low='Low'): 127 | """ 128 | Inside Bar 129 | Returns: list of ints = jhta.INSBAR(df, high='High', low='Low') 130 | """ 131 | insbar_list = [] 132 | for i in range(len(df[low])): 133 | if i < 1: 134 | insbar = float('NaN') 135 | else: 136 | insbar = 0 137 | if df[high][i] < df[high][i - 1] and df[low][i] > df[low][i - 1]: 138 | insbar = 1 139 | insbar_list.append(insbar) 140 | return insbar_list 141 | 142 | def OUTSBAR(df, high='High', low='Low'): 143 | """ 144 | Outside Bar 145 | Returns: list of ints = jhta.OUTSBAR(df, high='High', low='Low') 146 | """ 147 | outsbar_list = [] 148 | for i in range(len(df[low])): 149 | if i < 1: 150 | outsbar = float('NaN') 151 | else: 152 | outsbar = 0 153 | if df[high][i] > df[high][i - 1] and df[low][i] < df[low][i - 1]: 154 | outsbar = 1 155 | outsbar_list.append(outsbar) 156 | return outsbar_list 157 | 158 | def QSTICK(df, n, open='Open', close='Close'): 159 | """ 160 | Qstick 161 | Returns: list of floats = jhta.QSTICK(df, n, open='Open', close='Close') 162 | Source: https://www.fmlabs.com/reference/default.htm?url=Qstick.htm 163 | """ 164 | qstick_list = [] 165 | for i in range(len(df[close])): 166 | if i + 1 < n: 167 | qstick = float('NaN') 168 | else: 169 | start = i + 1 - n 170 | end = i + 1 171 | qstick = sum(jhta.CDLBODYS(df, open, close)[start:end]) / n 172 | qstick_list.append(qstick) 173 | return qstick_list 174 | 175 | def SHADOWT(df, n, open='Open', high='High', low='Low', close='Close'): 176 | """ 177 | Shadow Trends 178 | Returns: dict of lists of floats = jhta.SHADOWT(df, n, open='Open', high='High', low='Low', close='Close') 179 | Source: book: The New Technical Trader 180 | """ 181 | shadowt_dict = {'upper': [], 'lower': []} 182 | for i in range(len(df[close])): 183 | if i + 1 < n: 184 | upper = float('NaN') 185 | lower = float('NaN') 186 | else: 187 | start = i + 1 - n 188 | end = i + 1 189 | upper = sum(jhta.CDLUPPSHAS(df, open, high, close)[start:end]) / n 190 | lower = sum(jhta.CDLLOWSHAS(df, open, low, close)[start:end]) / n 191 | shadowt_dict['upper'].append(upper) 192 | shadowt_dict['lower'].append(lower) 193 | return shadowt_dict 194 | 195 | -------------------------------------------------------------------------------- /jhtalib/cycle_indicators/__init__.py: -------------------------------------------------------------------------------- 1 | from .cycle_indicators import * 2 | 3 | -------------------------------------------------------------------------------- /jhtalib/cycle_indicators/cycle_indicators.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | 4 | # Import Third-Party: 5 | 6 | # Import Homebrew: 7 | import jhtalib as jhta 8 | 9 | 10 | def HT_DCPERIOD(df, price='Close'): 11 | """ 12 | Hilbert Transform - Dominant Cycle Period 13 | """ 14 | 15 | def HT_DCPHASE(df, price='Close'): 16 | """ 17 | Hilbert Transform - Dominant Cycle Phase 18 | """ 19 | 20 | def HT_PHASOR(df, price='Close'): 21 | """ 22 | Hilbert Transform - Phasor Components 23 | """ 24 | 25 | def HT_SINE(df, price='Close'): 26 | """ 27 | Hilbert Transform - SineWave 28 | """ 29 | 30 | def HT_TRENDLINE(df, price='Close'): 31 | """ 32 | Hilbert Transform - Instantaneous Trendline 33 | """ 34 | 35 | def HT_TRENDMODE(df, price='Close'): 36 | """ 37 | Hilbert Transform - Trend vs Cycle Mode 38 | """ 39 | 40 | def TS(df, n, price='Close'): 41 | """ 42 | Trend Score 43 | Returns: list of floats = jhta.TS(df, n, price='Close') 44 | Source: https://www.fmlabs.com/reference/default.htm?url=TrendScore.htm 45 | """ 46 | t_list = [] 47 | for i in range(len(df[price])): 48 | if i < 1: 49 | t = 0 50 | else: 51 | if df[price][i] >= df[price][i - 1]: 52 | t = 1 53 | else: 54 | t = -1 55 | t_list.append(t) 56 | ts_list = [] 57 | for i in range(len(df[price])): 58 | if i + 1 < n: 59 | ts = float('NaN') 60 | else: 61 | start = i + 1 - n 62 | end = i + 1 63 | ts = sum(t_list[start:end]) 64 | ts_list.append(ts) 65 | return ts_list 66 | 67 | -------------------------------------------------------------------------------- /jhtalib/data/__init__.py: -------------------------------------------------------------------------------- 1 | from .data import * 2 | 3 | -------------------------------------------------------------------------------- /jhtalib/data/data.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | import csv 4 | import urllib.request 5 | 6 | # Import Third-Party: 7 | 8 | # Import Homebrew: 9 | import jhtalib as jhta 10 | 11 | 12 | def CSV2DF(csv_file_path, datetime='datetime', Open='Open', high='High', low='Low', close='Close', volume='Volume'): 13 | """ 14 | CSV file 2 DataFeed 15 | Returns: dict of tuples of floats = jhta.CSV2DF(csv_file_path, datetime='datetime', Open='Open', high='High', low='Low', close='Close', volume='Volume') 16 | """ 17 | df = {datetime: [], Open: [], high: [], low: [], close: [], volume: []} 18 | with open(csv_file_path) as csv_file: 19 | reader = csv.DictReader(csv_file) 20 | for row in reader: 21 | df[datetime].append(row[datetime]) 22 | df[Open].append(float(row[Open])) 23 | df[high].append(float(row[high])) 24 | df[low].append(float(row[low])) 25 | df[close].append(float(row[close])) 26 | df[volume].append(float(row[volume])) 27 | df[datetime] = tuple(df[datetime]) 28 | df[Open] = tuple(df[Open]) 29 | df[high] = tuple(df[high]) 30 | df[low] = tuple(df[low]) 31 | df[close] = tuple(df[close]) 32 | df[volume] = tuple(df[volume]) 33 | return dict(df) 34 | 35 | def CSVURL2DF(csv_file_url, datetime='datetime', open='Open', high='High', low='Low', close='Close', volume='Volume'): 36 | """ 37 | CSV file url 2 DataFeed 38 | Returns: dict of tuples of floats = jhta.CSVURL2DF(csv_file_url, datetime='datetime', open='Open', high='High', low='Low', close='Close', volume='Volume') 39 | """ 40 | df = {datetime: [], open: [], high: [], low: [], close: [], volume: []} 41 | csv_file = urllib.request.urlopen(csv_file_url).read().decode('utf-8').splitlines() 42 | reader = csv.DictReader(csv_file) 43 | for row in reader: 44 | df[datetime].append(row[datetime]) 45 | df[open].append(float(row[open])) 46 | df[high].append(float(row[high])) 47 | df[low].append(float(row[low])) 48 | df[close].append(float(row[close])) 49 | df[volume].append(float(row[volume])) 50 | df[datetime] = tuple(df[datetime]) 51 | df[open] = tuple(df[open]) 52 | df[high] = tuple(df[high]) 53 | df[low] = tuple(df[low]) 54 | df[close] = tuple(df[close]) 55 | df[volume] = tuple(df[volume]) 56 | return dict(df) 57 | 58 | def DF2CSV(df, csv_file_path, datetime='datetime', Open='Open', high='High', low='Low', close='Close', volume='Volume'): 59 | """ 60 | DataFeed 2 CSV file 61 | Returns: csv file = jhta.DF2CSV(df, csv_file_path, datetime='datetime', Open='Open', high='High', low='Low', close='Close', volume='Volume') 62 | """ 63 | with open(csv_file_path, 'w') as csv_file: 64 | fieldnames = [datetime, Open, high, low, close, volume] 65 | writer = csv.DictWriter(csv_file, fieldnames=fieldnames) 66 | writer.writeheader() 67 | for i in range(len(df[close])): 68 | writer.writerow({ 69 | datetime: df[datetime][i], 70 | Open: float(df[Open][i]), 71 | high: float(df[high][i]), 72 | low: float(df[low][i]), 73 | close: float(df[close][i]), 74 | volume: float(df[volume][i]) 75 | }) 76 | 77 | def DF2DFREV(df, datetime='datetime', open='Open', high='High', low='Low', close='Close', volume='Volume'): 78 | """ 79 | DataFeed 2 DataFeed Reversed 80 | Returns: dict of tuples of floats = jhta.DF2DFREV(df, datetime='datetime', open='Open', high='High', low='Low', close='Close', volume='Volume') 81 | """ 82 | df_r = {datetime: [], open: [], high: [], low: [], close: [], volume: []} 83 | i = len(df[close])-1 84 | while i > -1: 85 | df_r[datetime].append(df[datetime][i]) 86 | df_r[open].append(df[open][i]) 87 | df_r[high].append(df[high][i]) 88 | df_r[low].append(df[low][i]) 89 | df_r[close].append(df[close][i]) 90 | df_r[volume].append(df[volume][i]) 91 | i -= 1 92 | df_r[datetime] = tuple(df_r[datetime]) 93 | df_r[open] = tuple(df_r[open]) 94 | df_r[high] = tuple(df_r[high]) 95 | df_r[low] = tuple(df_r[low]) 96 | df_r[close] = tuple(df_r[close]) 97 | df_r[volume] = tuple(df_r[volume]) 98 | return dict(df_r) 99 | 100 | def DF2DFWIN(df, start=0, end=10, datetime='datetime', open='Open', high='High', low='Low', close='Close', volume='Volume'): 101 | """ 102 | DataFeed 2 DataFeed Window 103 | Returns: dict of tuples of floats = jhta.DF2DFWIN(df, start=0, end=10, datetime='datetime', open='Open', high='High', low='Low', close='Close', volume='Volume') 104 | """ 105 | return dict({ 106 | datetime: tuple(df[datetime][start:end]), 107 | open: tuple(df[open][start:end]), 108 | high: tuple(df[high][start:end]), 109 | low: tuple(df[low][start:end]), 110 | close: tuple(df[close][start:end]), 111 | volume: tuple(df[volume][start:end]) 112 | }) 113 | 114 | def DF2HEIKIN_ASHI(df, datetime='datetime', open='Open', high='High', low='Low', close='Close', volume='Volume'): 115 | """ 116 | DataFeed 2 Heikin-Ashi DataFeed 117 | Returns: dict of tuples of floats = jhta.DF2HEIKIN_ASHI(df, datetime='datetime', open='Open', high='High', low='Low', close='Close', volume='Volume') 118 | """ 119 | ha_Open_list = [] 120 | ha_High_list = [] 121 | ha_Low_list = [] 122 | ha_Close_list = [] 123 | for i in range(len(df[close])): 124 | if i == 0: 125 | ha_Open = (df[open][i] + df[close][i]) / 2 126 | ha_Close = (df[open][i] + df[high][i] + df[low][i] + df[close][i]) / 4 127 | ha_High = df[high][i] 128 | ha_Low = df[low][i] 129 | else: 130 | ha_Open = (ha_Open_list[i - 1] + ha_Close_list[i - 1]) / 2 131 | ha_Close = (df[open][i] + df[high][i] + df[low][i] + df[close][i]) / 4 132 | ha_High = max([df[high][i], ha_Open, ha_Close]) 133 | ha_Low = min([df[low][i], ha_Open, ha_Close]) 134 | ha_Open_list.append(float(ha_Open)) 135 | ha_High_list.append(float(ha_High)) 136 | ha_Low_list.append(float(ha_Low)) 137 | ha_Close_list.append(float(ha_Close)) 138 | return dict({ 139 | datetime: tuple(df[datetime]), 140 | open: tuple(ha_Open_list), 141 | high: tuple(ha_High_list), 142 | low: tuple(ha_Low_list), 143 | close: tuple(ha_Close_list), 144 | volume: tuple(df[volume]) 145 | }) 146 | 147 | def DF_HEAD(df, n=5, datetime='datetime', open='Open', high='High', low='Low', close='Close', volume='Volume'): 148 | """ 149 | DataFeed HEAD 150 | Returns: dict of tuples of floats = jhta.DF_HEAD(df, n=5, datetime='datetime', open='Open', high='High', low='Low', close='Close', volume='Volume') 151 | """ 152 | end = n 153 | return dict({ 154 | datetime: tuple(df[datetime][0:end]), 155 | open: tuple(df[open][0:end]), 156 | high: tuple(df[high][0:end]), 157 | low: tuple(df[low][0:end]), 158 | close: tuple(df[close][0:end]), 159 | volume: tuple(df[volume][0:end]) 160 | }) 161 | 162 | def DF_TAIL(df, n=5, datetime='datetime', open='Open', high='High', low='Low', close='Close', volume='Volume'): 163 | """ 164 | DataFeed TAIL 165 | Returns: dict of tuples of floats = jhta.DF_TAIL(df, n=5, datetime='datetime', open='Open', high='High', low='Low', close='Close', volume='Volume') 166 | """ 167 | start = len(df[close]) - n 168 | end = len(df[close]) 169 | return dict({ 170 | datetime: tuple(df[datetime][start:end]), 171 | open: tuple(df[open][start:end]), 172 | high: tuple(df[high][start:end]), 173 | low: tuple(df[low][start:end]), 174 | close: tuple(df[close][start:end]), 175 | volume: tuple(df[volume][start:end]) 176 | }) 177 | 178 | def NUMPY2DF(df_np, datetime='datetime', open='Open', high='High', low='Low', close='Close', volume='Volume'): 179 | """ 180 | NumPy DataFeed 2 DataFeed 181 | Returns: dict of tuples of floats = jhta.NUMPY2DF(df_np, datetime='datetime', open='Open', high='High', low='Low', close='Close', volume='Volume') 182 | """ 183 | return { 184 | datetime: tuple(df_np[datetime]), 185 | open: tuple(df_np[open]), 186 | high: tuple(df_np[high]), 187 | low: tuple(df_np[low]), 188 | close: tuple(df_np[close]), 189 | volume: tuple(df_np[volume]) 190 | } 191 | 192 | def PANDAS2DF(df_pd, datetime='datetime', open='Open', high='High', low='Low', close='Close', volume='Volume'): 193 | """ 194 | Pandas DataFeed 2 DataFeed 195 | Returns: dict of tuples of floats = jhta.PANDAS2DF(df_pd, datetime='datetime', open='Open', high='High', low='Low', close='Close', volume='Volume') 196 | """ 197 | return { 198 | datetime: tuple(df_pd[datetime]), 199 | open: tuple(df_pd[open]), 200 | high: tuple(df_pd[high]), 201 | low: tuple(df_pd[low]), 202 | close: tuple(df_pd[close]), 203 | volume: tuple(df_pd[volume]) 204 | } 205 | -------------------------------------------------------------------------------- /jhtalib/decorators.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | import functools 4 | import time 5 | 6 | # Import Third-Party: 7 | 8 | # Import Homebrew: 9 | import jhtalib as jhta 10 | 11 | 12 | def timer(func): 13 | """Print the runtime of the decorated function""" 14 | 15 | @functools.wraps(func) 16 | def wrapper_timer(*args, **kwargs): 17 | start_time = time.perf_counter() 18 | value = func(*args, **kwargs) 19 | end_time = time.perf_counter() 20 | run_time = end_time - start_time 21 | print('Finished {!r} in {:.8f} secs.'.format(func.__name__, run_time)) 22 | return value 23 | 24 | return wrapper_timer 25 | 26 | -------------------------------------------------------------------------------- /jhtalib/derivatives/__init__.py: -------------------------------------------------------------------------------- 1 | from .derivatives import * 2 | 3 | -------------------------------------------------------------------------------- /jhtalib/derivatives/derivatives.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | 4 | # Import Third-Party: 5 | 6 | # Import Homebrew: 7 | import jhtalib as jhta 8 | 9 | 10 | def get_leverage(total_exposure, total_equity): 11 | """ 12 | Leverage 13 | Returns: float = jhta.get_leverage(total_exposure, total_equity) 14 | """ 15 | return total_exposure / total_equity 16 | 17 | def get_ltv(total_exposure, total_equity): 18 | """ 19 | Loan to Value 20 | Returns: float = jhta.get_ltv(total_exposure, total_equity) 21 | """ 22 | return (total_exposure - total_equity) / total_exposure 23 | 24 | -------------------------------------------------------------------------------- /jhtalib/event_driven/__init__.py: -------------------------------------------------------------------------------- 1 | from .event_driven import * 2 | 3 | -------------------------------------------------------------------------------- /jhtalib/event_driven/event_driven.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | 4 | # Import Third-Party: 5 | 6 | # Import Homebrew: 7 | import jhtalib as jhta 8 | 9 | 10 | def ASI(df, L, open='Open', high='High', low='Low', close='Close'): 11 | """ 12 | Accumulation Swing Index (J. Welles Wilder) 13 | Returns: list of floats = jhta.ASI(df, L, open='Open', high='High', low='Low', close='Close') 14 | Source: book: New Concepts in Technical Trading Systems 15 | """ 16 | asi_list = [] 17 | si_list = jhta.SI(df, L, open, high, low, close) 18 | for i in range(len(df[close])): 19 | if i < 1: 20 | asi = float('NaN') 21 | asi_list.append(asi) 22 | asi = .0 23 | else: 24 | asi = asi + si_list[i] 25 | asi_list.append(asi) 26 | return asi_list 27 | 28 | def SAVGP(df, open='Open', high='High', low='Low', close='Close'): 29 | """ 30 | Swing Average Price - previous Average Price 31 | Returns: list of floats = jhta.SAVGP(df, open='Open', high='High', low='Low', close='Close') 32 | """ 33 | savgp_list = [] 34 | avgp_list = jhta.AVGPRICE(df, open, high, low, close) 35 | for i in range(len(df[close])): 36 | if i < 1: 37 | savgp = float('NaN') 38 | else: 39 | savgp = avgp_list[i] - avgp_list[i - 1] 40 | savgp_list.append(savgp) 41 | return savgp_list 42 | 43 | def SAVGPS(df, open='Open', high='High', low='Low', close='Close'): 44 | """ 45 | Swing Average Price - previous Average Price Summation 46 | Returns: list of floats = jhta.SAVGPS(df, open='Open', high='High', low='Low', close='Close') 47 | """ 48 | savgps_list = [] 49 | savgp_list = jhta.SAVGP(df, open, high, low, close) 50 | for i in range(len(df[close])): 51 | if i < 1: 52 | savgps = float('NaN') 53 | savgps_list.append(savgps) 54 | savgps = .0 55 | else: 56 | savgps = savgps + savgp_list[i] 57 | savgps_list.append(savgps) 58 | return savgps_list 59 | 60 | def SCO(df, open='Open', close='Close'): 61 | """ 62 | Swing Close - Open 63 | Returns: list of floats = jhta.SCO(df, open='Open', close='Close') 64 | """ 65 | return [df[close][i] - df[open][i] for i in range(len(df[close]))] 66 | 67 | def SCOS(df, open='Open', close='Close'): 68 | """ 69 | Swing Close - Open Summation 70 | Returns: list of floats = jhta.SCOS(df, open='Open', close='Close') 71 | """ 72 | scos_list = [] 73 | sco_list = jhta.SCO(df, open, close) 74 | scos = .0 75 | for i in range(len(df[close])): 76 | scos = scos + sco_list[i] 77 | scos_list.append(scos) 78 | return scos_list 79 | 80 | def SI(df, L, open='Open', high='High', low='Low', close='Close'): 81 | """ 82 | Swing Index (J. Welles Wilder) 83 | Returns: list of floats = jhta.SI(df, L, open='Open', high='High', low='Low', close='Close') 84 | Source: book: New Concepts in Technical Trading Systems 85 | """ 86 | si_list = [] 87 | for i in range(len(df[close])): 88 | if i < 1: 89 | si = float('NaN') 90 | else: 91 | N = (df[close][i] - df[close][i - 1]) + (.5 * (df[close][i] - df[open][i])) + (.25 * (df[close][i - 1] - df[open][i - 1])) 92 | R1 = df[high][i] - df[close][i - 1] 93 | R2 = df[low][i] - df[close][i - 1] 94 | R3 = df[high][i] - df[low][i] 95 | if R1 > R2 and R1 > R3: 96 | R = (df[high][i] - df[close][i - 1]) - (.5 * (df[low][i] - df[close][i - 1])) + (.25 * (df[close][i - 1] - df[open][i - 1])) 97 | if R2 > R1 and R2 > R3: 98 | R = (df[low][i] - df[close][i - 1]) - (.5 * (df[high][i] - df[close][i - 1])) + (.25 * (df[close][i - 1] - df[open][i - 1])) 99 | if R3 > R1 and R3 > R2: 100 | R = (df[high][i] - df[low][i]) + (.25 * (df[close][i - 1] - df[open][i - 1])) 101 | K1 = df[high][i] - df[close][i - 1] 102 | K2 = df[low][i] - df[close][i - 1] 103 | if K1 > K2: 104 | K = K1 105 | else: 106 | K = K2 107 | si = 50 * (N / R) * (K / L) 108 | si_list.append(si) 109 | return si_list 110 | 111 | def SMEDP(df, high='High', low='Low'): 112 | """ 113 | Swing Median Price - previous Median Price 114 | Returns: list of floats = jhta.SMEDP(df, high='High', low='Low') 115 | """ 116 | smedp_list = [] 117 | medp_list = jhta.MEDPRICE(df, high, low) 118 | for i in range(len(df[low])): 119 | if i < 1: 120 | smedp = float('NaN') 121 | else: 122 | smedp = medp_list[i] - medp_list[i - 1] 123 | smedp_list.append(smedp) 124 | return smedp_list 125 | 126 | def SMEDPS(df, high='High', low='Low'): 127 | """ 128 | Swing Median Price - previous Median Price Summation 129 | Returns: list of floats = jhta.SMEDPS(df, high='High', low='Low') 130 | """ 131 | smedps_list = [] 132 | smedp_list = jhta.SMEDP(df, high, low) 133 | for i in range(len(df[low])): 134 | if i < 1: 135 | smedps = float('NaN') 136 | smedps_list.append(smedps) 137 | smedps = .0 138 | else: 139 | smedps = smedps + smedp_list[i] 140 | smedps_list.append(smedps) 141 | return smedps_list 142 | 143 | def SPP(df, price='Close'): 144 | """ 145 | Swing Price - previous Price 146 | Returns: list of floats = jhta.SPP(df, price='Close') 147 | """ 148 | spp_list = [] 149 | for i in range(len(df[price])): 150 | if i < 1: 151 | spp = float('NaN') 152 | else: 153 | spp = df[price][i] - df[price][i - 1] 154 | spp_list.append(spp) 155 | return spp_list 156 | 157 | def SPPS(df, price='Close'): 158 | """ 159 | Swing Price - previous Price Summation 160 | Returns: list of floats = jhta.SPPS(df, price='Close') 161 | """ 162 | spps_list = [] 163 | spp_list = jhta.SPP(df, price) 164 | for i in range(len(df[price])): 165 | if i < 1: 166 | spps = float('NaN') 167 | spps_list.append(spps) 168 | spps = .0 169 | else: 170 | spps = spps + spp_list[i] 171 | spps_list.append(spps) 172 | return spps_list 173 | 174 | def STYPP(df, high='High', low='Low', close='Close'): 175 | """ 176 | Swing Typical Price - previous Typical Price 177 | Returns: list of floats = jhta.STYPP(df, high='High', low='Low', close='Close') 178 | """ 179 | stypp_list = [] 180 | typp_list = jhta.TYPPRICE(df, high, low, close) 181 | for i in range(len(df[close])): 182 | if i < 1: 183 | stypp = float('NaN') 184 | else: 185 | stypp = typp_list[i] - typp_list[i - 1] 186 | stypp_list.append(stypp) 187 | return stypp_list 188 | 189 | def STYPPS(df, high='High', low='Low', close='Close'): 190 | """ 191 | Swing Typical Price - previous Typical Price Summation 192 | Returns: list of floats = jhta.STYPPS(df, high='High', low='Low', close='Close') 193 | """ 194 | stypps_list = [] 195 | stypp_list = jhta.STYPP(df, high, low, close) 196 | for i in range(len(df[close])): 197 | if i < 1: 198 | stypps = float('NaN') 199 | stypps_list.append(stypps) 200 | stypps = .0 201 | else: 202 | stypps = stypps + stypp_list[i] 203 | stypps_list.append(stypps) 204 | return stypps_list 205 | 206 | def SWCLP(df, high='High', low='Low', close='Close'): 207 | """ 208 | Swing Weighted Close Price - previous Weighted Close Price 209 | Returns: list of floats = jhta.SWCLP(df, high='High', low='Low', close='Close') 210 | """ 211 | swclp_list = [] 212 | wclp_list = jhta.WCLPRICE(df, high, low, close) 213 | for i in range(len(df[close])): 214 | if i < 1: 215 | swclp = float('NaN') 216 | else: 217 | swclp = wclp_list[i] - wclp_list[i - 1] 218 | swclp_list.append(swclp) 219 | return swclp_list 220 | 221 | def SWCLPS(df, high='High', low='Low', close='Close'): 222 | """ 223 | Swing Weighted Close Price - previous Weighted Close Price Summation 224 | Returns: list of floats = jhta.SWCLPS(df, high='High', low='Low', close='Close') 225 | """ 226 | swclps_list = [] 227 | swclp_list = jhta.SWCLP(df, high, low, close) 228 | for i in range(len(df[close])): 229 | if i < 1: 230 | swclps = float('NaN') 231 | swclps_list.append(swclps) 232 | swclps = .0 233 | else: 234 | swclps = swclps + swclp_list[i] 235 | swclps_list.append(swclps) 236 | return swclps_list 237 | 238 | -------------------------------------------------------------------------------- /jhtalib/example.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | from pprint import pprint as pp 4 | 5 | # Import Third-Party: 6 | 7 | # Import Homebrew: 8 | import jhtalib as jhta 9 | 10 | 11 | @jhta.timer 12 | def example(): 13 | 14 | # df is DataFeed: 15 | df = { 16 | 'datetime': ('20151217', '20151218', '20151221', '20151222', '20151223', '20151224', '20151228', '20151229', '20151230', '20151231'), 17 | 'Open': (235.8, 232.3, 234.1, 232.2, 232.7, 235.4, 236.9, 234.85, 236.45, 235.0), 18 | 'High': (238.05, 236.9, 237.3, 232.4, 235.2, 236.15, 236.9, 237.6, 238.3, 237.25), 19 | 'Low': (234.55, 230.6, 230.2, 226.8, 231.5, 233.85, 233.05, 234.6, 234.55, 234.4), 20 | 'Close': (234.6, 233.6, 230.2, 230.05, 234.15, 236.15, 233.25, 237.6, 235.75, 234.4), 21 | 'Volume': (448294, 629039, 292528, 214170, 215545, 23548, 97574, 192908, 176839, 69347) 22 | } 23 | 24 | # basic usage: 25 | #pp (df) 26 | pp (jhta.SMA(df, 10)) 27 | #pp (jhta.BBANDS(df, 10)) 28 | -------------------------------------------------------------------------------- /jhtalib/experimental/__init__.py: -------------------------------------------------------------------------------- 1 | from .experimental import * 2 | 3 | -------------------------------------------------------------------------------- /jhtalib/experimental/experimental.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | import random 4 | 5 | # Import Third-Party: 6 | 7 | # Import Homebrew: 8 | import jhtalib as jhta 9 | 10 | 11 | def MONTECARLO(df, price='Close'): 12 | """ 13 | Monte Carlo 14 | Returns: list of ints = jhta.MONTECARLO(df, price='Close') 15 | Source: https://en.wikipedia.org/wiki/Monte_Carlo_method 16 | """ 17 | return [random.randint(0, 1) for i in range(len(df[price]))] 18 | 19 | def PAMPLITUDE(df, n, price='Close'): 20 | """ 21 | Peak Amplitude 22 | Returns: list of floats = jhta.PAMPLITUDE(df, n, price='Close') 23 | Source: https://en.wikipedia.org/wiki/Amplitude 24 | """ 25 | ppamplitude_list = jhta.PPAMPLITUDE(df, n, price) 26 | return [ppamplitude_list[i] / 2 for i in range(len(df[price]))] 27 | 28 | def PPAMPLITUDE(df, n, price='Close'): 29 | """ 30 | Peak-to-Peak Amplitude 31 | Returns: list of floats = jhta.PPAMPLITUDE(df, n, price='Close') 32 | Source: https://en.wikipedia.org/wiki/Amplitude 33 | """ 34 | ppamplitude_list = [] 35 | for i in range(len(df[price])): 36 | if i + 1 < n: 37 | ppamplitude = float('NaN') 38 | else: 39 | start = i + 1 - n 40 | end = i + 1 41 | ppamplitude = max(df[price][start:end]) - min(df[price][start:end]) 42 | ppamplitude_list.append(ppamplitude) 43 | return ppamplitude_list 44 | 45 | -------------------------------------------------------------------------------- /jhtalib/general/__init__.py: -------------------------------------------------------------------------------- 1 | from .general import * 2 | 3 | -------------------------------------------------------------------------------- /jhtalib/general/general.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | 4 | # Import Third-Party: 5 | 6 | # Import Homebrew: 7 | import jhtalib as jhta 8 | 9 | 10 | def CP(df1, df2, price1='Close', price2='Close'): 11 | """ 12 | Comparative Performance 13 | Returns: list of floats = jhta.CP(df1, df2, price1='Close', price2='Close') 14 | Source: https://www.fmlabs.com/reference/default.htm?url=CompPerformance.htm 15 | """ 16 | cp_list = [] 17 | for i in range(len(df1[price1])): 18 | cp = 1 + (((df1[price1][i] / df2[price2][i]) - (df1[price1][0] / df2[price2][0])) / (df1[price1][0] / df2[price2][0])) 19 | cp_list.append(cp) 20 | return cp_list 21 | 22 | def CRSI(df1, df2, n, price1='Close', price2='Close'): 23 | """ 24 | Comparative Relative Strength Index 25 | Returns: list of floats = jhta.CRSI(df1, df2, n, price1='Close', price2='Close') 26 | Source: https://www.fmlabs.com/reference/default.htm?url=RSIC.htm 27 | """ 28 | crsi_list = [] 29 | for i in range(len(df1[price1])): 30 | if i + 1 < n: 31 | crsi = float('NaN') 32 | else: 33 | crsi = (((df1[price1][i] / df2[price2][i]) - (df1[price1][i - n] / df2[price2][i - n])) / (df1[price1][i - n] / df2[price2][i - n])) 34 | crsi_list.append(crsi) 35 | return crsi_list 36 | 37 | def CS(df1, df2, price1='Close', price2='Close'): 38 | """ 39 | Comparative Strength 40 | Returns: list of floats = jhta.CS(df1, df2, price1='Close', price2='Close') 41 | Source: https://www.fmlabs.com/reference/default.htm?url=CompStrength.htm 42 | """ 43 | return [df1[price1][i] / df2[price2][i] for i in range(len(df1[price1]))] 44 | 45 | def NORMALIZE(df, price_max='High', price_min='Low', price='Close'): 46 | """ 47 | Normalize 48 | Returns: list of floats = jhta.NORMALIZE(df, price_max='High', price_min='Low', price='Close') 49 | Source: https://machinelearningmastery.com/normalize-standardize-time-series-data-python/ 50 | """ 51 | normalize_list = [] 52 | start = None 53 | for i in range(len(df[price])): 54 | if df[price_max][i] != df[price_max][i] or df[price_min][i] != df[price_min][i] or df[price][i] != df[price][i] or i < 1: 55 | normalize = float('NaN') 56 | else: 57 | if start is None: 58 | start = i 59 | x_max = df[price_max][start:] 60 | norm_max = jhta.MAX({'x': x_max}, len(x_max), 'x')[-1] 61 | x_min = df[price_min][start:] 62 | norm_min = jhta.MIN({'x': x_min}, len(x_min), 'x')[-1] 63 | normalize = (df[price][i] - norm_min) / (norm_max - norm_min) 64 | normalize_list.append(normalize) 65 | return normalize_list 66 | 67 | def RATIO(df1, df2, price1='Close', price2='Close'): 68 | """ 69 | Ratio 70 | Returns: list of floats = jhta.RATIO(df1, df2, price1='Close', price2='Close') 71 | Source: https://www.fmlabs.com/reference/default.htm?url=Ratio.htm 72 | """ 73 | return [df1[price1][i] / df2[price2][i] for i in range(len(df1[price1]))] 74 | 75 | def REMAP(x, old_min=0, old_max=1000, new_min=0, new_max=100): 76 | """ 77 | Remap 78 | Returns: float = jhta.REMAP(x, old_min=0, old_max=1000, new_min=0, new_max=100) 79 | """ 80 | old_range = old_max - old_min 81 | new_range = new_max - new_min 82 | return (((x - old_min) * new_range) / old_range) + new_min 83 | 84 | def REMAPS(df, old_min=0, old_max=1000, new_min=0, new_max=100, price='Close'): 85 | """ 86 | Remaps 87 | Returns: list of floats = jhta.REMAPS(df, old_min=0, old_max=1000, new_min=0, new_max=100, price='Close') 88 | """ 89 | remap_list = [] 90 | for i in range(len(df[price])): 91 | remap = REMAP(df[price][i], old_min=old_min, old_max=old_max, new_min=new_min, new_max=new_max) 92 | remap_list.append(remap) 93 | return remap_list 94 | 95 | def SPREAD(df1, df2, price1='Close', price2='Close'): 96 | """ 97 | Spread 98 | Returns: list of floats = jhta.SPREAD(df1, df2, price1='Close', price2='Close') 99 | """ 100 | return [df1[price1][i] - df2[price2][i] for i in range(len(df1[price1]))] 101 | 102 | def STANDARDIZE(df, price='Close'): 103 | """ 104 | Standardize 105 | Returns: list of floats = jhta.STANDARDIZE(df, price='Close') 106 | Source: https://machinelearningmastery.com/normalize-standardize-time-series-data-python/ 107 | """ 108 | standardize_list = [] 109 | start = None 110 | for i in range(len(df[price])): 111 | if df[price][i] != df[price][i] or i < 1: 112 | standardize = float('NaN') 113 | else: 114 | if start is None: 115 | start = i 116 | x = df[price][start:] 117 | mean = jhta.MEAN({'x': x}, len(x), 'x')[-1] 118 | standard_deviation = jhta.STDEV({'x': x}, len(x), 'x')[-1] 119 | standardize = (df[price][i] - mean) / standard_deviation 120 | standardize_list.append(standardize) 121 | return standardize_list 122 | 123 | -------------------------------------------------------------------------------- /jhtalib/helpers.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | 4 | # Import Third-Party: 5 | 6 | # Import Homebrew: 7 | import jhtalib as jhta 8 | 9 | 10 | -------------------------------------------------------------------------------- /jhtalib/information/__init__.py: -------------------------------------------------------------------------------- 1 | from .information import * 2 | 3 | -------------------------------------------------------------------------------- /jhtalib/information/information.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | 4 | # Import Third-Party: 5 | 6 | # Import Homebrew: 7 | import jhtalib as jhta 8 | 9 | 10 | def INFO(df, price='Close'): 11 | """ 12 | Print df Information 13 | Returns: print = jhta.INFO(df, price='Close') 14 | """ 15 | print ('{:_<28}:{:_>22}'.format('DF PRICE COLUMN', price)) 16 | print ('{:_<28}:{:_>22d}'.format('LEN', len(df[price]))) 17 | print ('{:_<28}:{:_>28.5f}'.format('MIN', jhta.MIN(df, len(df[price]), price)[-1])) 18 | print ('{:_<28}:{:_>28.5f}'.format('MAX', jhta.MAX(df, len(df[price]), price)[-1])) 19 | print ('{:_<28}:{:_>28.5f}'.format('SUM', jhta.SUM(df, len(df[price]), price)[-1])) 20 | print ('{:_<28}:{:_>28.5f}'.format('MEAN', jhta.MEAN(df, len(df[price]), price)[-1])) 21 | # print ('{:_<28}:{:_>28.5f}'.format('HARMONIC_MEAN', jhta.HARMONIC_MEAN(df, len(df[price]), price)[-1])) 22 | print ('{:_<28}:{:_>28.5f}'.format('MEDIAN', jhta.MEDIAN(df, len(df[price]), price)[-1])) 23 | print ('{:_<28}:{:_>28.5f}'.format('MEDIAN_LOW', jhta.MEDIAN_LOW(df, len(df[price]), price)[-1])) 24 | print ('{:_<28}:{:_>28.5f}'.format('MEDIAN_HIGH', jhta.MEDIAN_HIGH(df, len(df[price]), price)[-1])) 25 | print ('{:_<28}:{:_>28.5f}'.format('MEDIAN_GROUPED', jhta.MEDIAN_GROUPED(df, len(df[price]), price)[-1])) 26 | # print ('{:_<28}:{:_>28.5f}'.format('MODE', jhta.MODE(df, len(df[price]), price)[-1])) 27 | print ('{:_<28}:{:_>28.5f}'.format('PSTDEV', jhta.PSTDEV(df, len(df[price]), price)[-1])) 28 | print ('{:_<28}:{:_>28.5f}'.format('PVARIANCE', jhta.PVARIANCE(df, len(df[price]), price)[-1])) 29 | print ('{:_<28}:{:_>28.5f}'.format('STDEV', jhta.STDEV(df, len(df[price]), price)[-1])) 30 | print ('{:_<28}:{:_>28.5f}'.format('VARIANCE', jhta.VARIANCE(df, len(df[price]), price)[-1])) 31 | 32 | def INFO_TRADES(profit_trades_list, loss_trades_list): 33 | """ 34 | Print Trades Information 35 | Returns: print = jhta.INFO_TRADES(profit_trades_list, loss_trades_list) 36 | """ 37 | total_trades = len(profit_trades_list) + len(loss_trades_list) 38 | hr = jhta.HR(len(profit_trades_list), total_trades) 39 | plr = jhta.PLR((sum(profit_trades_list) / len(profit_trades_list)), (sum(loss_trades_list) / len(loss_trades_list))) 40 | ev = jhta.EV(hr, (sum(profit_trades_list) / len(profit_trades_list)), (sum(loss_trades_list) / len(loss_trades_list))) 41 | por = jhta.POR(hr, plr) 42 | print ('{:_<28}:{:_>22d}'.format('TOTAL TRADES', total_trades)) 43 | print ('{:_<28}:{:_>28.5f}'.format('HIT RATE / WIN RATE', hr)) 44 | print ('{:_<28}:{:_>28.5f}'.format('PROFIT/LOSS RATIO', plr)) 45 | print ('{:_<28}:{:_>28.5f}'.format('EXPECTED VALUE', ev)) 46 | print ('{:_<28}:{:_>22d}'.format('PROBABILITY OF RUIN', por)) 47 | 48 | -------------------------------------------------------------------------------- /jhtalib/math_functions/__init__.py: -------------------------------------------------------------------------------- 1 | from .math_functions import * 2 | 3 | -------------------------------------------------------------------------------- /jhtalib/math_functions/math_functions.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | import math 4 | import cmath 5 | 6 | # Import Third-Party: 7 | 8 | # Import Homebrew: 9 | import jhtalib as jhta 10 | 11 | 12 | def ACOS(df, price='Close'): 13 | """ 14 | Arc Cosine 15 | Returns: list of floats = jhta.ACOS(df, price='Close') 16 | """ 17 | return [cmath.acos(df[price][i]).real for i in range(len(df[price]))] 18 | 19 | def ACOSH(df, price='Close'): 20 | """ 21 | Inverse Hyperbolic Cosine 22 | Returns: list of floats = jhta.ACOSH(df, price='Close') 23 | """ 24 | return [cmath.acosh(df[price][i]).real for i in range(len(df[price]))] 25 | 26 | def ADD(df, high='High', low='Low'): 27 | """ 28 | Addition High + Low 29 | Returns: list of floats = jhta.ADD(df, high='High', low='Low') 30 | """ 31 | return [df[high][i] + df[low][i] for i in range(len(df[low]))] 32 | 33 | def ASIN(df, price='Close'): 34 | """ 35 | Arc Sine 36 | Returns: list of floats = jhta.ASIN(df, price='Close') 37 | """ 38 | return [cmath.asin(df[price][i]).real for i in range(len(df[price]))] 39 | 40 | def ASINH(df, price='Close'): 41 | """ 42 | Inverse Hyperbolic Sine 43 | Returns: list of floats = jhta.ASINH(df, price='Close') 44 | """ 45 | return [cmath.asinh(df[price][i]).real for i in range(len(df[price]))] 46 | 47 | def ATAN(df, price='Close'): 48 | """ 49 | Arc Tangent 50 | Returns: list of floats = jhta.ATAN(df, price='Close') 51 | """ 52 | return [cmath.atan(df[price][i]).real for i in range(len(df[price]))] 53 | 54 | def ATANH(df, price='Close'): 55 | """ 56 | Inverse Hyperbolic Tangent 57 | Returns: list of floats = jhta.ATANH(df, price='Close') 58 | """ 59 | return [cmath.atanh(df[price][i]).real for i in range(len(df[price]))] 60 | 61 | def CEIL(df, price='Close'): 62 | """ 63 | Ceiling 64 | Returns: list of floats = jhta.CEIL(df, price='Close') 65 | """ 66 | return [math.ceil(df[price][i]) for i in range(len(df[price]))] 67 | 68 | def COS(df, price='Close'): 69 | """ 70 | Cosine 71 | Returns: list of floats = jhta.COS(df, price='Close') 72 | """ 73 | return [cmath.cos(df[price][i]).real for i in range(len(df[price]))] 74 | 75 | def COSH(df, price='Close'): 76 | """ 77 | Hyperbolic Cosine 78 | Returns: list of floats = jhta.COSH(df, price='Close') 79 | """ 80 | return [cmath.cosh(df[price][i]).real for i in range(len(df[price]))] 81 | 82 | def DEGREES(df, price='Close'): 83 | """ 84 | Radians to Degrees 85 | Returns: list of floats = jhta.DEGREES(df, price='Close') 86 | """ 87 | return [math.degrees(df[price][i]) for i in range(len(df[price]))] 88 | 89 | def DIV(df, high='High', low='Low'): 90 | """ 91 | Division High / Low 92 | Returns: list of floats = jhta.DIV(df, high='High', low='Low') 93 | """ 94 | return [df[high][i] / df[low][i] for i in range(len(df[low]))] 95 | 96 | def E(): 97 | """ 98 | Mathematical constant E 99 | Returns: float = jhta.E() 100 | """ 101 | return cmath.e 102 | 103 | def ED(x1, y1, x2, y2): 104 | """ 105 | Euclidean Distance 106 | Returns: float = jhta.ED(x1, y1, x2, y2) 107 | Source: book: An Introduction to Algorithmic Trading 108 | """ 109 | return cmath.sqrt((x1 - x2)**2 + (y1 - y2)**2).real 110 | 111 | def EDS(df, n, price='Close'): 112 | """ 113 | Euclidean Distances 114 | Returns: list of floats = jhta.EDS(df, n, price='Close') 115 | Source: book: An Introduction to Algorithmic Trading 116 | """ 117 | ed_list = [] 118 | for i in range(len(df[price])): 119 | if i + 1 < n: 120 | ed = float('NaN') 121 | else: 122 | x1 = i - n 123 | y1 = df[price][i - n] 124 | x2 = i 125 | y2 = df[price][i] 126 | ed = jhta.ED(x1, y1, x2, y2) 127 | ed_list.append(ed) 128 | return ed_list 129 | 130 | def EXP(df, price='Close'): 131 | """ 132 | Exponential 133 | Returns: list of floats = jhta.EXP(df, price='Close') 134 | """ 135 | return [cmath.exp(df[price][i]).real for i in range(len(df[price]))] 136 | 137 | def FIB(n): 138 | """ 139 | Fibonacci series up to n 140 | Returns: list of ints = jhta.FIB(n) 141 | """ 142 | fib_list = [] 143 | a, b = 0, 1 144 | while a < n: 145 | fib_list.append(a) 146 | a, b = b, a + b 147 | return fib_list 148 | 149 | def FLOOR(df, price='Close'): 150 | """ 151 | Floor 152 | Returns: list of floats = jhta.FLOOR(df, price='Close') 153 | """ 154 | return [math.floor(df[price][i]) for i in range(len(df[price]))] 155 | 156 | def LOG(df, price='Close'): 157 | """ 158 | Logarithm 159 | Returns: list of floats = jhta.LOG(df, price='Close') 160 | """ 161 | return [cmath.log(df[price][i]).real for i in range(len(df[price]))] 162 | 163 | def LOG10(df, price='Close'): 164 | """ 165 | Base-10 Logarithm 166 | Returns: list of floats = jhta.LOG10(df, price='Close') 167 | """ 168 | return [cmath.log10(df[price][i]).real for i in range(len(df[price]))] 169 | 170 | def MAX(df, n, price='High'): 171 | """ 172 | Highest value over a specified period 173 | Returns: list of floats = jhta.MAX(df, n, price='High') 174 | """ 175 | max_list = [] 176 | if n == len(df[price]): 177 | start = None 178 | for i in range(len(df[price])): 179 | if df[price][i] != df[price][i]: 180 | MAX = float('NaN') 181 | else: 182 | if start is None: 183 | start = i 184 | end = i + 1 185 | MAX = max(df[price][start:end]) 186 | max_list.append(MAX) 187 | else: 188 | for i in range(len(df[price])): 189 | if i + 1 < n: 190 | MAX = float('NaN') 191 | else: 192 | start = i + 1 - n 193 | end = i + 1 194 | MAX = max(df[price][start:end]) 195 | max_list.append(MAX) 196 | return max_list 197 | 198 | def MAXINDEX(df, n, price='High'): 199 | """ 200 | Index of highest value over a specified period 201 | Returns: list of ints = jhta.MAXINDEX(df, n, price='High') 202 | """ 203 | max_index_list = [] 204 | if n == len(df[price]): 205 | start = None 206 | for i in range(len(df[price])): 207 | if df[price][i] != df[price][i]: 208 | max_index = float('NaN') 209 | else: 210 | if start is None: 211 | start = i 212 | end = i + 1 213 | max_index = df[price][start:end].index(max(df[price][start:end])) 214 | max_index_list.append(max_index) 215 | else: 216 | for i in range(len(df[price])): 217 | if i + 1 < n: 218 | max_index = float('NaN') 219 | else: 220 | start = i + 1 - n 221 | end = i + 1 222 | max_index = df[price][start:end].index(max(df[price][start:end])) 223 | max_index_list.append(max_index) 224 | return max_index_list 225 | 226 | def MIN(df, n, price='Low'): 227 | """ 228 | Lowest value over a specified period 229 | Returns: list of floats = jhta.MIN(df, n, price='Low') 230 | """ 231 | min_list = [] 232 | if n == len(df[price]): 233 | start = None 234 | for i in range(len(df[price])): 235 | if df[price][i] != df[price][i]: 236 | MIN = float('NaN') 237 | else: 238 | if start is None: 239 | start = i 240 | end = i + 1 241 | MIN = min(df[price][start:end]) 242 | min_list.append(MIN) 243 | else: 244 | for i in range(len(df[price])): 245 | if i + 1 < n: 246 | MIN = float('NaN') 247 | else: 248 | start = i + 1 - n 249 | end = i + 1 250 | MIN = min(df[price][start:end]) 251 | min_list.append(MIN) 252 | return min_list 253 | 254 | def MININDEX(df, n, price='Low'): 255 | """ 256 | Index of lowest value over a specified period 257 | Returns: list of ints = jhta.MININDEX(df, n, price='Low') 258 | """ 259 | min_index_list = [] 260 | if n == len(df[price]): 261 | start = None 262 | for i in range(len(df[price])): 263 | if df[price][i] != df[price][i]: 264 | min_index = float('NaN') 265 | else: 266 | if start is None: 267 | start = i 268 | end = i + 1 269 | min_index = df[price][start:end].index(min(df[price][start:end])) 270 | min_index_list.append(min_index) 271 | else: 272 | for i in range(len(df[price])): 273 | if i + 1 < n: 274 | min_index = float('NaN') 275 | else: 276 | start = i + 1 - n 277 | end = i + 1 278 | min_index = df[price][start:end].index(min(df[price][start:end])) 279 | min_index_list.append(min_index) 280 | return min_index_list 281 | 282 | def MINMAX(df, n, high='High', low='Low'): 283 | """ 284 | Lowest and highest values over a specified period 285 | Returns: dict of lists of floats = jhta.MINMAX(df, n, high='High', low='Low') 286 | """ 287 | return { 288 | 'max': jhta.MAX(df, n, high), 289 | 'min': jhta.MIN(df, n, low) 290 | } 291 | 292 | def MINMAXINDEX(df, n, high='High', low='Low'): 293 | """ 294 | Indexes of lowest and highest values over a specified period 295 | Returns: dict of lists of ints = jhta.MINMAXINDEX(df, n, high='High', low='Low') 296 | """ 297 | return { 298 | 'max': jhta.MAXINDEX(df, n, high), 299 | 'min': jhta.MININDEX(df, n, low) 300 | } 301 | 302 | def MULT(df, high='High', low='Low'): 303 | """ 304 | Multiply High * Low 305 | Returns: list of floats = jhta.MULT(df, high='High', low='Low') 306 | """ 307 | return [df[high][i] * df[low][i] for i in range(len(df[low]))] 308 | 309 | def PHI(): 310 | """ 311 | Mathematical constant PHI 312 | Returns: float = jhta.PHI() 313 | """ 314 | return (cmath.sqrt(5).real + 1) / 2 315 | 316 | def PI(): 317 | """ 318 | Mathematical constant PI 319 | Returns: float = jhta.PI() 320 | """ 321 | return cmath.pi 322 | 323 | def RADIANS(df, price='Close'): 324 | """ 325 | Degrees to Radians 326 | Returns: list of floats = jhta.RADIANS(df, price='Close') 327 | """ 328 | return [math.radians(df[price][i]) for i in range(len(df[price]))] 329 | 330 | def SIN(df, price='Close'): 331 | """ 332 | Sine 333 | Returns: list of floats = jhta.SIN(df, price='Close') 334 | """ 335 | return [cmath.sin(df[price][i]).real for i in range(len(df[price]))] 336 | 337 | def SINH(df, price='Close'): 338 | """ 339 | Hyperbolic Sine 340 | Returns: list of floats = jhta.SINH(df, price='Close') 341 | """ 342 | return [cmath.sinh(df[price][i]).real for i in range(len(df[price]))] 343 | 344 | def SLOPE(x1, y1, x2, y2): 345 | """ 346 | Slope 347 | Returns: float = jhta.SLOPE(x1, y1, x2, y2) 348 | Source: book: An Introduction to Algorithmic Trading 349 | """ 350 | return (y2 - y1) / (x2 - x1) 351 | 352 | def SLOPES(df, n, price='Close'): 353 | """ 354 | Slopes 355 | Returns: list of floats = jhta.SLOPES(df, n, price='Close') 356 | Source: book: An Introduction to Algorithmic Trading 357 | """ 358 | slope_list = [] 359 | for i in range(len(df[price])): 360 | if i + 1 < n: 361 | slope = float('NaN') 362 | else: 363 | x1 = i - n 364 | y1 = df[price][i - n] 365 | x2 = i 366 | y2 = df[price][i] 367 | slope = jhta.SLOPE(x1, y1, x2, y2) 368 | slope_list.append(slope) 369 | return slope_list 370 | 371 | def SQRT(df, price='Close'): 372 | """ 373 | Square Root 374 | Returns: list of floats = jhta.SQRT(df, price='Close') 375 | """ 376 | return [cmath.sqrt(df[price][i]).real for i in range(len(df[price]))] 377 | 378 | def SUB(df, high='High', low='Low'): 379 | """ 380 | Subtraction High - Low 381 | Returns: list of floats = jhta.SUB(df, high='High', low='Low') 382 | """ 383 | return [df[high][i] - df[low][i] for i in range(len(df[low]))] 384 | 385 | def SUM(df, n, price='Close'): 386 | """ 387 | Summation 388 | Returns: list of floats = jhta.SUM(df, n, price='Close') 389 | """ 390 | sum_list = [] 391 | if n == len(df[price]): 392 | start = None 393 | for i in range(len(df[price])): 394 | if df[price][i] != df[price][i]: 395 | SUM = float('NaN') 396 | else: 397 | if start is None: 398 | start = i 399 | end = i + 1 400 | SUM = sum(df[price][start:end]) 401 | sum_list.append(SUM) 402 | else: 403 | for i in range(len(df[price])): 404 | if i + 1 < n: 405 | SUM = float('NaN') 406 | else: 407 | start = i + 1 - n 408 | end = i + 1 409 | SUM = sum(df[price][start:end]) 410 | sum_list.append(SUM) 411 | return sum_list 412 | 413 | def TAN(df, price='Close'): 414 | """ 415 | Tangent 416 | Returns: list of floats = jhta.TAN(df, price='Close') 417 | """ 418 | return [cmath.tan(df[price][i]).real for i in range(len(df[price]))] 419 | 420 | def TANH(df, price='Close'): 421 | """ 422 | Hyperbolic Tangent 423 | Returns: list of floats = jhta.TANH(df, price='Close') 424 | """ 425 | return [cmath.tanh(df[price][i]).real for i in range(len(df[price]))] 426 | 427 | def TAU(): 428 | """ 429 | Mathematical constant TAU 430 | Returns: float = jhta.TAU() 431 | """ 432 | return cmath.tau 433 | 434 | -------------------------------------------------------------------------------- /jhtalib/momentum_indicators/__init__.py: -------------------------------------------------------------------------------- 1 | from .momentum_indicators import * 2 | 3 | -------------------------------------------------------------------------------- /jhtalib/momentum_indicators/momentum_indicators.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | 4 | # Import Third-Party: 5 | 6 | # Import Homebrew: 7 | import jhtalib as jhta 8 | 9 | 10 | def ADX(df, n): 11 | """ 12 | Average Directional Movement Index 13 | """ 14 | 15 | def ADXR(df, n): 16 | """ 17 | Average Directional Movement Index Rating 18 | """ 19 | 20 | def APO(df, n_fast, n_slow, price='Close'): 21 | """ 22 | Absolute Price Oscillator 23 | Returns: list of floats = jhta.APO(df, n_fast, n_slow, price='Close') 24 | Source: https://www.fmlabs.com/reference/default.htm?url=PriceOscillator.htm 25 | """ 26 | apo_list = [] 27 | for i in range(len(df[price])): 28 | if i + 1 < n_slow: 29 | apo = float('NaN') 30 | else: 31 | start_fast = i + 1 - n_fast 32 | end = i + 1 33 | sma_fast = sum(df[price][start_fast:end]) / n_fast 34 | start_slow = i + 1 - n_slow 35 | end = i + 1 36 | sma_slow = sum(df[price][start_slow:end]) / n_slow 37 | apo = sma_slow - sma_fast 38 | # apo *= -1 39 | apo_list.append(apo) 40 | return apo_list 41 | 42 | def AROON(df, n): 43 | """ 44 | Aroon 45 | """ 46 | 47 | def AROONOSC(df, n): 48 | """ 49 | Aroon Oscillator 50 | """ 51 | 52 | def BOP(df): 53 | """ 54 | Balance Of Power 55 | """ 56 | 57 | def CCI(df, n): 58 | """ 59 | Commodity Channel Index 60 | """ 61 | 62 | def CMO(df, n, price='Close'): 63 | """ 64 | Chande Momentum Oscillator 65 | """ 66 | 67 | def DX(df, n): 68 | """ 69 | Directional Movement Index 70 | """ 71 | 72 | def MACD(df, price='Close'): 73 | """ 74 | Moving Average Convergence/Divergence 75 | """ 76 | 77 | def MACDEXT(df, price='Close'): 78 | """ 79 | MACD with controllable MA type 80 | """ 81 | 82 | def MACDFIX(df, n, price='Close'): 83 | """ 84 | Moving Average Convergence/Divergence Fix 12/26 85 | """ 86 | 87 | def MFI(df, n, high='High', low='Low', close='Close', volume='Volume'): 88 | """ 89 | Money Flow Index 90 | Returns: list of floats = jhta.MFI(df, n, high='High', low='Low', close='Close', volume='Volume') 91 | Source: https://www.fmlabs.com/reference/default.htm?url=MoneyFlowIndex.htm 92 | """ 93 | mfi_list = [] 94 | typprice_list = jhta.TYPPRICE(df, high, low, close) 95 | mf_pos_list = [] 96 | mf_neg_list = [] 97 | for i in range(len(df[low])): 98 | mf = typprice_list[i] * df[volume][i] 99 | if i + 1 < n: 100 | mfi = float('NaN') 101 | mf_pos_list.append(float('NaN')) 102 | mf_neg_list.append(float('NaN')) 103 | else: 104 | start = i + 1 - n 105 | end = i + 1 106 | if typprice_list[i] > typprice_list[i - 1]: 107 | mf_pos_list.append(mf) 108 | mf_neg_list.append(.0) 109 | else: 110 | mf_pos_list.append(.0) 111 | mf_neg_list.append(mf) 112 | x = sum(mf_pos_list[start:end]) 113 | # FIX ZeroDivisionError: float division by zero: 114 | y = sum(mf_neg_list[start:end]) or .00000001 115 | mr = x / y 116 | mfi = 100 - (100 / (1 + mr)) 117 | mfi_list.append(mfi) 118 | return mfi_list 119 | 120 | def MINUS_DI(df, n): 121 | """ 122 | Minus Directional Indicator 123 | """ 124 | 125 | def MINUS_DM(df, n): 126 | """ 127 | Minus Directional Movement 128 | """ 129 | 130 | def MOM(df, n, price='Close'): 131 | """ 132 | Momentum 133 | Returns: list of floats = jhta.MOM(df, n, price='Close') 134 | Source: https://www.fmlabs.com/reference/default.htm?url=Momentum.htm 135 | """ 136 | mom_list = [] 137 | for i in range(len(df[price])): 138 | if i + 1 < n: 139 | mom = float('NaN') 140 | else: 141 | mom = df[price][i] - df[price][i - n] 142 | mom_list.append(mom) 143 | return mom_list 144 | 145 | def PLUS_DI(df, n): 146 | """ 147 | Plus Directional Indicator 148 | """ 149 | 150 | def PLUS_DM(df, n): 151 | """ 152 | Plus Directional Movement 153 | """ 154 | 155 | def PMOM(df, n, price='Close'): 156 | """ 157 | %Momentum 158 | Returns: list of floats = jhta.PMOM(df, n, price='Close') 159 | """ 160 | pmom_list = [] 161 | mom_list = jhta.MOM(df, n, price) 162 | for i in range(len(df[price])): 163 | if i + 1 < n: 164 | pmom = float('NaN') 165 | else: 166 | pmom = mom_list[i] / df[price][i - n] 167 | pmom_list.append(pmom) 168 | return pmom_list 169 | 170 | def PPO(df, price='Close'): 171 | """ 172 | Percentage Price Oscillator 173 | """ 174 | 175 | def RMI(df, n, price='Close'): 176 | """ 177 | Relative Momentum Index 178 | Returns: list of floats = jhta.RMI(df, n, price='Close') 179 | Source: https://www.fmlabs.com/reference/default.htm?url=RMI.htm 180 | """ 181 | rmi_list = [] 182 | upavg = .0 183 | dnavg = .0 184 | for i in range(len(df[price])): 185 | if i + 1 < n: 186 | rmi = float('NaN') 187 | else: 188 | if df[price][i] > df[price][i - n]: 189 | up = df[price][i] - df[price][i - n] 190 | dn = 0 191 | else: 192 | up = 0 193 | dn = df[price][i - n] - df[price][i] 194 | upavg = (upavg * (n - 1) + up) / n 195 | dnavg = (dnavg * (n - 1) + dn) / n 196 | if (upavg + dnavg) == 0: 197 | rmi = float('NaN') 198 | else: 199 | rmi = 100 * upavg / (upavg + dnavg) 200 | rmi_list.append(rmi) 201 | return rmi_list 202 | 203 | def ROC(df, n, price='Close'): 204 | """ 205 | Rate of change : ((price/prevPrice)-1)*100 206 | Returns: list of floats = jhta.ROC(df, n, price='Close') 207 | """ 208 | roc_list = [] 209 | for i in range(len(df[price])): 210 | if i + 1 < n: 211 | roc = float('NaN') 212 | else: 213 | roc = ((df[price][i] / df[price][i - n]) - 1) * 100 214 | roc_list.append(roc) 215 | return roc_list 216 | 217 | def ROCP(df, n, price='Close'): 218 | """ 219 | Rate of change Percentage: (price-prevPrice)/prevPrice 220 | Returns: list of floats = jhta.ROCP(df, n, price='Close') 221 | """ 222 | rocp_list = [] 223 | for i in range(len(df[price])): 224 | if i + 1 < n: 225 | rocp = float('NaN') 226 | else: 227 | rocp = (df[price][i] - df[price][i - n]) / df[price][i - n] 228 | rocp_list.append(rocp) 229 | return rocp_list 230 | 231 | def ROCR(df, n, price='Close'): 232 | """ 233 | Rate of change ratio: (price/prevPrice) 234 | Returns: list of floats = jhta.ROCR(df, n, price='Close') 235 | """ 236 | rocr_list = [] 237 | for i in range(len(df[price])): 238 | if i + 1 < n: 239 | rocr = float('NaN') 240 | else: 241 | rocr = df[price][i] / df[price][i - n] 242 | rocr_list.append(rocr) 243 | return rocr_list 244 | 245 | def ROCR100(df, n, price='Close'): 246 | """ 247 | Rate of change ratio 100 scale: (price/prevPrice)*100 248 | Returns: list of floats = jhta.ROCR100(df, n, price='Close') 249 | Source: https://www.fmlabs.com/reference/default.htm?url=RateOfChange.htm 250 | """ 251 | rocr100_list = [] 252 | for i in range(len(df[price])): 253 | if i + 1 < n: 254 | rocr100 = float('NaN') 255 | else: 256 | rocr100 = (df[price][i] / df[price][i - n]) * 100 257 | rocr100_list.append(rocr100) 258 | return rocr100_list 259 | 260 | def RSI(df, n, price='Close'): 261 | """ 262 | Relative Strength Index 263 | Returns: list of floats = jhta.RSI(df, n, price='Close') 264 | Source: https://www.fmlabs.com/reference/default.htm?url=rsi.htm 265 | """ 266 | rsi_list = [] 267 | upavg = .0 268 | dnavg = .0 269 | for i in range(len(df[price])): 270 | if i + 1 < n: 271 | rsi = float('NaN') 272 | else: 273 | if df[price][i] > df[price][i - 1]: 274 | up = df[price][i] - df[price][i - 1] 275 | dn = 0 276 | else: 277 | up = 0 278 | dn = df[price][i - 1] - df[price][i] 279 | upavg = (upavg * (n - 1) + up) / n 280 | dnavg = (dnavg * (n - 1) + dn) / n 281 | rsi = 100 * upavg / (upavg + dnavg) 282 | rsi_list.append(rsi) 283 | return rsi_list 284 | 285 | def STOCH(df, n, price='Close'): 286 | """ 287 | Stochastic 288 | Returns: list of floats = jhta.STOCH(df, n, price='Close') 289 | Source: https://www.fmlabs.com/reference/default.htm?url=Stochastic.htm 290 | """ 291 | stoch_list = [] 292 | for i in range(len(df[price])): 293 | if i + 1 < n: 294 | stoch = float('NaN') 295 | else: 296 | start = i + 1 - n 297 | end = i + 1 298 | lowest = min(df[price][start:end]) 299 | highest = max(df[price][start:end]) 300 | stoch = (df[price][i] - lowest) / (highest - lowest) 301 | stoch_list.append(stoch) 302 | return stoch_list 303 | 304 | def STOCHF(df): 305 | """ 306 | Stochastic Fast 307 | """ 308 | 309 | def STOCHRSI(df, n, price='Close'): 310 | """ 311 | Stochastic Relative Strength Index 312 | """ 313 | 314 | def TRIX(df, n, price='Close'): 315 | """ 316 | 1-day Rate-Of-Change (ROC) of a Triple Smooth EMA 317 | """ 318 | 319 | def ULTOSC(df): 320 | """ 321 | Ultimate Oscillator 322 | """ 323 | 324 | def VHF(df, n, price='Close'): 325 | """ 326 | Vertical Horizontal Filter 327 | Returns: list of floats = jhta.VHF(df, n, price='Close') 328 | Source: https://www.fmlabs.com/reference/default.htm?url=VHF.htm 329 | """ 330 | vhf_list = [] 331 | c_list = [] 332 | for i in range(len(df[price])): 333 | if i + 1 < n: 334 | vhf = float('NaN') 335 | c_list.append(float('NaN')) 336 | else: 337 | start = i + 1 - n 338 | end = i + 1 339 | highest = max(df[price][start:end]) 340 | lowest = min(df[price][start:end]) 341 | c0 = df[price][i] 342 | c1 = df[price][i - 1] 343 | c = (c0 - c1) / c1 344 | c_list.append(c) 345 | c_sum = sum(c_list[start:end]) 346 | vhf = (highest - lowest) / c_sum 347 | vhf_list.append(vhf) 348 | return vhf_list 349 | 350 | def WILLR(df, n, high='High', low='Low', close='Close'): 351 | """ 352 | Williams' %R 353 | Returns: list of floats = jhta.WILLR(df, n, high='High', low='Low', close='Close') 354 | Source: https://www.fmlabs.com/reference/default.htm?url=WilliamsR.htm 355 | """ 356 | willr_list = [] 357 | for i in range(len(df[close])): 358 | if i + 1 < n: 359 | willr = float('NaN') 360 | else: 361 | start = i + 1 - n 362 | end = i + 1 363 | willr = (max(df[high][start:end]) - df[close][i]) / (max(df[high][start:end]) - min(df[low][start:end])) * 100 364 | # willr *= -1 365 | willr_list.append(willr) 366 | return willr_list 367 | 368 | -------------------------------------------------------------------------------- /jhtalib/money_management/__init__.py: -------------------------------------------------------------------------------- 1 | from .money_management import * 2 | 3 | -------------------------------------------------------------------------------- /jhtalib/money_management/money_management.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | 4 | # Import Third-Party: 5 | 6 | # Import Homebrew: 7 | import jhtalib as jhta 8 | 9 | 10 | def EV(hitrate_float, mean_trade_profit_float, mean_trade_loss_float): 11 | """ 12 | Expected Value 13 | Returns: float = jhta.EV(hitrade_float, mean_trade_profit_float, mean_trade_loss_float) 14 | Source: https://en.wikipedia.org/wiki/Expected_value 15 | """ 16 | return float((hitrate_float * mean_trade_profit_float) + ((1 - hitrate_float) * mean_trade_loss_float * -1)) 17 | 18 | def HR(hit_trades_int, total_trades_int): 19 | """ 20 | Hit Rate / Win Rate 21 | Returns: float = jhta.HR(hit_trades_int, total_trades_int) 22 | """ 23 | return float(hit_trades_int / total_trades_int) 24 | 25 | def KELLY(hitrate_float, profit_loss_ratio_float): 26 | """ 27 | Kelly Criterion (Bet Size) 28 | Returns: float = jhta.KELLY(hitrate_float, profit_loss_ratio_float) 29 | Source: https://www.investopedia.com/terms/k/kellycriterion.asp 30 | """ 31 | W = hitrate_float 32 | R = profit_loss_ratio_float 33 | return float(W - (1 - W) / R) 34 | 35 | def PLR(mean_trade_profit_float, mean_trade_loss_float): 36 | """ 37 | Profit/Loss Ratio 38 | Returns: float = jhta.PLR(mean_trade_profit_float, mean_trade_loss_float) 39 | Source: https://www.investopedia.com/terms/p/profit_loss_ratio.asp 40 | """ 41 | return float(mean_trade_profit_float / mean_trade_loss_float) 42 | 43 | def POR(hitrate_float, profit_loss_ratio_float): 44 | """ 45 | Probability of Ruin (Table of Lucas and LeBeau) 46 | Returns: int = jhta.POR(hitrade_float, profit_loss_ratio_float) 47 | Source: book: Computer Analysis of the Futures Markets 48 | """ 49 | hitrate_list = [.0, .25, .3, .35, .4, .45, .5, .55, .6, .65, .7] 50 | profit_loss_ratio_list = [.0, .75, 1, 1.5, 2, 2.5, 3, 3.5, 4] 51 | 52 | table_lucas_lebeau_list = [ 53 | [100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100], 54 | [100, 100, 100, 100, 100, 100, 98, 77, 15, 1, 0], 55 | [100, 100, 100, 100, 99, 92, 50, 7, 1, 0, 0], 56 | [100, 100, 99, 90, 50, 12, 2, 0, 0, 0, 0], 57 | [100, 97, 79, 35, 9, 2, 1, 0, 0, 0, 0], 58 | [100, 79, 38, 12, 4, 1, 0, 0, 0, 0, 0], 59 | [100, 50, 19, 6, 2, 1, 0, 0, 0, 0, 0], 60 | [100, 31, 12, 5, 2, 1, 0, 0, 0, 0, 0], 61 | [100, 21, 9, 4, 2, 1, 0, 0, 0, 0, 0] 62 | ] 63 | 64 | key_hitrate = 0 65 | for i in range(len(hitrate_list)): 66 | if hitrate_float >= hitrate_list[i]: 67 | key_hitrate = i 68 | 69 | key_profit_loss_ratio = 0 70 | for i in range(len(profit_loss_ratio_list)): 71 | if profit_loss_ratio_float >= profit_loss_ratio_list[i]: 72 | key_profit_loss_ratio = i 73 | 74 | return int(table_lucas_lebeau_list[key_profit_loss_ratio][key_hitrate]) 75 | 76 | -------------------------------------------------------------------------------- /jhtalib/overlap_studies/__init__.py: -------------------------------------------------------------------------------- 1 | from .overlap_studies import * 2 | 3 | -------------------------------------------------------------------------------- /jhtalib/overlap_studies/overlap_studies.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | 4 | # Import Third-Party: 5 | 6 | # Import Homebrew: 7 | import jhtalib as jhta 8 | 9 | 10 | def BBANDS(df, n, f=2, high='High', low='Low', close='Close'): 11 | """ 12 | Bollinger Bands 13 | Returns: dict of lists of floats = jhta.BBANDS(df, n, f=2, high='High', low='Low', close='Close') 14 | Source: https://www.fmlabs.com/reference/default.htm?url=Bollinger.htm 15 | """ 16 | bbands_dict = {'midband': [], 'upperband': [], 'lowerband': []} 17 | tp_dict = {'tp': jhta.TYPPRICE(df, high, low, close)} 18 | sma_list = jhta.SMA(tp_dict, n, 'tp') 19 | stdev_list = jhta.STDEV(tp_dict, n, 'tp') 20 | for i in range(len(df[close])): 21 | if i + 1 < n: 22 | midband = float('NaN') 23 | upperband = float('NaN') 24 | lowerband = float('NaN') 25 | else: 26 | midband = sma_list[i] 27 | upperband = midband + f * stdev_list[i] 28 | lowerband = midband - f * stdev_list[i] 29 | bbands_dict['midband'].append(midband) 30 | bbands_dict['upperband'].append(upperband) 31 | bbands_dict['lowerband'].append(lowerband) 32 | return bbands_dict 33 | 34 | def BBANDW(df, n, f=2, high='High', low='Low', close='Close'): 35 | """ 36 | Bollinger Band Width 37 | Returns: list of floats = jhta.BBANDW(df, n, f=2, high='High', low='Low', close='Close') 38 | Source: https://www.fmlabs.com/reference/default.htm?url=BollingerWidth.htm 39 | """ 40 | bbandw_list = [] 41 | tp_dict = {'tp': jhta.TYPPRICE(df, high, low, close)} 42 | stdev_list = jhta.STDEV(tp_dict, n, 'tp') 43 | for i in range(len(df[close])): 44 | if i + 1 < n: 45 | bbandw = float('NaN') 46 | else: 47 | bbandw = 2 * f * stdev_list[i] 48 | bbandw_list.append(bbandw) 49 | return bbandw_list 50 | 51 | def DEMA(df, n): 52 | """ 53 | Double Exponential Moving Average 54 | """ 55 | 56 | def EMA(df, n, price='Close'): 57 | """ 58 | Exponential Moving Average 59 | Returns: list of floats = jhta.EMA(df, n, price='Close') 60 | Source: https://www.fmlabs.com/reference/default.htm?url=ExpMA.htm 61 | """ 62 | ema_list = [] 63 | for i in range(len(df[price])): 64 | if i + 1 < n: 65 | ema = float('NaN') 66 | else: 67 | if ema != ema: 68 | ema = df[price][i] 69 | k = 2 / (n + 1) 70 | ema = k * df[price][i] + (1 - k) * ema 71 | ema_list.append(ema) 72 | return ema_list 73 | 74 | def ENVP(df, pct=.01, price='Close'): 75 | """ 76 | Envelope Percent 77 | Returns: dict of lists of floats = jhta.ENVP(df, pct=.01, price='Close') 78 | Source: https://www.fmlabs.com/reference/default.htm?url=EnvelopePct.htm 79 | """ 80 | envp_dict = {'hi': [], 'lo': []} 81 | for i in range(len(df[price])): 82 | hi = df[price][i] + df[price][i] * pct 83 | lo = df[price][i] - df[price][i] * pct 84 | envp_dict['hi'].append(hi) 85 | envp_dict['lo'].append(lo) 86 | return envp_dict 87 | 88 | def EWMA(df, n, price='Close'): 89 | """ 90 | Exponential Weighted Moving Average (EWMA) 91 | Returns: list of floats = jhta.EWMA(df, n, price='Close') 92 | """ 93 | alpha = 2 / (n + 1) 94 | ewma_list = [float('NaN')] * (n - 1) 95 | 96 | ewma = df[price][n - 1] 97 | ewma_list.append(ewma) 98 | 99 | for i in range(n, len(df[price])): 100 | ewma = alpha * df[price][i] + (1 - alpha) * ewma 101 | ewma_list.append(ewma) 102 | 103 | return ewma_list 104 | 105 | def KAMA(df, n): 106 | """ 107 | Kaufman Adaptive Moving Average 108 | """ 109 | 110 | def MA(df, n): 111 | """ 112 | Moving average 113 | """ 114 | 115 | def MAMA(df, price='Close'): 116 | """ 117 | MESA Adaptive Moving Average 118 | """ 119 | 120 | def MAVP(df, price='Close'): 121 | """ 122 | Moving average with variable period 123 | """ 124 | 125 | def MIDPOINT(df, n, price='Close'): 126 | """ 127 | MidPoint over period 128 | Returns: list of floats = jhta.MIDPOINT(df, n, price='Close') 129 | Source: http://www.tadoc.org/indicator/MIDPOINT.htm 130 | """ 131 | midpoint_list = [] 132 | for i in range(len(df[price])): 133 | if i + 1 < n: 134 | midpoint = float('NaN') 135 | else: 136 | start = i + 1 - n 137 | end = i + 1 138 | midpoint = (max(df[price][start:end]) + min(df[price][start:end])) / 2 139 | midpoint_list.append(midpoint) 140 | return midpoint_list 141 | 142 | def MIDPRICE(df, n, high='High', low='Low'): 143 | """ 144 | Midpoint Price over period 145 | Returns: list of floats = jhta.MIDPRICE(df, n, high='High', low='Low') 146 | Source: http://www.tadoc.org/indicator/MIDPRICE.htm 147 | """ 148 | midprice_list = [] 149 | for i in range(len(df[low])): 150 | if i + 1 < n: 151 | midprice = float('NaN') 152 | else: 153 | start = i + 1 - n 154 | end = i + 1 155 | midprice = (max(df[high][start:end]) + min(df[low][start:end])) / 2 156 | midprice_list.append(midprice) 157 | return midprice_list 158 | 159 | def MMR(df, n=200, price='Close'): 160 | """ 161 | Mayer Multiple Ratio 162 | Returns: list of floats = jhta.MMR(df, n=200, price='Close') 163 | Source: https://www.theinvestorspodcast.com/bitcoin-mayer-multiple/ 164 | """ 165 | mmr_list = [] 166 | sma_list = jhta.SMA(df, n, price) 167 | for i in range(len(df[price])): 168 | if i + 1 < n: 169 | mmr = float('NaN') 170 | else: 171 | mmr = df[price][i] / sma_list[i] 172 | mmr_list.append(mmr) 173 | return mmr_list 174 | 175 | def SAR(df, af_step=.02, af_max=.2, high='High', low='Low'): 176 | """ 177 | Parabolic SAR (J. Welles Wilder) 178 | Returns: list of floats = jhta.SAR(df, af_step=.02, af_max=.2, high='High', low='Low') 179 | Source: book: New Concepts in Technical Trading Systems 180 | """ 181 | sar_list = [] 182 | for i in range(len(df[low])): 183 | if i < 1: 184 | sar = float('NaN') 185 | sar_list.append(sar) 186 | is_long = True 187 | sar = df[low][i] 188 | ep = df[high][i] 189 | af = af_step 190 | else: 191 | if is_long: 192 | if df[low][i] <= sar: 193 | is_long = False 194 | sar = ep 195 | if sar < df[high][i - 1]: 196 | sar = df[high][i - 1] 197 | if sar < df[high][i]: 198 | sar = df[high][i] 199 | sar_list.append(sar) 200 | af = af_step 201 | ep = df[low][i] 202 | sar = sar + af * (ep - sar) 203 | # sar = round(sar) 204 | if sar < df[high][i - 1]: 205 | sar = df[high][i - 1] 206 | if sar < df[high][i]: 207 | sar = df[high][i] 208 | else: 209 | sar_list.append(sar) 210 | if df[high][i] > ep: 211 | ep = df[high][i] 212 | af += af_step 213 | if af > af_max: 214 | af = af_max 215 | sar = sar + af * (ep - sar) 216 | # sar = round(sar) 217 | if sar > df[low][i - 1]: 218 | sar = df[low][i - 1] 219 | if sar > df[low][i]: 220 | sar = df[low][i] 221 | else: 222 | if df[high][i] >= sar: 223 | is_long = True 224 | sar = ep 225 | if sar > df[low][i - 1]: 226 | sar = df[low][i - 1] 227 | if sar > df[low][i]: 228 | sar = df[low][i] 229 | sar_list.append(sar) 230 | af = af_step 231 | ep = df[high][i] 232 | sar = sar + af * (ep - sar) 233 | # sar = round(sar) 234 | if sar > df[low][i - 1]: 235 | sar = df[low][i - 1] 236 | if sar > df[low][i]: 237 | sar = df[low][i] 238 | else: 239 | sar_list.append(sar) 240 | if df[low][i] < ep: 241 | ep = df[low][i] 242 | af += af_step 243 | if af > af_max: 244 | af = af_max 245 | sar = sar + af * (ep - sar) 246 | # sar = round(sar) 247 | if sar < df[high][i - 1]: 248 | sar = df[high][i - 1] 249 | if sar < df[high][i]: 250 | sar = df[high][i] 251 | return sar_list 252 | 253 | def SAREXT(df): 254 | """ 255 | Parabolic SAR - Extended 256 | """ 257 | 258 | def SMA(df, n, price='Close'): 259 | """ 260 | Simple Moving Average 261 | Returns: list of floats = jhta.SMA(df, n, price='Close') 262 | Source: https://www.fmlabs.com/reference/default.htm?url=SimpleMA.htm 263 | """ 264 | sma_list = [] 265 | for i in range(len(df[price])): 266 | if i + 1 < n: 267 | sma = float('NaN') 268 | else: 269 | start = i + 1 - n 270 | end = i + 1 271 | sma = sum(df[price][start:end]) / n 272 | sma_list.append(sma) 273 | return sma_list 274 | 275 | def T3(df, n, price='Close'): 276 | """ 277 | Triple Exponential Moving Average (T3) 278 | """ 279 | 280 | def TEMA(df, n, price='Close'): 281 | """ 282 | Triple Exponential Moving Average 283 | """ 284 | 285 | def TRIMA(df, n, price='Close'): 286 | """ 287 | Triangular Moving Average 288 | Returns: list of floats = jhta.TRIMA(df, n, price='Close') 289 | Source: https://www.fmlabs.com/reference/default.htm?url=TriangularMA.htm 290 | """ 291 | tma_list = [] 292 | sma_list = [] 293 | for i in range(len(df[price])): 294 | if n % 2 == 0: 295 | n_sma = n / 2 + 1 296 | start = i + 1 - n_sma 297 | end = i + 1 298 | sma = sum(df[price][start:end]) / n_sma 299 | sma_list.append(sma) 300 | n_tma = n / 2 301 | start = i + 1 - n_tma 302 | end = i + 1 303 | else: 304 | n_sma = (n + 1) / 2 305 | start = i + 1 - n_sma 306 | end = i + 1 307 | sma = sum(df[price][start:end]) / n_sma 308 | sma_list.append(sma) 309 | n_tma = (n + 1) / 2 310 | start = i + 1 - n_tma 311 | end = i + 1 312 | if i + 1 < n: 313 | tma = float('NaN') 314 | else: 315 | tma = sum(sma_list[start:end]) / n_tma 316 | tma_list.append(tma) 317 | return tma_list 318 | 319 | def VAMA(df, n, price='Close', volume='Volume'): 320 | """ 321 | Volume Adjusted Moving Average 322 | Returns: list of floats = jhta.VAMA(df, n, price='Close', volume='Volume') 323 | Source: https://www.fmlabs.com/reference/default.htm?url=VolAdjustedMA.htm 324 | """ 325 | vama_list = [] 326 | pv_list = [] 327 | for i in range(len(df[price])): 328 | if i + 1 < n: 329 | vama = float('NaN') 330 | pv = float('NaN') 331 | pv_list.append(pv) 332 | else: 333 | start = i + 1 - n 334 | end = i + 1 335 | pv = df[price][i] * df[volume][i] 336 | pv_list.append(pv) 337 | vama = sum(pv_list[start:end]) / sum(df[volume][start:end]) 338 | vama_list.append(vama) 339 | return vama_list 340 | 341 | def WMA(df, n, price='Close'): 342 | """ 343 | Weighted Moving Average 344 | """ 345 | 346 | def WWMA(df, n, price='Close'): 347 | """ 348 | Welles Wilder Moving Average 349 | Returns: list of floats = jhta.WWMA(df, n, price='Close') 350 | Source: https://www.fmlabs.com/reference/default.htm?url=WellesMA.htm 351 | """ 352 | wwma_list = [] 353 | for i in range(len(df[price])): 354 | if i + 1 < n: 355 | wwma = float('NaN') 356 | wwma_list.append(wwma) 357 | wwma = df[price][i] 358 | else: 359 | wwma = (wwma * (n - 1) + df[price][i]) / n 360 | wwma_list.append(wwma) 361 | return wwma_list 362 | 363 | def WWS(df, n, price='Close'): 364 | """ 365 | Welles Wilder Summation 366 | Returns: list of floats = jhta.WWS(df, n, price='Close') 367 | Source: https://www.fmlabs.com/reference/default.htm?url=WellesSum.htm 368 | """ 369 | wws_list = [] 370 | for i in range(len(df[price])): 371 | if i + 1 < n: 372 | wws = float('NaN') 373 | wws_list.append(wws) 374 | wws = df[price][i] 375 | else: 376 | start = i + 1 - n 377 | end = i + 1 378 | wws = wws - (sum(df[price][start:end]) / n) + df[price][i] 379 | wws_list.append(wws) 380 | return wws_list 381 | 382 | -------------------------------------------------------------------------------- /jhtalib/pattern_recognition/__init__.py: -------------------------------------------------------------------------------- 1 | from .pattern_recognition import * 2 | 3 | -------------------------------------------------------------------------------- /jhtalib/pattern_recognition/pattern_recognition.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | 4 | # Import Third-Party: 5 | 6 | # Import Homebrew: 7 | import jhtalib as jhta 8 | 9 | 10 | def CDL2CROWS(df): 11 | """ 12 | Two Crows 13 | """ 14 | 15 | def CDL3BLACKCROWS(df): 16 | """ 17 | Three Black Crows 18 | """ 19 | 20 | def CDL3INSIDE(df): 21 | """ 22 | Three Inside Up/Down 23 | """ 24 | 25 | def CDL3LINESTRIKE(df): 26 | """ 27 | Three-Line Strike 28 | """ 29 | 30 | def CDL3OUTSIDE(df): 31 | """ 32 | Three Outside Up/Down 33 | """ 34 | 35 | def CDL3STARSINSOUTH(df): 36 | """ 37 | Three Stars In The South 38 | """ 39 | 40 | def CDL3WHITESOLDIERS(df): 41 | """ 42 | Three Advancing White Soldiers 43 | """ 44 | 45 | def CDLABANDONEDBABY(df): 46 | """ 47 | Abandoned Baby 48 | """ 49 | 50 | def CDLADVANCEBLOCK(df): 51 | """ 52 | Advance Block 53 | """ 54 | 55 | def CDLBELTHOLD(df): 56 | """ 57 | Belt-hold 58 | """ 59 | 60 | def CDLBREAKAWAY(df): 61 | """ 62 | Breakaway 63 | """ 64 | 65 | def CDLCLOSINGMARUBOZU(df): 66 | """ 67 | Closing Marubozu 68 | """ 69 | 70 | def CDLCONSEALBABYSWALL(df): 71 | """ 72 | Concealing Baby Swallow 73 | """ 74 | 75 | def CDLCOUNTERATTACK(df): 76 | """ 77 | Counterattack 78 | """ 79 | 80 | def CDLDARKCLOUDCOVER(df): 81 | """ 82 | Dark Cloud Cover 83 | """ 84 | 85 | def CDLDOJI(df): 86 | """ 87 | Doji 88 | """ 89 | 90 | def CDLDOJISTAR(df): 91 | """ 92 | Doji Star 93 | """ 94 | 95 | def CDLDRAGONFLYDOJI(df): 96 | """ 97 | Dragonfly Doji 98 | """ 99 | 100 | def CDLENGULFING(df): 101 | """ 102 | Engulfing Pattern 103 | """ 104 | 105 | def CDLEVENINGDOJISTAR(df): 106 | """ 107 | Evening Doji Star 108 | """ 109 | 110 | def CDLEVENINGSTAR(df): 111 | """ 112 | Evening Star 113 | """ 114 | 115 | def CDLGAPSIDESIDEWHITE(df): 116 | """ 117 | Up/Down-gap side-by-side white lines 118 | """ 119 | 120 | def CDLGRAVESTONEDOJI(df): 121 | """ 122 | Gravestone Doji 123 | """ 124 | 125 | def CDLHAMMER(df): 126 | """ 127 | Hammer 128 | """ 129 | 130 | def CDLHANGINGMAN(df): 131 | """ 132 | Hanging Man 133 | """ 134 | 135 | def CDLHARAMI(df): 136 | """ 137 | Harami Pattern 138 | """ 139 | 140 | def CDLHARAMICROSS(df): 141 | """ 142 | Harami Cross Pattern 143 | """ 144 | 145 | def CDLHIGHWAVE(df): 146 | """ 147 | High-Wave Candle 148 | """ 149 | 150 | def CDLHIKKAKE(df): 151 | """ 152 | Hikkake Pattern 153 | """ 154 | 155 | def CDLHIKKAKEMOD(df): 156 | """ 157 | Modified Hikkake Pattern 158 | """ 159 | 160 | def CDLHOMINGPIGEON(df): 161 | """ 162 | Homing Pigeon 163 | """ 164 | 165 | def CDLIDENTICAL3CROWS(df): 166 | """ 167 | Identical Three Crows 168 | """ 169 | 170 | def CDLINNECK(df): 171 | """ 172 | In-Neck Pattern 173 | """ 174 | 175 | def CDLINVERTEDHAMMER(df): 176 | """ 177 | Inverted Hammer 178 | """ 179 | 180 | def CDLKICKING(df): 181 | """ 182 | Kicking 183 | """ 184 | 185 | def CDLKICKINGBYLENGTH(df): 186 | """ 187 | Kicking - bull/bear determined by the longer marubozu 188 | """ 189 | 190 | def CDLLADDERBOTTOM(df): 191 | """ 192 | Ladder Bottom 193 | """ 194 | 195 | def CDLLONGLEGGEDDOJI(df): 196 | """ 197 | Long Legged Doji 198 | """ 199 | 200 | def CDLLONGLINE(df): 201 | """ 202 | Long Line Candle 203 | """ 204 | 205 | def CDLMARUBOZU(df): 206 | """ 207 | Marubozu 208 | """ 209 | 210 | def CDLMATCHINGLOW(df): 211 | """ 212 | Matching Low 213 | """ 214 | 215 | def CDLMATHOLD(df): 216 | """ 217 | Mat Hold 218 | """ 219 | 220 | def CDLMORNINGDOJISTAR(df): 221 | """ 222 | Morning Doji Star 223 | """ 224 | 225 | def CDLMORNINGSTAR(df): 226 | """ 227 | Morning Star 228 | """ 229 | 230 | def CDLONNECK(df): 231 | """ 232 | On-Neck Pattern 233 | """ 234 | 235 | def CDLPIERCING(df): 236 | """ 237 | Piercing Pattern 238 | """ 239 | 240 | def CDLRICKSHAWMAN(df): 241 | """ 242 | Rickshaw Man 243 | """ 244 | 245 | def CDLRISEFALL3METHODS(df): 246 | """ 247 | Rising/Falling Three Methods 248 | """ 249 | 250 | def CDLSEPARATINGLINES(df): 251 | """ 252 | Separating Lines 253 | """ 254 | 255 | def CDLSHOOTINGSTAR(df): 256 | """ 257 | Shooting Star 258 | """ 259 | 260 | def CDLSHORTLINE(df): 261 | """ 262 | Short Line Candle 263 | """ 264 | 265 | def CDLSPINNINGTOP(df): 266 | """ 267 | Spinning Top 268 | """ 269 | 270 | def CDLSTALLEDPATTERN(df): 271 | """ 272 | Stalled Pattern 273 | """ 274 | 275 | def CDLSTICKSANDWICH(df): 276 | """ 277 | Stick Sandwich 278 | """ 279 | 280 | def CDLTAKURI(df): 281 | """ 282 | Takuri (Dragonfly Doji with very long lower shadow) 283 | """ 284 | 285 | def CDLTASUKIGAP(df): 286 | """ 287 | Tasuki Gap 288 | """ 289 | 290 | def CDLTHRUSTING(df): 291 | """ 292 | Thrusting Pattern 293 | """ 294 | 295 | def CDLTRISTAR(df): 296 | """ 297 | Tristar Pattern 298 | """ 299 | 300 | def CDLUNIQUE3RIVER(df): 301 | """ 302 | Unique 3 River 303 | """ 304 | 305 | def CDLUPSIDEGAP2CROWS(df): 306 | """ 307 | Upside Gap Two Crows 308 | """ 309 | 310 | def CDLXSIDEGAP3METHODS(df): 311 | """ 312 | Upside/Downside Gap Three Methods 313 | """ 314 | 315 | -------------------------------------------------------------------------------- /jhtalib/price_transform/__init__.py: -------------------------------------------------------------------------------- 1 | from .price_transform import * 2 | 3 | -------------------------------------------------------------------------------- /jhtalib/price_transform/price_transform.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | 4 | # Import Third-Party: 5 | 6 | # Import Homebrew: 7 | import jhtalib as jhta 8 | 9 | 10 | def AVGPRICE(df, open='Open', high='High', low='Low', close='Close'): 11 | """ 12 | Average Price 13 | Returns: list of floats = jhta.AVGPRICE(df, open='Open', high='High', low='Low', close='Close') 14 | Source: https://www.fmlabs.com/reference/default.htm?url=AvgPrices.htm 15 | """ 16 | avgprice_list = [] 17 | for i in range(len(df[close])): 18 | avgprice = (df[open][i] + df[high][i] + df[low][i] + df[close][i]) / 4 19 | avgprice_list.append(avgprice) 20 | return avgprice_list 21 | 22 | def MEDPRICE(df, high='High', low='Low'): 23 | """ 24 | Median Price 25 | Returns: list of floats = jhta.MEDPRICE(df, high='High', low='Low') 26 | Source: https://www.fmlabs.com/reference/default.htm?url=MedianPrices.htm 27 | """ 28 | return [(df[high][i] + df[low][i]) / 2 for i in range(len(df[low]))] 29 | 30 | def TYPPRICE(df, high='High', low='Low', close='Close'): 31 | """ 32 | Typical Price 33 | Returns: list of floats = jhta.TYPPRICE(df, high='High', low='Low', close='Close') 34 | Source: https://www.fmlabs.com/reference/default.htm?url=TypicalPrices.htm 35 | """ 36 | typprice_list = [] 37 | for i in range(len(df[close])): 38 | typprice = (df[high][i] + df[low][i] + df[close][i]) / 3 39 | typprice_list.append(typprice) 40 | return typprice_list 41 | 42 | def WCLPRICE(df, high='High', low='Low', close='Close'): 43 | """ 44 | Weighted Close Price 45 | Returns: list of floats = jhta.WCLPRICE(df, high='High', low='Low', close='Close') 46 | Source: https://www.fmlabs.com/reference/default.htm?url=WeightedCloses.htm 47 | """ 48 | wclprice_list = [] 49 | for i in range(len(df[close])): 50 | wclprice = (df[high][i] + df[low][i] + (df[close][i] * 2)) / 4 51 | wclprice_list.append(wclprice) 52 | return wclprice_list 53 | 54 | -------------------------------------------------------------------------------- /jhtalib/statistic_functions/__init__.py: -------------------------------------------------------------------------------- 1 | from .statistic_functions import * 2 | 3 | -------------------------------------------------------------------------------- /jhtalib/uncategorised/__init__.py: -------------------------------------------------------------------------------- 1 | from .uncategorised import * 2 | 3 | -------------------------------------------------------------------------------- /jhtalib/uncategorised/uncategorised.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | import cmath 4 | 5 | # Import Third-Party: 6 | 7 | # Import Homebrew: 8 | import jhtalib as jhta 9 | 10 | 11 | def BPPS(trade_start_price, trade_end_price, trade_start_timestamp, trade_end_timestamp): 12 | """ 13 | Basis Points per Second 14 | Returns: float = jhta.BPPS(trade_start_price, trade_end_price, trade_start_timestamp, trade_end_timestamp) 15 | Source: book: An Introduction to Algorithmic Trading 16 | """ 17 | return (((trade_end_price - trade_start_price) / trade_start_price) / (trade_end_timestamp - trade_start_timestamp)) * 10000 18 | 19 | def PRET(df, price='Close'): 20 | """ 21 | %Return 22 | Returns: list of floats = jhta.PRET(df, price='Close') 23 | Source: book: An Introduction to Algorithmic Trading 24 | """ 25 | pret_list = [] 26 | ret_list = jhta.RET(df, price) 27 | for i in range(len(df[price])): 28 | if i < 1: 29 | pret = float('NaN') 30 | else: 31 | pret = ret_list[i] / df[price][i - 1] 32 | pret_list.append(pret) 33 | return pret_list 34 | 35 | def PRETLOG(df, price='Close'): 36 | """ 37 | %Return Log 38 | Returns: list of floats = jhta.PRETLOG(df, price='Close') 39 | Source: https://fintechprofessor.com/2017/12/02/log-vs-simple-returns-examples-and-comparisons/ 40 | """ 41 | pretlog_list = [] 42 | for i in range(len(df[price])): 43 | if i < 1: 44 | pretlog = float('NaN') 45 | else: 46 | pretlog = cmath.log(df[price][i] / df[price][i - 1]).real 47 | pretlog_list.append(pretlog) 48 | return pretlog_list 49 | 50 | def PRETS(df, price='Close'): 51 | """ 52 | %Returns 53 | Returns: list of floats = jhta.PRETS(df, price='Close') 54 | Source: book: An Introduction to Algorithmic Trading 55 | """ 56 | prets_list = [] 57 | pret_list = jhta.PRET(df, price) 58 | for i in range(len(df[price])): 59 | if i < 1: 60 | prets = float('NaN') 61 | prets_list.append(prets) 62 | prets = .0 63 | else: 64 | prets = prets + pret_list[i] 65 | prets_list.append(prets) 66 | return prets_list 67 | 68 | def PRETSLOG(df, price='Close'): 69 | """ 70 | %Returns Log 71 | Returns: list of floats = jhta.PRETSLOG(df, price='Close') 72 | """ 73 | pretslog_list = [] 74 | pretlog_list = jhta.PRETLOG(df, price) 75 | for i in range(len(df[price])): 76 | if i < 1: 77 | pretslog = float('NaN') 78 | pretslog_list.append(pretslog) 79 | pretslog = .0 80 | else: 81 | pretslog = pretslog + pretlog_list[i] 82 | pretslog_list.append(pretslog) 83 | return pretslog_list 84 | 85 | def RET(df, price='Close'): 86 | """ 87 | Return 88 | Returns: list of floats = jhta.RET(df, price='Close') 89 | Source: book: An Introduction to Algorithmic Trading 90 | """ 91 | ret_list = [] 92 | for i in range(len(df[price])): 93 | if i < 1: 94 | ret = float('NaN') 95 | else: 96 | ret = df[price][i] - df[price][i - 1] 97 | ret_list.append(ret) 98 | return ret_list 99 | 100 | def RETLOG(df, price='Close'): 101 | """ 102 | Return Log 103 | Returns: list of floats = jhta.RETLOG(df, price='Close') 104 | Source: https://fintechprofessor.com/2017/12/02/log-vs-simple-returns-examples-and-comparisons/ 105 | """ 106 | ret_list = jhta.RET(df, price) 107 | return jhta.LOG({'ret': ret_list}, 'ret') 108 | 109 | def RETS(df, price='Close'): 110 | """ 111 | Returns 112 | Returns: list of floats = jhta.RETS(df, price='Close') 113 | Source: book: An Introduction to Algorithmic Trading 114 | """ 115 | rets_list = [] 116 | ret_list = jhta.RET(df, price) 117 | for i in range(len(df[price])): 118 | if i < 1: 119 | rets = float('NaN') 120 | rets_list.append(rets) 121 | rets = .0 122 | else: 123 | rets = rets + ret_list[i] 124 | rets_list.append(rets) 125 | return rets_list 126 | 127 | def RETSLOG(df, price='Close'): 128 | """ 129 | Returns Log 130 | Returns: list of floats = jhta.RETSLOG(df, price='Close') 131 | """ 132 | retslog_list = [] 133 | retlog_list = jhta.RETLOG(df, price) 134 | for i in range(len(df[price])): 135 | if i < 1: 136 | retslog = float('NaN') 137 | retslog_list.append(retslog) 138 | retslog = .0 139 | else: 140 | retslog = retslog + retlog_list[i] 141 | retslog_list.append(retslog) 142 | return retslog_list 143 | 144 | -------------------------------------------------------------------------------- /jhtalib/volatility_indicators/__init__.py: -------------------------------------------------------------------------------- 1 | from .volatility_indicators import * 2 | 3 | -------------------------------------------------------------------------------- /jhtalib/volatility_indicators/volatility_indicators.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | import math 4 | import statistics 5 | 6 | # Import Third-Party: 7 | 8 | # Import Homebrew: 9 | import jhtalib as jhta 10 | 11 | 12 | def AEM(df, high='High', low='Low', volume='Volume'): 13 | """ 14 | Arms Ease of Movement 15 | Returns: list of floats = jhta.AEM(df, high='High', low='Low', volume='Volume') 16 | Source: https://www.fmlabs.com/reference/default.htm?url=ArmsEMV.htm 17 | """ 18 | aem_list = [] 19 | for i in range(len(df[low])): 20 | if i < 1: 21 | aem = float('NaN') 22 | else: 23 | midpoint_move = ((df[high][i] - df[low][i]) / 2) - ((df[high][i - 1] - df[low][i - 1]) / 2) 24 | boxratio = (df[volume][i] / 10000) / (df[high][i] - df[low][i]) 25 | aem = midpoint_move / boxratio 26 | aem_list.append(aem) 27 | return aem_list 28 | 29 | def ATR(df, n, high='High', low='Low', close='Close'): 30 | """ 31 | Average True Range 32 | Returns: list of floats = jhta.ATR(df, n, high='High', low='Low', close='Close') 33 | Source: https://www.fmlabs.com/reference/default.htm?url=ATR.htm 34 | """ 35 | tr_list = jhta.TRANGE(df, high, low, close) 36 | atr_list = [] 37 | for i in range(len(df[close])): 38 | if i + 1 < n: 39 | atr = float('NaN') 40 | else: 41 | atr = ((tr_list[i - 1] * (n - 1)) + tr_list[i]) / n 42 | atr_list.append(atr) 43 | return atr_list 44 | 45 | def AVOLA(df, n=30, na=252, price='Close'): 46 | """ 47 | Annual Volatility 48 | Returns: list of floats = jhta.AVOLA(df, n=30, na=252, price='Close') 49 | Source: https://www.wallstreetmojo.com/volatility-formula/ 50 | """ 51 | dvola_list = jhta.DVOLA(df, n, price) 52 | avola_list = [] 53 | for i in range(len(df[price])): 54 | if i + 1 < n: 55 | avola = float('NaN') 56 | else: 57 | avola = math.sqrt(na) * dvola_list[i] 58 | avola_list.append(avola) 59 | return avola_list 60 | 61 | def DVOLA(df, n=30, price='Close'): 62 | """ 63 | Daily Volatility 64 | Returns: list of floats = jhta.DVOLA(df, n=30, price='Close') 65 | Source: https://www.wallstreetmojo.com/volatility-formula/ 66 | """ 67 | dvola_list = [] 68 | for i in range(len(df[price])): 69 | if i + 1 < n: 70 | dvola = float('NaN') 71 | else: 72 | start = i + 1 - n 73 | end = i + 1 74 | pvariance = statistics.pvariance(df[price][start:end]) 75 | dvola = math.sqrt(pvariance) 76 | dvola_list.append(dvola) 77 | return dvola_list 78 | 79 | def HVOL(df, n, scaling_factor=252, price='Close'): 80 | """ 81 | Historical Volatility 82 | Returns: list of floats = jhta.HVOL(df, n, scaling_factor=252, price='Close') 83 | """ 84 | hvol_list = [] 85 | for i in range(len(df[price])): 86 | if i + 1 < n: 87 | hvol = float('NaN') 88 | else: 89 | start = i + 1 - n 90 | end = i + 1 91 | data = df[price][start:end] 92 | returns = [(data[i] / data[i - 1] - 1) for i in range(1, len(data))] 93 | mean = sum(returns) / len(returns) 94 | variance = sum((r - mean) ** 2 for r in returns) / (len(returns) - 1) 95 | hvol = (variance ** 0.5) * (scaling_factor ** 0.5) 96 | hvol_list.append(hvol) 97 | return hvol_list 98 | 99 | def INERTIA(df, n, price='Close'): 100 | """ 101 | Inertia 102 | Returns: list of floats = jhta.INERTIA(df, n, price='Close') 103 | Source: https://www.fmlabs.com/reference/default.htm?url=Inertia.htm 104 | """ 105 | rvioc = jhta.RVIOC(df, n, price) 106 | return jhta.LSMA({'rvioc': rvioc}, n, 'rvioc') 107 | 108 | def NATR(df, n): 109 | """ 110 | Normalized Average True Range 111 | """ 112 | 113 | def PRANGE(df, n, max_price='High', min_price='Low'): 114 | """ 115 | %Range 116 | Returns: list of floats = jhta.PRANGE(df, n, max_price='High', min_price='Low') 117 | Source: book: An Introduction to Algorithmic Trading 118 | """ 119 | max_list = jhta.MAX(df, n, max_price) 120 | min_list = jhta.MIN(df, n, min_price) 121 | prange_list = [] 122 | for i in range(len(df[max_price])): 123 | if i + 1 < n: 124 | prange = float('NaN') 125 | else: 126 | prange = (max_list[i] - min_list[i]) / ((max_list[i] + min_list[i]) / 2) * 100 127 | prange_list.append(prange) 128 | return prange_list 129 | 130 | def RVI(df, n, high='High', low='Low'): 131 | """ 132 | Relative Volatility Index 133 | Returns: list of floats = jhta.RVI(df, n, high='High', low='Low') 134 | Source: https://www.fmlabs.com/reference/default.htm?url=RVI.htm 135 | """ 136 | rvi_list = [] 137 | h_upavg = .0 138 | h_dnavg = .0 139 | l_upavg = .0 140 | l_dnavg = .0 141 | for i in range(len(df[low])): 142 | if i + 1 < n or i < 9: 143 | h_rvi = float('NaN') 144 | l_rvi = float('NaN') 145 | else: 146 | start = i + 1 - n 147 | end = i + 1 148 | h = df[high][start:end] 149 | h_stdev = jhta.STDEV({'h': h}, 9, 'h')[-1] 150 | if df[high][i] > df[high][i - 1]: 151 | h_up = h_stdev 152 | h_dn = 0 153 | else: 154 | h_up = 0 155 | h_dn = h_stdev 156 | h_upavg = (h_upavg * (n - 1) + h_up) / n 157 | h_dnavg = (h_dnavg * (n - 1) + h_dn) / n 158 | h_rvi = 100 * h_upavg / (h_upavg + h_dnavg) 159 | l = df[low][start:end] 160 | l_stdev = jhta.STDEV({'l': l}, 9, 'l')[-1] 161 | if df[low][i] > df[low][i - 1]: 162 | l_up = l_stdev 163 | l_dn = 0 164 | else: 165 | l_up = 0 166 | l_dn = l_stdev 167 | l_upavg = (l_upavg * (n - 1) + l_up) / n 168 | l_dnavg = (l_dnavg * (n - 1) + l_dn) / n 169 | l_rvi = 100 * l_upavg / (l_upavg + l_dnavg) 170 | rvi = (h_rvi + l_rvi) / 2 171 | rvi_list.append(rvi) 172 | return rvi_list 173 | 174 | def RVIOC(df, n, price='Close'): 175 | """ 176 | Relative Volatility Index Original Calculation 177 | Returns: list of floats = jhta.RVIOC(df, n, price='Close') 178 | Source: https://www.fmlabs.com/reference/default.htm?url=RVIoriginal.htm 179 | """ 180 | rvioc_list = [] 181 | upavg = .0 182 | dnavg = .0 183 | for i in range(len(df[price])): 184 | if i + 1 < n or i < 9: 185 | rvioc = float('NaN') 186 | else: 187 | start = i + 1 - n 188 | end = i + 1 189 | y_list = df[price][start:end] 190 | stdev = jhta.STDEV({'y': y_list}, 9, 'y')[-1] 191 | if df[price][i] > df[price][i - 1]: 192 | up = stdev 193 | dn = 0 194 | else: 195 | up = 0 196 | dn = stdev 197 | upavg = (upavg * (n - 1) + up) / n 198 | dnavg = (dnavg * (n - 1) + dn) / n 199 | rvioc = 100 * upavg / (upavg + dnavg) 200 | rvioc_list.append(rvioc) 201 | return rvioc_list 202 | 203 | def TRANGE(df, high='High', low='Low', close='Close'): 204 | """ 205 | True Range 206 | Returns: list of floats = jhta.TRANGE(df, high='High', low='Low', close='Close') 207 | Source: https://www.fmlabs.com/reference/default.htm?url=TR.htm 208 | """ 209 | tr_list = [] 210 | for i in range(len(df[close])): 211 | if i < 1: 212 | tr = float('NaN') 213 | else: 214 | true_high = df[high][i] 215 | if df[close][i - 1] > df[high][i]: 216 | true_high = df[close][i - 1] 217 | true_low = df[low][i] 218 | if df[close][i - 1] < df[low][i]: 219 | true_low = df[close][i - 1] 220 | tr = true_high - true_low 221 | tr_list.append(tr) 222 | return tr_list 223 | 224 | -------------------------------------------------------------------------------- /jhtalib/volume_indicators/__init__.py: -------------------------------------------------------------------------------- 1 | from .volume_indicators import * 2 | 3 | -------------------------------------------------------------------------------- /jhtalib/volume_indicators/volume_indicators.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | 4 | # Import Third-Party: 5 | 6 | # Import Homebrew: 7 | import jhtalib as jhta 8 | 9 | 10 | def AD(df, high='High', low='Low', close='Close', volume='Volume'): 11 | """ 12 | Chaikin A/D Line 13 | Returns: list of floats = jhta.AD(df, high='High', low='Low', close='Close', volume='Volume') 14 | Source: https://www.fmlabs.com/reference/default.htm?url=AccumDist.htm 15 | """ 16 | ad_list = [] 17 | for i in range(len(df[close])): 18 | ad = 0 19 | if i > 0: 20 | clv = ((df[close][i] - df[low][i]) - (df[high][i] - df[close][i])) / (df[high][i] - df[low][i]) 21 | ad = ad_list[i - 1] + clv * df[volume][i] 22 | ad_list.append(ad) 23 | return ad_list 24 | 25 | def ADOSC(df): 26 | """ 27 | Chaikin A/D Oscillator 28 | """ 29 | 30 | def CMF(df, n, high='High', low='Low', close='Close', volume='Volume'): 31 | """ 32 | Chaikin Money Flow 33 | Returns: list of floats = jhta.CMF(df, n, price='Close') 34 | source: https://www.fidelity.com/learning-center/trading-investing/technical-analysis/technical-indicator-guide/cmf 35 | """ 36 | cmf_list = [] 37 | for i in range(len(df[close])): 38 | if i + 1 < n: 39 | cmf = float('NaN') 40 | else: 41 | start = i + 1 - n 42 | end = i + 1 43 | formula_list = [] 44 | for i2 in range(len(df[close][start:end])): 45 | h = df[high][start:end][i2] 46 | l = df[low][start:end][i2] 47 | c = df[close][start:end][i2] 48 | v = df[volume][start:end][i2] 49 | hl = (h - l) or .00000001 50 | formula = (((c - l) - (h - c)) / hl) * v 51 | # formula = (((c - l) - (h - c)) / (h - l)) * v 52 | formula_list.append(formula) 53 | sum_formula = sum(formula_list) 54 | sum_volume = sum(df[volume][start:end]) 55 | cmf = sum_formula / sum_volume 56 | cmf_list.append(cmf) 57 | return cmf_list 58 | 59 | def MFAI(df, high='High', low='Low', volume='Volume'): 60 | """ 61 | Market Facilitation Index 62 | Returns: list of floats = jhta.MFAI(df, high='High', low='Low', volume='Volume') 63 | Source: https://www.fmlabs.com/reference/default.htm?url=MFI.htm 64 | """ 65 | return [(df[high][i] - df[low][i]) / df[volume][i] for i in range(len(df[low]))] 66 | 67 | def NVI(df, price='Close', volume='Volume'): 68 | """ 69 | Negative Volume Index 70 | Returns: list of floats = jhta.NVI(df, price='Close', volume='Volume') 71 | Source: https://www.fmlabs.com/reference/default.htm?url=NVI.htm 72 | """ 73 | nvi_list = [] 74 | for i in range(len(df[price])): 75 | nvi = 0 76 | if i > 0: 77 | if df[volume][i] < df[volume][i - 1]: 78 | nvi = nvi_list[i - 1] + (df[price][i] - df[price][i - 1]) / df[price][i - 1] 79 | else: 80 | nvi = nvi_list[i - 1] 81 | nvi_list.append(nvi) 82 | return nvi_list 83 | 84 | def OBV(df, close='Close', volume='Volume'): 85 | """ 86 | On Balance Volume 87 | Returns: list of floats = jhta.OBV(df, close='Close', volume='Volume') 88 | Source: https://www.fmlabs.com/reference/default.htm?url=OBV.htm 89 | """ 90 | obv_list = [] 91 | for i in range(len(df[close])): 92 | obv = 0 93 | if i > 0: 94 | if df[close][i] > df[close][i - 1]: 95 | obv = obv_list[i - 1] + df[volume][i] 96 | elif df[close][i] < df[close][i - 1]: 97 | obv = obv_list[i - 1] - df[volume][i] 98 | else: 99 | obv = obv_list[i - 1] 100 | obv_list.append(obv) 101 | return obv_list 102 | 103 | def PVI(df, price='Close', volume='Volume'): 104 | """ 105 | Positive Volume Index 106 | Returns: list of floats = jhta.PVI(df, price='Close', volume='Volume') 107 | Source: https://www.fmlabs.com/reference/default.htm?url=PVI.htm 108 | """ 109 | pvi_list = [] 110 | for i in range(len(df[price])): 111 | pvi = 0 112 | if i > 0: 113 | if df[volume][i] > df[volume][i - 1]: 114 | pvi = pvi_list[i - 1] + (df[price][i] - df[price][i - 1]) / df[price][i - 1] 115 | else: 116 | pvi = pvi_list[i - 1] 117 | pvi_list.append(pvi) 118 | return pvi_list 119 | 120 | def PVR(df, price='Close', volume='Volume'): 121 | """ 122 | Price Volume Rank 123 | Returns: list of ints = jhta.PVR(df, price='Close', volume='Volume') 124 | Source: https://www.fmlabs.com/reference/default.htm?url=PVrank.htm 125 | """ 126 | pvr_list = [] 127 | for i in range(len(df[price])): 128 | if i < 1: 129 | pvr = float('NaN') 130 | else: 131 | if df[price][i] > df[price][i - 1] and df[volume][i] > df[volume][i - 1]: 132 | pvr = 1 133 | if df[price][i] > df[price][i - 1] and df[volume][i] < df[volume][i - 1]: 134 | pvr = 2 135 | if df[price][i] < df[price][i - 1] and df[volume][i] < df[volume][i - 1]: 136 | pvr = 3 137 | if df[price][i] < df[price][i - 1] and df[volume][i] > df[volume][i - 1]: 138 | pvr = 4 139 | pvr_list.append(pvr) 140 | return pvr_list 141 | 142 | def PVT(df, price='Close', volume='Volume'): 143 | """ 144 | Price Volume Trend 145 | Returns: list of floats = jhta.PVT(df, price='Close', volume='Volume') 146 | Source: https://www.fmlabs.com/reference/default.htm?url=PVT.htm 147 | """ 148 | pvt_list = [] 149 | for i in range(len(df[price])): 150 | pvt = 0 151 | if i > 0: 152 | pvt = pvt_list[i - 1] + df[volume][i] * (df[price][i] - df[price][i - 1]) / df[price][i - 1] 153 | pvt_list.append(pvt) 154 | return pvt_list 155 | 156 | def VWAP(df, open='Open', high='High', low='Low', close='Close', volume='Volume'): 157 | """ 158 | Volume Weighted Average Price 159 | Returns: list of floats = jhta.VWAP(df, open='Open', high='High', low='Low', close='Close', volume='Volume') 160 | Source: book: An Introduction to Algorithmic Trading 161 | """ 162 | vwap_list = [] 163 | pvs = .0 164 | for i in range(len(df[close])): 165 | o = df[open][i] 166 | h = df[high][i] 167 | l = df[low][i] 168 | c = df[close][i] 169 | v = df[volume][i] 170 | # vwap = sum([o * v/4, h * v/4, l * v/4, c * v/4]) / v 171 | pvs += (sum([o, h, l, c]) / 4) * v 172 | vwap = pvs / sum(df[volume][0:i + 1]) 173 | vwap_list.append(vwap) 174 | return vwap_list 175 | 176 | -------------------------------------------------------------------------------- /notebook/a_sane_and_simple_bitcoin_savings_plan_(sss).ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "a-sane-and-simple-bitcoin-savings-plan-(sss).ipynb", 7 | "provenance": [], 8 | "private_outputs": true, 9 | "collapsed_sections": [] 10 | }, 11 | "kernelspec": { 12 | "name": "python3", 13 | "display_name": "Python 3" 14 | }, 15 | "accelerator": "TPU" 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "code", 20 | "metadata": { 21 | "id": "d-WqBs882BUE", 22 | "colab_type": "code", 23 | "colab": {} 24 | }, 25 | "source": [ 26 | "# source: https://bitcointalk.org/index.php?topic=345065.0\n", 27 | "# source: https://jlopp.github.io/bitcoin-savings-plan/\n", 28 | "\n", 29 | "\n", 30 | "from tabulate import tabulate as tb\n", 31 | "\n", 32 | "\n", 33 | "initial_investment = 10\n", 34 | "initial_exchange_rate = 1\n", 35 | "rake = 10\n", 36 | "number_of_cycles = 20\n", 37 | "cycle_multiplier = 2\n", 38 | "\n", 39 | "table = [['BTC/FIAT', 'BTC Total', 'FIAT Value', 'BTC Sold', 'FIAT Bought', 'FIAT Total', 'BTC Invested %']]\n", 40 | "btc_fiat = initial_exchange_rate\n", 41 | "btc_total = initial_investment\n", 42 | "fiat_value = initial_exchange_rate * btc_total\n", 43 | "btc_sold = .0\n", 44 | "fiat_bought = .0\n", 45 | "fiat_total = .0\n", 46 | "table.append([btc_fiat, btc_total, fiat_value, btc_sold, fiat_bought, fiat_total, 100])\n", 47 | "for i in range(number_of_cycles):\n", 48 | " btc_fiat = btc_fiat * cycle_multiplier\n", 49 | " btc_sold = btc_total * (rake / 100)\n", 50 | " btc_total = btc_total * ((100 - rake) / 100)\n", 51 | " fiat_value = btc_fiat * btc_total\n", 52 | " fiat_bought = btc_fiat * btc_sold\n", 53 | " fiat_total += fiat_bought\n", 54 | " btc_invested = fiat_value / (fiat_value + fiat_total) * 100\n", 55 | " table.append([\n", 56 | " float('{:.2f}'.format(btc_fiat)),\n", 57 | " float('{:.8f}'.format(btc_total)),\n", 58 | " float('{:.2f}'.format(fiat_value)),\n", 59 | " float('{:.8f}'.format(btc_sold)),\n", 60 | " float('{:.2f}'.format(fiat_bought)),\n", 61 | " float('{:.2f}'.format(fiat_total)),\n", 62 | " float('{:.2f}'.format(btc_invested)),\n", 63 | " ])\n", 64 | "table.append(table[0])\n", 65 | "print (tb(table, headers='firstrow', tablefmt='grid', showindex='always'))\n" 66 | ], 67 | "execution_count": 0, 68 | "outputs": [] 69 | } 70 | ] 71 | } -------------------------------------------------------------------------------- /notebook/dollar_cost_averaging_discount_dcad.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "dollar-cost-averaging-discount-dcad.ipynb", 7 | "provenance": [], 8 | "private_outputs": true 9 | }, 10 | "kernelspec": { 11 | "name": "python3", 12 | "display_name": "Python 3" 13 | } 14 | }, 15 | "cells": [ 16 | { 17 | "cell_type": "code", 18 | "metadata": { 19 | "id": "Xw0PS3NGTC3M", 20 | "colab_type": "code", 21 | "colab": {} 22 | }, 23 | "source": [ 24 | "# source: https://medium.com/huddlofficial/how-to-buy-bitcoin-at-deep-discounts-599492ba5556\n", 25 | "\n", 26 | "\n", 27 | "import requests\n", 28 | "from datetime import datetime as dt\n", 29 | "import statistics\n", 30 | "from tabulate import tabulate as tb\n", 31 | "\n", 32 | "\n", 33 | "apikey = 'YOUR_API_KEY'\n", 34 | "url = 'https://min-api.cryptocompare.com/data/v2/histoday?fsym=BTC&tsym=USD&allData=true'\n", 35 | "#url = 'https://min-api.cryptocompare.com/data/v2/histoday?fsym=BTC&tsym=USD&limit=2000'\n", 36 | "headers = {'authorization': apikey}\n", 37 | "r = requests.get(url, headers=headers).json()\n", 38 | "df = {'datetime': [], 'Open': []}\n", 39 | "for i in range(len(r['Data']['Data'])):\n", 40 | " df['datetime'].append(dt.fromtimestamp(r['Data']['Data'][i]['time']).strftime('%Y-%m-%d'))\n", 41 | " df['Open'].append(float(r['Data']['Data'][i]['open']))\n", 42 | "\n", 43 | "btc_price_list = []\n", 44 | "invested = 0\n", 45 | "hodlings = .0\n", 46 | "table = [['Date', 'Investment', 'BTC price', 'Bought', 'Hodlings', 'Value', 'Invested', 'Profit $', 'Profit %', 'DCAD']]\n", 47 | "for i in range(len(df['datetime'])):\n", 48 | " if df['datetime'][i][-2:] == '01': # monthly.\n", 49 | "# if df['datetime'][i][-5:] == '01-01': # annually.\n", 50 | " investment = 100\n", 51 | " btc_price = float('{:.2f}'.format(df['Open'][i]))\n", 52 | " btc_price_list.append(btc_price)\n", 53 | " bought = float('{:.8f}'.format(investment / btc_price))\n", 54 | " hodlings = float('{:.8f}'.format(hodlings + bought))\n", 55 | " value = float('{:.2f}'.format(hodlings * btc_price))\n", 56 | " invested += investment\n", 57 | " profita = float('{:.2f}'.format(value - invested))\n", 58 | " profitp = float('{:.2f}'.format((value - invested) / invested * 100))\n", 59 | " arithmetic_mean = statistics.mean(btc_price_list)\n", 60 | " harmonic_mean = statistics.harmonic_mean(btc_price_list)\n", 61 | " dcad = float('{:.2f}'.format((arithmetic_mean - harmonic_mean) / arithmetic_mean * 100))\n", 62 | " table.append([\n", 63 | " df['datetime'][i], investment, btc_price, bought, hodlings, value, invested, profita, profitp, dcad\n", 64 | " ])\n", 65 | "table.append(table[0])\n", 66 | "print (tb(table, headers='firstrow', tablefmt='grid', showindex='always'))\n" 67 | ], 68 | "execution_count": 0, 69 | "outputs": [] 70 | } 71 | ] 72 | } -------------------------------------------------------------------------------- /notebook/recession_probability.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "recession-probability.ipynb", 7 | "version": "0.3.2", 8 | "provenance": [], 9 | "private_outputs": true, 10 | "collapsed_sections": [] 11 | }, 12 | "kernelspec": { 13 | "name": "python3", 14 | "display_name": "Python 3" 15 | }, 16 | "accelerator": "TPU" 17 | }, 18 | "cells": [ 19 | { 20 | "cell_type": "code", 21 | "metadata": { 22 | "id": "dOWU7_irDspA", 23 | "colab_type": "code", 24 | "colab": {} 25 | }, 26 | "source": [ 27 | "import requests\n", 28 | "from datetime import datetime as dt\n", 29 | "import math\n", 30 | "import matplotlib.dates as mdates\n", 31 | "import matplotlib.pyplot as plt\n", 32 | "from pandas.plotting import register_matplotlib_converters\n", 33 | "register_matplotlib_converters()\n", 34 | "\n", 35 | "\n", 36 | "def request_quandl(endpoint, **kwargs):\n", 37 | " params = {'order': 'asc', 'returns': 'numpy', 'authtoken': 'YOUR_AUTH_TOKEN'}\n", 38 | " params.update(kwargs)\n", 39 | " r = requests.get('https://www.quandl.com/api/v3/datasets/%s/data.json' % endpoint, params=params).json()\n", 40 | "# pp (r)\n", 41 | " return r['dataset_data']['data']\n", 42 | "\n", 43 | "start_date = '1964-07-06'\n", 44 | "collapse = 'weekly'\n", 45 | "\n", 46 | "# get 10-Year Treasury Constant Maturity Rate:\n", 47 | "r_dgs10 = request_quandl('FRED/DGS10', collapse=collapse, start_date=start_date)\n", 48 | "# get 3-Month Treasury Bill: Secondary Market Rate:\n", 49 | "r_dtb3 = request_quandl('FRED/DTB3', collapse=collapse, start_date=start_date)\n", 50 | "# get NBER based Recession Indicators for the United States from the Peak through the Period preceding the Trough:\n", 51 | "r_usrecdp = request_quandl('FRED/USRECDP', collapse=collapse, start_date=start_date)\n", 52 | "\n", 53 | "df = {'datetime': [], 'spread': [], 'recession': [], 'probability': [], 'probability_ratio': []}\n", 54 | "i = 0\n", 55 | "while i < len(r_dtb3):\n", 56 | " date = dt.strptime(r_dtb3[i][0], '%Y-%m-%d')\n", 57 | " df['datetime'].append(date)\n", 58 | " spread = r_dgs10[i][1] - r_dtb3[i][1]\n", 59 | " df['spread'].append(float(spread))\n", 60 | " df['recession'].append(int(r_usrecdp[i][1] * 5))\n", 61 | " a = (100-(spread + 3)*25)\n", 62 | " if a > 0:\n", 63 | " probability = 3\n", 64 | " probability_ratio = a\n", 65 | " else:\n", 66 | " probability = 0\n", 67 | " probability_ratio = a\n", 68 | " df['probability'].append(probability)\n", 69 | " df['probability_ratio'].append(probability_ratio)\n", 70 | " i += 1\n", 71 | "\n", 72 | "x = df['datetime']\n", 73 | "\n", 74 | "plt.figure(1, (30, 20))\n", 75 | "\n", 76 | "plt.subplot(211)\n", 77 | "plt.title('Recession Probability')\n", 78 | "plt.xlabel('Time')\n", 79 | "plt.ylabel('Price')\n", 80 | "plt.grid(True)\n", 81 | "plt.plot(x, df['spread'])\n", 82 | "plt.plot(x, df['recession'], color='green')\n", 83 | "plt.plot(x, df['probability'], color='red')\n", 84 | "plt.plot(x, [0] * len(x), color='black')\n", 85 | "plt.legend(['Spread', 'Recession', 'Probability', 'Zero-Line'], loc='upper left')\n", 86 | "plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))\n", 87 | "plt.gca().xaxis.set_major_locator(mdates.YearLocator())\n", 88 | "plt.gcf().autofmt_xdate()\n", 89 | "\n", 90 | "plt.subplot(212)\n", 91 | "plt.title('Recession Probability')\n", 92 | "plt.xlabel('Time')\n", 93 | "plt.ylabel('Ratio')\n", 94 | "plt.grid(True)\n", 95 | "plt.plot(x, df['recession'], color='green')\n", 96 | "plt.plot(x, df['probability_ratio'], color='red')\n", 97 | "plt.plot(x, [0] * len(x), color='black')\n", 98 | "plt.legend(['Recession', 'Probability', 'Zero-Line'], loc='upper left')\n", 99 | "plt.gca().xaxis.set_major_formatter(mdates.DateFormatter('%Y-%m-%d'))\n", 100 | "plt.gca().xaxis.set_major_locator(mdates.YearLocator())\n", 101 | "plt.gcf().autofmt_xdate()\n", 102 | "\n", 103 | "plt.show()\n" 104 | ], 105 | "execution_count": 0, 106 | "outputs": [] 107 | } 108 | ] 109 | } -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | from setuptools import setup, find_packages 4 | 5 | # Import Third-Party: 6 | 7 | # Import Homebrew: 8 | import jhtalib as jhta 9 | 10 | 11 | with open('README.md', 'r') as f: 12 | long_description = f.read() 13 | 14 | 15 | setup( 16 | name=jhta.__name__, 17 | version=jhta.__version__, 18 | description=jhta.__description__, 19 | long_description=long_description, 20 | long_description_content_type='text/markdown', 21 | url=jhta.__url__, 22 | author=jhta.__author__, 23 | author_email=jhta.__author_email__, 24 | classifiers=[ 25 | 'License :: OSI Approved :: GNU General Public License v3 (GPLv3)', 26 | 'Operating System :: OS Independent', 27 | 'Programming Language :: Python :: 3', 28 | ], 29 | project_urls={ 30 | 'Documentation': 'https://github.com/joosthoeks/jhTAlib/blob/master/README.md', 31 | 'Funding': 'https://github.com/joosthoeks/jhTAlib/stargazers', 32 | 'Say Thanks!': 'https://github.com/joosthoeks/jhTAlib/stargazers', 33 | 'Source': 'https://github.com/joosthoeks/jhTAlib', 34 | 'Tracker': 'https://github.com/joosthoeks/jhTAlib/issues', 35 | }, 36 | packages=find_packages(), 37 | py_modules=[], 38 | install_requires=[], 39 | python_requires='>=3', 40 | ) 41 | 42 | -------------------------------------------------------------------------------- /test/run-test.py: -------------------------------------------------------------------------------- 1 | """""" 2 | # Import Built-Ins: 3 | from pprint import pprint as pp 4 | 5 | # Import Third-Party: 6 | 7 | # Import Homebrew: 8 | import jhtalib as jhta 9 | 10 | 11 | # df is DataFeed: 12 | df = { 13 | 'datetime': ('20151217', '20151218', '20151221', '20151222', '20151223', '20151224', '20151228', '20151229', '20151230', '20151231'), 14 | 'Open': (235.8, 232.3, 234.1, 232.2, 232.7, 235.4, 236.9, 234.85, 236.45, 235.0), 15 | 'High': (238.05, 236.9, 237.3, 232.4, 235.2, 236.15, 236.9, 237.6, 238.3, 237.25), 16 | 'Low': (234.55, 230.6, 230.2, 226.8, 231.5, 233.85, 233.05, 234.6, 234.55, 234.4), 17 | 'Close': (234.6, 233.6, 230.2, 230.05, 234.15, 236.15, 233.25, 237.6, 235.75, 234.4), 18 | 'Volume': (448294, 629039, 292528, 214170, 215545, 23548, 97574, 192908, 176839, 69347) 19 | } 20 | 21 | # basic usage: 22 | #pp (df) 23 | pp (jhta.SMA(df, 10)) 24 | #pp (jhta.BBANDS(df, 10)) 25 | -------------------------------------------------------------------------------- /test/test.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | 3 | 4 | import numpy as np 5 | import pandas as pd 6 | import talib as ta 7 | import jhtalib as jhta 8 | 9 | 10 | def main(): 11 | # read csv file and transform it to datafeed (df): 12 | df = jhta.CSV2DF('data.csv') 13 | 14 | # transform datafeed to heikin-ashi datafeed (df): 15 | # df = jhta.DF2HEIKIN_ASHI(df) 16 | 17 | # set numpy datafeed from df: 18 | df_numpy = { 19 | 'datetime': np.array(df['datetime']), 20 | 'Open': np.array(df['Open'], dtype='float'), 21 | 'High': np.array(df['High'], dtype='float'), 22 | 'Low': np.array(df['Low'], dtype='float'), 23 | 'Close': np.array(df['Close'], dtype='float'), 24 | 'Volume': np.array(df['Volume'], dtype='int') 25 | } 26 | 27 | # set pandas datafeed from numpy datafeed: 28 | # df_pandas = pd.Series(df_numpy) 29 | 30 | # set talib indicator: 31 | indicator = ta.SMA(df_numpy['Close'], 10) 32 | 33 | # set jhtalib indicator: 34 | indicator2 = jhta.SMA(df, 10) 35 | 36 | # loop through datafeed (df): 37 | i = 0 38 | while i < len(df['Close']): 39 | # print row: 40 | print (df['datetime'][i]+' Open: '+str(df['Open'][i])+' High: '+str(df['High'][i])+' Low: '+str(df['Low'][i])+' Close: '+str(df['Close'][i])+' Volume: '+str(df['Volume'][i])) 41 | 42 | # print indicators and check for differences between talib and jhtalib: 43 | print (str(indicator[i])+' (talib)') 44 | print (str(indicator2[i])+' (jhTAlib)') 45 | i += 1 46 | 47 | 48 | if __name__ == '__main__': 49 | main() 50 | 51 | --------------------------------------------------------------------------------