[
  {
    "path": ".gitattributes",
    "content": "# Auto detect text files and perform LF normalization\n* text=auto\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "content": "ko_fi: brianthedev\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Submit a bug report\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps to reproduce the behavior.\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Code/Screenshots**\nIf applicable, attach your code or add screenshots to help explain your problem.\n\n**Version**\n - OS: [e.g. Ubuntu 21.04, Windows 10]\n - Python: [e.g. 3.8.6]\n - TradingView-TA: [e.g. 3.2.4]\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Submit a feature request\ntitle: ''\nlabels: enhancement\nassignees: ''\n\n---\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of what you want to happen.\n"
  },
  {
    "path": ".gitignore",
    "content": "# Byte-compiled / optimized / DLL files\n__pycache__/\n*.py[cod]\n*$py.class\n\n# C extensions\n*.so\n\n# Distribution / packaging\n.Python\nbuild/\ndevelop-eggs/\ndist/\ndownloads/\neggs/\n.eggs/\nlib/\nlib64/\nparts/\nsdist/\nvar/\nwheels/\npip-wheel-metadata/\nshare/python-wheels/\n*.egg-info/\n.installed.cfg\n*.egg\nMANIFEST\n\n# PyInstaller\n#  Usually these files are written by a python script from a template\n#  before PyInstaller builds the exe, so as to inject date/other infos into it.\n*.manifest\n*.spec\n\n# Installer logs\npip-log.txt\npip-delete-this-directory.txt\n\n# Unit test / coverage reports\nhtmlcov/\n.tox/\n.nox/\n.coverage\n.coverage.*\n.cache\nnosetests.xml\ncoverage.xml\n*.cover\n*.py,cover\n.hypothesis/\n.pytest_cache/\n\n# Translations\n*.mo\n*.pot\n\n# Django stuff:\n*.log\nlocal_settings.py\ndb.sqlite3\ndb.sqlite3-journal\n\n# Flask stuff:\ninstance/\n.webassets-cache\n\n# Scrapy stuff:\n.scrapy\n\n# Sphinx documentation\ndocs/_build/\n\n# PyBuilder\ntarget/\n\n# Jupyter Notebook\n.ipynb_checkpoints\n\n# IPython\nprofile_default/\nipython_config.py\n\n# pyenv\n.python-version\n\n# pipenv\n#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.\n#   However, in case of collaboration, if having platform-specific dependencies or dependencies\n#   having no cross-platform support, pipenv may install dependencies that don't work, or not\n#   install all needed dependencies.\n#Pipfile.lock\n\n# celery beat schedule file\ncelerybeat-schedule\n\n# SageMath parsed files\n*.sage.py\n\n# Environments\n.env\n.venv\nenv/\nvenv/\nENV/\nenv.bak/\nvenv.bak/\n\n# Spyder project settings\n.spyderproject\n.spyproject\n\n# Rope project settings\n.ropeproject\n\n# mkdocs documentation\n/site\n\n# mypy\n.mypy_cache/\n.dmypy.json\ndmypy.json\n\n# Pyre type checker\n.pyre/\n\n# VSCode settings\n.vscode/\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socio-economic status,\nnationality, personal appearance, race, religion, or sexual identity\nand orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n\n## Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n* Demonstrating empathy and kindness toward other people\n* Being respectful of differing opinions, viewpoints, and experiences\n* Giving and gracefully accepting constructive feedback\n* Accepting responsibility and apologizing to those affected by our mistakes,\n  and learning from the experience\n* Focusing on what is best not just for us as individuals, but for the\n  overall community\n\nExamples of unacceptable behavior include:\n\n* The use of sexualized language or imagery, and sexual attention or\n  advances of any kind\n* Trolling, insulting or derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or email\n  address, without their explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n## Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n## Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n## Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at\nbrian@brianthe.dev.\nAll complaints will be reviewed and investigated promptly and fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n## Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n### 2. Warning\n\n**Community Impact**: A violation through a single incident or series\nof actions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or\npermanent ban.\n\n### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior,  harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within\nthe community.\n\n## Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.0, available at\nhttps://www.contributor-covenant.org/version/2/0/code_of_conduct.html.\n\nCommunity Impact Guidelines were inspired by [Mozilla's code of conduct\nenforcement ladder](https://github.com/mozilla/diversity).\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see the FAQ at\nhttps://www.contributor-covenant.org/faq. Translations are available at\nhttps://www.contributor-covenant.org/translations.\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing to python-tradingview-ta\n\nBy 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.\n\n## Pull Request Process\n\n- Fork and clone this repository to your system.\n- Install the requirements using `pip install -r requirements.txt`.\n- Edit the code/docs.\n- If you edit the code, run the `test.py` file.\n- You DON'T need to increment the version, the maintainer will change it and publish your contribution.\n- Create a pull request. The maintainer will decide to merge it or not.\n\n## Contributor Covenant Code of Conduct\n\n### Our Pledge\n\nWe as members, contributors, and leaders pledge to make participation in our\ncommunity a harassment-free experience for everyone, regardless of age, body\nsize, visible or invisible disability, ethnicity, sex characteristics, gender\nidentity and expression, level of experience, education, socio-economic status,\nnationality, personal appearance, race, religion, or sexual identity\nand orientation.\n\nWe pledge to act and interact in ways that contribute to an open, welcoming,\ndiverse, inclusive, and healthy community.\n\n### Our Standards\n\nExamples of behavior that contributes to a positive environment for our\ncommunity include:\n\n* Demonstrating empathy and kindness toward other people\n* Being respectful of differing opinions, viewpoints, and experiences\n* Giving and gracefully accepting constructive feedback\n* Accepting responsibility and apologizing to those affected by our mistakes,\n  and learning from the experience\n* Focusing on what is best not just for us as individuals, but for the\n  overall community\n\nExamples of unacceptable behavior include:\n\n* The use of sexualized language or imagery, and sexual attention or\n  advances of any kind\n* Trolling, insulting or derogatory comments, and personal or political attacks\n* Public or private harassment\n* Publishing others' private information, such as a physical or email\n  address, without their explicit permission\n* Other conduct which could reasonably be considered inappropriate in a\n  professional setting\n\n### Enforcement Responsibilities\n\nCommunity leaders are responsible for clarifying and enforcing our standards of\nacceptable behavior and will take appropriate and fair corrective action in\nresponse to any behavior that they deem inappropriate, threatening, offensive,\nor harmful.\n\nCommunity leaders have the right and responsibility to remove, edit, or reject\ncomments, commits, code, wiki edits, issues, and other contributions that are\nnot aligned to this Code of Conduct, and will communicate reasons for moderation\ndecisions when appropriate.\n\n### Scope\n\nThis Code of Conduct applies within all community spaces, and also applies when\nan individual is officially representing the community in public spaces.\nExamples of representing our community include using an official e-mail address,\nposting via an official social media account, or acting as an appointed\nrepresentative at an online or offline event.\n\n### Enforcement\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported to the community leaders responsible for enforcement at\nbrian@brianthe.dev.\nAll complaints will be reviewed and investigated promptly and fairly.\n\nAll community leaders are obligated to respect the privacy and security of the\nreporter of any incident.\n\n### Enforcement Guidelines\n\nCommunity leaders will follow these Community Impact Guidelines in determining\nthe consequences for any action they deem in violation of this Code of Conduct:\n\n#### 1. Correction\n\n**Community Impact**: Use of inappropriate language or other behavior deemed\nunprofessional or unwelcome in the community.\n\n**Consequence**: A private, written warning from community leaders, providing\nclarity around the nature of the violation and an explanation of why the\nbehavior was inappropriate. A public apology may be requested.\n\n#### 2. Warning\n\n**Community Impact**: A violation through a single incident or series\nof actions.\n\n**Consequence**: A warning with consequences for continued behavior. No\ninteraction with the people involved, including unsolicited interaction with\nthose enforcing the Code of Conduct, for a specified period of time. This\nincludes avoiding interactions in community spaces as well as external channels\nlike social media. Violating these terms may lead to a temporary or\npermanent ban.\n\n#### 3. Temporary Ban\n\n**Community Impact**: A serious violation of community standards, including\nsustained inappropriate behavior.\n\n**Consequence**: A temporary ban from any sort of interaction or public\ncommunication with the community for a specified period of time. No public or\nprivate interaction with the people involved, including unsolicited interaction\nwith those enforcing the Code of Conduct, is allowed during this period.\nViolating these terms may lead to a permanent ban.\n\n#### 4. Permanent Ban\n\n**Community Impact**: Demonstrating a pattern of violation of community\nstandards, including sustained inappropriate behavior,  harassment of an\nindividual, or aggression toward or disparagement of classes of individuals.\n\n**Consequence**: A permanent ban from any sort of public interaction within\nthe community.\n\n### Attribution\n\nThis Code of Conduct is adapted from the [Contributor Covenant][homepage],\nversion 2.0, available at\nhttps://www.contributor-covenant.org/version/2/0/code_of_conduct.html.\n\nCommunity Impact Guidelines were inspired by [Mozilla's code of conduct\nenforcement ladder](https://github.com/mozilla/diversity).\n\n[homepage]: https://www.contributor-covenant.org\n\nFor answers to common questions about this code of conduct, see the FAQ at\nhttps://www.contributor-covenant.org/faq. Translations are available at\nhttps://www.contributor-covenant.org/translations.\n"
  },
  {
    "path": "LICENSE",
    "content": "MIT License\n\nCopyright (c) 2020 Brian\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "<h1 align=\"center\">Python TradingView TA by Analyzer.REST</h1>\n<div align=\"center\">\n  <img src=\"https://img.shields.io/readthedocs/python-tradingview-ta/latest?style=for-the-badge\" />\n  <img src=\"https://img.shields.io/github/license/analyzerrest/python-tradingview-ta?style=for-the-badge\" />\n  <img src=\"https://img.shields.io/pypi/v/tradingview-ta?style=for-the-badge\" />\n</div>\n<br>\n<div align=\"center\">\n  <p>An unofficial API wrapper for TradingView that allows you to fetch technical analysis data, now under new management.</p>\n  <h3>Brought to you by Analyzer.REST, which provides Technical Analysis-as-a-Service (TAaaS) through an intuitive and affordable API. <a href=\"https://analyzer.rest/\">Join the waitlist!</a></h3>\n  <img src=\"https://raw.githubusercontent.com/analyzerrest/python-tradingview-ta/main/images/tradingview.png\" />\n</div>\n\n## Important\n - Keep tradingview-ta up to date for new features and bug fixes: `pip install -U tradingview_ta`\n - 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).\n \n## Features\n* Faster response (older version of tradingview-ta requires Selenium)\n* [Support for multiple symbols](https://python-tradingview-ta.readthedocs.io/en/latest/usage.html#retrieving-multiple-analysis)\n* Indicators (Only TradingView built-in, does not support Pine Script/custom indicators)\n\n## Demo\nYou can try tradingview-ta online without installing Python: https://tvta-demo.analyzer.rest/.\n\n## Requirements\n - Python 3.6 or newer.\n - [Requests](https://pypi.org/project/requests/), included in installation.\n \n## Installation\n [PyPI](https://pypi.org/project/tradingview-ta/) (stable, recommended):\n \n```pip install tradingview_ta```\n\n GitHub (latest):\n \n```pip install git+https://github.com/analyzerrest/python-tradingview-ta.git```\n\n\n## Example\n```python\nfrom tradingview_ta import TA_Handler, Interval, Exchange\n\ntesla = TA_Handler(\n    symbol=\"TSLA\",\n    screener=\"america\",\n    exchange=\"NASDAQ\",\n    interval=Interval.INTERVAL_1_DAY,\n    # proxies={'http': 'http://example.com:8080'} # Uncomment to enable proxy (replace the URL).\n)\nprint(tesla.get_analysis().summary)\n# Example output: {\"RECOMMENDATION\": \"BUY\", \"BUY\": 8, \"NEUTRAL\": 6, \"SELL\": 3}\n```\n\nTip: Use https://tvdb.analyzer.rest/ if you don't know what symbol, screener, and exchange to use.\n\n## Documentation\n [Read The Docs](https://python-tradingview-ta.readthedocs.io)\n\n## Issue\n If you found a bug or have a question, please open an issue. Email will not be replied.\n  \n## Warning\n 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.\n\n## Contributing\n 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).\n \n## License\n 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:\n\n The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\n 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.\n"
  },
  {
    "path": "docs/Makefile",
    "content": "# Minimal makefile for Sphinx documentation\n#\n\n# You can set these variables from the command line.\nSPHINXOPTS    =\nSPHINXBUILD   = sphinx-build\nSOURCEDIR     = .\nBUILDDIR      = _build\n\n# Put it first so that \"make\" without argument is like \"make help\".\nhelp:\n\t@$(SPHINXBUILD) -M help \"$(SOURCEDIR)\" \"$(BUILDDIR)\" $(SPHINXOPTS) $(O)\n\n.PHONY: help Makefile\n\n# Catch-all target: route all unknown targets to Sphinx using the new\n# \"make mode\" option.  $(O) is meant as a shortcut for $(SPHINXOPTS).\n%: Makefile\n\t@$(SPHINXBUILD) -M $@ \"$(SOURCEDIR)\" \"$(BUILDDIR)\" $(SPHINXOPTS) $(O)"
  },
  {
    "path": "docs/changelog.rst",
    "content": "Changelog\n=========\n\n3.3.0\n-----\n\nNew:\n\n* Symbol search\n\n3.2.10\n------\n\nNew:\n\n* Support for proxy\n* Additional indicators support for ``get_multiple_analysis()``\n\n3.2.9\n-----\n\nNew:\n\n* Interval: 30 minutes and 2 hours\n\n3.2.8\n-----\n\nNew:\n\n* Indicators: change, low, high\n\n3.2.7\n-----\n\nBug fix:\n\n* ``get_multiple_analysis()`` will now return ``None`` if there is no analysis for a certain symbol. See `#55 <https://github.com/brian-the-dev/python-tradingview-ta/issues/55>`_ for more details.\n\n3.2.6\n-----\n\nBug fix:\n\n* Add indicators\n* Get multiple analysis\n\n3.2.5\n-----\n\nNew:\n\n* Retrieve indicators ``TA_Handler.get_indicators()``\n* Add custom indicators ``TA_Handler.add_indicators()``\n* Indicators: volume\n\nBug fix:\n\n* Update RSI algorithms\n\n3.2.4\n-----\n\nNew:\n\n* Retrieve multiple analysis\n\nBug fix:\n\n* Update compute algorithms\n\n3.2.3\n-----\n\nNew:\n\n* Timeout\n* Indicators: BBUpper and BBLower\n* Test script (test.py)\n\n3.2.2\n-----\n\nNew:\n\n* Indicators: open and P.SAR\n\n3.2.1\n-----\n\nNew:\n\n* Removed EMA5 and SMA5 from analysis\n\nBug fix:\n\n* Switched buy/sell on momentum\n\n3.2.0\n-----\n\nNew:\n\n* Instantiate ``TA_Handler`` using parameters\n\n3.1.6\n-----\n\nNew:\n\n* Set interval to ``\"1d\"`` if invalid\n\n3.1.5\n-----\n\nNew:\n\n* Move indicators to ``Analysis`` class\n\n3.1.4\n-----\n\nBug fix:\n\n* Pull request `#19 <https://github.com/brian-the-dev/python-tradingview-ta/pull/19>`_\n\n3.1.3\n-----\n\nNew:\n\n* Added user agent\n* Added ``__version__`` attribute\n\n3.1.1\n-----\n\nBug fix:\n\n* Pull request `#7 <https://github.com/brian-the-dev/python-tradingview-ta/pull/7>`_\n\n3.1.0\n-----\n\nNew:\n\n* Set symbol/exchange/screener/interval using functions\n\n3.0.0\n-----\n\nNew:\n\n* Use scanner (https://scanner.tradingview.com/america/scan) instead of selenium\n* Indicators\n\n2.5.0\n-----\n\nNew:\n\n* Support for Heroku\n\n2.2.0\n-----\n\nNew:\n\n* Rename ``pair`` to ``symbol``\n* Support for Python 3.4\n* Added warnings\n\n2.1.0\n-----\n\nBug fix:\n\n* Requirements\n\n2.0.0\n-----\n\nNew:\n\n* Use class\n* Use headless selenium webdriver"
  },
  {
    "path": "docs/conf.py",
    "content": "# -*- coding: utf-8 -*-\n#\n# Configuration file for the Sphinx documentation builder.\n#\n# This file does only contain a selection of the most common options. For a\n# full list see the documentation:\n# http://www.sphinx-doc.org/en/master/config\n\n# -- Path setup --------------------------------------------------------------\n\n# If extensions (or modules to document with autodoc) are in another directory,\n# add these directories to sys.path here. If the directory is relative to the\n# documentation root, use os.path.abspath to make it absolute, like shown here.\n#\n# import os\n# import sys\n# sys.path.insert(0, os.path.abspath('.'))\n\n# -- Imports -----------------------------------------------------\n\nimport sphinx\nimport sphinx_rtd_theme\nfrom recommonmark.transform import AutoStructify\n\n# -- Project information -----------------------------------------------------\n\nproject = u'python-tradingview-ta'\ncopyright = u'2021, deathlyface (Brian)'\nauthor = u'deathlyface (Brian)'\n\n# The short X.Y version\nversion = u''\n# The full version, including alpha/beta/rc tags\nrelease = u''\n\n\n# -- General configuration ---------------------------------------------------\n\n# If your documentation needs a minimal Sphinx version, state it here.\n#\n# needs_sphinx = '1.0'\n\n# Add any Sphinx extension module names here, as strings. They can be\n# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom\n# ones.\nextensions = [\n    'sphinx.ext.autodoc',\n    'recommonmark'\n]\n\n# Add any paths that contain templates here, relative to this directory.\ntemplates_path = ['_templates']\n\n# The suffix(es) of source filenames.\n# You can specify multiple suffix as a list of string:\n#\nsource_suffix = ['.rst', '.md']\n# source_suffix = '.rst'\n\n# The master toctree document.\nmaster_doc = 'index'\n\n# The language for content autogenerated by Sphinx. Refer to documentation\n# for a list of supported languages.\n#\n# This is also used if you do content translation via gettext catalogs.\n# Usually you set \"language\" from the command line for these cases.\nlanguage = None\n\n# List of patterns, relative to source directory, that match files and\n# directories to ignore when looking for source files.\n# This pattern also affects html_static_path and html_extra_path.\nexclude_patterns = [u'_build', 'Thumbs.db', '.DS_Store']\n\n# The name of the Pygments (syntax highlighting) style to use.\npygments_style = None\n\n\n# -- Options for HTML output -------------------------------------------------\n\npygments_style = 'sphinx'\nhtml_theme = 'sphinx_rtd_theme'\nhtml_theme_path = [sphinx_rtd_theme.get_html_theme_path()]\n#html_static_path = [str(Path(__file__).parent.parent / 'assets')]\n#html_logo = str(Path(__file__).parent.parent / 'logo.png')\nhtml_theme_options = {\n    'logo_only': True,\n    'display_version': False,\n    'style_external_links': False,\n    'style_nav_header_background': '#2c3e50',\n}\n\n# -- Options for HTMLHelp output ---------------------------------------------\n\n# Output file base name for HTML help builder.\nhtmlhelp_basename = 'python-tradingview-tadoc'\n\n\n# -- Options for LaTeX output ------------------------------------------------\n\nlatex_elements = {\n    # The paper size ('letterpaper' or 'a4paper').\n    #\n    # 'papersize': 'letterpaper',\n\n    # The font size ('10pt', '11pt' or '12pt').\n    #\n    # 'pointsize': '10pt',\n\n    # Additional stuff for the LaTeX preamble.\n    #\n    # 'preamble': '',\n\n    # Latex figure (float) alignment\n    #\n    # 'figure_align': 'htbp',\n}\n\n# Grouping the document tree into LaTeX files. List of tuples\n# (source start file, target name, title,\n#  author, documentclass [howto, manual, or own class]).\nlatex_documents = [\n    (master_doc, 'python-tradingview-ta.tex', u'python-tradingview-ta Documentation',\n     u'deathlyface (Brian)', 'manual'),\n]\n\n\n# -- Options for manual page output ------------------------------------------\n\n# One entry per manual page. List of tuples\n# (source start file, name, description, authors, manual section).\nman_pages = [\n    (master_doc, 'python-tradingview-ta', u'python-tradingview-ta Documentation',\n     [author], 1)\n]\n\n\n# -- Options for Texinfo output ----------------------------------------------\n\n# Grouping the document tree into Texinfo files. List of tuples\n# (source start file, target name, title, author,\n#  dir menu entry, description, category)\ntexinfo_documents = [\n    (master_doc, 'python-tradingview-ta', u'python-tradingview-ta Documentation',\n     author, 'python-tradingview-ta', 'One line description of project.',\n     'Miscellaneous'),\n]\n\n\n# -- Options for Epub output -------------------------------------------------\n\n# Bibliographic Dublin Core info.\nepub_title = project\n\n# The unique identifier of the text. This can be a ISBN number\n# or the project homepage.\n#\n# epub_identifier = ''\n\n# A unique identification for the text.\n#\n# epub_uid = ''\n\n# A list of files that should not be packed into the epub file.\nepub_exclude_files = ['search.html']\n\n\n# -- Extension configuration -------------------------------------------------\n\n# app setup hook\ndef setup(app):\n    app.add_config_value('recommonmark_config', {\n        #'url_resolver': lambda url: github_doc_root + url,\n        'auto_toc_tree_section': 'Contents',\n        'auto_toc_maxdepth': 2,\n    }, True)\n    app.add_transform(AutoStructify)"
  },
  {
    "path": "docs/faq.rst",
    "content": "FAQ\n===\n\nIs the data delayed?\n--------------------\n\nYes and no. Quoted from TradingView:\n\n    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.\n\n.. note:: TradingView_TA does not support paid real-time data at the moment.\n\n.. note:: Please refer to `TradingView's website <https://www.tradingview.com/gopro/#markets>`_ to see whether the data is delayed or not.\n\nHow do I get past data?\n-----------------------\n\nRetrieving past data is currently not supported.\n\nHow do I create a trading bot?\n------------------------------\n\n.. warning:: Trading (especially using bots) is very risky. I won't be responsible for any financial loss. You have been warned.\n\nThe pseudocode below should help you get started in creating your own trading bot.\n\n.. code-block:: python3\n\n    # Import packages.\n    from tradingview_ta import TA_Handler, Interval, Exchange\n    import time\n\n    # Store the last order.\n    last_order = \"sell\"\n\n    # Instantiate TA_Handler.\n    handler = TA_Handler(\n        symbol=\"SYMBOL\",\n        exchange=\"EXCHANGE\",\n        screener=\"SCREENER\",\n        interval=\"INTERVAL\",\n    )\n\n    # Repeat forever.\n    while True:\n        # Retrieve recommendation.\n        rec = handler.get_analysis()[\"RECOMMENDATION\"]\n\n        # Create a buy order if the recommendation is \"BUY\" or \"STRONG_BUY\" and the last order is \"sell\".\n        # Create a sell order if the recommendation is \"SELL\" or \"STRONG_SELL\" and the last order is \"buy\".\n        if \"BUY\" in rec and last_order == \"sell\":\n            # REPLACE COMMENT: Create a buy order using your exchange's API.\n\n            last_order = \"buy\"\n        elif \"SELL\" in rec and last_order == \"buy\":\n            # REPLACE COMMENT: Create a sell order using your exchange's API.\n\n            last_order = \"sell\"\n\n        # Wait for x seconds before retrieving new analysis.\n        # The time should be the same as the interval.\n        time.sleep(x)\n\n\n.. warning:: ``last_order`` won't be saved when the program exit. When the bot restarts, it will always create a new buy order.\n\n.. tip:: Always paper trade before risking your money.\n\nHow can I get involved?\n-----------------------\n\nIf you found a bug, please `create an issue <https://github.com/brian-the-dev/python-tradingview-ta/issues>`_ on the GitHub repository.\n\nYou can contribute (new features, bug fix, typo, etc) through the `GitHub repository <https://github.com/brian-the-dev/python-tradingview-ta>`_. Please follow the `guidelines <https://github.com/brian-the-dev/python-tradingview-ta/blob/main/CONTRIBUTING.md>`_ and don't send spammy pull requests.\n\nHow does TradingView_TA works?\n------------------------------\n\nA simple network inspection on TradingView's website revealed that the data is retrieved through an `undocumented API <https://scanner.tradingview.com/america/scan>`_.\n\nTradingView_TA works by calculating similar data using `algorithms <https://github.com/brian-the-dev/python-tradingview-ta/blob/main/tradingview_ta/technicals.py>`_ reverse-engineered from their `JavaScript code <https://gist.github.com/brian-the-dev/f0bb91658c1f161cafe8990db1473bd6>`_.\n\nWhy do I get 4XX error?\n-----------------------\n\n400 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.\n\n404 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."
  },
  {
    "path": "docs/index.rst",
    "content": "Welcome to TradingView-TA's documentation!\n==========================================\n\nTradingView_TA is an unofficial Python API wrapper to retrieve technical analysis from TradingView.\n\nThis documentation will help you to understand and use TradingView-TA.\n\n\n.. toctree::\n    :maxdepth: 2\n\n    overview.md\n    usage.md\n    changelog.rst\n    faq.rst\n\n"
  },
  {
    "path": "docs/make.bat",
    "content": "@ECHO OFF\n\npushd %~dp0\n\nREM Command file for Sphinx documentation\n\nif \"%SPHINXBUILD%\" == \"\" (\n\tset SPHINXBUILD=sphinx-build\n)\nset SOURCEDIR=.\nset BUILDDIR=_build\n\nif \"%1\" == \"\" goto help\n\n%SPHINXBUILD% >NUL 2>NUL\nif errorlevel 9009 (\n\techo.\n\techo.The 'sphinx-build' command was not found. Make sure you have Sphinx\n\techo.installed, then set the SPHINXBUILD environment variable to point\n\techo.to the full path of the 'sphinx-build' executable. Alternatively you\n\techo.may add the Sphinx directory to PATH.\n\techo.\n\techo.If you don't have Sphinx installed, grab it from\n\techo.http://sphinx-doc.org/\n\texit /b 1\n)\n\n%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%\ngoto end\n\n:help\n%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%\n\n:end\npopd\n"
  },
  {
    "path": "docs/overview.rst",
    "content": "Getting Started\n===============\n\nThis guide will help you understand the basics of TradingView_TA package.\n\nRequirements\n------------\n\n* Python 3.6 or newer\n* Internet access\n\nInstallation\n------------\n\nTradingView_TA is available on `PyPI <https://pypi.org/project/tradingview-ta/>`_.\n\n.. code-block:: console\n\n    pip install tradingview-ta\n\nQuick Start\n-----------\n\n.. code-block:: python3\n\n    from tradingview_ta import TA_Handler, Interval, Exchange\n\n    tesla = TA_Handler(\n        symbol=\"TSLA\",\n        screener=\"america\",\n        exchange=\"NASDAQ\",\n        interval=Interval.INTERVAL_1_DAY\n    )\n    print(tesla.get_analysis().summary)\n    # Example output: {\"RECOMMENDATION\": \"BUY\", \"BUY\": 8, \"NEUTRAL\": 6, \"SELL\": 3}"
  },
  {
    "path": "docs/usage.rst",
    "content": "Usage\n=====\n\n.. note:: Please install or update TradingView_TA to the latest version. Please read the `getting started <overview.rst>`_ guide before continuing.\n\n.. warning:: TradingView_TA older than v3.2.0 is no longer supported. Please update using ``pip install tradingview_ta --upgrade``.\n\nImporting TradingView_TA\n------------------------\n\n.. code-block:: python3\n\n    from tradingview_ta import TA_Handler, Interval, Exchange\n    import tradingview_ta\n\n\nChecking the version\n--------------------\n\nStarting from version 3.1.3, you can retrieve the version of TradingView_TA through the ``__version__`` attribute.\n\n.. code-block:: python3\n\n    print(tradingview_ta.__version__)\n    # Example output: 3.1.3\n\nInstantiating TA_Handler\n------------------------\n\n.. code-block:: python3\n\n    handler = TA_Handler(\n        symbol=\"\",\n        exchange=\"\",\n        screener=\"\",\n        interval=\"\",\n        timeout=None\n    )\n\nParameters: \n\n    .. tip::\n\n        You can search on https://tvdb.brianthe.dev to see which symbol, exchange, and screener to use.\n\n        .. image:: https://raw.githubusercontent.com/brian-the-dev/python-tradingview-ta/main/images/tv-list.png\n\n    * symbol (``str``) – Ticker symbol (e.g., ``\"AAPL\"``, ``\"TLKM\"``, ``\"USDEUR\"``, ``\"BTCUSDT\"``).\n    * exchange (``str``) – Exchange (e.g., ``\"nasdaq\"``, ``\"idx\"``, ``Exchange.FOREX``, ``\"binance\"``).\n    * screener (``str``) – Screener (e.g., ``\"america\"``, ``\"indonesia\"``, ``\"forex\"``, ``\"crypto\"``).\n\n        .. note::\n\n            * If you're looking for stocks, enter the exchange's country as the screener.\n            * If you're looking for cryptocurrency, enter ``\"crypto\"`` as the screener.\n            * If you're looking for forex, enter ``\"forex\"`` as the screener.\n\n    * interval (``str``) – Time frame\n\n        .. note::\n\n            Please see the Interval class for available intervals.\n\n            .. code-block:: python3\n\n                class Interval:\n                    INTERVAL_1_MINUTE = \"1m\"\n                    INTERVAL_5_MINUTES = \"5m\"\n                    INTERVAL_15_MINUTES = \"15m\"\n                    INTERVAL_30_MINUTES = \"30m\"\n                    INTERVAL_1_HOUR = \"1h\"\n                    INTERVAL_2_HOURS = \"2h\"\n                    INTERVAL_4_HOURS = \"4h\"\n                    INTERVAL_1_DAY = \"1d\"\n                    INTERVAL_1_WEEK = \"1W\"\n                    INTERVAL_1_MONTH = \"1M\"\n\n    * timeout (``float``, optional) – How long to wait (in seconds) for the server to return a response.\n\nRetrieving the analysis\n-----------------------\n\n.. code-block:: python3\n\n    analysis = handler.get_analysis()\n\n.. note::\n\n    ``analysis`` is an instance of Analysis class. \n    It contains information such as the exchange, symbol, screener, interval, local time (datetime.datetime), etc.\n\nAttributes:\n\n    * symbol (``str``) – The symbol set earlier.\n    * exchange (``str``) – The exchange set earlier.\n    * screener (``str``) – The screener set earlier.\n    * interval (``str``) – The interval set earlier.\n    * time (``datetime.datetime``) – The time when the data is retrieved.\n    * summary (``dict``) – Technical analysis (based on both oscillators and moving averages).\n\n        .. code-block:: python3\n\n            # Example\n            {'RECOMMENDATION': 'BUY', 'BUY': 12, 'SELL': 7, 'NEUTRAL': 9}\n\n    * oscillators (``dict``) – Technical analysis (based on oscillators).\n\n        .. code-block:: python3\n\n            # Example\n            {'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'}}\n\n    * moving_averages (``dict``) – Technical analysis (based on moving averages).\n\n        .. code-block:: python3\n\n            # Example\n            {'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'}}\n\n    * indicators (``dict``) – Technical indicators.\n\n        .. code-block:: python3\n\n            # Example\n            {'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}\n\n        .. tip::\n\n            Useful indicators:\n\n            * Opening price: ``analysis.indicators[\"open\"]``\n            * Closing price: ``analysis.indicators[\"close\"]``\n            * Momentum: ``analysis.indicators[\"Mom\"]``\n            * RSI: ``analysis.indicators[\"RSI\"]``\n            * MACD: ``analysis.indicators[\"MACD.macd\"]``\n\nRetrieving multiple analysis\n----------------------------\n\n.. code-block:: python3\n\n    from tradingview_ta import *\n    analysis = get_multiple_analysis(screener=\"america\", interval=Interval.INTERVAL_1_HOUR, symbols=[\"nasdaq:tsla\", \"nyse:docn\", \"nasdaq:aapl\"])\n\n.. note::\n\n    You can't mix different screener and interval.\n\nParameters: \n\n* symbols (``list``) – List of exchange and ticker symbol separated by a colon. Example: [\"NASDAQ:TSLA\", \"NYSE:DOCN\"] or [\"BINANCE:BTCUSDT\", \"BITSTAMP:ETHUSD\"].\n* screener (``str``) – Screener (e.g., ``\"america\"``, ``\"indonesia\"``, ``\"forex\"``, ``\"crypto\"``).\n* timeout (``float``, optional) – How long to wait (in seconds) for the server to return a response.\n* additional_indicators (``list``, optional) – List of additional indicators to retrieve. Example: ``[\"RSI\", \"Mom\"]``.\n* interval (``str``) – Time frame\n  \n    .. note::\n\n        Please see the Interval class for available intervals.\n\n        .. code-block:: python3\n\n            class Interval:\n                INTERVAL_1_MINUTE = \"1m\"\n                INTERVAL_5_MINUTES = \"5m\"\n                INTERVAL_15_MINUTES = \"15m\"\n                INTERVAL_30_MINUTES = \"30m\"\n                INTERVAL_1_HOUR = \"1h\"\n                INTERVAL_2_HOURS = \"2h\"\n                INTERVAL_4_HOURS = \"4h\"\n                INTERVAL_1_DAY = \"1d\"\n                INTERVAL_1_WEEK = \"1W\"\n                INTERVAL_1_MONTH = \"1M\"\n\n.. note::\n    ``get_multiple_analysis()`` returns a dictionary with a format of {\"EXCHANGE:SYMBOL\": Analysis}.\n\n    .. code-block:: python3\n        \n        # Example\n        {'NYSE:DOCN': <tradingview_ta.main.Analysis object at 0x7f3a5ba49be0>, 'NASDAQ:TSLA': <tradingview_ta.main.Analysis object at 0x7f3a5ba65040>, 'NASDAQ:AAPL': <tradingview_ta.main.Analysis object at 0x7f3a5ba801c0>}\n\n    Please use UPPERCASE letters when accessing the dictionary.\n\n    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:\n\n    .. code-block:: python3\n\n        # Example\n        {'BINANCE:DEXEUSDT': None, 'BINANCE:BTCUSDT': <tradingview_ta.main.Analysis object at 0x7f3561cdeb20>}\n\nSymbol search\n-------------\n.. versionadded:: 3.3.0\n\nSearch for symbols using the TradingView symbol search API. Returns a list of symbols, exchanges, types, descriptions, and logo URLs matching the search query.\n\n.. code-block:: python3\n\n    from tradingview_ta import TradingView\n    print(TradingView.search(\"tesla\", \"america\"))\n    # Output: [{'symbol': 'TSLA', 'exchange': 'NASDAQ', 'type': 'stock', 'description': 'Tesla, Inc.', 'logo': 'https://s3-symbol-logo.tradingview.com/tesla.svg'}, ...]\n\n.. note::\n\n    While symbols listed on https://tvdb.brianthe.dev are guaranteed to work with the \"get analysis()\" function, symbols returned by this function may not.\n\nParameters: \n\n* text (``str``) – Query string.\n* type (``str``, optional) – Type of asset (stock, crypto, futures, index). Defaults to None (all).\n\nProxy\n-----\nSimply 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.\n\n    .. code-block:: python3\n\n        from tradingview_ta import TA_Handler, Interval, Exchange\n        tesla = TA_Handler(\n            symbol=\"TSLA\",\n            screener=\"america\",\n            exchange=\"NASDAQ\",\n            interval=Interval.INTERVAL_1_DAY,\n            proxies={'http': 'http://0.0.0.0:8080', 'https': 'https://0.0.0.0:443'}\n        )\n        print(tesla.get_analysis().summary)\n        # Example output: {\"RECOMMENDATION\": \"BUY\", \"BUY\": 8, \"NEUTRAL\": 6, \"SELL\": 3}\n"
  },
  {
    "path": "requirements.txt",
    "content": "requests\ncolorama"
  },
  {
    "path": "setup.cfg",
    "content": "[metadata]\nlicense_file = LICENSE\n"
  },
  {
    "path": "setup.py",
    "content": "import setuptools\n\nwith open(\"README.md\", \"r\") as fh:\n    long_description = fh.read()\n\nsetuptools.setup(\n    name='tradingview_ta',\n    version='3.3.0',\n    description=\"Unofficial TradingView technical analysis API wrapper.\",\n    long_description=long_description,\n    long_description_content_type=\"text/markdown\",\n    url='https://github.com/brian-the-dev/python-tradingview-ta',\n    author='Brian',\n    author_email='brian@brianthe.dev',\n    packages=['tradingview_ta'],\n    classifiers=[\n        \"Programming Language :: Python :: 3\",\n        \"License :: OSI Approved :: MIT License\",\n        \"Operating System :: OS Independent\",\n    ],\n    install_requires=[\n          'requests',\n    ],\n    python_requires='>=3.6',\n    project_urls={\n        'Demo': 'https://tradingview.brianthe.dev',\n        'Documentation': 'https://python-tradingview-ta.readthedocs.io',\n        'Source': 'https://github.com/brian-the-dev/python-tradingview-ta',\n    },\n)\n"
  },
  {
    "path": "test.py",
    "content": "from colorama import Fore, Style\nfrom tradingview_ta import TA_Handler, Interval, get_multiple_analysis\nimport tradingview_ta, requests, argparse\n\narg_parser = argparse.ArgumentParser()\n\narg_parser.add_argument(\"--proxy\", help=\"Use HTTP proxy\")\narg_parser.add_argument(\"--secureproxy\", help=\"Use HTTPS proxy\")\n\nargs = arg_parser.parse_args()\nproxies = {}\nif args.proxy:\n    proxies[\"http\"] = args.proxy\nif args.secureproxy:\n    proxies[\"https\"] = args.secureproxy\n\nprint(\"------------------------------------------------\")\nprint(\"Testing {}Tradingview-TA{} v{}{}\".format(Fore.CYAN, Fore.MAGENTA, tradingview_ta.__version__, Style.RESET_ALL))\nprint(\"This test is {}semi-automatic{}. Please compare with tradingview's data manually.\".format(Fore.LIGHTRED_EX, Style.RESET_ALL))\nprint(\"------------------------------------------------\")\n\nCOUNT = 7\nsuccess = 0\n\nprint(\"{}#0{} {}Testing invalid symbol{}\".format(Fore.BLUE, Style.RESET_ALL, Fore.LIGHTBLUE_EX, Style.RESET_ALL))\nhandler = TA_Handler(\n    symbol=\"ThisSymbolIsInvalid\",\n    interval=\"1m\",\n    screener=\"america\",\n    exchange=\"NASDAQ\",\n    proxies = proxies\n)\ntry:\n    analysis = handler.get_analysis()\n    if analysis:\n        print(\"{}#0{} Invalid symbol test {}failed{}. No exception occured.\".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL))\nexcept Exception as e:\n    if str(e) == \"Exchange or symbol not found.\":\n        print(\"{}#0{} Invalid symbol test {}success{}.\".format(Fore.BLUE, Style.RESET_ALL, Fore.GREEN, Style.RESET_ALL))\n        success += 1\n    else:\n        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))\n\n\nprint(\"{}#1{} {}Testing invalid exchange{}\".format(Fore.BLUE, Style.RESET_ALL, Fore.LIGHTBLUE_EX, Style.RESET_ALL))\nhandler = TA_Handler(\n    symbol=\"TSLA\",\n    interval=\"1m\",\n    screener=\"america\",\n    exchange=\"binance\",\n    proxies = proxies\n)\ntry:\n    analysis = handler.get_analysis()\n    if analysis:\n        print(\"{}#1{} Invalid exchange test {}failed{}. No exception occured.\".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL))\nexcept Exception as e:\n    if str(e) == \"Exchange or symbol not found.\":\n        print(\"{}#1{} Invalid exchange test {}success{}.\".format(Fore.BLUE, Style.RESET_ALL, Fore.GREEN, Style.RESET_ALL))\n        success += 1\n    else:\n        print(\"{}#1{} Invalid exchange test {}failed{}. An exception occured, but symbol is valid.\".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL))\n\nprint(\"{}#2{} {}Testing timeout{}\".format(Fore.BLUE, Style.RESET_ALL, Fore.LIGHTBLUE_EX, Style.RESET_ALL))\nhandler = TA_Handler(\n    symbol=\"AAPL\",\n    interval=Interval.INTERVAL_1_DAY,\n    screener=\"america\",\n    exchange=\"NASDAQ\",\n    timeout=0.0001,\n    proxies = proxies\n)\ntry:\n    analysis = handler.get_analysis()\n    if analysis:\n        print(\"{}#2{} Timeout test {}failed{}.\".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL))\nexcept Exception as e:\n    if type(e) == requests.exceptions.ConnectTimeout:\n        print(\"{}#2{} Timeout test {}success{}.\".format(Fore.BLUE, Style.RESET_ALL, Fore.GREEN, Style.RESET_ALL))\n        success += 1\n\n\nprint(\"{}#3{} {}Testing invalid interval{}\".format(Fore.BLUE, Style.RESET_ALL, Fore.LIGHTBLUE_EX, Style.RESET_ALL))\nhandler = TA_Handler(\n    symbol=\"TSLA\",\n    interval=\"1 minute\",\n    screener=\"america\",\n    exchange=\"NASDAQ\",\n    proxies = proxies\n)\ntry:\n    analysis = handler.get_analysis()\n    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\":\n        print(\"{}#3{} Invalid interval test {}success{}.\".format(Fore.BLUE, Style.RESET_ALL, Fore.GREEN, Style.RESET_ALL))\n        success += 1\n    else:\n        print(\"{}#3{} Invalid interval test {}failed{}\".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL))\n\nexcept Exception as e:\n    print(\"{}#3{} Invalid interval test {}failed{}. An exception occured: {}\".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL, e))\n\nprint(\"{}#4{} {}Testing stock (NASDAQ:AAPL){}\".format(Fore.BLUE, Style.RESET_ALL, Fore.LIGHTBLUE_EX, Style.RESET_ALL))\nhandler = TA_Handler(\n    symbol=\"AAPL\",\n    interval=Interval.INTERVAL_1_DAY,\n    screener=\"america\",\n    exchange=\"NASDAQ\",\n    proxies = proxies\n)\ntry:\n    analysis = handler.get_analysis()\n    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))\n    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\"]))\n    if input(\"{}#4{} Are the results the same? (Y/N) \".format(Fore.BLUE, Style.RESET_ALL)).lower() == \"y\":\n        print(\"{}#4{} Stock test {}success{}.\".format(Fore.BLUE, Style.RESET_ALL, Fore.GREEN, Style.RESET_ALL))\n        success += 1\n    else:\n        print(\"{}#4{} Stock test {}failed{}\".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL))\nexcept Exception as e:\n    print(\"{}#4{} Stock test {}failed{}. An exception occured: {}\".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL, e))\n\nprint(\"{}#5{} {}Testing multiple analysis (NASDAQ:TSLA and NYSE:DOCN){}\".format(Fore.BLUE, Style.RESET_ALL, Fore.LIGHTBLUE_EX, Style.RESET_ALL))\ntry:\n    analysis = get_multiple_analysis(screener=\"america\", interval=Interval.INTERVAL_1_HOUR, symbols=[\"nasdaq:tsla\", \"nyse:docn\"])\n    for key, value in analysis.items():\n        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))\n        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\"]))\n    if input(\"{}#5{} Are the results the same? (Y/N) \".format(Fore.BLUE, Style.RESET_ALL)).lower() == \"y\":\n        print(\"{}#5{} Multiple analysis test {}success{}.\".format(Fore.BLUE, Style.RESET_ALL, Fore.GREEN, Style.RESET_ALL))\n        success += 1\n    else:\n        print(\"{}#5{} Multiple analysis test {}failed{}\".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL))\nexcept Exception as e:\n    print(\"{}#5{} Multiple analysis test {}failed{}. An exception occured: {}\".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL, e))\n\nprint(\"{}#6{} {}Testing get indicators (BINANCE:BTCUSDT){}\".format(Fore.BLUE, Style.RESET_ALL, Fore.LIGHTBLUE_EX, Style.RESET_ALL))\nhandler = TA_Handler(\n    symbol=\"BTCUSDT\",\n    interval=Interval.INTERVAL_1_DAY,\n    screener=\"crypto\",\n    exchange=\"binance\",\n    proxies = proxies\n)\ntry:\n    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))\n    print(\"{}#6{} {}\".format(Fore.BLUE, Style.RESET_ALL, handler.get_indicators()))\n    if input(\"{}#6{} Are the results the same? (Y/N) \".format(Fore.BLUE, Style.RESET_ALL)).lower() == \"y\":\n        print(\"{}#6{} Get indicators test {}success{}.\".format(Fore.BLUE, Style.RESET_ALL, Fore.GREEN, Style.RESET_ALL))\n        success += 1\n    else:\n        print(\"{}#6{} Get indicators test {}failed{}\".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL))\nexcept Exception as e:\n    print(\"{}#6{} Get indicators test {}failed{}. An exception occured: {}\".format(Fore.BLUE, Style.RESET_ALL, Fore.RED, Style.RESET_ALL, e))\n\n\nprint(\"------------------------------------------------\")\nprint(\"Test finished. Result: {}{}/{}{}.\".format(Fore.LIGHTWHITE_EX, success, COUNT, Style.RESET_ALL))\n"
  },
  {
    "path": "tradingview_ta/__init__.py",
    "content": "from .main import TA_Handler, TradingView, Analysis, Interval, Exchange, get_multiple_analysis, __version__\nfrom .technicals import Recommendation, Compute\n"
  },
  {
    "path": "tradingview_ta/main.py",
    "content": "# Tradingview Technical Analysis (tradingview-ta)\n# Author: deathlyface (https://github.com/deathlyface)\n# License: MIT\n\nimport requests\nimport json\nimport datetime\nimport warnings\nfrom .technicals import Compute\n\n__version__ = \"3.3.0\"\n\n\nclass Analysis(object):\n    exchange = \"\"\n    symbol = \"\"\n    screener = \"\"\n    time = \"\"\n    interval = \"\"\n    summary = {}\n    oscillators = {}\n    moving_averages = {}\n    indicators = {}\n\n\nclass Interval:\n    INTERVAL_1_MINUTE = \"1m\"\n    INTERVAL_5_MINUTES = \"5m\"\n    INTERVAL_15_MINUTES = \"15m\"\n    INTERVAL_30_MINUTES = \"30m\"\n    INTERVAL_1_HOUR = \"1h\"\n    INTERVAL_2_HOURS = \"2h\"\n    INTERVAL_4_HOURS = \"4h\"\n    INTERVAL_1_DAY = \"1d\"\n    INTERVAL_1_WEEK = \"1W\"\n    INTERVAL_1_MONTH = \"1M\"\n\n\nclass Exchange:\n    FOREX = \"FX_IDC\"\n    CFD = \"TVC\"\n\n\nclass TradingView:\n    # 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.\n    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\",\n                  \"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\"]\n\n    scan_url = \"https://scanner.tradingview.com/\"\n\n    def data(symbols, interval, indicators):\n        \"\"\"Format TradingView's Scanner Post Data\n\n        Args:\n            symbols (list): List of EXCHANGE:SYMBOL (ex: [\"NASDAQ:AAPL\"] or [\"BINANCE:BTCUSDT\"])\n            interval (string): Time Interval (ex: 1m, 5m, 15m, 1h, 4h, 1d, 1W, 1M)\n\n        Returns:\n            string: JSON object as a string.\n        \"\"\"\n        if interval == \"1m\":\n            # 1 Minute\n            data_interval = \"|1\"\n        elif interval == \"5m\":\n            # 5 Minutes\n            data_interval = \"|5\"\n        elif interval == \"15m\":\n            # 15 Minutes\n            data_interval = \"|15\"\n        elif interval == \"30m\":\n            # 30 Minutes\n            data_interval = \"|30\"\n        elif interval == \"1h\":\n            # 1 Hour\n            data_interval = \"|60\"\n        elif interval == \"2h\":\n            # 2 Hours\n            data_interval = \"|120\"\n        elif interval == \"4h\":\n            # 4 Hour\n            data_interval = \"|240\"\n        elif interval == \"1W\":\n            # 1 Week\n            data_interval = \"|1W\"\n        elif interval == \"1M\":\n            # 1 Month\n            data_interval = \"|1M\"\n        else:\n            if interval != '1d':\n                warnings.warn(\n                    \"Interval is empty or not valid, defaulting to 1 day.\")\n            # Default, 1 Day\n            data_interval = \"\"\n\n        data_json = {\"symbols\": {\"tickers\": [symbol.upper() for symbol in symbols], \"query\": {\n            \"types\": []}}, \"columns\": [x + data_interval for x in indicators]}\n\n        return data_json\n\n    def search(text, type=None):\n        \"\"\"Search for assets on TradingView. Returns the symbol, exchange, type, and description of the asset.\n\n        Args:\n            text (str, required): Query string\n            type (str, optional): Type of asset (stock, crypto, futures, index). Defaults to None.\n        \"\"\"\n        req = requests.post(\n            \"https://symbol-search.tradingview.com/symbol_search\", params={\"text\": text, \"type\": type})\n        symbols = json.loads(req.text)\n        res = []\n        for symbol in symbols:\n            if \"logoid\" in symbol:\n                logo = f\"https://s3-symbol-logo.tradingview.com/{symbol['logoid']}.svg\"\n            elif \"base-currency-logoid\" in symbol:\n                logo = f\"https://s3-symbol-logo.tradingview.com/{symbol['base-currency-logoid']}.svg\"\n            elif \"country\" in symbol:\n                logo = f\"https://s3-symbol-logo.tradingview.com/country/{symbol['country']}.svg\"\n            else:\n                logo = None\n            res.append({\"symbol\": symbol[\"symbol\"], \"exchange\": symbol[\"exchange\"],\n                        \"type\": symbol[\"type\"], \"description\": symbol[\"description\"], \"logo\": logo})\n        return res\n\n\ndef calculate(indicators, indicators_key, screener, symbol, exchange, interval):\n    oscillators_counter, ma_counter = {\"BUY\": 0, \"SELL\": 0, \"NEUTRAL\": 0}, {\n        \"BUY\": 0, \"SELL\": 0, \"NEUTRAL\": 0}\n    computed_oscillators, computed_ma = {}, {}\n\n    indicators = list(indicators.values())\n\n    # RECOMMENDATIONS\n    if None not in indicators[0:2]:\n        recommend_oscillators = Compute.Recommend(indicators[0])\n        recommend_summary = Compute.Recommend(indicators[1])\n        recommend_moving_averages = Compute.Recommend(indicators[2])\n    else:\n        return None\n\n    # OSCILLATORS\n    # RSI (14)\n    if None not in indicators[3:5]:\n        computed_oscillators[\"RSI\"] = Compute.RSI(indicators[3], indicators[4])\n        oscillators_counter[computed_oscillators[\"RSI\"]] += 1\n    # Stoch %K\n    if None not in indicators[5:9]:\n        computed_oscillators[\"STOCH.K\"] = Compute.Stoch(\n            indicators[5], indicators[6], indicators[7], indicators[8])\n        oscillators_counter[computed_oscillators[\"STOCH.K\"]] += 1\n    # CCI (20)\n    if None not in indicators[9:11]:\n        computed_oscillators[\"CCI\"] = Compute.CCI20(\n            indicators[9], indicators[10])\n        oscillators_counter[computed_oscillators[\"CCI\"]] += 1\n    # ADX (14)\n    if None not in indicators[11:16]:\n        computed_oscillators[\"ADX\"] = Compute.ADX(\n            indicators[11], indicators[12], indicators[13], indicators[14], indicators[15])\n        oscillators_counter[computed_oscillators[\"ADX\"]] += 1\n    # AO\n    if None not in indicators[16:18] and indicators[86] != None:\n        computed_oscillators[\"AO\"] = Compute.AO(\n            indicators[16], indicators[17], indicators[86])\n        oscillators_counter[computed_oscillators[\"AO\"]] += 1\n    # Mom (10)\n    if None not in indicators[18:20]:\n        computed_oscillators[\"Mom\"] = Compute.Mom(\n            indicators[18], indicators[19])\n        oscillators_counter[computed_oscillators[\"Mom\"]] += 1\n    # MACD\n    if None not in indicators[20:22]:\n        computed_oscillators[\"MACD\"] = Compute.MACD(\n            indicators[20], indicators[21])\n        oscillators_counter[computed_oscillators[\"MACD\"]] += 1\n    # Stoch RSI\n    if indicators[22] != None:\n        computed_oscillators[\"Stoch.RSI\"] = Compute.Simple(indicators[22])\n        oscillators_counter[computed_oscillators[\"Stoch.RSI\"]] += 1\n    # W%R\n    if indicators[24] != None:\n        computed_oscillators[\"W%R\"] = Compute.Simple(indicators[24])\n        oscillators_counter[computed_oscillators[\"W%R\"]] += 1\n    # BBP\n    if indicators[26] != None:\n        computed_oscillators[\"BBP\"] = Compute.Simple(indicators[26])\n        oscillators_counter[computed_oscillators[\"BBP\"]] += 1\n    # UO\n    if indicators[28] != None:\n        computed_oscillators[\"UO\"] = Compute.Simple(indicators[28])\n        oscillators_counter[computed_oscillators[\"UO\"]] += 1\n\n    # MOVING AVERAGES\n    ma_list = [\"EMA10\", \"SMA10\", \"EMA20\", \"SMA20\", \"EMA30\", \"SMA30\",\n               \"EMA50\", \"SMA50\", \"EMA100\", \"SMA100\", \"EMA200\", \"SMA200\"]\n    close = indicators[30]\n    ma_list_counter = 0\n    for index in range(33, 45):\n        if indicators[index] != None:\n            computed_ma[ma_list[ma_list_counter]] = Compute.MA(\n                indicators[index], close)\n            ma_counter[computed_ma[ma_list[ma_list_counter]]] += 1\n            ma_list_counter += 1\n\n    # MOVING AVERAGES, pt 2\n    # ICHIMOKU\n    if indicators[45] != None:\n        computed_ma[\"Ichimoku\"] = Compute.Simple(indicators[45])\n        ma_counter[computed_ma[\"Ichimoku\"]] += 1\n    # VWMA\n    if indicators[47] != None:\n        computed_ma[\"VWMA\"] = Compute.Simple(indicators[47])\n        ma_counter[computed_ma[\"VWMA\"]] += 1\n    # HullMA (9)\n    if indicators[49] != None:\n        computed_ma[\"HullMA\"] = Compute.Simple(indicators[49])\n        ma_counter[computed_ma[\"HullMA\"]] += 1\n\n    analysis = Analysis()\n    analysis.screener = screener\n    analysis.exchange = exchange\n    analysis.symbol = symbol\n    analysis.interval = interval\n    analysis.time = datetime.datetime.now()\n\n    for x in range(len(indicators)):\n        analysis.indicators[indicators_key[x]] = indicators[x]\n\n    analysis.indicators = analysis.indicators.copy()\n\n    analysis.oscillators = {\"RECOMMENDATION\": recommend_oscillators,\n                            \"BUY\": oscillators_counter[\"BUY\"], \"SELL\": oscillators_counter[\"SELL\"], \"NEUTRAL\": oscillators_counter[\"NEUTRAL\"], \"COMPUTE\": computed_oscillators}\n    analysis.moving_averages = {\"RECOMMENDATION\": recommend_moving_averages,\n                                \"BUY\": ma_counter[\"BUY\"], \"SELL\": ma_counter[\"SELL\"], \"NEUTRAL\": ma_counter[\"NEUTRAL\"], \"COMPUTE\": computed_ma}\n    analysis.summary = {\"RECOMMENDATION\": recommend_summary, \"BUY\": oscillators_counter[\"BUY\"] + ma_counter[\"BUY\"],\n                        \"SELL\": oscillators_counter[\"SELL\"] + ma_counter[\"SELL\"], \"NEUTRAL\": oscillators_counter[\"NEUTRAL\"] + ma_counter[\"NEUTRAL\"]}\n\n    return analysis\n\n\nclass TA_Handler(object):\n    screener = \"\"\n    exchange = \"\"\n    symbol = \"\"\n    interval = \"\"\n    timeout = None\n\n    indicators = TradingView.indicators.copy()\n\n    def __init__(self, screener=\"\", exchange=\"\", symbol=\"\", interval=\"\", timeout=None, proxies=None):\n        \"\"\"Create an instance of TA_Handler class\n\n        Args:\n            screener (str, required): Screener (see documentation and tradingview's site).\n            exchange (str, required): Exchange (see documentation and tradingview's site).\n            symbol (str, required): Abbreviation of a stock or currency (see documentation and tradingview's site).\n            interval (str, optional): See the interval class and the documentation. Defaults to 1 day.\n            timeout (float, optional): Timeout for requests (in seconds). Defaults to None.\n            proxies (dict, optional): Proxies to be used for requests. Defaults to None (disabled).\n        \"\"\"\n        self.screener = screener\n        self.exchange = exchange\n        self.symbol = symbol\n        self.interval = interval\n        self.timeout = timeout\n        self.proxies = proxies\n\n    # Set functions\n    def set_screener_as_stock(self, country):\n        \"\"\"Set the screener as a country (for stocks).\n\n        Args:\n            country (string): Stock's country (ex: If NFLX or AAPL, then \"america\" is the screener)\n        \"\"\"\n        self.screener = country\n\n    def set_screener_as_crypto(self):\n        \"\"\"Set the screener as crypto (for cryptocurrencies).\n        \"\"\"\n        self.screener = \"crypto\"\n\n    def set_screener_as_cfd(self):\n        \"\"\"Set the screener as cfd (contract for differences).\n        \"\"\"\n        self.screener = \"cfd\"\n\n    def set_screener_as_forex(self):\n        \"\"\"Set the screener as forex.\n        \"\"\"\n        self.screener = \"forex\"\n\n    def set_exchange_as_crypto_or_stock(self, exchange):\n        \"\"\"Set the exchange\n\n        Args:\n            exchange (string): Stock/Crypto's exchange (NASDAQ, NYSE, BINANCE, BITTREX, etc).\n        \"\"\"\n        self.exchange = exchange\n\n    def set_exchange_as_forex(self):\n        \"\"\"Set the exchange as FX_IDC for forex.\n        \"\"\"\n        self.exchange = \"FX_IDC\"\n\n    def set_exchange_as_cfd(self):\n        \"\"\"Set the exchange as TVC for cfd.\n        \"\"\"\n        self.exchange = \"TVC\"\n\n    def set_interval_as(self, intvl):\n        \"\"\"Set the interval.\n\n        Refer to: https://python-tradingview-ta.readthedocs.io/en/latest/usage.html#setting-the-interval\n\n        Args:\n            intvl (string): interval. You can use values from the Interval class.\n\n        \"\"\"\n        self.interval = intvl\n\n    def set_symbol_as(self, symbol):\n        \"\"\"Set the symbol.\n\n        Refer to: https://python-tradingview-ta.readthedocs.io/en/latest/usage.html#setting-the-symbol\n\n        Args:\n            symbol (string): abbreviation of a stock or currency (ex: NFLX, AAPL, BTCUSD).\n        \"\"\"\n        self.symbol = symbol\n\n    def get_indicators(self, indicators=[]):\n        \"\"\"Just the indicators, please. See valid indicators on https://pastebin.com/1DjWv2Hd.\n\n        Args:\n            indicators (list, optional): List of string of indicators (ex: [\"RSI7\", \"open\"]). Defaults to self.indicators.\n\n        Returns:\n            dict: A dictionary with a format of {\"indicator\": value}.\n        \"\"\"\n        if len(indicators) == 0:\n            indicators = self.indicators\n\n        if self.screener == \"\" or type(self.screener) != str:\n            raise Exception(\"Screener is empty or not valid.\")\n        elif self.exchange == \"\" or type(self.exchange) != str:\n            raise Exception(\"Exchange is empty or not valid.\")\n        elif self.symbol == \"\" or type(self.symbol) != str:\n            raise Exception(\"Symbol is empty or not valid.\")\n\n        exchange_symbol = f\"{self.exchange}:{self.symbol}\"\n        data = TradingView.data([exchange_symbol], self.interval, indicators)\n        scan_url = f\"{TradingView.scan_url}{self.screener.lower()}/scan\"\n        headers = {\"User-Agent\": \"tradingview_ta/{}\".format(__version__)}\n        response = requests.post(\n            scan_url, json=data, headers=headers, timeout=self.timeout, proxies=self.proxies)\n\n        # Return False if can't get data\n        if response.status_code != 200:\n            raise Exception(\"Can't access TradingView's API. HTTP status code: {}. Check for invalid symbol, exchange, or indicators.\".format(\n                response.status_code))\n\n        result = json.loads(response.text)[\"data\"]\n        if result != []:\n            indicators_val = {}\n            for x in range(len(indicators)):\n                indicators_val[indicators[x]] = result[0][\"d\"][x]\n            return indicators_val\n        else:\n            raise Exception(\"Exchange or symbol not found.\")\n\n    # Add custom indicators\n    def add_indicators(self, indicators):\n        \"\"\"Add custom indicators. See valid indicators on https://pastebin.com/1DjWv2Hd.\n\n        Args:\n            indicators (list): List of strings of indicators. (ex: [\"RSI7\", \"VWMA\"])\n        \"\"\"\n        self.indicators += indicators\n\n    # Get analysis\n    def get_analysis(self):\n        \"\"\"Get analysis from TradingView and compute it.\n\n        Returns:\n            Analysis: Contains information about the analysis.\n        \"\"\"\n\n        return calculate(indicators=self.get_indicators(), indicators_key=self.indicators, screener=self.screener, symbol=self.symbol, exchange=self.exchange, interval=self.interval)\n\n\ndef get_multiple_analysis(screener, interval, symbols, additional_indicators=[], timeout=None, proxies=None):\n    \"\"\"Retrieve multiple technical analysis at once. Note: You can't mix different screener and interval\n\n    Args:\n        screener (str, required): Screener (see documentation and tradingview's site).\n        interval (str, optional): See the interval class and the documentation. Defaults to 1 day.\n        symbols (list, required): List of exchange and ticker symbol separated by a colon. Example: [\"NASDAQ:TSLA\", \"NYSE:DOCN\"] or [\"BINANCE:BTCUSDT\", \"BITSTAMP:ETHUSD\"].\n        additional_indicators (list, optional): List of additional indicators to be requested from TradingView, see valid indicators on https://pastebin.com/1DjWv2Hd.\n        timeout (float, optional): Timeout for requests (in seconds). Defaults to None.\n        proxies (dict, optional): Proxies to be used for requests. Defaults to None (disabled).\n\n    Returns:\n        dict: dictionary with a format of {\"EXCHANGE:SYMBOL\": Analysis}.\n    \"\"\"\n    if screener == \"\" or type(screener) != str:\n        raise Exception(\"Screener is empty or not valid.\")\n    if len(symbols) == 0 or type(symbols) != list:\n        raise Exception(\"Symbols is empty or not valid.\")\n    for symbol in symbols:\n        if len(symbol.split(\":\")) != 2 or \"\" in symbol.split(\":\"):\n            raise Exception(\n                \"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\\\"].\")\n\n    indicators_key = TradingView.indicators.copy()\n\n    if additional_indicators:\n        indicators_key += additional_indicators\n\n    data = TradingView.data(symbols, interval, indicators_key)\n    scan_url = f\"{TradingView.scan_url}{screener.lower()}/scan\"\n    headers = {\"User-Agent\": \"tradingview_ta/{}\".format(__version__)}\n    response = requests.post(\n        scan_url, json=data, headers=headers, timeout=timeout, proxies=proxies)\n\n    result = json.loads(response.text)[\"data\"]\n    final = {}\n\n    for analysis in result:\n        # Convert list to dict\n        indicators = {}\n        for x in range(len(analysis[\"d\"])):\n            indicators[indicators_key[x]] = analysis[\"d\"][x]\n\n        final[analysis[\"s\"]] = calculate(indicators=indicators, indicators_key=indicators_key, screener=screener, symbol=analysis[\"s\"].split(\n            \":\")[1], exchange=analysis[\"s\"].split(\":\")[0], interval=interval)\n\n    for symbol in symbols:\n        # Add None if there is no analysis for symbol\n        if symbol.upper() not in final:\n            final[symbol.upper()] = None\n\n    return final\n"
  },
  {
    "path": "tradingview_ta/technicals.py",
    "content": "# Tradingview Technical Analysis (tradingview-ta)\n# Author: deathlyface (https://github.com/deathlyface)\n# Rewritten from https://www.tradingview.com/static/bundles/technicals.f2e6e6a51aebb6cd46f8.js\n# License: MIT\n\nclass Recommendation:\n    buy = \"BUY\"\n    strong_buy = \"STRONG_BUY\"\n    sell = \"SELL\"\n    strong_sell = \"STRONG_SELL\"\n    neutral = \"NEUTRAL\"\n    error = \"ERROR\"\n\nclass Compute:\n    def MA(ma, close):\n        \"\"\"Compute Moving Average\n\n        Args:\n            ma (float): MA value\n            close (float): Close value\n\n        Returns:\n            string: \"BUY\", \"SELL\", or \"NEUTRAL\"\n        \"\"\"\n        if (ma < close):\n            return Recommendation.buy\n        elif (ma > close):\n            return Recommendation.sell\n        else:\n            return Recommendation.neutral\n\n    def RSI(rsi, rsi1):\n        \"\"\"Compute Relative Strength Index\n\n        Args:\n            rsi (float): RSI value\n            rsi1 (float): RSI[1] value\n\n        Returns:\n            string: \"BUY\", \"SELL\", or \"NEUTRAL\"\n        \"\"\"\n        if (rsi < 30 and rsi1 < rsi):\n            return Recommendation.buy\n        elif (rsi > 70 and rsi1 > rsi):\n            return Recommendation.sell\n        else:\n            return Recommendation.neutral\n\n    def Stoch(k, d, k1, d1):\n        \"\"\"Compute Stochastic\n\n        Args:\n            k (float): Stoch.K value\n            d (float): Stoch.D value\n            k1 (float): Stoch.K[1] value\n            d1 (float): Stoch.D[1] value\n\n        Returns:\n            string: \"BUY\", \"SELL\", or \"NEUTRAL\"\n        \"\"\"\n        if (k < 20 and d < 20 and k > d and k1 < d1):\n            return Recommendation.buy\n        elif (k > 80 and d > 80 and k < d and k1 > d1):\n            return Recommendation.sell\n        else:\n            return Recommendation.neutral\n\n    def CCI20(cci20, cci201):\n        \"\"\"Compute Commodity Channel Index 20\n\n        Args:\n            cci20 (float): CCI20 value\n            cci201 ([type]): CCI20[1] value\n\n        Returns:\n            string: \"BUY\", \"SELL\", or \"NEUTRAL\"\n        \"\"\"\n        if (cci20 < -100 and cci20 > cci201):\n            return Recommendation.buy\n        elif (cci20 > 100 and cci20 < cci201):\n            return Recommendation.sell\n        else:\n            return Recommendation.neutral\n\n    def ADX(adx, adxpdi, adxndi, adxpdi1, adxndi1):\n        \"\"\"Compute Average Directional Index\n\n        Args:\n            adx (float): ADX value\n            adxpdi (float): ADX+DI value\n            adxndi (float): ADX-DI value\n            adxpdi1 (float): ADX+DI[1] value\n            adxndi1 (float): ADX-DI[1] value\n\n        Returns:\n            string: \"BUY\", \"SELL\", or \"NEUTRAL\"\n        \"\"\"\n        if (adx > 20 and adxpdi1 < adxndi1 and adxpdi > adxndi):\n            return Recommendation.buy\n        elif (adx > 20 and adxpdi1 > adxndi1 and adxpdi < adxndi):\n            return Recommendation.sell\n        else:\n            return Recommendation.neutral\n\n    def AO(ao, ao1, ao2):\n        \"\"\"Compute Awesome Oscillator\n\n        Args:\n            ao (float): AO value\n            ao1 (float): AO[1] value\n            ao2 (float): AO[2] value\n\n        Returns:\n            string: \"BUY\", \"SELL\", or \"NEUTRAL\"\n        \"\"\"\n        if (ao > 0 and ao1 < 0) or (ao > 0 and ao1 > 0 and ao > ao1 and ao2 > ao1):\n            return Recommendation.buy\n        elif (ao < 0 and ao1 > 0) or (ao < 0 and ao1 < 0 and ao < ao1 and ao2 < ao1):\n            return Recommendation.sell\n        else:\n            return Recommendation.neutral\n\n    def Mom(mom, mom1):\n        \"\"\"Compute Momentum\n\n        Args:\n            mom (float): Mom value\n            mom1 (float): Mom[1] value\n\n        Returns:\n            string: \"BUY\", \"SELL\", or \"NEUTRAL\"\n        \"\"\"\n        if (mom < mom1):\n            return Recommendation.sell\n        elif (mom > mom1):\n            return Recommendation.buy\n        else:\n            return Recommendation.neutral\n\n    def MACD(macd, signal):\n        \"\"\"Compute Moving Average Convergence/Divergence\n\n        Args:\n            macd (float): MACD.macd value\n            signal (float): MACD.signal value\n\n        Returns:\n            string: \"BUY\", \"SELL\", or \"NEUTRAL\"\n        \"\"\"\n        if (macd > signal):\n            return Recommendation.buy\n        elif (macd < signal):\n            return Recommendation.sell\n        else:\n            return Recommendation.neutral\n        \n    def BBBuy(close, bblower):\n        \"\"\"Compute Bull Bear Buy\n\n        Args:\n            close (float): close value\n            bblower (float): BB.lower value\n\n        Returns:\n            string: \"BUY\", \"SELL\", or \"NEUTRAL\"\n        \"\"\"\n        if (close < bblower):\n            return Recommendation.buy\n        else:\n            return Recommendation.neutral\n\n    def BBSell(close, bbupper):\n        \"\"\"Compute Bull Bear Sell\n\n        Args:\n            close (float): close value\n            bbupper (float): BB.upper value\n\n        Returns:\n            string: \"BUY\", \"SELL\", or \"NEUTRAL\"\n        \"\"\"\n        if (close > bbupper):\n            return Recommendation.sell\n        else:\n            return Recommendation.neutral\n\n    def PSAR(psar, open):\n        \"\"\"Compute Parabolic Stop-And-Reverse\n\n        Args:\n            psar (float): P.SAR value\n            open (float): open value\n\n        Returns:\n            string: \"BUY\", \"SELL\", or \"NEUTRAL\"\n        \"\"\"\n        if (psar < open):\n            return Recommendation.buy\n        elif (psar > open):\n            return Recommendation.sell\n        else:\n            return Recommendation.neutral\n\n    def Recommend(value):\n        \"\"\"Compute Recommend\n\n        Args:\n            value (float): recommend value\n\n        Returns:\n            string: \"STRONG_BUY\", \"BUY\", \"NEUTRAL\", \"SELL\", \"STRONG_SELL\", or \"ERROR\"\n        \"\"\"\n        if value >= -1 and value < -.5:\n            return Recommendation.strong_sell\n        elif value >= -.5 and value < -.1:\n            return Recommendation.sell\n        elif value >= -.1 and value <= .1:\n            return Recommendation.neutral\n        elif value > .1 and value <= .5 :\n            return Recommendation.buy\n        elif value > .5 and value <= 1:\n            return Recommendation.strong_buy\n        else:\n            return Recommendation.error\n\n    def Simple(value):\n        \"\"\"Compute Simple\n\n        Args:\n            value (float): Rec.X value\n\n        Returns:\n            string: \"BUY\", \"SELL\", or \"NEUTRAL\"\n        \"\"\"\n        if (value == -1):\n            return Recommendation.sell\n        elif (value == 1):\n            return Recommendation.buy\n        else:\n            return Recommendation.neutral\n"
  }
]