Repository: brian-the-dev/python-tradingview-ta
Branch: main
Commit: 4a113824cae1
Files: 24
Total size: 75.7 KB
Directory structure:
gitextract_93dvnwww/
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ └── ISSUE_TEMPLATE/
│ ├── bug_report.md
│ └── feature_request.md
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── docs/
│ ├── Makefile
│ ├── changelog.rst
│ ├── conf.py
│ ├── faq.rst
│ ├── index.rst
│ ├── make.bat
│ ├── overview.rst
│ └── usage.rst
├── requirements.txt
├── setup.cfg
├── setup.py
├── test.py
└── tradingview_ta/
├── __init__.py
├── main.py
└── technicals.py
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
# Auto detect text files and perform LF normalization
* text=auto
================================================
FILE: .github/FUNDING.yml
================================================
ko_fi: brianthedev
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Submit a bug report
title: ''
labels: bug
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior.
**Expected behavior**
A clear and concise description of what you expected to happen.
**Code/Screenshots**
If applicable, attach your code or add screenshots to help explain your problem.
**Version**
- OS: [e.g. Ubuntu 21.04, Windows 10]
- Python: [e.g. 3.8.6]
- TradingView-TA: [e.g. 3.2.4]
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Submit a feature request
title: ''
labels: enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
================================================
FILE: .gitignore
================================================
# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class
# C extensions
*.so
# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
pip-wheel-metadata/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST
# PyInstaller
# Usually these files are written by a python script from a template
# before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec
# Installer logs
pip-log.txt
pip-delete-this-directory.txt
# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
# Translations
*.mo
*.pot
# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal
# Flask stuff:
instance/
.webassets-cache
# Scrapy stuff:
.scrapy
# Sphinx documentation
docs/_build/
# PyBuilder
target/
# Jupyter Notebook
.ipynb_checkpoints
# IPython
profile_default/
ipython_config.py
# pyenv
.python-version
# pipenv
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
# However, in case of collaboration, if having platform-specific dependencies or dependencies
# having no cross-platform support, pipenv may install dependencies that don't work, or not
# install all needed dependencies.
#Pipfile.lock
# celery beat schedule file
celerybeat-schedule
# SageMath parsed files
*.sage.py
# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/
# Spyder project settings
.spyderproject
.spyproject
# Rope project settings
.ropeproject
# mkdocs documentation
/site
# mypy
.mypy_cache/
.dmypy.json
dmypy.json
# Pyre type checker
.pyre/
# VSCode settings
.vscode/
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
## Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders 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, and will communicate reasons for moderation
decisions when appropriate.
## Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
brian@brianthe.dev.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
## Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to python-tradingview-ta
By contributing to python-tradingview-ta, you accept and agree to the Code of Conduct below. Your contribution (code) are licensed under the MIT license. Please follow this contribution guidelines before submitting a pull request.
## Pull Request Process
- Fork and clone this repository to your system.
- Install the requirements using `pip install -r requirements.txt`.
- Edit the code/docs.
- If you edit the code, run the `test.py` file.
- You DON'T need to increment the version, the maintainer will change it and publish your contribution.
- Create a pull request. The maintainer will decide to merge it or not.
## Contributor Covenant Code of Conduct
### Our Pledge
We as members, contributors, and leaders pledge to make participation in our
community a harassment-free experience for everyone, regardless of age, body
size, visible or invisible disability, ethnicity, sex characteristics, gender
identity and expression, level of experience, education, socio-economic status,
nationality, personal appearance, race, religion, or sexual identity
and orientation.
We pledge to act and interact in ways that contribute to an open, welcoming,
diverse, inclusive, and healthy community.
### Our Standards
Examples of behavior that contributes to a positive environment for our
community include:
* Demonstrating empathy and kindness toward other people
* Being respectful of differing opinions, viewpoints, and experiences
* Giving and gracefully accepting constructive feedback
* Accepting responsibility and apologizing to those affected by our mistakes,
and learning from the experience
* Focusing on what is best not just for us as individuals, but for the
overall community
Examples of unacceptable behavior include:
* The use of sexualized language or imagery, and sexual attention or
advances of any kind
* Trolling, insulting or derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or email
address, without their explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
### Enforcement Responsibilities
Community leaders are responsible for clarifying and enforcing our standards of
acceptable behavior and will take appropriate and fair corrective action in
response to any behavior that they deem inappropriate, threatening, offensive,
or harmful.
Community leaders 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, and will communicate reasons for moderation
decisions when appropriate.
### Scope
This Code of Conduct applies within all community spaces, and also applies when
an individual is officially representing the community in public spaces.
Examples of representing our community include using an official e-mail address,
posting via an official social media account, or acting as an appointed
representative at an online or offline event.
### Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
brian@brianthe.dev.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the
reporter of any incident.
### Enforcement Guidelines
Community leaders will follow these Community Impact Guidelines in determining
the consequences for any action they deem in violation of this Code of Conduct:
#### 1. Correction
**Community Impact**: Use of inappropriate language or other behavior deemed
unprofessional or unwelcome in the community.
**Consequence**: A private, written warning from community leaders, providing
clarity around the nature of the violation and an explanation of why the
behavior was inappropriate. A public apology may be requested.
#### 2. Warning
**Community Impact**: A violation through a single incident or series
of actions.
**Consequence**: A warning with consequences for continued behavior. No
interaction with the people involved, including unsolicited interaction with
those enforcing the Code of Conduct, for a specified period of time. This
includes avoiding interactions in community spaces as well as external channels
like social media. Violating these terms may lead to a temporary or
permanent ban.
#### 3. Temporary Ban
**Community Impact**: A serious violation of community standards, including
sustained inappropriate behavior.
**Consequence**: A temporary ban from any sort of interaction or public
communication with the community for a specified period of time. No public or
private interaction with the people involved, including unsolicited interaction
with those enforcing the Code of Conduct, is allowed during this period.
Violating these terms may lead to a permanent ban.
#### 4. Permanent Ban
**Community Impact**: Demonstrating a pattern of violation of community
standards, including sustained inappropriate behavior, harassment of an
individual, or aggression toward or disparagement of classes of individuals.
**Consequence**: A permanent ban from any sort of public interaction within
the community.
### Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at
https://www.contributor-covenant.org/translations.
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2020 Brian
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
Python TradingView TA by Analyzer.REST
An unofficial API wrapper for TradingView that allows you to fetch technical analysis data, now under new management.
Brought to you by Analyzer.REST, which provides Technical Analysis-as-a-Service (TAaaS) through an intuitive and affordable API. Join the waitlist!
## Important
- Keep tradingview-ta up to date for new features and bug fixes: `pip install -U tradingview_ta`
- Technical analysis for indices (index) is not supported by both TradingView and tradingview-ta, see issue [#67](https://github.com/analyzerrest/python-tradingview-ta/issues/67) and [#84](https://github.com/analyzerrest/python-tradingview-ta/issues/84).
## Features
* Faster response (older version of tradingview-ta requires Selenium)
* [Support for multiple symbols](https://python-tradingview-ta.readthedocs.io/en/latest/usage.html#retrieving-multiple-analysis)
* Indicators (Only TradingView built-in, does not support Pine Script/custom indicators)
## Demo
You can try tradingview-ta online without installing Python: https://tvta-demo.analyzer.rest/.
## Requirements
- Python 3.6 or newer.
- [Requests](https://pypi.org/project/requests/), included in installation.
## Installation
[PyPI](https://pypi.org/project/tradingview-ta/) (stable, recommended):
```pip install tradingview_ta```
GitHub (latest):
```pip install git+https://github.com/analyzerrest/python-tradingview-ta.git```
## Example
```python
from tradingview_ta import TA_Handler, Interval, Exchange
tesla = TA_Handler(
symbol="TSLA",
screener="america",
exchange="NASDAQ",
interval=Interval.INTERVAL_1_DAY,
# proxies={'http': 'http://example.com:8080'} # Uncomment to enable proxy (replace the URL).
)
print(tesla.get_analysis().summary)
# Example output: {"RECOMMENDATION": "BUY", "BUY": 8, "NEUTRAL": 6, "SELL": 3}
```
Tip: Use https://tvdb.analyzer.rest/ if you don't know what symbol, screener, and exchange to use.
## Documentation
[Read The Docs](https://python-tradingview-ta.readthedocs.io)
## Issue
If you found a bug or have a question, please open an issue. Email will not be replied.
## Warning
Trading is a risky activity, especially when done using an automated program. Never trade automatically without your supervision using results provided by tradingview-ta. Any monetary losses are not my fault.
## Contributing
Pull requests (docs, bug fix, features) are welcomed! Any pull request (documentation, bug fix, features, etc) are welcomed. Please follow the [guidelines](https://github.com/analyzerrest/python-tradingview-ta/blob/main/CONTRIBUTING.md) and the [code of conduct](https://github.com/analyzerrest/python-tradingview-ta/blob/main/CODE_OF_CONDUCT.md).
## License
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: docs/Makefile
================================================
# Minimal makefile for Sphinx documentation
#
# You can set these variables from the command line.
SPHINXOPTS =
SPHINXBUILD = sphinx-build
SOURCEDIR = .
BUILDDIR = _build
# Put it first so that "make" without argument is like "make help".
help:
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
.PHONY: help Makefile
# Catch-all target: route all unknown targets to Sphinx using the new
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
%: Makefile
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
================================================
FILE: docs/changelog.rst
================================================
Changelog
=========
3.3.0
-----
New:
* Symbol search
3.2.10
------
New:
* Support for proxy
* Additional indicators support for ``get_multiple_analysis()``
3.2.9
-----
New:
* Interval: 30 minutes and 2 hours
3.2.8
-----
New:
* Indicators: change, low, high
3.2.7
-----
Bug fix:
* ``get_multiple_analysis()`` will now return ``None`` if there is no analysis for a certain symbol. See `#55 `_ for more details.
3.2.6
-----
Bug fix:
* Add indicators
* Get multiple analysis
3.2.5
-----
New:
* Retrieve indicators ``TA_Handler.get_indicators()``
* Add custom indicators ``TA_Handler.add_indicators()``
* Indicators: volume
Bug fix:
* Update RSI algorithms
3.2.4
-----
New:
* Retrieve multiple analysis
Bug fix:
* Update compute algorithms
3.2.3
-----
New:
* Timeout
* Indicators: BBUpper and BBLower
* Test script (test.py)
3.2.2
-----
New:
* Indicators: open and P.SAR
3.2.1
-----
New:
* Removed EMA5 and SMA5 from analysis
Bug fix:
* Switched buy/sell on momentum
3.2.0
-----
New:
* Instantiate ``TA_Handler`` using parameters
3.1.6
-----
New:
* Set interval to ``"1d"`` if invalid
3.1.5
-----
New:
* Move indicators to ``Analysis`` class
3.1.4
-----
Bug fix:
* Pull request `#19 `_
3.1.3
-----
New:
* Added user agent
* Added ``__version__`` attribute
3.1.1
-----
Bug fix:
* Pull request `#7 `_
3.1.0
-----
New:
* Set symbol/exchange/screener/interval using functions
3.0.0
-----
New:
* Use scanner (https://scanner.tradingview.com/america/scan) instead of selenium
* Indicators
2.5.0
-----
New:
* Support for Heroku
2.2.0
-----
New:
* Rename ``pair`` to ``symbol``
* Support for Python 3.4
* Added warnings
2.1.0
-----
Bug fix:
* Requirements
2.0.0
-----
New:
* Use class
* Use headless selenium webdriver
================================================
FILE: docs/conf.py
================================================
# -*- coding: utf-8 -*-
#
# Configuration file for the Sphinx documentation builder.
#
# This file does only contain a selection of the most common options. For a
# full list see the documentation:
# http://www.sphinx-doc.org/en/master/config
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- Imports -----------------------------------------------------
import sphinx
import sphinx_rtd_theme
from recommonmark.transform import AutoStructify
# -- Project information -----------------------------------------------------
project = u'python-tradingview-ta'
copyright = u'2021, deathlyface (Brian)'
author = u'deathlyface (Brian)'
# The short X.Y version
version = u''
# The full version, including alpha/beta/rc tags
release = u''
# -- General configuration ---------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#
# needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.autodoc',
'recommonmark'
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix(es) of source filenames.
# You can specify multiple suffix as a list of string:
#
source_suffix = ['.rst', '.md']
# source_suffix = '.rst'
# The master toctree document.
master_doc = 'index'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#
# This is also used if you do content translation via gettext catalogs.
# Usually you set "language" from the command line for these cases.
language = None
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = [u'_build', 'Thumbs.db', '.DS_Store']
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = None
# -- Options for HTML output -------------------------------------------------
pygments_style = 'sphinx'
html_theme = 'sphinx_rtd_theme'
html_theme_path = [sphinx_rtd_theme.get_html_theme_path()]
#html_static_path = [str(Path(__file__).parent.parent / 'assets')]
#html_logo = str(Path(__file__).parent.parent / 'logo.png')
html_theme_options = {
'logo_only': True,
'display_version': False,
'style_external_links': False,
'style_nav_header_background': '#2c3e50',
}
# -- Options for HTMLHelp output ---------------------------------------------
# Output file base name for HTML help builder.
htmlhelp_basename = 'python-tradingview-tadoc'
# -- Options for LaTeX output ------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#
# 'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#
# 'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#
# 'preamble': '',
# Latex figure (float) alignment
#
# 'figure_align': 'htbp',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title,
# author, documentclass [howto, manual, or own class]).
latex_documents = [
(master_doc, 'python-tradingview-ta.tex', u'python-tradingview-ta Documentation',
u'deathlyface (Brian)', 'manual'),
]
# -- Options for manual page output ------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
(master_doc, 'python-tradingview-ta', u'python-tradingview-ta Documentation',
[author], 1)
]
# -- Options for Texinfo output ----------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
(master_doc, 'python-tradingview-ta', u'python-tradingview-ta Documentation',
author, 'python-tradingview-ta', 'One line description of project.',
'Miscellaneous'),
]
# -- Options for Epub output -------------------------------------------------
# Bibliographic Dublin Core info.
epub_title = project
# The unique identifier of the text. This can be a ISBN number
# or the project homepage.
#
# epub_identifier = ''
# A unique identification for the text.
#
# epub_uid = ''
# A list of files that should not be packed into the epub file.
epub_exclude_files = ['search.html']
# -- Extension configuration -------------------------------------------------
# app setup hook
def setup(app):
app.add_config_value('recommonmark_config', {
#'url_resolver': lambda url: github_doc_root + url,
'auto_toc_tree_section': 'Contents',
'auto_toc_maxdepth': 2,
}, True)
app.add_transform(AutoStructify)
================================================
FILE: docs/faq.rst
================================================
FAQ
===
Is the data delayed?
--------------------
Yes and no. Quoted from TradingView:
We provide real-time data for free whenever we're allowed. However, some data is delayed due to specific exchange regulations. Because of this, real-time data must be purchased separately using the page below. US stock market data is real-time and provided by CBOE BZX.
.. note:: TradingView_TA does not support paid real-time data at the moment.
.. note:: Please refer to `TradingView's website `_ to see whether the data is delayed or not.
How do I get past data?
-----------------------
Retrieving past data is currently not supported.
How do I create a trading bot?
------------------------------
.. warning:: Trading (especially using bots) is very risky. I won't be responsible for any financial loss. You have been warned.
The pseudocode below should help you get started in creating your own trading bot.
.. code-block:: python3
# Import packages.
from tradingview_ta import TA_Handler, Interval, Exchange
import time
# Store the last order.
last_order = "sell"
# Instantiate TA_Handler.
handler = TA_Handler(
symbol="SYMBOL",
exchange="EXCHANGE",
screener="SCREENER",
interval="INTERVAL",
)
# Repeat forever.
while True:
# Retrieve recommendation.
rec = handler.get_analysis()["RECOMMENDATION"]
# Create a buy order if the recommendation is "BUY" or "STRONG_BUY" and the last order is "sell".
# Create a sell order if the recommendation is "SELL" or "STRONG_SELL" and the last order is "buy".
if "BUY" in rec and last_order == "sell":
# REPLACE COMMENT: Create a buy order using your exchange's API.
last_order = "buy"
elif "SELL" in rec and last_order == "buy":
# REPLACE COMMENT: Create a sell order using your exchange's API.
last_order = "sell"
# Wait for x seconds before retrieving new analysis.
# The time should be the same as the interval.
time.sleep(x)
.. warning:: ``last_order`` won't be saved when the program exit. When the bot restarts, it will always create a new buy order.
.. tip:: Always paper trade before risking your money.
How can I get involved?
-----------------------
If you found a bug, please `create an issue `_ on the GitHub repository.
You can contribute (new features, bug fix, typo, etc) through the `GitHub repository `_. Please follow the `guidelines `_ and don't send spammy pull requests.
How does TradingView_TA works?
------------------------------
A simple network inspection on TradingView's website revealed that the data is retrieved through an `undocumented API `_.
TradingView_TA works by calculating similar data using `algorithms `_ reverse-engineered from their `JavaScript code `_.
Why do I get 4XX error?
-----------------------
400 error indicates that the request is invalid. Usually, this is caused when the indicators does not exist. See https://pastebin.com/1DjWv2Hd for valid indicators.
404 error indicates that the webpage does not exist. Usually, this is caused when the screener does not exist. Check if the screener, symbol, and exchange are correct using this tool: https://tvdb.brianthe.dev.
================================================
FILE: docs/index.rst
================================================
Welcome to TradingView-TA's documentation!
==========================================
TradingView_TA is an unofficial Python API wrapper to retrieve technical analysis from TradingView.
This documentation will help you to understand and use TradingView-TA.
.. toctree::
:maxdepth: 2
overview.md
usage.md
changelog.rst
faq.rst
================================================
FILE: docs/make.bat
================================================
@ECHO OFF
pushd %~dp0
REM Command file for Sphinx documentation
if "%SPHINXBUILD%" == "" (
set SPHINXBUILD=sphinx-build
)
set SOURCEDIR=.
set BUILDDIR=_build
if "%1" == "" goto help
%SPHINXBUILD% >NUL 2>NUL
if errorlevel 9009 (
echo.
echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
echo.installed, then set the SPHINXBUILD environment variable to point
echo.to the full path of the 'sphinx-build' executable. Alternatively you
echo.may add the Sphinx directory to PATH.
echo.
echo.If you don't have Sphinx installed, grab it from
echo.http://sphinx-doc.org/
exit /b 1
)
%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
goto end
:help
%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
:end
popd
================================================
FILE: docs/overview.rst
================================================
Getting Started
===============
This guide will help you understand the basics of TradingView_TA package.
Requirements
------------
* Python 3.6 or newer
* Internet access
Installation
------------
TradingView_TA is available on `PyPI `_.
.. code-block:: console
pip install tradingview-ta
Quick Start
-----------
.. code-block:: python3
from tradingview_ta import TA_Handler, Interval, Exchange
tesla = TA_Handler(
symbol="TSLA",
screener="america",
exchange="NASDAQ",
interval=Interval.INTERVAL_1_DAY
)
print(tesla.get_analysis().summary)
# Example output: {"RECOMMENDATION": "BUY", "BUY": 8, "NEUTRAL": 6, "SELL": 3}
================================================
FILE: docs/usage.rst
================================================
Usage
=====
.. note:: Please install or update TradingView_TA to the latest version. Please read the `getting started `_ guide before continuing.
.. warning:: TradingView_TA older than v3.2.0 is no longer supported. Please update using ``pip install tradingview_ta --upgrade``.
Importing TradingView_TA
------------------------
.. code-block:: python3
from tradingview_ta import TA_Handler, Interval, Exchange
import tradingview_ta
Checking the version
--------------------
Starting from version 3.1.3, you can retrieve the version of TradingView_TA through the ``__version__`` attribute.
.. code-block:: python3
print(tradingview_ta.__version__)
# Example output: 3.1.3
Instantiating TA_Handler
------------------------
.. code-block:: python3
handler = TA_Handler(
symbol="",
exchange="",
screener="",
interval="",
timeout=None
)
Parameters:
.. tip::
You can search on https://tvdb.brianthe.dev to see which symbol, exchange, and screener to use.
.. image:: https://raw.githubusercontent.com/brian-the-dev/python-tradingview-ta/main/images/tv-list.png
* symbol (``str``) – Ticker symbol (e.g., ``"AAPL"``, ``"TLKM"``, ``"USDEUR"``, ``"BTCUSDT"``).
* exchange (``str``) – Exchange (e.g., ``"nasdaq"``, ``"idx"``, ``Exchange.FOREX``, ``"binance"``).
* screener (``str``) – Screener (e.g., ``"america"``, ``"indonesia"``, ``"forex"``, ``"crypto"``).
.. note::
* If you're looking for stocks, enter the exchange's country as the screener.
* If you're looking for cryptocurrency, enter ``"crypto"`` as the screener.
* If you're looking for forex, enter ``"forex"`` as the screener.
* interval (``str``) – Time frame
.. note::
Please see the Interval class for available intervals.
.. code-block:: python3
class Interval:
INTERVAL_1_MINUTE = "1m"
INTERVAL_5_MINUTES = "5m"
INTERVAL_15_MINUTES = "15m"
INTERVAL_30_MINUTES = "30m"
INTERVAL_1_HOUR = "1h"
INTERVAL_2_HOURS = "2h"
INTERVAL_4_HOURS = "4h"
INTERVAL_1_DAY = "1d"
INTERVAL_1_WEEK = "1W"
INTERVAL_1_MONTH = "1M"
* timeout (``float``, optional) – How long to wait (in seconds) for the server to return a response.
Retrieving the analysis
-----------------------
.. code-block:: python3
analysis = handler.get_analysis()
.. note::
``analysis`` is an instance of Analysis class.
It contains information such as the exchange, symbol, screener, interval, local time (datetime.datetime), etc.
Attributes:
* symbol (``str``) – The symbol set earlier.
* exchange (``str``) – The exchange set earlier.
* screener (``str``) – The screener set earlier.
* interval (``str``) – The interval set earlier.
* time (``datetime.datetime``) – The time when the data is retrieved.
* summary (``dict``) – Technical analysis (based on both oscillators and moving averages).
.. code-block:: python3
# Example
{'RECOMMENDATION': 'BUY', 'BUY': 12, 'SELL': 7, 'NEUTRAL': 9}
* oscillators (``dict``) – Technical analysis (based on oscillators).
.. code-block:: python3
# Example
{'RECOMMENDATION': 'BUY', 'BUY': 2, 'SELL': 1, 'NEUTRAL': 8, 'COMPUTE': {'RSI': 'NEUTRAL', 'STOCH.K': 'NEUTRAL', 'CCI': 'NEUTRAL', 'ADX': 'NEUTRAL', 'AO': 'NEUTRAL', 'Mom': 'BUY', 'MACD': 'SELL', 'Stoch.RSI': 'NEUTRAL', 'W%R': 'NEUTRAL', 'BBP': 'BUY', 'UO': 'NEUTRAL'}}
* moving_averages (``dict``) – Technical analysis (based on moving averages).
.. code-block:: python3
# Example
{'RECOMMENDATION': 'BUY', 'BUY': 9, 'SELL': 5, 'NEUTRAL': 1, 'COMPUTE': {'EMA10': 'SELL', 'SMA10': 'SELL', 'EMA20': 'SELL', 'SMA20': 'SELL', 'EMA30': 'BUY', 'SMA30': 'BUY', 'EMA50': 'BUY', 'SMA50': 'BUY', 'EMA100': 'BUY', 'SMA100': 'BUY', 'EMA200': 'BUY', 'SMA200': 'BUY', 'Ichimoku': 'NEUTRAL', 'VWMA': 'SELL', 'HullMA': 'BUY'}}
* indicators (``dict``) – Technical indicators.
.. code-block:: python3
# Example
{'Recommend.Other': 0, 'Recommend.All': 0.26666667, 'Recommend.MA': 0.53333333, 'RSI': 60.28037412, 'RSI[1]': 58.58364778, 'Stoch.K': 73.80404453, 'Stoch.D': 79.64297643, 'Stoch.K[1]': 78.88160227, 'Stoch.D[1]': 85.97647064, 'CCI20': 46.58442886, 'CCI20[1]': 34.57058796, 'ADX': 35.78754863, 'ADX+DI': 23.16948389, 'ADX-DI': 13.82449817, 'ADX+DI[1]': 24.15991909, 'ADX-DI[1]': 13.87125505, 'AO': 6675.72158824, 'AO[1]': 7283.92420588, 'Mom': 1532.6, 'Mom[1]': 108.29, 'MACD.macd': 2444.73734978, 'MACD.signal': 2606.00138275, 'Rec.Stoch.RSI': 0, 'Stoch.RSI.K': 18.53740187, 'Rec.WR': 0, 'W.R': -26.05634845, 'Rec.BBPower': 0, 'BBPower': 295.52055898, 'Rec.UO': 0, 'UO': 55.68311917, 'close': 45326.97, 'EMA5': 45600.06414333, 'SMA5': 45995.592, 'EMA10': 45223.22433151, 'SMA10': 45952.635, 'EMA20': 43451.52018338, 'SMA20': 43609.214, 'EMA30': 41908.5944052, 'SMA30': 40880.391, 'EMA50': 40352.10222373, 'SMA50': 37819.3566, 'EMA100': 40356.09177879, 'SMA100': 38009.7808, 'EMA200': 39466.50411569, 'SMA200': 45551.36135, 'Rec.Ichimoku': 0, 'Ichimoku.BLine': 40772.57, 'Rec.VWMA': 1, 'VWMA': 43471.81729377, 'Rec.HullMA9': -1, 'HullMA9': 45470.37107407, 'Pivot.M.Classic.S3': 11389.27666667, 'Pivot.M.Classic.S2': 24559.27666667, 'Pivot.M.Classic.S1': 33010.55333333, 'Pivot.M.Classic.Middle': 37729.27666667, 'Pivot.M.Classic.R1': 46180.55333333, 'Pivot.M.Classic.R2': 50899.27666667, 'Pivot.M.Classic.R3': 64069.27666667, 'Pivot.M.Fibonacci.S3': 24559.27666667, 'Pivot.M.Fibonacci.S2': 29590.21666667, 'Pivot.M.Fibonacci.S1': 32698.33666667, 'Pivot.M.Fibonacci.Middle': 37729.27666667, 'Pivot.M.Fibonacci.R1': 42760.21666667, 'Pivot.M.Fibonacci.R2': 45868.33666667, 'Pivot.M.Fibonacci.R3': 50899.27666667, 'Pivot.M.Camarilla.S3': 37840.08, 'Pivot.M.Camarilla.S2': 39047.33, 'Pivot.M.Camarilla.S1': 40254.58, 'Pivot.M.Camarilla.Middle': 37729.27666667, 'Pivot.M.Camarilla.R1': 42669.08, 'Pivot.M.Camarilla.R2': 43876.33, 'Pivot.M.Camarilla.R3': 45083.58, 'Pivot.M.Woodie.S3': 21706.84, 'Pivot.M.Woodie.S2': 25492.42, 'Pivot.M.Woodie.S1': 34876.84, 'Pivot.M.Woodie.Middle': 38662.42, 'Pivot.M.Woodie.R1': 48046.84, 'Pivot.M.Woodie.R2': 51832.42, 'Pivot.M.Woodie.R3': 61216.84, 'Pivot.M.Demark.S1': 35369.915, 'Pivot.M.Demark.Middle': 38908.9575, 'Pivot.M.Demark.R1': 48539.915, 'open': 44695.95, 'P.SAR': 48068.64, 'BB.lower': 37961.23510877, 'BB.upper': 49257.19289123, 'AO[2]': 7524.31223529, 'volume': 32744.424503, 'change': 1.44612354, 'low': 44203.28, 'high': 45560}
.. tip::
Useful indicators:
* Opening price: ``analysis.indicators["open"]``
* Closing price: ``analysis.indicators["close"]``
* Momentum: ``analysis.indicators["Mom"]``
* RSI: ``analysis.indicators["RSI"]``
* MACD: ``analysis.indicators["MACD.macd"]``
Retrieving multiple analysis
----------------------------
.. code-block:: python3
from tradingview_ta import *
analysis = get_multiple_analysis(screener="america", interval=Interval.INTERVAL_1_HOUR, symbols=["nasdaq:tsla", "nyse:docn", "nasdaq:aapl"])
.. note::
You can't mix different screener and interval.
Parameters:
* symbols (``list``) – List of exchange and ticker symbol separated by a colon. Example: ["NASDAQ:TSLA", "NYSE:DOCN"] or ["BINANCE:BTCUSDT", "BITSTAMP:ETHUSD"].
* screener (``str``) – Screener (e.g., ``"america"``, ``"indonesia"``, ``"forex"``, ``"crypto"``).
* timeout (``float``, optional) – How long to wait (in seconds) for the server to return a response.
* additional_indicators (``list``, optional) – List of additional indicators to retrieve. Example: ``["RSI", "Mom"]``.
* interval (``str``) – Time frame
.. note::
Please see the Interval class for available intervals.
.. code-block:: python3
class Interval:
INTERVAL_1_MINUTE = "1m"
INTERVAL_5_MINUTES = "5m"
INTERVAL_15_MINUTES = "15m"
INTERVAL_30_MINUTES = "30m"
INTERVAL_1_HOUR = "1h"
INTERVAL_2_HOURS = "2h"
INTERVAL_4_HOURS = "4h"
INTERVAL_1_DAY = "1d"
INTERVAL_1_WEEK = "1W"
INTERVAL_1_MONTH = "1M"
.. note::
``get_multiple_analysis()`` returns a dictionary with a format of {"EXCHANGE:SYMBOL": Analysis}.
.. code-block:: python3
# Example
{'NYSE:DOCN': , 'NASDAQ:TSLA': , 'NASDAQ:AAPL': }
Please use UPPERCASE letters when accessing the dictionary.
If there is no analysis for a certain symbol, ``Analysis`` will be replaced with a ``None``. For example, ``BINANCE:DEXEUSDT`` does not have an analysis, but ``BINANCE:BTCUSDT`` has:
.. code-block:: python3
# Example
{'BINANCE:DEXEUSDT': None, 'BINANCE:BTCUSDT': }
Symbol search
-------------
.. versionadded:: 3.3.0
Search for symbols using the TradingView symbol search API. Returns a list of symbols, exchanges, types, descriptions, and logo URLs matching the search query.
.. code-block:: python3
from tradingview_ta import TradingView
print(TradingView.search("tesla", "america"))
# Output: [{'symbol': 'TSLA', 'exchange': 'NASDAQ', 'type': 'stock', 'description': 'Tesla, Inc.', 'logo': 'https://s3-symbol-logo.tradingview.com/tesla.svg'}, ...]
.. note::
While symbols listed on https://tvdb.brianthe.dev are guaranteed to work with the "get analysis()" function, symbols returned by this function may not.
Parameters:
* text (``str``) – Query string.
* type (``str``, optional) – Type of asset (stock, crypto, futures, index). Defaults to None (all).
Proxy
-----
Simply add the ``proxies`` parameter if you wish to utilize a proxy. Works with both ``TA_Handler()`` and ``get_multiple_analysis()``. It's worth noting that a bad proxy could result in TradingView rejecting your request.
.. code-block:: python3
from tradingview_ta import TA_Handler, Interval, Exchange
tesla = TA_Handler(
symbol="TSLA",
screener="america",
exchange="NASDAQ",
interval=Interval.INTERVAL_1_DAY,
proxies={'http': 'http://0.0.0.0:8080', 'https': 'https://0.0.0.0:443'}
)
print(tesla.get_analysis().summary)
# Example output: {"RECOMMENDATION": "BUY", "BUY": 8, "NEUTRAL": 6, "SELL": 3}
================================================
FILE: requirements.txt
================================================
requests
colorama
================================================
FILE: setup.cfg
================================================
[metadata]
license_file = LICENSE
================================================
FILE: setup.py
================================================
import setuptools
with open("README.md", "r") as fh:
long_description = fh.read()
setuptools.setup(
name='tradingview_ta',
version='3.3.0',
description="Unofficial TradingView technical analysis API wrapper.",
long_description=long_description,
long_description_content_type="text/markdown",
url='https://github.com/brian-the-dev/python-tradingview-ta',
author='Brian',
author_email='brian@brianthe.dev',
packages=['tradingview_ta'],
classifiers=[
"Programming Language :: Python :: 3",
"License :: OSI Approved :: MIT License",
"Operating System :: OS Independent",
],
install_requires=[
'requests',
],
python_requires='>=3.6',
project_urls={
'Demo': 'https://tradingview.brianthe.dev',
'Documentation': 'https://python-tradingview-ta.readthedocs.io',
'Source': 'https://github.com/brian-the-dev/python-tradingview-ta',
},
)
================================================
FILE: test.py
================================================
from colorama import Fore, Style
from tradingview_ta import TA_Handler, Interval, get_multiple_analysis
import tradingview_ta, requests, argparse
arg_parser = argparse.ArgumentParser()
arg_parser.add_argument("--proxy", help="Use HTTP proxy")
arg_parser.add_argument("--secureproxy", help="Use HTTPS proxy")
args = arg_parser.parse_args()
proxies = {}
if args.proxy:
proxies["http"] = args.proxy
if args.secureproxy:
proxies["https"] = args.secureproxy
print("------------------------------------------------")
print("Testing {}Tradingview-TA{} v{}{}".format(Fore.CYAN, Fore.MAGENTA, tradingview_ta.__version__, Style.RESET_ALL))
print("This test is {}semi-automatic{}. Please compare with tradingview's data manually.".format(Fore.LIGHTRED_EX, Style.RESET_ALL))
print("------------------------------------------------")
COUNT = 7
success = 0
print("{}#0{} {}Testing invalid symbol{}".format(Fore.BLUE, Style.RESET_ALL, Fore.LIGHTBLUE_EX, Style.RESET_ALL))
handler = TA_Handler(
symbol="ThisSymbolIsInvalid",
interval="1m",
screener="america",
exchange="NASDAQ",
proxies = proxies
)
try:
analysis = handler.get_analysis()
if analysis:
print("{}#0{} Invalid symbol test {}failed{}. No exception occured.".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL))
except Exception as e:
if str(e) == "Exchange or symbol not found.":
print("{}#0{} Invalid symbol test {}success{}.".format(Fore.BLUE, Style.RESET_ALL, Fore.GREEN, Style.RESET_ALL))
success += 1
else:
print("{}#0{} Invalid symbol test {}failed{}. An exception occured, but the symbol is valid.".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL))
print("{}#1{} {}Testing invalid exchange{}".format(Fore.BLUE, Style.RESET_ALL, Fore.LIGHTBLUE_EX, Style.RESET_ALL))
handler = TA_Handler(
symbol="TSLA",
interval="1m",
screener="america",
exchange="binance",
proxies = proxies
)
try:
analysis = handler.get_analysis()
if analysis:
print("{}#1{} Invalid exchange test {}failed{}. No exception occured.".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL))
except Exception as e:
if str(e) == "Exchange or symbol not found.":
print("{}#1{} Invalid exchange test {}success{}.".format(Fore.BLUE, Style.RESET_ALL, Fore.GREEN, Style.RESET_ALL))
success += 1
else:
print("{}#1{} Invalid exchange test {}failed{}. An exception occured, but symbol is valid.".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL))
print("{}#2{} {}Testing timeout{}".format(Fore.BLUE, Style.RESET_ALL, Fore.LIGHTBLUE_EX, Style.RESET_ALL))
handler = TA_Handler(
symbol="AAPL",
interval=Interval.INTERVAL_1_DAY,
screener="america",
exchange="NASDAQ",
timeout=0.0001,
proxies = proxies
)
try:
analysis = handler.get_analysis()
if analysis:
print("{}#2{} Timeout test {}failed{}.".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL))
except Exception as e:
if type(e) == requests.exceptions.ConnectTimeout:
print("{}#2{} Timeout test {}success{}.".format(Fore.BLUE, Style.RESET_ALL, Fore.GREEN, Style.RESET_ALL))
success += 1
print("{}#3{} {}Testing invalid interval{}".format(Fore.BLUE, Style.RESET_ALL, Fore.LIGHTBLUE_EX, Style.RESET_ALL))
handler = TA_Handler(
symbol="TSLA",
interval="1 minute",
screener="america",
exchange="NASDAQ",
proxies = proxies
)
try:
analysis = handler.get_analysis()
if analysis and input('{}#3{} Did you see a "defaulting to 1 day" {}warning{}? (Y/N) '.format(Fore.BLUE, Style.RESET_ALL, Fore.YELLOW, Style.RESET_ALL)).lower() == "y":
print("{}#3{} Invalid interval test {}success{}.".format(Fore.BLUE, Style.RESET_ALL, Fore.GREEN, Style.RESET_ALL))
success += 1
else:
print("{}#3{} Invalid interval test {}failed{}".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL))
except Exception as e:
print("{}#3{} Invalid interval test {}failed{}. An exception occured: {}".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL, e))
print("{}#4{} {}Testing stock (NASDAQ:AAPL){}".format(Fore.BLUE, Style.RESET_ALL, Fore.LIGHTBLUE_EX, Style.RESET_ALL))
handler = TA_Handler(
symbol="AAPL",
interval=Interval.INTERVAL_1_DAY,
screener="america",
exchange="NASDAQ",
proxies = proxies
)
try:
analysis = handler.get_analysis()
print("{}#4{} Please compare with {}https://www.tradingview.com/symbols/NASDAQ-AAPL/technicals/{}.".format(Fore.BLUE, Style.RESET_ALL, Fore.LIGHTMAGENTA_EX, Style.RESET_ALL))
print("{}#4{} (Summary) Rec: {}, Sell: {}, Neutral: {}, Buy: {}".format(Fore.BLUE, Style.RESET_ALL, analysis.summary["RECOMMENDATION"], analysis.summary["SELL"], analysis.summary["NEUTRAL"], analysis.summary["BUY"]))
if input("{}#4{} Are the results the same? (Y/N) ".format(Fore.BLUE, Style.RESET_ALL)).lower() == "y":
print("{}#4{} Stock test {}success{}.".format(Fore.BLUE, Style.RESET_ALL, Fore.GREEN, Style.RESET_ALL))
success += 1
else:
print("{}#4{} Stock test {}failed{}".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL))
except Exception as e:
print("{}#4{} Stock test {}failed{}. An exception occured: {}".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL, e))
print("{}#5{} {}Testing multiple analysis (NASDAQ:TSLA and NYSE:DOCN){}".format(Fore.BLUE, Style.RESET_ALL, Fore.LIGHTBLUE_EX, Style.RESET_ALL))
try:
analysis = get_multiple_analysis(screener="america", interval=Interval.INTERVAL_1_HOUR, symbols=["nasdaq:tsla", "nyse:docn"])
for key, value in analysis.items():
print("{}#5{} Please compare with {}https://www.tradingview.com/symbols/{}/technicals/{}. (Switch to 1 hour tab)".format(Fore.BLUE, Style.RESET_ALL, Fore.LIGHTMAGENTA_EX, key, Style.RESET_ALL))
print("{}#5{} (Summary) Rec: {}, Sell: {}, Neutral: {}, Buy: {}".format(Fore.BLUE, Style.RESET_ALL, value.summary["RECOMMENDATION"], value.summary["SELL"], value.summary["NEUTRAL"], value.summary["BUY"]))
if input("{}#5{} Are the results the same? (Y/N) ".format(Fore.BLUE, Style.RESET_ALL)).lower() == "y":
print("{}#5{} Multiple analysis test {}success{}.".format(Fore.BLUE, Style.RESET_ALL, Fore.GREEN, Style.RESET_ALL))
success += 1
else:
print("{}#5{} Multiple analysis test {}failed{}".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL))
except Exception as e:
print("{}#5{} Multiple analysis test {}failed{}. An exception occured: {}".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL, e))
print("{}#6{} {}Testing get indicators (BINANCE:BTCUSDT){}".format(Fore.BLUE, Style.RESET_ALL, Fore.LIGHTBLUE_EX, Style.RESET_ALL))
handler = TA_Handler(
symbol="BTCUSDT",
interval=Interval.INTERVAL_1_DAY,
screener="crypto",
exchange="binance",
proxies = proxies
)
try:
print("{}#6{} Please compare with {}https://www.tradingview.com/symbols/BINANCE:BTCUSDT/technicals/{}. (Check for indicators)".format(Fore.BLUE, Style.RESET_ALL, Fore.LIGHTMAGENTA_EX, Style.RESET_ALL))
print("{}#6{} {}".format(Fore.BLUE, Style.RESET_ALL, handler.get_indicators()))
if input("{}#6{} Are the results the same? (Y/N) ".format(Fore.BLUE, Style.RESET_ALL)).lower() == "y":
print("{}#6{} Get indicators test {}success{}.".format(Fore.BLUE, Style.RESET_ALL, Fore.GREEN, Style.RESET_ALL))
success += 1
else:
print("{}#6{} Get indicators test {}failed{}".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL))
except Exception as e:
print("{}#6{} Get indicators test {}failed{}. An exception occured: {}".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL, e))
print("------------------------------------------------")
print("Test finished. Result: {}{}/{}{}.".format(Fore.LIGHTWHITE_EX, success, COUNT, Style.RESET_ALL))
================================================
FILE: tradingview_ta/__init__.py
================================================
from .main import TA_Handler, TradingView, Analysis, Interval, Exchange, get_multiple_analysis, __version__
from .technicals import Recommendation, Compute
================================================
FILE: tradingview_ta/main.py
================================================
# Tradingview Technical Analysis (tradingview-ta)
# Author: deathlyface (https://github.com/deathlyface)
# License: MIT
import requests
import json
import datetime
import warnings
from .technicals import Compute
__version__ = "3.3.0"
class Analysis(object):
exchange = ""
symbol = ""
screener = ""
time = ""
interval = ""
summary = {}
oscillators = {}
moving_averages = {}
indicators = {}
class Interval:
INTERVAL_1_MINUTE = "1m"
INTERVAL_5_MINUTES = "5m"
INTERVAL_15_MINUTES = "15m"
INTERVAL_30_MINUTES = "30m"
INTERVAL_1_HOUR = "1h"
INTERVAL_2_HOURS = "2h"
INTERVAL_4_HOURS = "4h"
INTERVAL_1_DAY = "1d"
INTERVAL_1_WEEK = "1W"
INTERVAL_1_MONTH = "1M"
class Exchange:
FOREX = "FX_IDC"
CFD = "TVC"
class TradingView:
# Note: Please DO NOT modify the order or DELETE existing indicators, it will break the technical analysis. You may APPEND custom indicator to the END of the list.
indicators = ["Recommend.Other", "Recommend.All", "Recommend.MA", "RSI", "RSI[1]", "Stoch.K", "Stoch.D", "Stoch.K[1]", "Stoch.D[1]", "CCI20", "CCI20[1]", "ADX", "ADX+DI", "ADX-DI", "ADX+DI[1]", "ADX-DI[1]", "AO", "AO[1]", "Mom", "Mom[1]", "MACD.macd", "MACD.signal", "Rec.Stoch.RSI", "Stoch.RSI.K", "Rec.WR", "W.R", "Rec.BBPower", "BBPower", "Rec.UO", "UO", "close", "EMA5", "SMA5", "EMA10", "SMA10", "EMA20", "SMA20", "EMA30", "SMA30", "EMA50", "SMA50", "EMA100", "SMA100", "EMA200", "SMA200", "Rec.Ichimoku", "Ichimoku.BLine", "Rec.VWMA", "VWMA", "Rec.HullMA9", "HullMA9", "Pivot.M.Classic.S3", "Pivot.M.Classic.S2", "Pivot.M.Classic.S1", "Pivot.M.Classic.Middle", "Pivot.M.Classic.R1",
"Pivot.M.Classic.R2", "Pivot.M.Classic.R3", "Pivot.M.Fibonacci.S3", "Pivot.M.Fibonacci.S2", "Pivot.M.Fibonacci.S1", "Pivot.M.Fibonacci.Middle", "Pivot.M.Fibonacci.R1", "Pivot.M.Fibonacci.R2", "Pivot.M.Fibonacci.R3", "Pivot.M.Camarilla.S3", "Pivot.M.Camarilla.S2", "Pivot.M.Camarilla.S1", "Pivot.M.Camarilla.Middle", "Pivot.M.Camarilla.R1", "Pivot.M.Camarilla.R2", "Pivot.M.Camarilla.R3", "Pivot.M.Woodie.S3", "Pivot.M.Woodie.S2", "Pivot.M.Woodie.S1", "Pivot.M.Woodie.Middle", "Pivot.M.Woodie.R1", "Pivot.M.Woodie.R2", "Pivot.M.Woodie.R3", "Pivot.M.Demark.S1", "Pivot.M.Demark.Middle", "Pivot.M.Demark.R1", "open", "P.SAR", "BB.lower", "BB.upper", "AO[2]", "volume", "change", "low", "high"]
scan_url = "https://scanner.tradingview.com/"
def data(symbols, interval, indicators):
"""Format TradingView's Scanner Post Data
Args:
symbols (list): List of EXCHANGE:SYMBOL (ex: ["NASDAQ:AAPL"] or ["BINANCE:BTCUSDT"])
interval (string): Time Interval (ex: 1m, 5m, 15m, 1h, 4h, 1d, 1W, 1M)
Returns:
string: JSON object as a string.
"""
if interval == "1m":
# 1 Minute
data_interval = "|1"
elif interval == "5m":
# 5 Minutes
data_interval = "|5"
elif interval == "15m":
# 15 Minutes
data_interval = "|15"
elif interval == "30m":
# 30 Minutes
data_interval = "|30"
elif interval == "1h":
# 1 Hour
data_interval = "|60"
elif interval == "2h":
# 2 Hours
data_interval = "|120"
elif interval == "4h":
# 4 Hour
data_interval = "|240"
elif interval == "1W":
# 1 Week
data_interval = "|1W"
elif interval == "1M":
# 1 Month
data_interval = "|1M"
else:
if interval != '1d':
warnings.warn(
"Interval is empty or not valid, defaulting to 1 day.")
# Default, 1 Day
data_interval = ""
data_json = {"symbols": {"tickers": [symbol.upper() for symbol in symbols], "query": {
"types": []}}, "columns": [x + data_interval for x in indicators]}
return data_json
def search(text, type=None):
"""Search for assets on TradingView. Returns the symbol, exchange, type, and description of the asset.
Args:
text (str, required): Query string
type (str, optional): Type of asset (stock, crypto, futures, index). Defaults to None.
"""
req = requests.post(
"https://symbol-search.tradingview.com/symbol_search", params={"text": text, "type": type})
symbols = json.loads(req.text)
res = []
for symbol in symbols:
if "logoid" in symbol:
logo = f"https://s3-symbol-logo.tradingview.com/{symbol['logoid']}.svg"
elif "base-currency-logoid" in symbol:
logo = f"https://s3-symbol-logo.tradingview.com/{symbol['base-currency-logoid']}.svg"
elif "country" in symbol:
logo = f"https://s3-symbol-logo.tradingview.com/country/{symbol['country']}.svg"
else:
logo = None
res.append({"symbol": symbol["symbol"], "exchange": symbol["exchange"],
"type": symbol["type"], "description": symbol["description"], "logo": logo})
return res
def calculate(indicators, indicators_key, screener, symbol, exchange, interval):
oscillators_counter, ma_counter = {"BUY": 0, "SELL": 0, "NEUTRAL": 0}, {
"BUY": 0, "SELL": 0, "NEUTRAL": 0}
computed_oscillators, computed_ma = {}, {}
indicators = list(indicators.values())
# RECOMMENDATIONS
if None not in indicators[0:2]:
recommend_oscillators = Compute.Recommend(indicators[0])
recommend_summary = Compute.Recommend(indicators[1])
recommend_moving_averages = Compute.Recommend(indicators[2])
else:
return None
# OSCILLATORS
# RSI (14)
if None not in indicators[3:5]:
computed_oscillators["RSI"] = Compute.RSI(indicators[3], indicators[4])
oscillators_counter[computed_oscillators["RSI"]] += 1
# Stoch %K
if None not in indicators[5:9]:
computed_oscillators["STOCH.K"] = Compute.Stoch(
indicators[5], indicators[6], indicators[7], indicators[8])
oscillators_counter[computed_oscillators["STOCH.K"]] += 1
# CCI (20)
if None not in indicators[9:11]:
computed_oscillators["CCI"] = Compute.CCI20(
indicators[9], indicators[10])
oscillators_counter[computed_oscillators["CCI"]] += 1
# ADX (14)
if None not in indicators[11:16]:
computed_oscillators["ADX"] = Compute.ADX(
indicators[11], indicators[12], indicators[13], indicators[14], indicators[15])
oscillators_counter[computed_oscillators["ADX"]] += 1
# AO
if None not in indicators[16:18] and indicators[86] != None:
computed_oscillators["AO"] = Compute.AO(
indicators[16], indicators[17], indicators[86])
oscillators_counter[computed_oscillators["AO"]] += 1
# Mom (10)
if None not in indicators[18:20]:
computed_oscillators["Mom"] = Compute.Mom(
indicators[18], indicators[19])
oscillators_counter[computed_oscillators["Mom"]] += 1
# MACD
if None not in indicators[20:22]:
computed_oscillators["MACD"] = Compute.MACD(
indicators[20], indicators[21])
oscillators_counter[computed_oscillators["MACD"]] += 1
# Stoch RSI
if indicators[22] != None:
computed_oscillators["Stoch.RSI"] = Compute.Simple(indicators[22])
oscillators_counter[computed_oscillators["Stoch.RSI"]] += 1
# W%R
if indicators[24] != None:
computed_oscillators["W%R"] = Compute.Simple(indicators[24])
oscillators_counter[computed_oscillators["W%R"]] += 1
# BBP
if indicators[26] != None:
computed_oscillators["BBP"] = Compute.Simple(indicators[26])
oscillators_counter[computed_oscillators["BBP"]] += 1
# UO
if indicators[28] != None:
computed_oscillators["UO"] = Compute.Simple(indicators[28])
oscillators_counter[computed_oscillators["UO"]] += 1
# MOVING AVERAGES
ma_list = ["EMA10", "SMA10", "EMA20", "SMA20", "EMA30", "SMA30",
"EMA50", "SMA50", "EMA100", "SMA100", "EMA200", "SMA200"]
close = indicators[30]
ma_list_counter = 0
for index in range(33, 45):
if indicators[index] != None:
computed_ma[ma_list[ma_list_counter]] = Compute.MA(
indicators[index], close)
ma_counter[computed_ma[ma_list[ma_list_counter]]] += 1
ma_list_counter += 1
# MOVING AVERAGES, pt 2
# ICHIMOKU
if indicators[45] != None:
computed_ma["Ichimoku"] = Compute.Simple(indicators[45])
ma_counter[computed_ma["Ichimoku"]] += 1
# VWMA
if indicators[47] != None:
computed_ma["VWMA"] = Compute.Simple(indicators[47])
ma_counter[computed_ma["VWMA"]] += 1
# HullMA (9)
if indicators[49] != None:
computed_ma["HullMA"] = Compute.Simple(indicators[49])
ma_counter[computed_ma["HullMA"]] += 1
analysis = Analysis()
analysis.screener = screener
analysis.exchange = exchange
analysis.symbol = symbol
analysis.interval = interval
analysis.time = datetime.datetime.now()
for x in range(len(indicators)):
analysis.indicators[indicators_key[x]] = indicators[x]
analysis.indicators = analysis.indicators.copy()
analysis.oscillators = {"RECOMMENDATION": recommend_oscillators,
"BUY": oscillators_counter["BUY"], "SELL": oscillators_counter["SELL"], "NEUTRAL": oscillators_counter["NEUTRAL"], "COMPUTE": computed_oscillators}
analysis.moving_averages = {"RECOMMENDATION": recommend_moving_averages,
"BUY": ma_counter["BUY"], "SELL": ma_counter["SELL"], "NEUTRAL": ma_counter["NEUTRAL"], "COMPUTE": computed_ma}
analysis.summary = {"RECOMMENDATION": recommend_summary, "BUY": oscillators_counter["BUY"] + ma_counter["BUY"],
"SELL": oscillators_counter["SELL"] + ma_counter["SELL"], "NEUTRAL": oscillators_counter["NEUTRAL"] + ma_counter["NEUTRAL"]}
return analysis
class TA_Handler(object):
screener = ""
exchange = ""
symbol = ""
interval = ""
timeout = None
indicators = TradingView.indicators.copy()
def __init__(self, screener="", exchange="", symbol="", interval="", timeout=None, proxies=None):
"""Create an instance of TA_Handler class
Args:
screener (str, required): Screener (see documentation and tradingview's site).
exchange (str, required): Exchange (see documentation and tradingview's site).
symbol (str, required): Abbreviation of a stock or currency (see documentation and tradingview's site).
interval (str, optional): See the interval class and the documentation. Defaults to 1 day.
timeout (float, optional): Timeout for requests (in seconds). Defaults to None.
proxies (dict, optional): Proxies to be used for requests. Defaults to None (disabled).
"""
self.screener = screener
self.exchange = exchange
self.symbol = symbol
self.interval = interval
self.timeout = timeout
self.proxies = proxies
# Set functions
def set_screener_as_stock(self, country):
"""Set the screener as a country (for stocks).
Args:
country (string): Stock's country (ex: If NFLX or AAPL, then "america" is the screener)
"""
self.screener = country
def set_screener_as_crypto(self):
"""Set the screener as crypto (for cryptocurrencies).
"""
self.screener = "crypto"
def set_screener_as_cfd(self):
"""Set the screener as cfd (contract for differences).
"""
self.screener = "cfd"
def set_screener_as_forex(self):
"""Set the screener as forex.
"""
self.screener = "forex"
def set_exchange_as_crypto_or_stock(self, exchange):
"""Set the exchange
Args:
exchange (string): Stock/Crypto's exchange (NASDAQ, NYSE, BINANCE, BITTREX, etc).
"""
self.exchange = exchange
def set_exchange_as_forex(self):
"""Set the exchange as FX_IDC for forex.
"""
self.exchange = "FX_IDC"
def set_exchange_as_cfd(self):
"""Set the exchange as TVC for cfd.
"""
self.exchange = "TVC"
def set_interval_as(self, intvl):
"""Set the interval.
Refer to: https://python-tradingview-ta.readthedocs.io/en/latest/usage.html#setting-the-interval
Args:
intvl (string): interval. You can use values from the Interval class.
"""
self.interval = intvl
def set_symbol_as(self, symbol):
"""Set the symbol.
Refer to: https://python-tradingview-ta.readthedocs.io/en/latest/usage.html#setting-the-symbol
Args:
symbol (string): abbreviation of a stock or currency (ex: NFLX, AAPL, BTCUSD).
"""
self.symbol = symbol
def get_indicators(self, indicators=[]):
"""Just the indicators, please. See valid indicators on https://pastebin.com/1DjWv2Hd.
Args:
indicators (list, optional): List of string of indicators (ex: ["RSI7", "open"]). Defaults to self.indicators.
Returns:
dict: A dictionary with a format of {"indicator": value}.
"""
if len(indicators) == 0:
indicators = self.indicators
if self.screener == "" or type(self.screener) != str:
raise Exception("Screener is empty or not valid.")
elif self.exchange == "" or type(self.exchange) != str:
raise Exception("Exchange is empty or not valid.")
elif self.symbol == "" or type(self.symbol) != str:
raise Exception("Symbol is empty or not valid.")
exchange_symbol = f"{self.exchange}:{self.symbol}"
data = TradingView.data([exchange_symbol], self.interval, indicators)
scan_url = f"{TradingView.scan_url}{self.screener.lower()}/scan"
headers = {"User-Agent": "tradingview_ta/{}".format(__version__)}
response = requests.post(
scan_url, json=data, headers=headers, timeout=self.timeout, proxies=self.proxies)
# Return False if can't get data
if response.status_code != 200:
raise Exception("Can't access TradingView's API. HTTP status code: {}. Check for invalid symbol, exchange, or indicators.".format(
response.status_code))
result = json.loads(response.text)["data"]
if result != []:
indicators_val = {}
for x in range(len(indicators)):
indicators_val[indicators[x]] = result[0]["d"][x]
return indicators_val
else:
raise Exception("Exchange or symbol not found.")
# Add custom indicators
def add_indicators(self, indicators):
"""Add custom indicators. See valid indicators on https://pastebin.com/1DjWv2Hd.
Args:
indicators (list): List of strings of indicators. (ex: ["RSI7", "VWMA"])
"""
self.indicators += indicators
# Get analysis
def get_analysis(self):
"""Get analysis from TradingView and compute it.
Returns:
Analysis: Contains information about the analysis.
"""
return calculate(indicators=self.get_indicators(), indicators_key=self.indicators, screener=self.screener, symbol=self.symbol, exchange=self.exchange, interval=self.interval)
def get_multiple_analysis(screener, interval, symbols, additional_indicators=[], timeout=None, proxies=None):
"""Retrieve multiple technical analysis at once. Note: You can't mix different screener and interval
Args:
screener (str, required): Screener (see documentation and tradingview's site).
interval (str, optional): See the interval class and the documentation. Defaults to 1 day.
symbols (list, required): List of exchange and ticker symbol separated by a colon. Example: ["NASDAQ:TSLA", "NYSE:DOCN"] or ["BINANCE:BTCUSDT", "BITSTAMP:ETHUSD"].
additional_indicators (list, optional): List of additional indicators to be requested from TradingView, see valid indicators on https://pastebin.com/1DjWv2Hd.
timeout (float, optional): Timeout for requests (in seconds). Defaults to None.
proxies (dict, optional): Proxies to be used for requests. Defaults to None (disabled).
Returns:
dict: dictionary with a format of {"EXCHANGE:SYMBOL": Analysis}.
"""
if screener == "" or type(screener) != str:
raise Exception("Screener is empty or not valid.")
if len(symbols) == 0 or type(symbols) != list:
raise Exception("Symbols is empty or not valid.")
for symbol in symbols:
if len(symbol.split(":")) != 2 or "" in symbol.split(":"):
raise Exception(
"One or more symbol is invalid. Symbol should be a list of exchange and ticker symbol separated by a colon. Example: [\"NASDAQ:TSLA\", \"NYSE:DOCN\"] or [\"BINANCE:BTCUSDT\", \"BITSTAMP:ETHUSD\"].")
indicators_key = TradingView.indicators.copy()
if additional_indicators:
indicators_key += additional_indicators
data = TradingView.data(symbols, interval, indicators_key)
scan_url = f"{TradingView.scan_url}{screener.lower()}/scan"
headers = {"User-Agent": "tradingview_ta/{}".format(__version__)}
response = requests.post(
scan_url, json=data, headers=headers, timeout=timeout, proxies=proxies)
result = json.loads(response.text)["data"]
final = {}
for analysis in result:
# Convert list to dict
indicators = {}
for x in range(len(analysis["d"])):
indicators[indicators_key[x]] = analysis["d"][x]
final[analysis["s"]] = calculate(indicators=indicators, indicators_key=indicators_key, screener=screener, symbol=analysis["s"].split(
":")[1], exchange=analysis["s"].split(":")[0], interval=interval)
for symbol in symbols:
# Add None if there is no analysis for symbol
if symbol.upper() not in final:
final[symbol.upper()] = None
return final
================================================
FILE: tradingview_ta/technicals.py
================================================
# Tradingview Technical Analysis (tradingview-ta)
# Author: deathlyface (https://github.com/deathlyface)
# Rewritten from https://www.tradingview.com/static/bundles/technicals.f2e6e6a51aebb6cd46f8.js
# License: MIT
class Recommendation:
buy = "BUY"
strong_buy = "STRONG_BUY"
sell = "SELL"
strong_sell = "STRONG_SELL"
neutral = "NEUTRAL"
error = "ERROR"
class Compute:
def MA(ma, close):
"""Compute Moving Average
Args:
ma (float): MA value
close (float): Close value
Returns:
string: "BUY", "SELL", or "NEUTRAL"
"""
if (ma < close):
return Recommendation.buy
elif (ma > close):
return Recommendation.sell
else:
return Recommendation.neutral
def RSI(rsi, rsi1):
"""Compute Relative Strength Index
Args:
rsi (float): RSI value
rsi1 (float): RSI[1] value
Returns:
string: "BUY", "SELL", or "NEUTRAL"
"""
if (rsi < 30 and rsi1 < rsi):
return Recommendation.buy
elif (rsi > 70 and rsi1 > rsi):
return Recommendation.sell
else:
return Recommendation.neutral
def Stoch(k, d, k1, d1):
"""Compute Stochastic
Args:
k (float): Stoch.K value
d (float): Stoch.D value
k1 (float): Stoch.K[1] value
d1 (float): Stoch.D[1] value
Returns:
string: "BUY", "SELL", or "NEUTRAL"
"""
if (k < 20 and d < 20 and k > d and k1 < d1):
return Recommendation.buy
elif (k > 80 and d > 80 and k < d and k1 > d1):
return Recommendation.sell
else:
return Recommendation.neutral
def CCI20(cci20, cci201):
"""Compute Commodity Channel Index 20
Args:
cci20 (float): CCI20 value
cci201 ([type]): CCI20[1] value
Returns:
string: "BUY", "SELL", or "NEUTRAL"
"""
if (cci20 < -100 and cci20 > cci201):
return Recommendation.buy
elif (cci20 > 100 and cci20 < cci201):
return Recommendation.sell
else:
return Recommendation.neutral
def ADX(adx, adxpdi, adxndi, adxpdi1, adxndi1):
"""Compute Average Directional Index
Args:
adx (float): ADX value
adxpdi (float): ADX+DI value
adxndi (float): ADX-DI value
adxpdi1 (float): ADX+DI[1] value
adxndi1 (float): ADX-DI[1] value
Returns:
string: "BUY", "SELL", or "NEUTRAL"
"""
if (adx > 20 and adxpdi1 < adxndi1 and adxpdi > adxndi):
return Recommendation.buy
elif (adx > 20 and adxpdi1 > adxndi1 and adxpdi < adxndi):
return Recommendation.sell
else:
return Recommendation.neutral
def AO(ao, ao1, ao2):
"""Compute Awesome Oscillator
Args:
ao (float): AO value
ao1 (float): AO[1] value
ao2 (float): AO[2] value
Returns:
string: "BUY", "SELL", or "NEUTRAL"
"""
if (ao > 0 and ao1 < 0) or (ao > 0 and ao1 > 0 and ao > ao1 and ao2 > ao1):
return Recommendation.buy
elif (ao < 0 and ao1 > 0) or (ao < 0 and ao1 < 0 and ao < ao1 and ao2 < ao1):
return Recommendation.sell
else:
return Recommendation.neutral
def Mom(mom, mom1):
"""Compute Momentum
Args:
mom (float): Mom value
mom1 (float): Mom[1] value
Returns:
string: "BUY", "SELL", or "NEUTRAL"
"""
if (mom < mom1):
return Recommendation.sell
elif (mom > mom1):
return Recommendation.buy
else:
return Recommendation.neutral
def MACD(macd, signal):
"""Compute Moving Average Convergence/Divergence
Args:
macd (float): MACD.macd value
signal (float): MACD.signal value
Returns:
string: "BUY", "SELL", or "NEUTRAL"
"""
if (macd > signal):
return Recommendation.buy
elif (macd < signal):
return Recommendation.sell
else:
return Recommendation.neutral
def BBBuy(close, bblower):
"""Compute Bull Bear Buy
Args:
close (float): close value
bblower (float): BB.lower value
Returns:
string: "BUY", "SELL", or "NEUTRAL"
"""
if (close < bblower):
return Recommendation.buy
else:
return Recommendation.neutral
def BBSell(close, bbupper):
"""Compute Bull Bear Sell
Args:
close (float): close value
bbupper (float): BB.upper value
Returns:
string: "BUY", "SELL", or "NEUTRAL"
"""
if (close > bbupper):
return Recommendation.sell
else:
return Recommendation.neutral
def PSAR(psar, open):
"""Compute Parabolic Stop-And-Reverse
Args:
psar (float): P.SAR value
open (float): open value
Returns:
string: "BUY", "SELL", or "NEUTRAL"
"""
if (psar < open):
return Recommendation.buy
elif (psar > open):
return Recommendation.sell
else:
return Recommendation.neutral
def Recommend(value):
"""Compute Recommend
Args:
value (float): recommend value
Returns:
string: "STRONG_BUY", "BUY", "NEUTRAL", "SELL", "STRONG_SELL", or "ERROR"
"""
if value >= -1 and value < -.5:
return Recommendation.strong_sell
elif value >= -.5 and value < -.1:
return Recommendation.sell
elif value >= -.1 and value <= .1:
return Recommendation.neutral
elif value > .1 and value <= .5 :
return Recommendation.buy
elif value > .5 and value <= 1:
return Recommendation.strong_buy
else:
return Recommendation.error
def Simple(value):
"""Compute Simple
Args:
value (float): Rec.X value
Returns:
string: "BUY", "SELL", or "NEUTRAL"
"""
if (value == -1):
return Recommendation.sell
elif (value == 1):
return Recommendation.buy
else:
return Recommendation.neutral