├── polygon ├── stocks │ └── __init__.py ├── crypto │ └── __init__.py ├── forex │ └── __init__.py ├── indices │ └── __init__.py ├── reference_apis │ └── __init__.py ├── streaming │ ├── __init__.py │ ├── constants.py │ └── streaming.py ├── options │ └── __init__.py ├── __init__.py └── enums.py ├── setup.cfg ├── docs ├── _static │ ├── github_logo.png │ ├── discord_logo.png │ └── patreon_logo.jpeg ├── Makefile ├── make.bat ├── index.rst ├── getting_help.rst ├── conf.py ├── Indices.rst ├── bugs_discussions_wikis_faqs.rst ├── contrib_and_license.rst ├── References.rst ├── Stocks.rst ├── using_enums.rst ├── Library-Interface-Documentation.rst ├── Forex_Crypto.rst ├── bulk_data_download_functions.rst ├── Callback-Streaming.rst ├── Async-Streaming.rst ├── Options.rst └── Getting-Started.rst ├── requirements ├── requirements.txt └── requirements.dev ├── tests └── __init__.py ├── .github └── ISSUE_TEMPLATE │ ├── blank-issue-template.md │ ├── blank-feature-request-template.md │ ├── feature_request.md │ └── submitting-a-bug-issue.md ├── .readthedocs.yaml ├── EXAMPLES ├── rest_examples │ ├── regular_clients │ │ ├── paginated_responses.py │ │ └── basic_stocks_data.py │ └── async_clients │ │ ├── paginated_responses.py │ │ └── basic_stocks_data.py └── streaming_examples │ ├── callback_streaming │ └── simple_stream.py │ └── async_streaming │ └── simple_stream.py ├── LICENSE ├── setup.py ├── .gitignore ├── README.md └── CHANGELOG.md /polygon/stocks/__init__.py: -------------------------------------------------------------------------------- 1 | from .stocks import StocksClient 2 | -------------------------------------------------------------------------------- /polygon/crypto/__init__.py: -------------------------------------------------------------------------------- 1 | from .crypto_api import CryptoClient 2 | -------------------------------------------------------------------------------- /polygon/forex/__init__.py: -------------------------------------------------------------------------------- 1 | from .forex_api import ForexClient 2 | -------------------------------------------------------------------------------- /polygon/indices/__init__.py: -------------------------------------------------------------------------------- 1 | from .indices import IndexClient 2 | -------------------------------------------------------------------------------- /polygon/reference_apis/__init__.py: -------------------------------------------------------------------------------- 1 | from .reference_api import ReferenceClient 2 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [bdist_wheel] 2 | universal = 1 3 | 4 | [metadata] 5 | license_file = LICENSE -------------------------------------------------------------------------------- /docs/_static/github_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pssolanki111/polygon/HEAD/docs/_static/github_logo.png -------------------------------------------------------------------------------- /docs/_static/discord_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pssolanki111/polygon/HEAD/docs/_static/discord_logo.png -------------------------------------------------------------------------------- /docs/_static/patreon_logo.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pssolanki111/polygon/HEAD/docs/_static/patreon_logo.jpeg -------------------------------------------------------------------------------- /polygon/streaming/__init__.py: -------------------------------------------------------------------------------- 1 | from .streaming import StreamClient 2 | from .async_streaming import AsyncStreamClient 3 | -------------------------------------------------------------------------------- /requirements/requirements.txt: -------------------------------------------------------------------------------- 1 | requests 2 | websocket-client 3 | websockets 4 | httpx 5 | orjson 6 | 7 | # Only needed for uvloop implementation - can NOT be installed on windows 8 | # uvloop 9 | -------------------------------------------------------------------------------- /polygon/streaming/constants.py: -------------------------------------------------------------------------------- 1 | # Forex and Crypto Prefixes are no longer needed on the streaming API 2 | STREAM_CLUSTER_PREFIX_MAP = {"options": "O:", "forex": "C:", "crypto": "X:", "indices": "I:"} 3 | -------------------------------------------------------------------------------- /tests/__init__.py: -------------------------------------------------------------------------------- 1 | # All existing test cases have been removed in favor of rewriting the test cases in a better manner. 2 | # Feel free to contribute test cases. 3 | 4 | # Test cases must use unittest/pytest 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/blank-issue-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Blank Issue Template 3 | about: A simple blank template for Issues... 4 | title: "[BUG] " 5 | labels: Potential Bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/blank-feature-request-template.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Blank Feature Request Template 3 | about: A blank page for feature requests 4 | title: '' 5 | labels: enhancement, Feature Request 6 | assignees: '' 7 | 8 | --- 9 | 10 | 11 | -------------------------------------------------------------------------------- /requirements/requirements.dev: -------------------------------------------------------------------------------- 1 | # Formatting (use command `black -l 120 .`) 2 | black 3 | 4 | # Only needed for documentation 5 | sphinx 6 | sphinx_rtd_theme 7 | 8 | # Only needed for tests 9 | asynctest 10 | pytz 11 | 12 | # Only needed for uvloop implementation - can NOT be installed on windows 13 | # uvloop -------------------------------------------------------------------------------- /polygon/options/__init__.py: -------------------------------------------------------------------------------- 1 | from .options import ( 2 | OptionsClient, 3 | build_option_symbol, 4 | parse_option_symbol, 5 | OptionSymbol, 6 | build_polygon_option_symbol, 7 | parse_polygon_option_symbol, 8 | convert_option_symbol_formats, 9 | detect_option_symbol_format, 10 | ) 11 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # Read the Docs configuration file for Sphinx projects 2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 3 | 4 | version: 2 5 | 6 | build: 7 | os: ubuntu-22.04 8 | tools: 9 | python: "3.10" 10 | 11 | python: 12 | install: 13 | - requirements: requirements/requirements.txt 14 | - requirements: requirements/requirements.dev 15 | 16 | # Build documentation in the "docs/" directory with Sphinx 17 | sphinx: 18 | builder: html 19 | configuration: docs/conf.py 20 | -------------------------------------------------------------------------------- /EXAMPLES/rest_examples/regular_clients/paginated_responses.py: -------------------------------------------------------------------------------- 1 | from polygon import ReferenceClient 2 | 3 | 4 | KEY = "API_KEY" 5 | 6 | reference_client = ReferenceClient(KEY) 7 | 8 | # getting ALL ticker names from polygon 9 | 10 | responses = [] # just creating a list to store all responses that we get. You can use your own approach here 11 | 12 | response = reference_client.get_tickers(limit=1000) 13 | 14 | while "next_url" in response.keys(): 15 | next_page = reference_client.get_next_page(response) 16 | responses.append(next_page) 17 | 18 | print(f"All pages received. Total pages: {len(responses)}") 19 | -------------------------------------------------------------------------------- /EXAMPLES/streaming_examples/callback_streaming/simple_stream.py: -------------------------------------------------------------------------------- 1 | import polygon 2 | from polygon.enums import StreamCluster 3 | 4 | 5 | def my_own_message_handler(ws, msg): 6 | print(f"msg received: {msg}") 7 | 8 | 9 | def main(): 10 | api_key = "YOUR_KEY" 11 | 12 | stream_client = polygon.StreamClient(api_key, StreamCluster.STOCKS, on_message=my_own_message_handler) 13 | stream_client.start_stream_thread() 14 | stream_client.subscribe_stock_trades(["AMD", "NVDA"]) 15 | stream_client.subscribe_stock_second_aggregates() # ALL tickers 16 | 17 | 18 | if __name__ == "__main__": 19 | main() 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Standard Feature request 3 | about: See something missing? Got an idea about project? Let us know! 4 | title: "[Feature Request]" 5 | labels: enhancement, Feature Request 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | description of what would you want to have to make it better 15 | 16 | **Describe alternatives you've considered** 17 | If you've thought of any alternates, write them here 18 | 19 | **Additional context** 20 | Anything else we might wanna know? 21 | -------------------------------------------------------------------------------- /docs/Makefile: -------------------------------------------------------------------------------- 1 | # Minimal makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line, and also 5 | # from the environment for the first two. 6 | SPHINXOPTS ?= 7 | SPHINXBUILD ?= sphinx-build 8 | SOURCEDIR = . 9 | BUILDDIR = _build 10 | 11 | # Put it first so that "make" without argument is like "make help". 12 | help: 13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 14 | 15 | .PHONY: help Makefile 16 | 17 | # Catch-all target: route all unknown targets to Sphinx using the new 18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). 19 | %: Makefile 20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) 21 | -------------------------------------------------------------------------------- /EXAMPLES/rest_examples/async_clients/paginated_responses.py: -------------------------------------------------------------------------------- 1 | from polygon import ReferenceClient 2 | import asyncio 3 | 4 | KEY = "API_KEY" 5 | 6 | 7 | async def main(): 8 | reference_client = ReferenceClient(KEY, True) 9 | 10 | # getting ALL ticker names from polygon 11 | 12 | responses = [] # just creating a list to store all responses that we get. You can use your own approach here 13 | 14 | response = await reference_client.get_tickers(limit=1000) 15 | 16 | while "next_url" in response.keys(): 17 | next_page = await reference_client.get_next_page(response) 18 | responses.append(next_page) 19 | 20 | print(f"All pages received. Total pages: {len(responses)}") 21 | 22 | 23 | if __name__ == "__main__": 24 | asyncio.run(main()) 25 | -------------------------------------------------------------------------------- /polygon/__init__.py: -------------------------------------------------------------------------------- 1 | # ========================================================= # 2 | from . import enums 3 | from .base_client import BaseClient, BaseAsyncClient 4 | from .crypto import CryptoClient 5 | from .forex import ForexClient 6 | from .options import ( 7 | OptionsClient, 8 | build_option_symbol, 9 | parse_option_symbol, 10 | OptionSymbol, 11 | build_polygon_option_symbol, 12 | parse_polygon_option_symbol, 13 | convert_option_symbol_formats, 14 | detect_option_symbol_format, 15 | ) 16 | from .reference_apis import ReferenceClient 17 | from .stocks import StocksClient 18 | from .indices import IndexClient 19 | from .streaming import StreamClient, AsyncStreamClient 20 | 21 | # ========================================================= # 22 | 23 | 24 | __version__ = "1.2.8" 25 | 26 | # ========================================================= # 27 | -------------------------------------------------------------------------------- /docs/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | pushd %~dp0 4 | 5 | REM Command file for Sphinx documentation 6 | 7 | if "%SPHINXBUILD%" == "" ( 8 | set SPHINXBUILD=sphinx-build 9 | ) 10 | set SOURCEDIR=. 11 | set BUILDDIR=_build 12 | 13 | if "%1" == "" goto help 14 | 15 | %SPHINXBUILD% >NUL 2>NUL 16 | if errorlevel 9009 ( 17 | echo. 18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx 19 | echo.installed, then set the SPHINXBUILD environment variable to point 20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you 21 | echo.may add the Sphinx directory to PATH. 22 | echo. 23 | echo.If you don't have Sphinx installed, grab it from 24 | echo.https://www.sphinx-doc.org/ 25 | exit /b 1 26 | ) 27 | 28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 29 | goto end 30 | 31 | :help 32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% 33 | 34 | :end 35 | popd 36 | -------------------------------------------------------------------------------- /EXAMPLES/streaming_examples/async_streaming/simple_stream.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | import polygon 3 | from polygon.enums import StreamCluster 4 | 5 | 6 | async def stock_trades_handler(msg): # it is possible to create one common message handler for different services. 7 | print(f"msg received: {msg}") 8 | 9 | 10 | async def stock_aggregates_handler(msg): 11 | print(f"aggregate msg: {msg}") 12 | 13 | 14 | async def main(): 15 | api_key = "YOUR_KEY" 16 | 17 | stream_client = polygon.AsyncStreamClient(api_key, StreamCluster.STOCKS) 18 | 19 | await stream_client.subscribe_stock_trades(handler_function=stock_trades_handler) # ALL tickers 20 | await stream_client.subscribe_stock_second_aggregates(["AMD", "NVDA"], stock_aggregates_handler) 21 | 22 | while 1: 23 | await stream_client.handle_messages() # the lib provides auto reconnect functionality. See docs for info 24 | 25 | 26 | if __name__ == "__main__": 27 | asyncio.run(main()) 28 | -------------------------------------------------------------------------------- /EXAMPLES/rest_examples/regular_clients/basic_stocks_data.py: -------------------------------------------------------------------------------- 1 | import polygon 2 | from datetime import date 3 | 4 | KEY = "YOUR_API_KEY" # recommend to keep your key in a separate file and import that here 5 | 6 | client = polygon.StocksClient(KEY) 7 | 8 | # current price for a stock 9 | current_price = client.get_current_price("AMD") 10 | 11 | # LAST QUOTE for a stock 12 | last_quote = client.get_last_quote("AMD") 13 | 14 | print(last_quote) 15 | 16 | # LAST TRADE for a stock 17 | last_trade = client.get_last_trade("NVDA") 18 | 19 | # You get the idea, right? ...RIGHT?? 20 | 21 | # okay a few more 22 | 23 | # TRADES on a specific date for a stock 24 | trades = client.get_trades("AMD", date(2021, 6, 28)) 25 | 26 | # OCHLV for a specific day for a stock 27 | ochlv = client.get_daily_open_close("AMD", "2021-06-21") 28 | 29 | # Day's Gainers OR Losers 30 | gainers = client.get_gainers_and_losers() 31 | losers = client.get_gainers_and_losers("losers") 32 | 33 | # Snapshot for a stock 34 | 35 | snapshot = client.get_snapshot("NVDA") 36 | -------------------------------------------------------------------------------- /docs/index.rst: -------------------------------------------------------------------------------- 1 | 2 | ``polygon`` - A complete Python Client for Polygon.io 3 | ===================================================== 4 | 5 | .. image:: _static/github_logo.png 6 | :width: 100 7 | :height: 70 8 | :target: https://github.com/pssolanki111/polygon 9 | 10 | .. image:: _static/patreon_logo.jpeg 11 | :width: 100 12 | :height: 70 13 | :target: https://www.patreon.com/pssolanki 14 | 15 | .. image:: _static/discord_logo.png 16 | :width: 100 17 | :height: 70 18 | :target: https://discord.gg/jPkARduU6N 19 | 20 | .. toctree:: 21 | :maxdepth: 1 22 | :caption: Contents: 23 | 24 | Getting-Started 25 | Stocks 26 | Options 27 | Indices 28 | References 29 | Forex_Crypto 30 | Callback-Streaming 31 | Async-Streaming 32 | bulk_data_download_functions 33 | using_enums 34 | getting_help 35 | bugs_discussions_wikis_faqs 36 | contrib_and_license 37 | Library-Interface-Documentation 38 | 39 | Indices and tables 40 | ================== 41 | 42 | * :ref:`genindex` 43 | * :ref:`modindex` 44 | * :ref:`search` 45 | 46 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/submitting-a-bug-issue.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Submitting A Bug/Issue 3 | about: Please Tell us about the issue/bug to help us improve... 4 | title: "[Issue]" 5 | labels: Potential Bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | ### Though it is suggested to follow the below structure to file an issue, feel free to use your own way to file issues too. Just ensure you're providing adequate information about the issue. That's all we'd need :) 11 | 12 | **Describe the bug** 13 | So Looks like there is this issue where ........... 14 | 15 | **To Reproduce** 16 | > How did you find the error? 17 | 18 | **Expected behavior** 19 | what did you expect it to do? 20 | 21 | **Screenshots** 22 | Only if you have them and they add value to the report and make the issue easier to understand. 23 | 24 | **Environment Details:** 25 | - Operating System: e.g. Arch, Ubuntu, Window 10 26 | - Library Version [e.g. 1.0.1] 27 | - Any other tech env details you think might be relevant 28 | 29 | 30 | **Additional Info or context** 31 | What else do you think we should know about the issue? 32 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) [2024] [Pankaj Singh Solanki] 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /EXAMPLES/rest_examples/async_clients/basic_stocks_data.py: -------------------------------------------------------------------------------- 1 | import asyncio 2 | from datetime import date 3 | import polygon 4 | 5 | 6 | KEY = "YOUR_API_KEY" # recommend to keep your key in a separate file and import that here 7 | 8 | 9 | async def main(): 10 | client = polygon.StocksClient(KEY, True) 11 | 12 | # current price for a stock 13 | current_price = await client.get_current_price("AMD") 14 | 15 | # LAST QUOTE for a stock 16 | last_quote = await client.get_last_quote("AMD") 17 | 18 | print(last_quote) 19 | 20 | # LAST TRADE for a stock 21 | last_trade = await client.get_last_trade("NVDA") 22 | 23 | # You get the idea, right? ...RIGHT?? 24 | 25 | # okay a few more 26 | 27 | # TRADES on a specific date for a stock 28 | trades = await client.get_trades("AMD", date(2021, 6, 28)) 29 | 30 | # OCHLV for a specific day for a stock 31 | ochlv = await client.get_daily_open_close("AMD", "2021-06-21") 32 | 33 | # Day's Gainers OR Losers 34 | gainers = await client.get_gainers_and_losers() 35 | losers = await client.get_gainers_and_losers("losers") 36 | 37 | # Snapshot for a stock 38 | 39 | snapshot = await client.get_snapshot("NVDA") 40 | 41 | 42 | if __name__ == "__main__": 43 | asyncio.run(main()) 44 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | with open("README.md") as file: 4 | long_description = file.read() 5 | 6 | setup( 7 | name="polygon", 8 | version="1.2.8", 9 | packages=[ 10 | "polygon", 11 | "polygon.forex", 12 | "polygon.crypto", 13 | "polygon.stocks", 14 | "polygon.indices", 15 | "polygon.streaming", 16 | "polygon.reference_apis", 17 | "polygon.options", 18 | ], 19 | url="https://github.com/pssolanki111/polygon", 20 | license="MIT", 21 | author="Pankaj Singh Solanki", 22 | author_email="nice_try@fbi.com", 23 | description="A Complete Python Wrapper for Polygon.io APIs.", 24 | long_description=long_description, 25 | long_description_content_type="text/markdown", 26 | project_urls={ 27 | "Issue Tracker": "https://github.com/pssolanki111/polygon/issues", 28 | "Discussions": "https://github.com/pssolanki111/polygon/discussions", 29 | "Support": "https://www.patreon.com/pssolanki", 30 | }, 31 | classifiers=[ 32 | "Programming Language :: Python :: 3", 33 | "License :: OSI Approved :: MIT License", 34 | "Operating System :: OS Independent", 35 | "Intended Audience :: Developers", 36 | "Development Status :: 5 - Production/Stable", 37 | "Natural Language :: English", 38 | "Topic :: Office/Business :: Financial :: Investment", 39 | ], 40 | python_requires=">=3.6", 41 | install_requires=["requests", "websockets", "websocket-client", "httpx"], 42 | extras_require={"uvloop": ["uvloop"], "orjson": ["orjson"], "all": ["orjson", "uvloop"]}, 43 | keywords="finance trading equities bonds options research data markets", 44 | ) 45 | -------------------------------------------------------------------------------- /docs/getting_help.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _help_header: 3 | 4 | Getting Help 5 | ============ 6 | 7 | Generally, feel free to join our `Discord Server `__ for help/discussions. 8 | 9 | If you're stuck at something. don't worry, everyone does. Need a hand? Here is how you can get help. 10 | 11 | * See if you can find the relevant info in :ref:`faq_header` or :ref:`wikis_header` 12 | * See if there is an `Open Issue `__ or a `Pull Request `__ related to your concern already. 13 | * See if your issue has been discussed already in one of the :ref:`discussions_header` 14 | * If you believe the issue could be on polygon.io end, get in touch with their support team. They're quite helpful. There is a button in bottom right corner of every documentation page 15 | 16 | **Once you have gone through these and haven't found your answer, you can** 17 | 18 | * Join our `Discord Server `__ and ask your question/discuss or chat with people. 19 | * Start a `Discussion `__. You can ask your questions in general channel or create a QnA discussion from left. 20 | 21 | If your question is more of a bug report, you can raise a new `issue or feature request `__ with adequate information. 22 | 23 | Remember that Issues is not a good place to ask for general help. 24 | 25 | **Always make sure to provide enough information when asking for help. This includes** but not limited to 26 | 27 | * Your Operating system (Ubuntu? Arch? Windows?) 28 | * Your execution environment (Pycharm? VSC? A usual terminal? a cloud instance? a rasp pi?) 29 | * Your python version and ``polygon`` version. always ensure you are on the latest version of the library. You can update if you're not using command ``pip install --upgrade polygon`` 30 | * The full stack traceback and error message if any. **Do not attempt to describe error messages in your own languages. Sometimes error messages don't mean what they say** 31 | * The source code which causes the error. **If your code is supposed to be secret, write a sample script which can reproduce the issue. Always make sure to remove sensitive info from logs/code** 32 | -------------------------------------------------------------------------------- /docs/conf.py: -------------------------------------------------------------------------------- 1 | # Configuration file for the Sphinx documentation builder. 2 | # 3 | # This file only contains a selection of the most common options. For a full 4 | # list see the documentation: 5 | # https://www.sphinx-doc.org/en/master/usage/configuration.html 6 | 7 | # -- Path setup -------------------------------------------------------------- 8 | 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | # 13 | import os 14 | import sys 15 | 16 | print(f'path found: {os.path.abspath("..")}') 17 | sys.path.insert(0, os.path.abspath("..")) 18 | 19 | 20 | # -- Project information ----------------------------------------------------- 21 | 22 | project = "polygon" 23 | copyright = "2024, Pankaj Singh Solanki" 24 | author = "Pankaj Singh Solanki" 25 | 26 | # The full version, including alpha/beta/rc tags 27 | release = "1.2.8" 28 | 29 | 30 | # -- General configuration --------------------------------------------------- 31 | 32 | # Add any Sphinx extension module names here, as strings. They can be 33 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom 34 | # ones. 35 | extensions = ["sphinx.ext.autodoc", "sphinx_rtd_theme", "sphinx.ext.autosectionlabel"] 36 | 37 | # Add any paths that contain templates here, relative to this directory. 38 | templates_path = ["_templates"] 39 | 40 | # List of patterns, relative to source directory, that match files and 41 | # directories to ignore when looking for source files. 42 | # This pattern also affects html_static_path and html_extra_path. 43 | exclude_patterns = ["_build", "Thumbs.db", ".DS_Store"] 44 | 45 | autosectionlabel_prefix_document = True 46 | autosectionlabel_maxdepth = 4 47 | 48 | # -- Options for HTML output ------------------------------------------------- 49 | 50 | # The theme to use for HTML and HTML Help pages. See the documentation for 51 | # a list of builtin themes. 52 | # 53 | html_theme = "sphinx_rtd_theme" 54 | 55 | # Add any paths that contain custom static files (such as style sheets) here, 56 | # relative to this directory. They are copied after the builtin static files, 57 | # so a file named "default.css" will overwrite the builtin "default.css". 58 | html_static_path = ["_static"] 59 | 60 | # Don't emit module names in autogenerated documentation. 61 | add_module_names = True 62 | 63 | # Explicitly specify the master file because ReadTheDocs is running on Sphinx 64 | # 1.8.5 65 | master_doc = "index" 66 | -------------------------------------------------------------------------------- /docs/Indices.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _indices_header: 3 | 4 | Indices 5 | ======= 6 | 7 | So you have completed the initial steps and are ready to dive deep into endpoints. Read this page to know everything you need to know 8 | about using the various Indices HTTP endpoints. 9 | 10 | See :ref:`async_support_header` for asynchronous use cases. 11 | 12 | Docs below assume you have already read getting started page and know how to create the client. 13 | If you do not know how to create the client, first see :ref:`create_and_use_header` and create client as below. As always you can have all 5 different clients together. 14 | 15 | .. code-block:: python 16 | 17 | import polygon 18 | 19 | stocks_client = polygon.IndexClient('KEY') # for usual sync client 20 | async_stock_client = polygon.IndexClient('KEY', True) # for an async client 21 | 22 | here is how the client initializer looks like: 23 | 24 | .. autofunction:: polygon.indices.indices.IndexClient 25 | 26 | **Endpoints** 27 | 28 | To use any of the below method, simply call it on the client you created above. so if you named your client ``client``, 29 | you'd call the methods as ``client.get_aggregate_bars`` and so on. Async methods will need to be awaited, see :ref:`async_support_header`. 30 | 31 | SMA 32 | --- 33 | 34 | Simple Moving Average. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 35 | 36 | .. automethod:: polygon.indices.indices.SyncIndexClient.get_sma 37 | :noindex: 38 | 39 | EMA 40 | --- 41 | 42 | Exponential Moving Average. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 43 | 44 | .. automethod:: polygon.indices.indices.SyncIndexClient.get_ema 45 | :noindex: 46 | 47 | RSI 48 | --- 49 | 50 | Relative Strength Index. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 51 | 52 | .. automethod:: polygon.indices.indices.SyncIndexClient.get_rsi 53 | :noindex: 54 | 55 | MACD 56 | ---- 57 | 58 | Moving Average Convergence/Divergence. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 59 | 60 | .. automethod:: polygon.indices.indices.SyncIndexClient.get_macd 61 | :noindex: 62 | 63 | Get Previous Close 64 | ------------------ 65 | 66 | .. automethod:: polygon.indices.indices.SyncIndexClient.get_previous_close 67 | :noindex: 68 | 69 | Get Daily Open Close 70 | -------------------- 71 | 72 | .. automethod:: polygon.indices.indices.SyncIndexClient.get_daily_open_close 73 | :noindex: 74 | 75 | Get Aggregate Bars 76 | ------------------ 77 | The library added a better aggregate function if you're looking to get data for large time frames at minute/hour granularity. 78 | 79 | (for example 15 years historical data , 1 minute candles) 80 | 81 | See :ref:`better_aggs_header` for complete details on how to use it well and control how it behaves. 82 | 83 | .. automethod:: polygon.indices.indices.SyncIndexClient.get_aggregate_bars 84 | :noindex: 85 | 86 | Get Snapshot 87 | ------------ 88 | 89 | .. automethod:: polygon.indices.indices.SyncIndexClient.get_snapshot 90 | :noindex: 91 | -------------------------------------------------------------------------------- /docs/bugs_discussions_wikis_faqs.rst: -------------------------------------------------------------------------------- 1 | 2 | 3 | .. _bugs_discuss_wiki_faq_header: 4 | 5 | Bugs, Discussions, Wikis, FAQs 6 | ============================== 7 | 8 | This section provides info on Issues tracker, Discussions functionality, community wikis and FAQs. 9 | 10 | .. _bugs_header: 11 | 12 | Bug Reports or Feature Requests 13 | ------------------------------- 14 | 15 | Got a bug/report to report or a feature request? You're in the right place. 16 | 17 | Before submitting, make sure you have enough information to provide. It is advised to follow the provided template but feel free to use your own. 18 | Just ensure you provide the following info: 19 | 20 | * Your Operating system (Linux? Windows?) 21 | * Your execution environment (Pycharm? VSC? A usual terminal? a cloud instance? a rasp pi?) 22 | * Your python version and ``polygon`` version. always ensure you are on the latest version of the library. You can update if you're not using command ``pip install --upgrade polygon`` 23 | * The full stack traceback and error message if any. Do not attempt to describe error messages in your own languages. Sometimes messages don't mean what they say 24 | * The code which causes the error. If your code is supposed to be secret, write a sample script which can reproduce the issue. Always make sure to remove sensitive info from logs/code 25 | 26 | In case of feature requests, describe what functionality would you like to be added to the library. 27 | 28 | Open issues/feature requests `here `__ 29 | 30 | .. _discussions_header: 31 | 32 | Discussions 33 | ----------- 34 | 35 | `Discussions `__ are meant to be a place for discussing general stuff which is not worth having an open issue for. 36 | 37 | there are two discussion channels by default, `one meant for everyone `__ and `other meant for contributors/developers `__ 38 | 39 | while it is possible to create your own discussions, it is preferred to keep it to those two channels unless needed. 40 | 41 | .. _wikis_header: 42 | 43 | Community Wikis 44 | --------------- 45 | 46 | `The community wiki `__ is a place for everything which the community finds useful for others but isn't in the documentation. 47 | every article is just a title and the description text. written in good old markdown. You can write plain text too if you're unsure of what markdown is. 48 | 49 | Figured out how to achieve a specific task? Found something interesting? share it with the community by creating a wiki page. Every contribution is significant so don't hesitate. 50 | 51 | Read the wiki articles, you may find your answers there. 52 | 53 | 54 | .. _faq_header: 55 | 56 | FAQs 57 | ---- 58 | 59 | This is a handpicked collection of common questions and answers about the lib and endpoints in general. 60 | A must read if you're looking for answers. 61 | 62 | FAQs are added here as soon I have any solid conclusions about a useful question. 63 | 64 | Feel free to join our `Discord Server `__ if you suggestions for questions to add. 65 | You don't necessarily need to know the answer :D 66 | -------------------------------------------------------------------------------- /docs/contrib_and_license.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _contrib_and_license_header: 3 | 4 | Contributing and License 5 | ======================== 6 | 7 | Contributing to the library 8 | --------------------------- 9 | 10 | A bug you can fix? Improving documentation? Just wanna structure the code better? Every improvement matters. 11 | 12 | Read this small guide to know how you can start contributing. 13 | 14 | **If this is your first time contributing to an open source project, Welcome. You'd probably want to contribute to something you are confident about** 15 | 16 | Want to discuss anything related to the lib? head over to `Developer Discussions `__. 17 | You may also use discussions to ask anything related to contributions or library in general. 18 | 19 | Picking up what to work on 20 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ 21 | 22 | If you already know what you're going to work on, Great! If you don't or just wanna explore the options; below are the places to look at: 23 | 24 | 1. Take a look at `open issues `__ and see which ones you can work on. 25 | #. Anything which could be improved in the `documentation `__ or `readme `__ ? 26 | #. Any new endpoints introduced by polygon.io which are not in the library? 27 | #. Any changes to endpoints which are already in the lib but not adjusted according to the new changes? 28 | 29 | Once you know what to work on, you can proceed with setting up your environment. 30 | 31 | Setting Up the Development Environment 32 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 33 | 34 | May not be needed for documentation improvements. 35 | 36 | Dependencies are listed in `requirements.txt `__ and `requirements.dev `__. 37 | 38 | It is highly recommended to install the dependencies in a virtual environment. 39 | 40 | .. code-block:: shell 41 | 42 | pip install virtualenv 43 | virtualenv venv 44 | . venv/bin/activate 45 | 46 | The last instruction above is for \*nix machines. For windows ``.\venv\Scripts\activate.bat`` (or similar) is used 47 | 48 | Install the requirements using 49 | 50 | .. code-block:: shell 51 | 52 | pip install -r requirements/requirements.txt 53 | pip install -r requirements/requirements.dev 54 | 55 | **Now you can make your changes** 56 | 57 | Testing your changes 58 | ~~~~~~~~~~~~~~~~~~~~ 59 | 60 | Existing Test cases have been removed as part of release 1.1.1 in favor of REWRITING all test cases using a better approach. This will be a work in progress. Please feel free to contribute test cases written in **unittest/pytest**. 61 | 62 | However if you made changes to the documentation, run the below commands to build locally and test the documentation 63 | 64 | .. code-block:: shell 65 | 66 | cd docs 67 | make html 68 | 69 | The built docs would be placed under ``docs/_build/_html``. Open ``index.html`` here in a browser and see your changes. When you're happy with them, raise the PR. 70 | 71 | Remember to document your changes like this library does already. 72 | 73 | License 74 | ------- 75 | 76 | Don't kid yourself. You don't care what license the project uses, do you? Anyways the project is licensed under 77 | MIT License. See `License `__ for more details. 78 | -------------------------------------------------------------------------------- /docs/References.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _references_header: 3 | 4 | Reference APIs 5 | ============== 6 | 7 | Read this page to know everything you need to know about using the various References HTTP endpoints. 8 | 9 | See :ref:`async_support_header` for asynchronous use cases. 10 | 11 | Docs below assume you have already read getting started page and know how to create the client. 12 | If you do not know how to create the client, first see :ref:`create_and_use_header` and create client as below. As always you can have all 5 different clients together. 13 | 14 | .. code-block:: python 15 | 16 | import polygon 17 | 18 | reference_client = polygon.ReferenceClient('KEY') # for usual sync client 19 | async_reference_client = polygon.ReferenceClient('KEY', True) # for an async client 20 | 21 | here is how the client initializer looks like: 22 | 23 | .. autofunction:: polygon.reference_apis.reference_api.ReferenceClient 24 | 25 | **Endpoints** 26 | 27 | To use any of the below method, simply call it on the client you created above. so if you named your client ``client``, 28 | you'd call the methods as ``client.get_tickers`` and so on. Async methods will need to be awaited, see :ref:`async_support_header`. 29 | 30 | Get Tickers 31 | ----------- 32 | 33 | This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 34 | 35 | .. automethod:: polygon.reference_apis.reference_api.SyncReferenceClient.get_tickers 36 | :noindex: 37 | 38 | Get Ticker Types 39 | ---------------- 40 | 41 | .. automethod:: polygon.reference_apis.reference_api.SyncReferenceClient.get_ticker_types 42 | :noindex: 43 | 44 | 45 | Get Ticker Details 46 | ------------------ 47 | 48 | .. automethod:: polygon.reference_apis.reference_api.SyncReferenceClient.get_ticker_details 49 | :noindex: 50 | 51 | 52 | Get Option Contract 53 | ------------------- 54 | 55 | .. automethod:: polygon.reference_apis.reference_api.SyncReferenceClient.get_option_contract 56 | :noindex: 57 | 58 | Get Option Contracts 59 | -------------------- 60 | 61 | This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 62 | 63 | .. automethod:: polygon.reference_apis.reference_api.SyncReferenceClient.get_option_contracts 64 | :noindex: 65 | 66 | Get Ticker News 67 | --------------- 68 | 69 | This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 70 | 71 | .. automethod:: polygon.reference_apis.reference_api.SyncReferenceClient.get_ticker_news 72 | :noindex: 73 | 74 | Get Stock dividends 75 | ------------------- 76 | 77 | This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 78 | 79 | .. automethod:: polygon.reference_apis.reference_api.SyncReferenceClient.get_stock_dividends 80 | :noindex: 81 | 82 | Get Stock financials vX 83 | ----------------------- 84 | 85 | .. automethod:: polygon.reference_apis.reference_api.SyncReferenceClient.get_stock_financials_vx 86 | :noindex: 87 | 88 | Get Stock Splits 89 | ---------------- 90 | 91 | This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 92 | 93 | .. automethod:: polygon.reference_apis.reference_api.SyncReferenceClient.get_stock_splits 94 | :noindex: 95 | 96 | Get Market Holidays 97 | ------------------- 98 | 99 | .. automethod:: polygon.reference_apis.reference_api.SyncReferenceClient.get_market_holidays 100 | :noindex: 101 | 102 | Get Market Status 103 | ----------------- 104 | 105 | .. automethod:: polygon.reference_apis.reference_api.SyncReferenceClient.get_market_status 106 | :noindex: 107 | 108 | Get Conditions 109 | -------------- 110 | 111 | .. automethod:: polygon.reference_apis.reference_api.SyncReferenceClient.get_conditions 112 | :noindex: 113 | 114 | Get Exchanges 115 | ------------- 116 | 117 | .. automethod:: polygon.reference_apis.reference_api.SyncReferenceClient.get_exchanges 118 | :noindex: 119 | 120 | -------------------------------------------------------------------------------- /docs/Stocks.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _stocks_header: 3 | 4 | Stocks 5 | ====== 6 | 7 | So you have completed the initial steps and are ready to dive deep into endpoints. Read this page to know everything you need to know 8 | about using the various Stocks HTTP endpoints. 9 | 10 | See :ref:`async_support_header` for asynchronous use cases. 11 | 12 | Docs below assume you have already read getting started page and know how to create the client. 13 | If you do not know how to create the client, first see :ref:`create_and_use_header` and create client as below. As always you can have all 5 different clients together. 14 | 15 | .. code-block:: python 16 | 17 | import polygon 18 | 19 | stocks_client = polygon.StocksClient('KEY') # for usual sync client 20 | async_stock_client = polygon.StocksClient('KEY', True) # for an async client 21 | 22 | here is how the client initializer looks like: 23 | 24 | .. autofunction:: polygon.stocks.stocks.StocksClient 25 | 26 | **Endpoints** 27 | 28 | To use any of the below method, simply call it on the client you created above. so if you named your client ``client``, 29 | you'd call the methods as ``client.get_trades`` and so on. Async methods will need to be awaited, see :ref:`async_support_header`. 30 | 31 | SMA 32 | --- 33 | 34 | Simple Moving Average. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 35 | 36 | .. automethod:: polygon.stocks.stocks.SyncStocksClient.get_sma 37 | :noindex: 38 | 39 | EMA 40 | --- 41 | 42 | Exponential Moving Average. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 43 | 44 | .. automethod:: polygon.stocks.stocks.SyncStocksClient.get_ema 45 | :noindex: 46 | 47 | RSI 48 | --- 49 | 50 | Relative Strength Index. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 51 | 52 | .. automethod:: polygon.stocks.stocks.SyncStocksClient.get_rsi 53 | :noindex: 54 | 55 | MACD 56 | ---- 57 | 58 | Moving Average Convergence/Divergence. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 59 | 60 | .. automethod:: polygon.stocks.stocks.SyncStocksClient.get_macd 61 | :noindex: 62 | 63 | Get Trades 64 | ---------- 65 | 66 | .. automethod:: polygon.stocks.stocks.SyncStocksClient.get_trades 67 | :noindex: 68 | 69 | Get Trades v3 70 | ------------- 71 | 72 | This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 73 | 74 | .. automethod:: polygon.stocks.stocks.SyncStocksClient.get_trades_v3 75 | :noindex: 76 | 77 | Get Quotes 78 | ---------- 79 | 80 | .. automethod:: polygon.stocks.stocks.SyncStocksClient.get_quotes 81 | :noindex: 82 | 83 | Get Quotes v3 84 | ------------- 85 | 86 | This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 87 | 88 | .. automethod:: polygon.stocks.stocks.SyncStocksClient.get_quotes_v3 89 | :noindex: 90 | 91 | Get Last Trade 92 | -------------- 93 | 94 | .. automethod:: polygon.stocks.stocks.SyncStocksClient.get_last_trade 95 | :noindex: 96 | 97 | Get last Quote 98 | -------------- 99 | 100 | .. automethod:: polygon.stocks.stocks.SyncStocksClient.get_last_quote 101 | :noindex: 102 | 103 | Get Daily Open Close 104 | -------------------- 105 | 106 | .. automethod:: polygon.stocks.stocks.SyncStocksClient.get_daily_open_close 107 | :noindex: 108 | 109 | Get Aggregate Bars (Candles) 110 | ---------------------------- 111 | 112 | The library added a better aggregate function if you're looking to get data for large time frames at minute/hour granularity. 113 | 114 | (for example 15 years historical data , 1 minute candles) 115 | 116 | See :ref:`better_aggs_header` for complete details on how to use it well and control how it behaves. 117 | 118 | .. automethod:: polygon.stocks.stocks.SyncStocksClient.get_aggregate_bars 119 | :noindex: 120 | 121 | Get Grouped daily Bars (Candles) 122 | -------------------------------- 123 | 124 | .. automethod:: polygon.stocks.stocks.SyncStocksClient.get_grouped_daily_bars 125 | :noindex: 126 | 127 | Get Previous Close 128 | ------------------ 129 | 130 | .. automethod:: polygon.stocks.stocks.SyncStocksClient.get_previous_close 131 | :noindex: 132 | 133 | Get Snapshot 134 | ------------ 135 | 136 | .. automethod:: polygon.stocks.stocks.SyncStocksClient.get_snapshot 137 | :noindex: 138 | 139 | Get Snapshot (All) 140 | ------------------ 141 | 142 | .. automethod:: polygon.stocks.stocks.SyncStocksClient.get_snapshot_all 143 | :noindex: 144 | 145 | Get Current Price 146 | ----------------- 147 | 148 | .. automethod:: polygon.stocks.stocks.SyncStocksClient.get_current_price 149 | :noindex: 150 | 151 | Get Gainers & Losers 152 | -------------------- 153 | 154 | .. automethod:: polygon.stocks.stocks.SyncStocksClient.get_gainers_and_losers 155 | :noindex: 156 | 157 | 158 | -------------------------------------------------------------------------------- /docs/using_enums.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _enums_header: 3 | 4 | What the Hell are Enums Anyways 5 | =============================== 6 | 7 | Sooooo... you've had enough of these ``enums`` and finally decided to know what the hell they actually are and why you should care about them. 8 | 9 | Well read this page to get your answers. 10 | 11 | You should have seen them on many methods' documentation as argument choices. 12 | 13 | First up, does everyone need them? that depends on their use case. enums in this library are only used on some endpoints, especially the ones in reference APIs and some basic uses in 14 | stream clients. So if someone only needs to get ochlv chart data, they probably won't need to use enums. 15 | 16 | If you notice any value which is supported by the API but not included in the enums, you may let me know on our 17 | `Discord Server `__ or GitHub Discussions. 18 | 19 | What are they 20 | ------------- 21 | 22 | Simplest non technical terms definition 23 | They are a way to define pseudo constants (read constants) in python (python doesn't have anything as constants. That's why enums are precious :D). They have many use cases other than constants but for this library you only need to know this far. 24 | 25 | For example 26 | consider the enum :class:`polygon.enums.AssetClass` which has 4 values inside of it. The values are just class attribute and you can access 27 | them just like you'd access any other class attribute. ``print(polygon.enums.AssetClass.STOCKS)`` would print the string ``stocks``. 28 | so in another words this enum class has 4 member enums which can be used to specify the value wherever needed. 29 | Like this ``some_function(arg1, asset=AssetClass.STOCKS)``. 30 | 31 | when you pass in an enum to a function or a method, it is equal to passing in the value of that enum. 32 | 33 | so instead of ``some_function(arg1, asset=AssetClass.STOCKS)`` i could have said ``some_function(arg1, asset='stocks')`` and both mean the same thing. 34 | 35 | Here are `All the enums of this library in one place `__ 36 | 37 | Then why not just pass in raw values? Why do we need enums? 38 | ----------------------------------------------------------- 39 | 40 | I mean you could do that. In fact many people would still do that despite the notes here (I'll be watching you all :/). 41 | 42 | but think about it this way, can you have enums for a parameter which expects a person's name? Of course not. 43 | Because there isn't any constant value (or a fixed set of values) to choose from. 44 | 45 | but can i have enums for TickerTypes? Yes. 46 | Because it has a set of fixed values and the API would not return the correct data if the value passed in is different than the ones which are 47 | in the fixed set. 48 | 49 | **Using enums** 50 | 51 | * Avoids passing in incorrect values. 52 | * Avoids typing mistakes while passing in parameter values (I'm looking at you ``TRAILING_TWELVE_MONTHS_ANNUALIZED``) 53 | * gives you a fixed set of values to choose from and you don't have to hit and trial to know supported values. 54 | * And finally, IDE autocomplete would make your life even easier while writing code that makes use of enums 55 | 56 | Finally, it's not an absolute necessity to use enums but they are very much recommended. 57 | 58 | Okay how do I use them 59 | ---------------------- 60 | 61 | To start off, like any other name, you'd need to import the names. Now there are many ways to do that and it's up to your 62 | coding preferences. Make use of your IDE auto-completions to make it easier to fill in enums. 63 | 64 | Some common ways are 65 | 66 | Approach 1 - importing all enums at once 67 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 68 | 69 | .. code-block:: python 70 | 71 | import polygon # which you already do for using other clients so nothing new to import here 72 | 73 | # now you can use enums as 74 | 75 | client.some_function(other_args, arg=polygon.enums.TickerType.ADRC) 76 | 77 | # OR 78 | import polygon.enums as enums 79 | 80 | client.some_function(other_args, arg=enums.TickerType.ETF) 81 | 82 | as you see this allows you to access `all enums `__ without having to import each 83 | one individually. But this also mean you'd be typing longer names (not big of an issue considering IDE completions). 84 | 85 | Note that importing all enums doesn't have any resource overhead so don't worry about enums eating your RAM. 86 | 87 | Approach 2 - importing just the enums you need 88 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 89 | 90 | This approach is nicer for cases when you only specifically need a few enums. 91 | 92 | .. code-block:: python 93 | 94 | from polygon.enums import TickerType 95 | 96 | # using it as 97 | client.some_function(other_args, arg=TickerType.CS) 98 | 99 | # OR 100 | from polygon.enums import (TickerType, AssetClass) 101 | 102 | client.some_function(other_args, arg=TickerType.CS) 103 | 104 | client.some_other_function(other_args, arg=TickerType.CS, other_arg=AssetClass.STOCKS) 105 | 106 | Other Approaches 107 | ~~~~~~~~~~~~~~~~ 108 | 109 | You could use any other import syntax if you like. such as ``from polygon.enums import *`` but I `wouldn't recommend `__ 110 | `wild card imports `__. -------------------------------------------------------------------------------- /docs/Library-Interface-Documentation.rst: -------------------------------------------------------------------------------- 1 | 2 | 3 | .. _lib_interface_doc_header: 4 | 5 | +++++++++++++++++++++++++++++++ 6 | Library Interface Documentation 7 | +++++++++++++++++++++++++++++++ 8 | 9 | Here is the Entire Library Interface reference. 10 | 11 | .. _base_client_interface_header: 12 | 13 | Base Clients 14 | ------------ 15 | 16 | Base Client 17 | ~~~~~~~~~~~ 18 | 19 | .. autoclass:: polygon.base_client.Base 20 | :members: 21 | :special-members: __init__ 22 | :private-members: 23 | :undoc-members: 24 | :member-order: bysource 25 | 26 | Base Sync Client 27 | ~~~~~~~~~~~~~~~~ 28 | 29 | .. autoclass:: polygon.base_client.BaseClient 30 | :members: 31 | :special-members: __init__ 32 | :private-members: 33 | :undoc-members: 34 | :member-order: bysource 35 | 36 | Base Async Client 37 | ~~~~~~~~~~~~~~~~~ 38 | 39 | .. autoclass:: polygon.base_client.BaseAsyncClient 40 | :members: 41 | :special-members: __init__ 42 | :private-members: 43 | :undoc-members: 44 | :member-order: bysource 45 | 46 | .. _stocks_client_interface_header: 47 | 48 | Stocks Clients 49 | -------------- 50 | 51 | Stocks Sync Client 52 | ~~~~~~~~~~~~~~~~~~ 53 | 54 | .. autoclass:: polygon.stocks.stocks.SyncStocksClient 55 | :members: 56 | :special-members: __init__ 57 | :private-members: 58 | :member-order: bysource 59 | 60 | Stocks Async Client 61 | ~~~~~~~~~~~~~~~~~~~ 62 | 63 | .. autoclass:: polygon.stocks.stocks.AsyncStocksClient 64 | :members: 65 | :special-members: __init__ 66 | :private-members: 67 | :member-order: bysource 68 | 69 | .. _options_client_interface_header: 70 | 71 | Options Clients 72 | --------------- 73 | 74 | Option Symbol Helper Functions & Objects 75 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 76 | 77 | .. autofunction:: polygon.options.options.build_option_symbol 78 | 79 | .. autofunction:: polygon.options.options.parse_option_symbol 80 | 81 | .. autofunction:: polygon.options.options.build_polygon_option_symbol 82 | 83 | .. autofunction:: polygon.options.options.parse_polygon_option_symbol 84 | 85 | .. autofunction:: polygon.options.options.convert_option_symbol_formats 86 | 87 | .. autofunction:: polygon.options.options.detect_option_symbol_format 88 | 89 | .. autofunction:: polygon.options.options.ensure_prefix 90 | 91 | .. autoclass:: polygon.options.options.OptionSymbol 92 | :members: 93 | :special-members: __init__, __repr__ 94 | :undoc-members: 95 | :private-members: 96 | :member-order: bysource 97 | 98 | Options Sync Client 99 | ~~~~~~~~~~~~~~~~~~~ 100 | 101 | .. autoclass:: polygon.options.options.SyncOptionsClient 102 | :members: 103 | :special-members: __init__ 104 | :private-members: 105 | :member-order: bysource 106 | 107 | Options Async Client 108 | ~~~~~~~~~~~~~~~~~~~~ 109 | 110 | .. autoclass:: polygon.options.options.AsyncOptionsClient 111 | :members: 112 | :special-members: __init__ 113 | :private-members: 114 | :member-order: bysource 115 | 116 | .. _references_client_interface_header: 117 | 118 | References Clients 119 | ------------------ 120 | 121 | Reference Sync Client 122 | ~~~~~~~~~~~~~~~~~~~~~ 123 | 124 | .. autoclass:: polygon.reference_apis.reference_api.SyncReferenceClient 125 | :members: 126 | :special-members: __init__ 127 | :private-members: 128 | :member-order: bysource 129 | 130 | Reference Async Client 131 | ~~~~~~~~~~~~~~~~~~~~~~ 132 | 133 | .. autoclass:: polygon.reference_apis.reference_api.AsyncReferenceClient 134 | :members: 135 | :special-members: __init__ 136 | :private-members: 137 | :member-order: bysource 138 | 139 | .. _forex_client_interface_header: 140 | 141 | Forex Clients 142 | ------------- 143 | 144 | Forex Sync Client 145 | ~~~~~~~~~~~~~~~~~ 146 | 147 | .. autoclass:: polygon.forex.forex_api.SyncForexClient 148 | :members: 149 | :special-members: __init__ 150 | :private-members: 151 | :member-order: bysource 152 | 153 | Forex Async Client 154 | ~~~~~~~~~~~~~~~~~~ 155 | 156 | .. autoclass:: polygon.forex.forex_api.AsyncForexClient 157 | :members: 158 | :special-members: __init__ 159 | :private-members: 160 | :member-order: bysource 161 | 162 | .. _crypto_client_interface_header: 163 | 164 | Crypto Clients 165 | -------------- 166 | 167 | Crypto Sync Client 168 | ~~~~~~~~~~~~~~~~~~ 169 | 170 | .. autoclass:: polygon.crypto.crypto_api.SyncCryptoClient 171 | :members: 172 | :special-members: __init__ 173 | :private-members: 174 | :member-order: bysource 175 | 176 | Crypto Async Client 177 | ~~~~~~~~~~~~~~~~~~~ 178 | 179 | .. autoclass:: polygon.crypto.crypto_api.AsyncCryptoClient 180 | :members: 181 | :special-members: __init__ 182 | :private-members: 183 | :member-order: bysource 184 | 185 | .. _callback_streamer_client_interface_header: 186 | 187 | Callback Streamer Client (Sync) 188 | ------------------------------- 189 | .. autoclass:: polygon.streaming.streaming.StreamClient 190 | :members: 191 | :special-members: __init__ 192 | :private-members: 193 | :undoc-members: 194 | :member-order: bysource 195 | 196 | .. _async_streamer_client_interface_header: 197 | 198 | Async Streamer Client 199 | --------------------- 200 | .. autoclass:: polygon.streaming.async_streaming.AsyncStreamClient 201 | :members: 202 | :special-members: __init__ 203 | :private-members: 204 | :member-order: bysource 205 | 206 | .. _enums_interface_header: 207 | 208 | Enums Interface 209 | --------------- 210 | 211 | .. automodule:: polygon.enums 212 | :members: 213 | :undoc-members: 214 | :member-order: bysource 215 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Sometimes a file finds a way to slip through and make it through repo... 2 | 3 | test.py 4 | .idea 5 | ./idea 6 | ./.idea/ 7 | .vscode/* 8 | .vs/* 9 | *.exe 10 | build 11 | polygon.egg-info 12 | dist 13 | .local 14 | *.pyc 15 | cred.py 16 | docs/_build 17 | venv 18 | *.d 19 | *.o 20 | *.dll 21 | output.png 22 | passwords.txt 23 | downloads/* 24 | polygon_api_test_ps.egg-info 25 | polygn.egg_info 26 | *.bmp 27 | *.jpg 28 | *.jpeg 29 | *.wav 30 | test.c 31 | test.cpp 32 | ## Ignore Visual Studio temporary files, build results, and 33 | ## files generated by popular Visual Studio add-ons. 34 | ## 35 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore 36 | # User-specific files 37 | *.rsuser 38 | *.suo 39 | *.user 40 | *.userosscache 41 | *.sln.docstates 42 | 43 | # User-specific files (MonoDevelop/Xamarin Studio) 44 | *.userprefs 45 | 46 | # Mono auto generated files 47 | mono_crash.* 48 | 49 | # Build results 50 | [Dd]ebug/ 51 | [Dd]ebugPublic/ 52 | [Rr]elease/ 53 | [Rr]eleases/ 54 | x64/ 55 | x86/ 56 | [Ww][Ii][Nn]32/ 57 | [Aa][Rr][Mm]/ 58 | [Aa][Rr][Mm]64/ 59 | bld/ 60 | [Bb]in/ 61 | [Oo]bj/ 62 | [Ll]og/ 63 | [Ll]ogs/ 64 | 65 | # Visual Studio 2015/2017 cache/options directory 66 | .vs/ 67 | # Uncomment if you have tasks that create the project's static files in wwwroot 68 | #wwwroot/ 69 | 70 | # Visual Studio 2017 auto generated files 71 | Generated\ Files/ 72 | 73 | # MSTest test Results 74 | [Tt]est[Rr]esult*/ 75 | [Bb]uild[Ll]og.* 76 | 77 | # NUnit 78 | *.VisualState.xml 79 | TestResult.xml 80 | nunit-*.xml 81 | 82 | # Build Results of an ATL Project 83 | [Dd]ebugPS/ 84 | [Rr]eleasePS/ 85 | dlldata.c 86 | *.lock 87 | Pipfile 88 | # Benchmark Results 89 | BenchmarkDotNet.Artifacts/ 90 | 91 | # .NET Core 92 | project.lock.json 93 | project.fragment.lock.json 94 | artifacts/ 95 | 96 | # ASP.NET Scaffolding 97 | ScaffoldingReadMe.txt 98 | 99 | # StyleCop 100 | StyleCopReport.xml 101 | 102 | # Files built by Visual Studio 103 | *_i.c 104 | *_p.c 105 | *_h.h 106 | *.ilk 107 | *.meta 108 | *.obj 109 | *.iobj 110 | *.pch 111 | *.pdb 112 | *.ipdb 113 | *.pgc 114 | *.pgd 115 | *.rsp 116 | *.sbr 117 | *.tlb 118 | *.tli 119 | *.tlh 120 | *.tmp 121 | *.tmp_proj 122 | *_wpftmp.csproj 123 | *.log 124 | *.vspscc 125 | *.vssscc 126 | .builds 127 | *.pidb 128 | *.svclog 129 | *.scc 130 | 131 | # Chutzpah Test files 132 | _Chutzpah* 133 | 134 | # Visual C++ cache files 135 | ipch/ 136 | *.aps 137 | *.ncb 138 | *.opendb 139 | *.opensdf 140 | *.sdf 141 | *.cachefile 142 | *.VC.db 143 | *.VC.VC.opendb 144 | 145 | # Visual Studio profiler 146 | *.psess 147 | *.vsp 148 | *.vspx 149 | *.sap 150 | 151 | # Visual Studio Trace Files 152 | *.e2e 153 | 154 | # TFS 2012 Local Workspace 155 | $tf/ 156 | 157 | # Guidance Automation Toolkit 158 | *.gpState 159 | 160 | # ReSharper is a .NET coding add-in 161 | _ReSharper*/ 162 | *.[Rr]e[Ss]harper 163 | *.DotSettings.user 164 | 165 | # TeamCity is a build add-in 166 | _TeamCity* 167 | 168 | # DotCover is a Code Coverage Tool 169 | *.dotCover 170 | 171 | # AxoCover is a Code Coverage Tool 172 | .axoCover/* 173 | !.axoCover/settings.json 174 | 175 | # Coverlet is a free, cross platform Code Coverage Tool 176 | coverage*.json 177 | coverage*.xml 178 | coverage*.info 179 | 180 | # Visual Studio code coverage results 181 | *.coverage 182 | *.coveragexml 183 | 184 | # NCrunch 185 | _NCrunch_* 186 | .*crunch*.local.xml 187 | nCrunchTemp_* 188 | 189 | # MightyMoose 190 | *.mm.* 191 | AutoTest.Net/ 192 | 193 | # Web workbench (sass) 194 | .sass-cache/ 195 | 196 | # Installshield output folder 197 | [Ee]xpress/ 198 | 199 | # DocProject is a documentation generator add-in 200 | DocProject/buildhelp/ 201 | DocProject/Help/*.HxT 202 | DocProject/Help/*.HxC 203 | DocProject/Help/*.hhc 204 | DocProject/Help/*.hhk 205 | DocProject/Help/*.hhp 206 | DocProject/Help/Html2 207 | DocProject/Help/html 208 | 209 | # Click-Once directory 210 | publish/ 211 | 212 | # Publish Web Output 213 | *.[Pp]ublish.xml 214 | *.azurePubxml 215 | # Note: Comment the next line if you want to checkin your web deploy settings, 216 | # but database connection strings (with potential passwords) will be unencrypted 217 | *.pubxml 218 | *.publishproj 219 | 220 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 221 | # checkin your Azure Web App publish settings, but sensitive information contained 222 | # in these scripts will be unencrypted 223 | PublishScripts/ 224 | 225 | # NuGet Packages 226 | *.nupkg 227 | # NuGet Symbol Packages 228 | *.snupkg 229 | # The packages folder can be ignored because of Package Restore 230 | **/[Pp]ackages/* 231 | # except build/, which is used as an MSBuild target. 232 | !**/[Pp]ackages/build/ 233 | # Uncomment if necessary however generally it will be regenerated when needed 234 | #!**/[Pp]ackages/repositories.config 235 | # NuGet v3's project.json files produces more ignorable files 236 | *.nuget.props 237 | *.nuget.targets 238 | 239 | # Microsoft Azure Build Output 240 | csx/ 241 | *.build.csdef 242 | 243 | # Microsoft Azure Emulator 244 | ecf/ 245 | rcf/ 246 | 247 | # Windows Store app package directories and files 248 | AppPackages/ 249 | BundleArtifacts/ 250 | Package.StoreAssociation.xml 251 | _pkginfo.txt 252 | *.appx 253 | *.appxbundle 254 | *.appxupload 255 | 256 | # Visual Studio cache files 257 | # files ending in .cache can be ignored 258 | *.[Cc]ache 259 | # but keep track of directories ending in .cache 260 | !?*.[Cc]ache/ 261 | 262 | # Others 263 | ClientBin/ 264 | ~$* 265 | *~ 266 | *.dbmdl 267 | *.dbproj.schemaview 268 | *.jfm 269 | *.pfx 270 | *.publishsettings 271 | orleans.codegen.cs 272 | 273 | # Including strong name files can present a security risk 274 | # (https://github.com/github/gitignore/pull/2483#issue-259490424) 275 | #*.snk 276 | 277 | # Since there are multiple workflows, uncomment next line to ignore bower_components 278 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 279 | #bower_components/ 280 | 281 | # RIA/Silverlight projects 282 | Generated_Code/ 283 | 284 | # Backup & report files from converting an old project file 285 | # to a newer Visual Studio version. Backup files are not needed, 286 | # because we have git ;-) 287 | _UpgradeReport_Files/ 288 | Backup*/ 289 | UpgradeLog*.XML 290 | UpgradeLog*.htm 291 | ServiceFabricBackup/ 292 | *.rptproj.bak 293 | 294 | # SQL Server files 295 | *.mdf 296 | *.ldf 297 | *.ndf 298 | 299 | # Business Intelligence projects 300 | *.rdl.data 301 | *.bim.layout 302 | *.bim_*.settings 303 | *.rptproj.rsuser 304 | *- [Bb]ackup.rdl 305 | *- [Bb]ackup ([0-9]).rdl 306 | *- [Bb]ackup ([0-9][0-9]).rdl 307 | 308 | # Microsoft Fakes 309 | FakesAssemblies/ 310 | 311 | # GhostDoc plugin setting file 312 | *.GhostDoc.xml 313 | 314 | # Node.js Tools for Visual Studio 315 | .ntvs_analysis.dat 316 | node_modules/ 317 | 318 | # Visual Studio 6 build log 319 | *.plg 320 | 321 | # Visual Studio 6 workspace options file 322 | *.opt 323 | 324 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.) 325 | *.vbw 326 | 327 | # Visual Studio LightSwitch build output 328 | **/*.HTMLClient/GeneratedArtifacts 329 | **/*.DesktopClient/GeneratedArtifacts 330 | **/*.DesktopClient/ModelManifest.xml 331 | **/*.Server/GeneratedArtifacts 332 | **/*.Server/ModelManifest.xml 333 | _Pvt_Extensions 334 | 335 | # Paket dependency manager 336 | .paket/paket.exe 337 | paket-files/ 338 | 339 | # FAKE - F# Make 340 | .fake/ 341 | .pypirc 342 | 343 | # CodeRush personal settings 344 | .cr/personal 345 | 346 | # Python Tools for Visual Studio (PTVS) 347 | __pycache__/ 348 | 349 | # Cake - Uncomment if you are using it 350 | # tools/** 351 | # !tools/packages.config 352 | 353 | # Tabs Studio 354 | *.tss 355 | 356 | # Telerik's JustMock configuration file 357 | *.jmconfig 358 | 359 | # BizTalk build output 360 | *.btp.cs 361 | *.btm.cs 362 | *.odx.cs 363 | *.xsd.cs 364 | 365 | # OpenCover UI analysis results 366 | OpenCover/ 367 | 368 | # Azure Stream Analytics local run output 369 | ASALocalRun/ 370 | 371 | # MSBuild Binary and Structured Log 372 | *.binlog 373 | 374 | # NVidia Nsight GPU debugger configuration file 375 | *.nvuser 376 | 377 | # MFractors (Xamarin productivity tool) working folder 378 | .mfractor/ 379 | 380 | # Local History for Visual Studio 381 | .localhistory/ 382 | 383 | # BeatPulse healthcheck temp database 384 | healthchecksdb 385 | 386 | # Backup folder for Package Reference Convert tool in Visual Studio 2017 387 | MigrationBackup/ 388 | 389 | # Ionide (cross platform F# VS Code tools) working folder 390 | .ionide/ 391 | 392 | # Fody - auto-generated XML schema 393 | FodyWeavers.xsd -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # `polygon`: A Complete Polygon.io API Wrapper 2 | 3 | [![Discord](https://img.shields.io/discord/903351697995337820)](https://discord.gg/jPkARduU6N) [![Downloads](https://static.pepy.tech/personalized-badge/polygon?period=total&units=international_system&left_color=grey&right_color=orange&left_text=Downloads)](https://pepy.tech/project/polygon) [![Documentation Status](https://readthedocs.org/projects/polygon/badge/?version=latest)](https://polygon.readthedocs.io/en/latest/Getting-Started.html) [![pypi](https://img.shields.io/pypi/v/polygon?label=latest%20version)](https://pypi.org/project/polygon/) [![CodeFactor](https://www.codefactor.io/repository/github/pssolanki111/polygon/badge/main)](https://www.codefactor.io/repository/github/pssolanki111/polygon/overview/main) [![ff](https://img.shields.io/github/issues-raw/pssolanki111/polygon)](https://github.com/pssolanki111/polygon/issues) [![fd](https://img.shields.io/github/contributors/pssolanki111/polygon)](https://github.com/pssolanki111/polygon/graphs/contributors) [![Licenses](https://img.shields.io/pypi/l/polygon)](https://github.com/pssolanki111/polygon/blob/main/LICENSE) [![gh](https://img.shields.io/github/followers/pssolanki111?label=Github%20Follows)](https://github.com/pssolanki111) 4 | 5 | ## what is `polygon` 6 | `polygon` is a Complete Python Wrapper for [Polygon.io APIs](https://polygon.io/). It offers 7 | simple and elegant programmatic access over each endpoint. Functionalities include but not limited to: 8 | 9 | - Stocks, Index and Options data 10 | - Forex and Crypto data 11 | - Real time Websocket streaming (both callback and async based) 12 | - Technical Indicators (SMA, EMA, RSI, MACD) 13 | - Market Info, News, Holidays, Schedules, Tickers, Conditions, Dividends, Splits 14 | - Async support for REST endpoints 15 | - Built In stream reconnection functionality (Experimental, async streamer only) 16 | - Full builtin Pagination support (with internal merging of responses) 17 | - **Bulk** data download functions: bulk OCHLV aggregates bars, bulk ticker details etc. 18 | - Extensive Option Symbology supporting 6 option symbol formats 19 | 20 | and a lot more... 21 | 22 | ## How Do I Use `polygon` 23 | 24 | The complete description of everything you need to know is available in the [Documentation](https://polygon.readthedocs.io/en/latest/Getting-Started.html) which has answers to 25 | any question you might have with example uses included wherever needed. Docs are a must-read for most people. 26 | 27 | - For examples to get started with, see the [examples](https://github.com/pssolanki111/polygon/tree/main/EXAMPLES) 28 | - For an advanced use case example code involving redis queue and postgresql database, check out 29 | - [MarketMakerLite/polygon](https://github.com/MarketMakerLite/polygon) 30 | - The lib is also officially supported by the popular TA library [pandas-ta](https://github.com/twopirllc/pandas-ta) 31 | as an underlying data source instead of the default `yfinance`. See relevant docs to know how to use 32 | - To see an advanced use case of downloading ALL OCHLV data for ALL tickers for 20+ years and write it to a 33 | timescale enabled postgresql database efficiently, see [This Script](https://github.com/MarketMakerLite/polygon/blob/main/historical_data/advanced.py) by [MML](https://github.com/MarketMakerLite). 34 | - The [documentation](https://polygon.readthedocs.io/en/latest/Getting-Started.html) also contain TONS of sample 35 | code snippets wherever necessary. 36 | 37 | ### Quick Setup Guide With Examples 38 | 39 | Before you do anything, you'll need to have a polygon account and get your API key. 40 | Visit [Your Dashboard](https://polygon.io/dashboard/api-keys) to get yours. 41 | 42 | Next, you'd need to install `polygon` 43 | 44 | ```shell 45 | pip install polygon 46 | ``` 47 | 48 | **and You're good to Go!** 49 | 50 | Here are a few quick usage examples. 51 | 52 | ### Getting a Stock's Previous Day OCHLV 53 | 54 | ```python 55 | import polygon 56 | 57 | api_key = 'YOUR_KEY' 58 | 59 | stocks_client = polygon.StocksClient(api_key) 60 | 61 | previous_close = stocks_client.get_previous_close('AMD') 62 | 63 | print(previous_close) 64 | ``` 65 | 66 | ### An Async Example for REST endpoints - Previous Close 67 | 68 | ```python 69 | import polygon 70 | import asyncio 71 | 72 | async def main(): 73 | api_key = 'YOUR_KEY' 74 | 75 | stocks_client = polygon.StocksClient(api_key, True) 76 | 77 | previous_close = await stocks_client.get_previous_close('AMD') 78 | await stocks_client.close() # Recommended to close the httpx session when it's not needed. 79 | print(previous_close) 80 | 81 | if __name__ == '__main__': 82 | asyncio.run(main()) 83 | ``` 84 | 85 | ### A Streaming Example (Callback Based) 86 | 87 | ```python 88 | import polygon 89 | from polygon.enums import StreamCluster 90 | 91 | def my_own_message_handler(ws, msg): 92 | print(f'msg received: {msg}') 93 | 94 | def main(): 95 | api_key = 'YOUR_KEY' 96 | 97 | stream_client = polygon.StreamClient(api_key, StreamCluster.STOCKS, on_message=my_own_message_handler) 98 | stream_client.start_stream_thread() 99 | stream_client.subscribe_stock_trades(['AMD', 'NVDA']) 100 | 101 | if __name__ == '__main__': 102 | main() 103 | ``` 104 | ### An Async Streaming Example 105 | 106 | ```python 107 | import asyncio 108 | import polygon 109 | from polygon.enums import StreamCluster 110 | 111 | async def stock_trades_handler(msg): # it is possible to create one common message handler for different services. 112 | print(f'msg received: {msg}') 113 | 114 | async def main(): 115 | api_key = 'YOUR_KEY' 116 | 117 | stream_client = polygon.AsyncStreamClient(api_key, StreamCluster.STOCKS) 118 | 119 | await stream_client.subscribe_stock_trades(['AMD', 'NVDA'], stock_trades_handler) 120 | 121 | while 1: 122 | await stream_client.handle_messages() # the lib provides auto reconnect functionality. See docs for info 123 | if __name__ == '__main__': 124 | asyncio.run(main()) 125 | 126 | ``` 127 | This only scratches the surface of the library. 128 | 129 | **See the [Documentation](https://polygon.readthedocs.io/) to start using the library with its full functionalities.** 130 | 131 | Latest development source code of the library can be found on the 132 | [development branch](https://github.com/pssolanki111/polygon/tree/dev) 133 | 134 | ## What if I need help? 135 | 136 | We have a helpful & vibrant community in our [Discord Server](https://discord.gg/jPkARduU6N). Join in to ask a 137 | question, share your ideas or observations or to just chat with interesting people, or maybe just for lurking :eyes: 138 | 139 | See [Getting Help](https://polygon.readthedocs.io/en/latest/getting_help.html) or you can also [start a quick discussion](https://github.com/pssolanki111/polygon/discussions) 140 | 141 | ## Quick Links for `Speed Runners` 142 | 143 | - [Getting Started](https://polygon.readthedocs.io/en/latest/Getting-Started.html) - a must-read for almost everyone 144 | - [Async support for HTTP endpoints](https://polygon.readthedocs.io/en/latest/Getting-Started.html#async-support-for-rest-endpoints) 145 | - [Bulk Data Download Functions](https://polygon.readthedocs.io/en/latest/bulk_data_download_functions.html) 146 | - [Pagination Support](https://polygon.readthedocs.io/en/latest/Getting-Started.html#pagination-support) || [Option Symbology](https://polygon.readthedocs.io/en/latest/Options.html#working-with-option-symbols) 147 | - [Stocks](https://polygon.readthedocs.io/en/latest/Stocks.html) || [Indices](https://polygon.readthedocs.io/en/latest/Indices.html) || [Options](https://polygon.readthedocs.io/en/latest/Options.html) || [Reference APIs](https://polygon.readthedocs.io/en/latest/References.html) 148 | - [Forex & Crypto](https://polygon.readthedocs.io/en/latest/Forex_Crypto.html) 149 | - [Callback Streaming](https://polygon.readthedocs.io/en/latest/Callback-Streaming.html) || [Async Streaming](https://polygon.readthedocs.io/en/latest/Async-Streaming.html) 150 | - [Easy guide to enums](https://polygon.readthedocs.io/en/latest/using_enums.html) || [Library Interface Docs](https://polygon.readthedocs.io/en/latest/Library-Interface-Documentation.html) 151 | - [bugs, discussions, wikis and FAQs](https://polygon.readthedocs.io/en/latest/bugs_discussions_wikis_faqs.html) 152 | 153 | ## What else? 154 | 155 | - Bug reports, suggestions and pull requests are always welcome. 156 | - See [Contributing](https://polygon.readthedocs.io/en/latest/contrib_and_license.html) if you wish to contribute. 157 | - Read [This](https://polygon.readthedocs.io/en/latest/bugs_discussions_wikis_faqs.html) before raising a bug. 158 | - [CHANGELOG](https://github.com/pssolanki111/polygon/blob/main/CHANGELOG.md) for the project is available within the same repository 159 | - `polygon` is released under the [MIT License](https://github.com/pssolanki111/polygon/blob/main/LICENSE) 160 | 161 | --- 162 | #### Made with Passion & Python by [P S Solanki](https://github.com/pssolanki111) 163 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog - `polygon` 2 | 3 | All notable changes to the project are documented here. 4 | 5 | Version history is sorted from the most recent release to the least recent 6 | 7 | --- 8 | 9 | ## `v1.2.8` - (2025-08-29) 10 | 11 | - Add new streams - crypto second aggregates and forex second aggregates 12 | - Fix issue with stream client for mishandling prefix for crypto and forex - Thanks to @yarimiz for contributing. 13 | 14 | ## `v1.2.7` - (2025-08-09) 15 | 16 | - Fix missing import for IndexClient and bad AsyncIndexClient __init__ signature. 17 | 18 | ## `v1.2.6` - (2024-12-13) 19 | 20 | - Add `expired` parameter on Get Option Contracts endpoint (Reference APIs) 21 | 22 | ## `v1.2.5` - (2024-09-07) 23 | 24 | - FMV on the async client is finally fixed. 25 | - Run a Black refactor 26 | 27 | ## `v1.2.4` - (2024-09-04) 28 | 29 | - Fix issues with FMV handler function, and sync client prefixes 30 | 31 | ## `v1.2.2 & 1.2.3` - (2024-09-02) 32 | 33 | - Add FMV (Fair Market Value) and Value (Indices) on the websocket streaming client 34 | - Improve Indices Support for websocket streaming 35 | 36 | ## `v1.2.1` - (2024-08-03) 37 | 38 | - Add Business websocket host as an enum 39 | 40 | ## `v1.2.0` - (2024-01-30) 41 | 42 | - Add support for all INDEX endpoints. Available as `IndexClient` 43 | 44 | ## `v1.1.6` - (2024-01-28) 45 | 46 | - Add missing feature - pagination on Technical Indicator endpoints. Thanks `afestekjian` for reporting it. 47 | 48 | ## `v1.1.4 - v1.1.5` - (2024-01-10) 49 | 50 | - Added `second` aggregate timespan as an enum. Thanks @Slade Wilson for letting me know. 51 | 52 | ## `v1.1.3` - (2023-11-14) 53 | 54 | - Gracefully handle JSON Parser issues (Thanks @MuradGithub for the contribution) 55 | - Add `info` log level handler to pagination methods (Thanks @MuradGithub for the contribution) 56 | - Add `tos1` option symbol format. (Thanks @greko6 for bringing this up as [#16](https://github.com/pssolanki111/polygon/issues/16)) 57 | 58 | ## `v1.1.2` - (2023-09-24) 59 | 60 | - Fixed minor bug: Wrong underlying API call for `get_macd`. [#14](https://github.com/pssolanki111/polygon/issues/14) 61 | 62 | ## `v1.1.1` - (2023-09-21) 63 | 64 | - `as_of` parameter now supported on option contract endpoint 65 | - Restructure of requirements file and minor updates to documentation 66 | 67 | ## `v1.1.0` - (2022-09-13) 68 | 69 | - Added the new technical Indicator endpoints to library. Includes SMA, EMA, RSI and MACD. See docs for more details. 70 | 71 | ## `v1.0.9` - (2022-07-11) 72 | 73 | - Added [Bulk Ticker Details](https://polygon.readthedocs.io/en/latest/bulk_data_download_functions.html#bulk-ticker-details). Thanks to @AlbusFrigoris for the suggestion. 74 | - Bulk download functions get [their own page](https://polygon.readthedocs.io/en/latest/bulk_data_download_functions.html) in the documentation. You may suggest new functions on our [Discord Server](https://discord.gg/jPkARduU6N) 75 | - Forex and crypto documentations are merged into a [single page](https://polygon.readthedocs.io/en/latest/Forex_Crypto.html). 76 | - Added the method `get_dates_between` and added custom timezone support to `normalize_datetime`. 77 | - Other internal changes that you don't care about 78 | 79 | --- 80 | ## `v1.0.8` - (2022-06-25) 81 | 82 | - Docs for this version are available [Here](https://polygon.readthedocs.io/en/1.0.8/) 83 | - Removed orjson from REST clients, using `.json()` response method again due to a drop in multicore performance. 84 | Thanks to @Baker XBL for the reports. 85 | - The option symbology is UPDATED and BETTER than ever. [Docs](https://polygon.readthedocs.io/en/latest/Options.html#working-with-option-symbols) are re-written. Support for 6 symbol formats added. 86 | - added `force_uppercase_symbols` on both streamers to allow optionally disabling the upper case enforcement 87 | - The option symbology change is not backward compatible. Hence, I've decided to keep the documentation for `v1.0.7` 88 | persistent. You can use the **version switch on bottom left of documentation** to navigate between documentation for different versions 89 | - If you were not using option symbology so far, you should not have any issues upgrading. If you were, just update 90 | existing code to use new structure (which is very similar so should be very quick to change) 91 | - Added the total downloads badge on GH readme 92 | 93 | --- 94 | ## `v1.0.7` - (2022-06-05) 95 | 96 | - Docs for this version are available [Here](https://polygon.readthedocs.io/en/1.0.7/) 97 | - We now have an Official `CHANGELOG`. View it [HERE](https://github.com/pssolanki111/polygon/blob/main/CHANGELOG.md). 98 | Thanks to @Baker XBL for the suggestion 99 | - The lib will now use `orjson` if it's installed for all JSON operations. `orjson` is no longer a required 100 | dependency for the library. Both `uvloop` and `orjson` are moved to optional extra dependencies. See [here](https://polygon.readthedocs.io/en/latest/Getting-Started.html#installing-polygon) for 101 | more info 102 | - An issue with `lt, gt, lte & gte` filters was fixed. Thanks to @Baker XBL for the report & reproducible examples 103 | 104 | --- 105 | ## `1.0.6` - (2022-04-21) 106 | 107 | - option contract endpoint added to reference client. view [here](https://polygon.readthedocs.io/en/latest/References.html#get-option-contract) 108 | - All `pagination` methods now accept a `verbose` argument defaulting to False. Setting it to `verbose=True` will print relevant status messages about 109 | the underlying pagination process. **Useful for people who don't trust me** and want to know what exactly the lib is 110 | doing at a certain point in time. 111 | - Links to official documentation were broken due to a change by polygon.io, which restructured all links. (kinda don't like the new schema lol). 112 | That should be fixed. All methods now have correct direct specific links to their official counterparts. 113 | - some internal changes to how the lib handles `timestamp` and `datetimes` and `dates`. To know how to fine tune results, 114 | see [relevant docs](https://polygon.readthedocs.io/en/latest/Getting-Started.html#passing-dates-datetime-values-or-timestamps) 115 | 116 | --- 117 | ## `v1.0.5` - (2022-03-04) 118 | 119 | - newly released `options quotes` endpoints are now included in the lib. They were released by polygon yesterday I 120 | believe. Both `http` and `websocket` streaming endpoints are covered 121 | - Some updates to interfacing around `vX/v3` because polygon would deprecate a few older v2 endpoints tomorrow 122 | (mar 5th). To maintain backward compatibility, I have tried my best to raise relevant warnings. 123 | - other internal bug fixes which you don't care about :P 124 | 125 | --- 126 | ## `1.0.2` - (2022-02-06) 127 | 128 | - the `better aggregates` functionality is officially released & documented. gets a dedicated section 129 | [in the docs](https://polygon.readthedocs.io/en/latest/Getting-Started.html#better-aggregate-bars-function) 130 | . HUGE thanks to @Baker XBL for the suggestions and helping test it. 131 | - Other internal changes and fixes which, again, you don't care about :D 132 | 133 | --- 134 | ## `v1.0.1` - (2022-01-29) 135 | 136 | - The pagination functionality is officially released and documented 137 | [here](https://polygon.readthedocs.io/en/latest/Getting-Started.html#pagination-support) 138 | 139 | --- 140 | ## `1.0.0` - (2022-01-25) 141 | 142 | - Marks our **FIRST Production Release** 143 | - the powerful filter options of `lt, lte, gt, gte` (less than, less than or equal to and so on) is patched to work 144 | well. Thanks to @Slade Wilson for letting me know about the issue. 145 | - ThinkOrSwim dot notation parser fixed. thanks to @fatdragon and @Baker XBL for the inputs. 146 | - More control over `timeouts` and limits on `httpx pool`. Came across a limitation while helping in @AlbusFrigoris's 147 | use case. Suitable for highly concurrent async applications. 148 | 149 | --- 150 | ## `v0.9.8` - (2022-01-18) 151 | 152 | - added the new `stock splits` and `stock dividends` endpoints (V3 of both). deprecated the older ones. 153 | - `ticker details vx` is now `ticker details v3` (damn it polygon, stop changing paths). all of the above endpoints are 154 | no longer experimental. 155 | - added support for `dot notation` for option symbols from `tda` (encountered when exporting any data from ThinkOrSwim 156 | or similar tools). thanks to @Slade Wilson for the suggestion 157 | - added a function to detect the option symbol format. recognises polygon standard, tda API and ThinkOrSwim dot 158 | notation. thanks to @Baker XBL for the suggestion. 159 | 160 | --- 161 | ## `0.9.6` - (2021-11-16) 162 | 163 | - added ALL `options endpoints` (newly released) 164 | 165 | --- 166 | ## `v0.9.5` - (2021-11-07) 167 | 168 | - Update the lib based on changes by polygon to endpoints 169 | 170 | --- 171 | ## `0.8.2` - (2021-10-20 ) 172 | 173 | - Re-did the entire async interface. 174 | - The docs for this version are available [here](https://polygon.readthedocs.io/en/0.8.2/) 175 | - It is highly suggested to upgrade if you're using this version. This was the only version which wasn't backward 176 | compatible 177 | 178 | --- 179 | #### All past releases were meant for initial testings and MUST be upgraded to the latest version. 180 | -------------------------------------------------------------------------------- /docs/Forex_Crypto.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _forex_and_crypto_header: 3 | 4 | Forex & Crypto 5 | ============== 6 | 7 | .. _forex_header: 8 | 9 | Forex 10 | ----- 11 | 12 | Read this section to know everything you need to know about using the various Forex HTTP endpoints. 13 | 14 | See :ref:`async_support_header` for asynchronous use cases. 15 | 16 | Docs below assume you have already read getting started page and know how to create the client. 17 | If you do not know how to create the client, first see :ref:`create_and_use_header` and create client as below. As always you can have all 5 different clients together. 18 | 19 | .. code-block:: python 20 | 21 | import polygon 22 | 23 | forex_client = polygon.ForexClient('KEY') # for usual sync client 24 | async_forex_client = polygon.ForexClient('KEY', True) # for an async client 25 | 26 | Note that most endpoints require you to specify the currency pairs as separate symbols (a ``from_symbol`` and a ``to_symbol``). 27 | 28 | however a few endpoints require you to supply them as one combined symbol. An example would be the ``get_aggregates_bars`` method. 29 | In those methods, the symbol is expected to have a prefix ``C:`` before the currency symbol names. **but the library allows you to specify the symbol with or without the prefix**. 30 | See the relevant method's docs for more information on what the parameters expect. 31 | 32 | here is how the client initializer looks like: 33 | 34 | .. autofunction:: polygon.forex.forex_api.ForexClient 35 | 36 | **Endpoints** 37 | 38 | To use any of the below method, simply call it on the client you created above. so if you named your client ``client``, 39 | you'd call the methods as ``client.get_historic_forex_ticks`` and so on. Async methods will need to be awaited, see :ref:`async_support_header`. 40 | 41 | SMA 42 | --- 43 | 44 | Simple Moving Average. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 45 | 46 | .. automethod:: polygon.forex.forex_api.SyncForexClient.get_sma 47 | :noindex: 48 | 49 | EMA 50 | --- 51 | 52 | Exponential Moving Average. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 53 | 54 | .. automethod:: polygon.forex.forex_api.SyncForexClient.get_ema 55 | :noindex: 56 | 57 | RSI 58 | --- 59 | 60 | Relative Strength Index. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 61 | 62 | .. automethod:: polygon.forex.forex_api.SyncForexClient.get_rsi 63 | :noindex: 64 | 65 | MACD 66 | ---- 67 | 68 | Moving Average Convergence/Divergence. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 69 | 70 | .. automethod:: polygon.forex.forex_api.SyncForexClient.get_macd 71 | :noindex: 72 | 73 | Real Time currency conversion 74 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 75 | 76 | .. automethod:: polygon.forex.forex_api.SyncForexClient.real_time_currency_conversion 77 | :noindex: 78 | 79 | 80 | Get Historic forex ticks 81 | ~~~~~~~~~~~~~~~~~~~~~~~~ 82 | 83 | .. automethod:: polygon.forex.forex_api.SyncForexClient.get_historic_forex_ticks 84 | :noindex: 85 | 86 | Get Quotes (NBBO) 87 | ~~~~~~~~~~~~~~~~~ 88 | 89 | This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 90 | 91 | .. automethod:: polygon.forex.forex_api.SyncForexClient.get_quotes 92 | :noindex: 93 | 94 | Get Last Quote 95 | ~~~~~~~~~~~~~~ 96 | 97 | .. automethod:: polygon.forex.forex_api.SyncForexClient.get_last_quote 98 | :noindex: 99 | 100 | Get Aggregate Bars (Candles) 101 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 102 | 103 | The library added a better aggregate function if you're looking to get data for large time frames at minute/hour granularity. 104 | 105 | (for example 15 years historical data , 1 minute candles) 106 | 107 | See :ref:`better_aggs_header` for complete details on how to use it well and control how it behaves. 108 | 109 | .. automethod:: polygon.forex.forex_api.SyncForexClient.get_aggregate_bars 110 | :noindex: 111 | 112 | Get Grouped Daily Bars (Candles) 113 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 114 | 115 | .. automethod:: polygon.forex.forex_api.SyncForexClient.get_grouped_daily_bars 116 | :noindex: 117 | 118 | Get Previous Close 119 | ~~~~~~~~~~~~~~~~~~ 120 | 121 | .. automethod:: polygon.forex.forex_api.SyncForexClient.get_previous_close 122 | :noindex: 123 | 124 | Get Gainers & Losers 125 | ~~~~~~~~~~~~~~~~~~~~ 126 | 127 | .. automethod:: polygon.forex.forex_api.SyncForexClient.get_gainers_and_losers 128 | :noindex: 129 | 130 | 131 | .. _crypto_header: 132 | 133 | Crypto 134 | ------ 135 | 136 | Read this section to know everything you need to know about using the various Crypto HTTP endpoints. 137 | 138 | See :ref:`async_support_header` for asynchronous use cases. 139 | 140 | Docs below assume you have already read getting started page and know how to create the client. 141 | If you do not know how to create the client, first see :ref:`create_and_use_header` and create client as below. As always you can have all 5 different clients together. 142 | 143 | .. code-block:: python 144 | 145 | import polygon 146 | 147 | crypto_client = polygon.CryptoClient('KEY') # for usual sync client 148 | async_crypto_client = polygon.CryptoClient('KEY', True) # for an async client 149 | 150 | Note that most endpoints require you to specify the currency pairs as separate symbols (a ``from_symbol`` and a ``to_symbol``). 151 | 152 | however a few endpoints require you to supply them as one combined symbol. An example would be the ``get_aggregates_bars`` method. 153 | In those methods, the symbol is expected to have a prefix ``X:`` before the currency symbol names. **but the library allows you to specify the symbol with or without the prefix**. 154 | See the relevant method's docs for more information on what the parameters expect. 155 | 156 | here is how the client initializer looks like: 157 | 158 | .. autofunction:: polygon.crypto.crypto_api.CryptoClient 159 | 160 | **Endpoints** 161 | 162 | To use any of the below method, simply call it on the client you created above. so if you named your client ``client``, 163 | you'd call the methods as ``client.get_historic_trades`` and so on. Async methods will need to be awaited, see :ref:`async_support_header`. 164 | 165 | 166 | SMA 167 | --- 168 | 169 | Simple Moving Average. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 170 | 171 | .. automethod:: polygon.crypto.crypto_api.SyncCryptoClient.get_sma 172 | :noindex: 173 | 174 | EMA 175 | --- 176 | 177 | Exponential Moving Average. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 178 | 179 | .. automethod:: polygon.crypto.crypto_api.SyncCryptoClient.get_ema 180 | :noindex: 181 | 182 | RSI 183 | --- 184 | 185 | Relative Strength Index. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 186 | 187 | .. automethod:: polygon.crypto.crypto_api.SyncCryptoClient.get_rsi 188 | :noindex: 189 | 190 | MACD 191 | ---- 192 | 193 | Moving Average Convergence/Divergence. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 194 | 195 | .. automethod:: polygon.crypto.crypto_api.SyncCryptoClient.get_macd 196 | :noindex: 197 | 198 | 199 | Get Historic Trades 200 | ~~~~~~~~~~~~~~~~~~~ 201 | 202 | .. automethod:: polygon.crypto.crypto_api.SyncCryptoClient.get_historic_trades 203 | :noindex: 204 | 205 | Get Trades 206 | ~~~~~~~~~~ 207 | 208 | This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 209 | 210 | .. automethod:: polygon.crypto.crypto_api.SyncCryptoClient.get_trades 211 | :noindex: 212 | 213 | Get Last Trade 214 | ~~~~~~~~~~~~~~ 215 | 216 | .. automethod:: polygon.crypto.crypto_api.SyncCryptoClient.get_last_trade 217 | :noindex: 218 | 219 | Get Daily Open Close 220 | ~~~~~~~~~~~~~~~~~~~~ 221 | 222 | .. automethod:: polygon.crypto.crypto_api.SyncCryptoClient.get_daily_open_close 223 | :noindex: 224 | 225 | Get Aggregate Bars (Candles) 226 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 227 | 228 | The library added a better aggregate function if you're looking to get data for large time frames at minute/hour granularity. 229 | 230 | (for example 15 years historical data , 1 minute candles) 231 | 232 | See :ref:`better_aggs_header` for complete details on how to use it well and control how it behaves. 233 | 234 | .. automethod:: polygon.crypto.crypto_api.SyncCryptoClient.get_aggregate_bars 235 | :noindex: 236 | 237 | Get Grouped Daily Bars (Candles) 238 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 239 | 240 | .. automethod:: polygon.crypto.crypto_api.SyncCryptoClient.get_grouped_daily_bars 241 | :noindex: 242 | 243 | Get Previous Close 244 | ~~~~~~~~~~~~~~~~~~ 245 | 246 | .. automethod:: polygon.crypto.crypto_api.SyncCryptoClient.get_previous_close 247 | :noindex: 248 | 249 | Get Snapshot All 250 | ~~~~~~~~~~~~~~~~ 251 | 252 | .. automethod:: polygon.crypto.crypto_api.SyncCryptoClient.get_snapshot_all 253 | :noindex: 254 | 255 | Get Snapshot 256 | ~~~~~~~~~~~~ 257 | 258 | .. automethod:: polygon.crypto.crypto_api.SyncCryptoClient.get_snapshot 259 | :noindex: 260 | 261 | Get Gainers and Losers 262 | ~~~~~~~~~~~~~~~~~~~~~~ 263 | 264 | .. automethod:: polygon.crypto.crypto_api.SyncCryptoClient.get_gainers_and_losers 265 | :noindex: 266 | 267 | Get Level 2 Book 268 | ~~~~~~~~~~~~~~~~ 269 | 270 | .. automethod:: polygon.crypto.crypto_api.SyncCryptoClient.get_level2_book 271 | :noindex: 272 | -------------------------------------------------------------------------------- /docs/bulk_data_download_functions.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _bulk_data_download_header: 3 | 4 | Bulk Data Download Functions 5 | ============================ 6 | 7 | This page documents all the bulk data download functions the library offers. New functions are added 8 | based on community feedback. 9 | 10 | To suggest a bulk download function which might be useful to be in the lib or to provide feedback/questions on 11 | existing ones, join our `Discord Server `__ 12 | 13 | Below is a short description of the available bulk data functions in the library 14 | 15 | ===================== ==================== 16 | Name Summary 17 | ===================== ==================== 18 | Full Range Aggregates Historical OCHLV candles for a large duration 19 | Bulk Ticker Details Ticker Details for a date range 20 | ===================== ==================== 21 | 22 | .. _better_aggs_header: 23 | 24 | Bulk Aggregate Bars (Full Range) 25 | -------------------------------- 26 | 27 | Available on both regular and async clients, this function makes it easy to get historical price history (OCHLV 28 | candles) for a large duration. For example **One Minute candles for AMD for the past 15 years** 29 | 30 | How does the function work 31 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ 32 | 33 | Skip if you don't care :D 34 | 35 | - This function attempts to work around the 50k candles' limit set by polygon. 50k is enough for 1 month duration, but 36 | not for 15 years as you can tell 37 | - The library splits your specified date range into smaller chunks of time, gets data for them in parallel 38 | (threads/coroutines) or sequential (if you say so), merges all responses, drops duplicates & candles outside the 39 | specified range and finally returns a single list of all candles. 40 | 41 | General Advice 42 | ~~~~~~~~~~~~~~ 43 | 44 | - If you are looking to use this functionality for MANY symbols (read more than 4-5), then it is better to use the 45 | async client. Due to GIL limitation in python, regular client can't run more than 1 threadpool at a time. 46 | - For most people, the default values should be enough, but for the ones who hate themselves ( :P ), it is possible to 47 | customize the behavior however they like. 48 | - The concept is the same for all clients (stocks, options, forex and crypto). Knowing it once is 49 | enough for all other clients as they all have same method names. 50 | 51 | Enough Talking, Show me how to use it 52 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 53 | 54 | You may call this function in two ways, 55 | 56 | - Calling the usual ``client.get_aggregate_bars()`` method and passing ``full_range=True``. 57 | - Directly calling ``client.get_full_range_aggregate_bars()`` (added in ``v1.0.9``) (do NOT use for now. There is a know issue to be fixed in a coming release) 58 | 59 | for example the below two calls are identical 60 | 61 | .. code-block:: python 62 | 63 | # 'client' can be any client out of stocks, options, forex & crypto. 64 | client.get_aggregate_bars('AMD', '2005-06-28', '2022-06-28', full_range=True) 65 | 66 | # same effect as above, different call (added in v1.0.9) 67 | client.get_full_range_aggregate_bars('AMD', '2005-06-28', '2022-06-28') 68 | 69 | The output format is a **single list of all candles**. 70 | 71 | Now that you know how to use it, below is info on how to customize how the function runs, to suit your architecture and 72 | requirements 73 | 74 | - By default: library runs an internal Threadpool (regular sync client) OR a set of coroutines (async client). Both 75 | run different smaller time chunks in parallel. 76 | 77 | - If you don't want it to run in parallel (not recommended), you can just specify ``run_parallel=False``. doing that 78 | will make the library request data one by one, using the last response received as the new start point until end 79 | date is reached. This might be useful if you're running a thread pool of your own and don't want the internal 80 | thread pool to mess with your own thread pool. **on async client, always prefer to run parallel** 81 | 82 | - In parallel (default) style run, if you deal with an asset which trades for a higher number hours in a day, you can 83 | add the additional argument ``smaller_time_chunks=True``. This will make the library further reduce its time chunk size. 84 | This argument was renamed from ``high_volatility`` to ``smaller_time_chunks`` in **v1.0.9** 85 | 86 | - By default, function will also print some warnings if they occur. You can turn off those warnings using 87 | ``warnings=False``. 88 | 89 | - When working with the parallel versions, you also have the ability to specify how many concurrent threads/coroutines you wish to spawn using ``max_concurrent_workers=a new number`` 90 | ONLY change it if you know you need it. This can sometimes help reduce loads or gain performance boost. 91 | The default is ``your cpu core count * 5`` 92 | 93 | - By default, the results returned will be in ascending order (oldest candles first in the final output). To change 94 | that simply specify descending order. You can either pass an enum 95 | :class:`polygon.enums.SortOrder` (recommended) or pass a string ``sort='desc'``. 96 | 97 | 98 | I want to do it manually, but could use some help 99 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 100 | 101 | Sure. The function used by these functions internally to split a large date range into 102 | smaller time chunks, is also available to use directly. 103 | 104 | It returns a list of time chunks with their respective start and end times. You can then use your own logic to get 105 | data for those chunks, process and merge it however you like. 106 | 107 | The method you want to call is ``client.split_date_range()``, like so: 108 | 109 | .. code-block:: python 110 | 111 | import polygon 112 | 113 | client = polygon.StocksClient('KEY') 114 | 115 | time_frames = client.split_date_range('2005-06-28', '2022-06-28', timespan='minute') 116 | print(time_frames) 117 | 118 | - By default the list returned will have newer timeframes first. To change that, pass ``reverse=False`` 119 | 120 | - The argument ``smaller_time_chunks`` is available here too and can be used for assets which are traded a high 121 | number of hours in a day. This argument was renamed from ``high_volatility`` to ``smaller_time_chunks`` in **v1.0.9** 122 | 123 | Here is the method signature 124 | 125 | .. automethod:: polygon.base_client.Base.split_date_range 126 | :noindex: 127 | 128 | .. _bulk_ticker_details_header: 129 | 130 | Bulk Ticker Details 131 | ------------------- 132 | 133 | Available on both regular and async clients, this function makes it easy to get ticker details for a specified 134 | ticker, for each day in a given date range. 135 | 136 | It's useful for quickly collecting data such as **historical outstanding shares for a symbol**. 137 | 138 | How does the function work 139 | ~~~~~~~~~~~~~~~~~~~~~~~~~~ 140 | 141 | Skip if you don't care :D 142 | 143 | - This function would generate a final list of dates from the range of dates and/or custom dates. 144 | - The response for all dates is fetched in parallel (threads/coroutines) or sequential (if you say so) 145 | - The function returns an ``OrderedDict`` with the dates as keys and the ticker details as values. 146 | 147 | General Advice 148 | ~~~~~~~~~~~~~~ 149 | 150 | - If you are looking to use this functionality for MANY symbols (read more than 4-5), then it is better to use the 151 | async client. Due to GIL limitation in python, regular client can't run more than 1 threadpool at a time. 152 | - For most people, the default values should be enough, but for the ones who hate themselves ( :P ), it is possible to 153 | customize the behavior however they like. 154 | - The method is ONLY available on ``ReferenceClient`` for obvious reasons. 155 | 156 | Enough Talking, Show me how to use it 157 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 158 | 159 | Some example calls: 160 | 161 | .. code-block:: python 162 | 163 | res = client.get_bulk_ticker_details('AMD', '2005-06-28', '2022-07-11') 164 | res = client.get_bulk_ticker_details('AMD', from_date='2005-06-28', to_date='2022-07-11') # this & above are equivalent 165 | 166 | res = client.get_bulk_ticker_details('NVDA', custom_dates=['2005-06-28', '2022-07-20']) # without date range 167 | res = client.get_bulk_ticker_details('NVDA', from_date='2005-07-02', to_date='2022-07-11', 168 | custom_dates=['2005-06-28', '2022-07-01']) # with custom dates and a range 169 | 170 | Return Value 171 | The function returns an ``OrderedDict`` with the dates as keys and the ticker details as values. Iterating over the 172 | result would iterate over a fixed order (ascending by default) of the dates. You can set ``sort='desc'`` to reverse. 173 | 174 | Customizing Behavior: 175 | 176 | - When using async client, just await the method call. ``res = await client.get_bulk_ticker_details(...)`` 177 | - You CAN supply both a date range (from-to) and custom_dates. You MUST supply either one of those. Duplicate dates 178 | are dropped by the library internally. 179 | 180 | - If you don't want it to run in parallel (not recommended), you can just specify ``run_parallel=False``. doing that 181 | will make the library request data one by one. This might be useful if you're running a thread pool of your own 182 | and don't want the internal thread pool to mess with your own thread pool. 183 | **on async client, always prefer to run parallel** 184 | 185 | - By default, function will also print some warnings if they occur. You can turn off those warnings using 186 | ``warnings=False``. 187 | 188 | - When working with the parallel versions, you also have the ability to specify how many concurrent threads/coroutines you wish to spawn using ``max_concurrent_workers=a new number`` 189 | ONLY change it if you know you need it. This can sometimes help reduce loads or gain performance boost. 190 | The default is ``your cpu core count * 5`` 191 | 192 | Here is the method signature: 193 | 194 | .. automethod:: polygon.reference_apis.reference_api.SyncReferenceClient.get_bulk_ticker_details 195 | :noindex: 196 | 197 | I want to do it manually, but could use some help 198 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 199 | 200 | Sure. The function used to get a list of unique, sorted dates between two dates, is also available to use directly. 201 | Call it like: 202 | 203 | .. code-block:: python 204 | 205 | # client can be any client instance out of stocks, options, references, forex or crypto 206 | all_dates = client.get_dates_between('2005-03-08', '2022-06-28') 207 | all_dates = client.get_dates_between('2005-03-08', '2022-06-29', include_to_date=False) 208 | 209 | You can then use your own logic to get data for these dates, process and aggregate them however you like. Here is the 210 | method signature 211 | 212 | .. automethod:: polygon.base_client.Base.get_dates_between 213 | :noindex: 214 | -------------------------------------------------------------------------------- /docs/Callback-Streaming.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _callback_streaming_header: 3 | 4 | Callback Streaming 5 | ================== 6 | 7 | A convenient wrapper around the `Streaming API `__ 8 | 9 | **IMPORTANT** Polygon.io allows one simultaneous connection to one cluster at a time (clusters: stocks, options, forex, crypto). 10 | which means 4 total concurrent streams (Of course you need to have subscriptions for them). 11 | 12 | **Connecting to a cluster which already has an existing stream connected to it would result in existing connection getting dropped and new connection would be established** 13 | 14 | Note that This page describes the callback based streaming client. 15 | If you're looking for async based streaming client, See :ref:`async_streaming_header` 16 | 17 | Also note that callback based streamer is supposed to get a builtin functionality to reconnect in the library. Async streamer has it already. It's on TODO for this client. 18 | Have a reconnect mechanism to share? Share in `discussions `__ or on the `wiki `__. 19 | 20 | Creating the client 21 | ------------------- 22 | 23 | Creating a client is just creating an instance of ``polygon.StreamClient``. Note that this expects a few arguments where most of them have default values. 24 | 25 | This is how the initializer looks like: 26 | 27 | .. automethod:: polygon.streaming.streaming.StreamClient.__init__ 28 | :noindex: 29 | 30 | Example use: 31 | 32 | .. code-block:: python 33 | 34 | import polygon 35 | 36 | stream_client = polygon.StreamClient('KEY', 'stocks', on_message=my_own_handler_function) # in the simplest form 37 | 38 | Note that you don't have to call login methods as the library does it internally itself. 39 | 40 | Starting the Stream 41 | ------------------- 42 | 43 | Once you have a stream client, you can start the stream thread by calling the method: ``start_stream_thread``. 44 | 45 | This method has default values which should be good enough for most people. For those who need customization, here is how it looks like: 46 | 47 | .. automethod:: polygon.streaming.streaming.StreamClient.start_stream_thread 48 | :noindex: 49 | 50 | Example use: 51 | 52 | .. code-block:: python 53 | 54 | import polygon 55 | 56 | stream_client = polygon.StreamClient('KEY', 'stocks', on_message=my_own_handler_function) 57 | 58 | stream_client.start_stream_thread() 59 | 60 | # subscriptions here. 61 | 62 | Important Concepts 63 | ------------------ 64 | 65 | Important stuff to know before you connect your first stream. Note that when writing applications, you should create the client and start the stream thread before subscribing. 66 | 67 | Subscribing/Unsubscribing to Streams 68 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 69 | 70 | All subscription methods have names in pattern ``subscribe_service_name`` and ``unsubscribe_service_name`` (listed below) 71 | 72 | Symbols names must be specified as a list of symbols: ``['AMD', 'NVDA', 'LOL']`` is the correct way to specify symbols. 73 | Not specifying a list of symbols results in the action being applied to ``ALL`` tickers in that service. 74 | Note that either of ``[]``, ``None``, ``['*']`` or ``'all'`` as value of symbols would also results in ALL tickers. 75 | 76 | The library allows specifying a string for symbol argument (that string is sent exactly as it is without processing), 77 | but only do that if you have the absolute need to. Most people should just specify a list. Note that a list of single 78 | ticker is accepted. 79 | 80 | **Options and Crypto stream endpoints expect prefixes ``O:, X:`` respectively in front of every ticker. The library handles this for you** 81 | so you can pass symbols with or without those prefixes. 82 | 83 | By default, the library will also enforce upper case for all symbols being passed. To disable this enforcement, just 84 | pass in ``force_uppercase_symbols=False`` when subscribing in the methods below. 85 | 86 | Handling messages 87 | ~~~~~~~~~~~~~~~~~ 88 | 89 | Your handler function should accept two arguments. You can ignore the first argument which is going to be the websocket instance itself. The second argument is the actual message. 90 | 91 | In callback streaming, **the library can't do the json decoding for you internally, and you will always receive a raw string** as received from the websocket server. 92 | messages). **You will have to do** ``json decoding`` **yourself**. 93 | 94 | .. code-block:: python 95 | 96 | def sample_handler(ws, msg): 97 | print(msg) # here msg is the raw string which contains the msg. to convert it to a list/dict, it needs to be decoded. 98 | 99 | # DECODING the msg from string to list/dict 100 | # ensure you have 'import json' at the top of file in imports 101 | 102 | msg = json.loads(msg) # now msg is a python object which you can use easily to access data from. 103 | 104 | Once you have the message in your callback handler function, you can process it the way you want. print it out, write it to a file, push it to a redis queue, write to a database, 105 | offload to a multi-threaded queue. Just whatever. 106 | 107 | The default handler for the messages is ``_default_on_msg`` which does some checks on messages having event as ``status``. and prints out other messages. 108 | Messages from polygon having the key ``ev`` equal to ``status`` are status updates from polygon about login and relevant actions you take (ev indicates event) 109 | 110 | The data messages will have different ``ev`` value than the string 'status'. The ev values for those would match the :class:`polygon.enums.StreamServicePrefix` values. 111 | 112 | You can specify your own handlers for other callbacks (``on_error``, ``on_close`` etc) too or leave those to defaults. 113 | 114 | **if you choose to override default handlers for** ``on_error`` **and** ``on_close``, **here is how they need to be written** 115 | 116 | ``on_error`` handler must accept two arguments. You can ignore the first argument which is just the websocket instance itself. The second argument is going to be the actual error 117 | 118 | .. code-block:: python 119 | 120 | def sample_error_handler(ws, error): 121 | print(error) 122 | 123 | ``on_close`` handler must accept three arguments. you can ignore the first arg which is just the websocket instance itself. The second arg is close code, and third would be the 124 | close message. note that this handler is only called when the stream is being closed. 125 | 126 | .. code-block:: python 127 | 128 | def sample_close_handler(ws, close_code, close_msg): 129 | print(f'Stream close with code: {close_code} || msg: {close_msg}') 130 | 131 | Closing Stream 132 | ~~~~~~~~~~~~~~ 133 | 134 | To turn off the streamer and shut down the websockets connection gracefully, it is advised to call ``stream_client.close_stream()`` method 135 | when closing the application. Not an absolute necessity but a good software practice. 136 | 137 | **Streams** 138 | 139 | Common Streams 140 | -------------- 141 | 142 | these streams are available in 4 clusters (stocks, options, forex, crypto) EXCEPT indices 143 | 144 | Fair Market Value (FMV) 145 | ~~~~~~~~~~~~~~~~~~~~~~~ 146 | 147 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_fair_market_value 148 | :noindex: 149 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_fair_market_value 150 | :noindex: 151 | 152 | 153 | Stocks Streams 154 | -------------- 155 | 156 | Stock Trades 157 | ~~~~~~~~~~~~ 158 | 159 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_stock_trades 160 | :noindex: 161 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_stock_trades 162 | :noindex: 163 | 164 | Stock Quotes 165 | ~~~~~~~~~~~~ 166 | 167 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_stock_quotes 168 | :noindex: 169 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_stock_quotes 170 | :noindex: 171 | 172 | Stock Minute Aggregates (OCHLV) 173 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 174 | 175 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_stock_minute_aggregates 176 | :noindex: 177 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_stock_minute_aggregates 178 | :noindex: 179 | 180 | Stock Second Aggregates (OCHLV) 181 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 182 | 183 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_stock_second_aggregates 184 | :noindex: 185 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_stock_second_aggregates 186 | :noindex: 187 | 188 | Stock Limit Up Limit Down (LULD) 189 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 190 | 191 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_stock_limit_up_limit_down 192 | :noindex: 193 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_stock_limit_up_limit_down 194 | :noindex: 195 | 196 | Stock Imbalances 197 | ~~~~~~~~~~~~~~~~ 198 | 199 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_stock_imbalances 200 | :noindex: 201 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_stock_imbalances 202 | :noindex: 203 | 204 | Options Streams 205 | --------------- 206 | 207 | Options Trades 208 | ~~~~~~~~~~~~~~ 209 | 210 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_option_trades 211 | :noindex: 212 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_option_trades 213 | :noindex: 214 | 215 | Options Quotes 216 | ~~~~~~~~~~~~~~ 217 | 218 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_option_quotes 219 | :noindex: 220 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_option_quotes 221 | :noindex: 222 | 223 | Options Minute Aggregates (OCHLV) 224 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 225 | 226 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_option_minute_aggregates 227 | :noindex: 228 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_option_minute_aggregates 229 | :noindex: 230 | 231 | Options Second Aggregates (OCHLV) 232 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 233 | 234 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_option_second_aggregates 235 | :noindex: 236 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_option_second_aggregates 237 | :noindex: 238 | 239 | 240 | Forex Streams 241 | ------------- 242 | 243 | Forex Quotes 244 | ~~~~~~~~~~~~ 245 | 246 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_forex_quotes 247 | :noindex: 248 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_forex_quotes 249 | :noindex: 250 | 251 | Forex Minute Aggregates (OCHLV) 252 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 253 | 254 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_forex_minute_aggregates 255 | :noindex: 256 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_forex_minute_aggregates 257 | :noindex: 258 | 259 | Crypto Streams 260 | -------------- 261 | 262 | Crypto Trades 263 | ~~~~~~~~~~~~~ 264 | 265 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_crypto_trades 266 | :noindex: 267 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_crypto_trades 268 | :noindex: 269 | 270 | Crypto Quotes 271 | ~~~~~~~~~~~~~ 272 | 273 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_crypto_quotes 274 | :noindex: 275 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_crypto_quotes 276 | :noindex: 277 | 278 | Crypto Minute Aggregates (OCHLV) 279 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 280 | 281 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_crypto_minute_aggregates 282 | :noindex: 283 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_crypto_minute_aggregates 284 | :noindex: 285 | 286 | Crypto Level 2 Book 287 | ~~~~~~~~~~~~~~~~~~~ 288 | 289 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_crypto_level2_book 290 | :noindex: 291 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_crypto_level2_book 292 | :noindex: 293 | 294 | Indices Streams 295 | --------------- 296 | 297 | Minute Aggregates 298 | ~~~~~~~~~~~~~~~~~ 299 | 300 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_indices_minute_aggregates 301 | :noindex: 302 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_indices_minute_aggregates 303 | :noindex: 304 | 305 | Second Aggregates 306 | ~~~~~~~~~~~~~~~~~ 307 | 308 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_indices_second_aggregates 309 | :noindex: 310 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_indices_second_aggregates 311 | :noindex: 312 | 313 | Value 314 | ~~~~~~~~~~~~~~~~~ 315 | 316 | .. automethod:: polygon.streaming.streaming.StreamClient.subscribe_index_value 317 | :noindex: 318 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_indices_value 319 | :noindex: 320 | 321 | 322 | 323 | -------------------------------------------------------------------------------- /polygon/enums.py: -------------------------------------------------------------------------------- 1 | # ========================================================= # 2 | import enum 3 | 4 | # ========================================================= # 5 | 6 | 7 | # Ticker Market Types - Reference APIs 8 | class TickerMarketType(enum.Enum): 9 | """ 10 | Market Types for method: ``ReferenceClient.get_tickers()`` 11 | """ 12 | 13 | STOCKS = "stocks" 14 | OPTIONS = "options" 15 | FOREX = "fx" 16 | CRYPTO = "crypto" 17 | 18 | 19 | # Ticker Types - Reference APIs 20 | class TickerType(enum.Enum): 21 | """ 22 | Ticker types for method: ``ReferenceClient.get_tickers()`` 23 | """ 24 | 25 | CS = "CS" 26 | COMMON_STOCKS = "CS" 27 | ADRC = "ADRC" 28 | ADRP = "ADRP" 29 | ADRR = "ADRR" 30 | UNIT = "UNIT" 31 | RIGHT = "RIGHT" 32 | PFD = "PFD" 33 | FUND = "FUND" 34 | SP = "SP" 35 | WARRANT = "WARRANT" 36 | INDEX = "INDEX" 37 | ETF = "ETF" 38 | ETN = "ETN" 39 | 40 | 41 | # Ticker Sort Type - Reference APIs 42 | class TickerSortType(enum.Enum): 43 | """Sort key for method: ``ReferenceClient.get_tickers()``""" 44 | 45 | TICKER = "ticker" 46 | NAME = "name" 47 | MARKET = "market" 48 | LOCALE = "locale" 49 | PRIMARY_EXCHANGE = "primary_exchange" 50 | TYPE = "type" 51 | ACTIVE = "active" 52 | CURRENCY_SYMBOL = "currency_symbol" 53 | CURRENCY_NAME = "currency_name" 54 | BASE_CURRENCY_SYMBOL = "base_currency_symbol" 55 | BASE_CURRENCY_NAME = "base_currency_name" 56 | CIK = "cik" 57 | COMPOSITE_FIGI = "composite_figi" 58 | SHARE_CLASS_FIGI = "share_class_figi" 59 | LAST_UPDATED_UTC = "last_updated_utc" 60 | DELISTED_UTC = "delisted_utc" 61 | 62 | 63 | # SORT Order - Common for most endpoints 64 | class SortOrder(enum.Enum): 65 | """ 66 | Order of sort. Ascending usually means oldest at the top. Descending usually means newest at the top. It is 67 | recommended to ensure the behavior in the corresponding function's docs. This enum can be used by any method 68 | accepting Sort order values. 69 | """ 70 | 71 | ASCENDING = "asc" 72 | ASC = "asc" 73 | DESCENDING = "desc" 74 | DESC = "desc" 75 | 76 | 77 | # Ticker Type Asset Class - Reference APIs 78 | class TickerTypeAssetClass(enum.Enum): 79 | """ 80 | Asset Class for method: ``ReferenceClient.get_ticker_types_v3()`` 81 | """ 82 | 83 | STOCKS = "stocks" 84 | OPTIONS = "options" 85 | FOREX = "fx" 86 | CRYPTO = "crypto" 87 | 88 | 89 | # Ticker News Sort - Reference APIs 90 | class TickerNewsSort(enum.Enum): 91 | """ 92 | Sort key for method: ``ReferenceClient.get_ticker_news()`` 93 | """ 94 | 95 | PUBLISHED_UTC = "published_utc" 96 | ALL = None 97 | 98 | 99 | # Stock Report Type - Reference APIs 100 | class StockReportType(enum.Enum): 101 | """ 102 | Type of report for method: ``ReferenceClient.get_stock_financials()`` 103 | """ 104 | 105 | YEAR = "Y" 106 | Y = "Y" 107 | YA = "YA" 108 | YEAR_ANNUALIZED = "YA" 109 | Q = "Q" 110 | QUARTER = "Q" 111 | QA = "QA" 112 | QUARTER_ANNUALIZED = "QA" 113 | T = "T" 114 | TRAILING_TWELVE_MONTHS = "T" 115 | TA = "TA" 116 | TRAILING_TWELVE_MONTHS_ANNUALIZED = "TA" 117 | 118 | 119 | # Stock Report Sort Type - Reference APIs 120 | class StockFinancialsSortType(enum.Enum): 121 | """ 122 | Direction to use for sorting report for method: ``ReferenceClient.get_stock_financials()`` 123 | """ 124 | 125 | REPORT_PERIOD = "reportPeriod" 126 | REVERSE_REPORT_PERIOD = "-reportPeriod" 127 | CALENDAR_DATE = "calendarDate" 128 | REVERSE_CALENDAR_DATE = "-calendarDate" 129 | 130 | 131 | # Stock Financial Time Frame - Reference APIs 132 | class StockFinancialsTimeframe(enum.Enum): 133 | """ 134 | Query by timeframe. Annual financials originate from 10-K filings, and quarterly financials originate from 10-Q 135 | filings. Note: Most companies do not file quarterly reports for Q4 and instead include those financials in their 136 | annual report, so some companies my not return quarterly financials for Q4 137 | for method: ``ReferenceClient.get_stock_financials_vx()`` 138 | """ 139 | 140 | ANNUAL = "annual" 141 | QUARTERLY = "quarterly" 142 | 143 | 144 | # Stock Financials Sort Key - Reference APIS 145 | class StockFinancialsSortKey(enum.Enum): 146 | """ 147 | Sort field for method: ``ReferenceClient.get_stock_financials_vx()`` 148 | """ 149 | 150 | FILLING_DATE = "filling_date" 151 | PERIOD_OF_REPORT_DATE = "period_of_report_date" 152 | 153 | 154 | # Index Snapshot Sort Key - Index APIs 155 | class IndexSnapshotSortKey(enum.Enum): 156 | """ 157 | Sort field for method: ``IndexClient.get_snapshot()`` 158 | """ 159 | 160 | TICKER = "ticker" 161 | 162 | 163 | # Conditions Mapping Tick Type - Reference APIs 164 | class ConditionMappingTickType(enum.Enum): 165 | """ 166 | Tick Type for method: ``ReferenceClient.get_condition_mappings()`` 167 | """ 168 | 169 | TRADES = "trades" 170 | QUOTES = "quotes" 171 | 172 | 173 | # Conditions Data Type - Reference APIs 174 | class ConditionsDataType(enum.Enum): 175 | """ 176 | Type of data for method: ``ReferenceClient.get_conditions()`` 177 | """ 178 | 179 | TRADE = "trade" 180 | BBO = "bbo" 181 | NBBO = "nbbo" 182 | 183 | 184 | # Conditions SIP - Reference APIs 185 | class ConditionsSIP(enum.Enum): 186 | """ 187 | SIP for method: ``ReferenceClient.get_conditions()`` 188 | """ 189 | 190 | CTA = "CTA" 191 | UTP = "UTP" 192 | OPRA = "OPRA" 193 | 194 | 195 | # Conditions Sort key - Reference APIs 196 | class ConditionsSortKey(enum.Enum): 197 | """ 198 | Sort key for method: ``ReferenceClient.get_conditions()`` 199 | """ 200 | 201 | ASSET_CLASS = "asset_class" 202 | ID = "id" 203 | TYPE = "type" 204 | NAME = "name" 205 | DATA_TYPES = "data_types" 206 | LEGACY = "legacy" 207 | 208 | 209 | # Asset Class - Common 210 | class AssetClass(enum.Enum): 211 | """ 212 | Asset Class for methods: ``ReferenceClient.get_exchanges_v3()`` and ``ReferenceClient.get_conditions()`` and 213 | wherever needed. 214 | """ 215 | 216 | STOCKS = "stocks" 217 | OPTIONS = "options" 218 | FOREX = "fx" 219 | CRYPTO = "crypto" 220 | 221 | 222 | # Locales - common 223 | class Locale(enum.Enum): 224 | """ 225 | Locale name`` 226 | """ 227 | 228 | US = "us" 229 | GLOBAL = "global" 230 | 231 | 232 | # Snapshot Direction - Stocks, Fx, Crypto APIs 233 | class SnapshotDirection: 234 | """Direction to be supplied to the SnapShot - Gainers and Losers APIs on Stocks, Forex and Crypto endpoints""" 235 | 236 | GAINERS = "gainers" 237 | GAIN = "gainers" 238 | LOSERS = "losers" 239 | LOSE = "losers" 240 | 241 | 242 | # Pagination direction - common for all 243 | class PaginationDirection(enum.Enum): 244 | """ 245 | The direction to paginate in. 246 | """ 247 | 248 | NEXT = "next" 249 | FORWARD = "next" 250 | PREV = "previous" 251 | PREVIOUS = "previous" 252 | BACKWARD = "previous" 253 | 254 | 255 | # Stream Cluster - Websockets 256 | class StreamCluster(enum.Enum): 257 | """ 258 | The cluster to connect to. To be used for both callback and async stream client. NEVER connect to the same 259 | cluster again if there is an existing stream connected to it. The existing connection would be dropped and new 260 | one will be established. You can have up to 4 concurrent streams connected to 4 different clusters. 261 | """ 262 | 263 | STOCKS = "stocks" 264 | OPTIONS = "options" 265 | FOREX = "forex" 266 | CRYPTO = "crypto" 267 | INDICES = "indices" 268 | 269 | 270 | # Options Contract Type - Common 271 | class OptionsContractType(enum.Enum): 272 | """ 273 | Contract Type for method: ``ReferenceClient.get_options_contracts()`` 274 | """ 275 | 276 | CALL = "call" 277 | PUT = "put" 278 | OTHER = "other" 279 | 280 | 281 | # Option contract Sort Key - Options 282 | class OptionsContractsSortType(enum.Enum): 283 | """ 284 | Sort field used for ordering for method: ``ReferenceClient.get_options_contracts()`` 285 | """ 286 | 287 | TICKER = "ticker" 288 | UNDERLYING_TICKER = "underlying_ticker" 289 | EXPIRATION_DATE = "expiration_date" 290 | STRIKE_PRICE = "strike_price" 291 | 292 | 293 | # Option Trades Sort Type - Options 294 | class OptionTradesSort(enum.Enum): 295 | """ 296 | Sort field used for ordering option trades. Used for method: ``OptionsClient.get_trades`` 297 | """ 298 | 299 | TIMESTAMP = "timestamp" 300 | 301 | 302 | # Option Quotes Sort Type - Options 303 | class OptionQuotesSort(enum.Enum): 304 | """ 305 | Sort field used for ordering option quotes. Used for method: ``OptionsClient.get_quotes`` 306 | """ 307 | 308 | TIMESTAMP = "timestamp" 309 | 310 | 311 | # Stocks Trades Sort Type - Stocks 312 | class StocksTradesSort(enum.Enum): 313 | """ 314 | Sort field used for ordering Stocks trades. Used for method: ``StocksClient.get_trades`` 315 | """ 316 | 317 | TIMESTAMP = "timestamp" 318 | 319 | 320 | # Stocks Quotes Sort Type - Stocks 321 | class StocksQuotesSort(enum.Enum): 322 | """ 323 | Sort field used for ordering Stocks quotes. Used for method: ``StocksClient.get_quotes`` 324 | """ 325 | 326 | TIMESTAMP = "timestamp" 327 | 328 | 329 | # Stocks Splits Sort Type - References 330 | class SplitsSortKey(enum.Enum): 331 | """ 332 | Sort field used for ordering stock splits. Used for method ``ReferenceClient.get_stock_splits`` 333 | """ 334 | 335 | EXECUTION_DATE = "execution_date" 336 | TICKER = "ticker" 337 | 338 | 339 | # Stocks Dividends Payout Frequency - References 340 | class PayoutFrequency(enum.Enum): 341 | """ 342 | the number of times per year the dividend is paid out. Possible values are 0 (one-time), 1 (annually), 343 | 2 (bi-annually), 4 (quarterly), and 12 (monthly). used by method ``ReferenceClient.get_stock_dividends`` 344 | """ 345 | 346 | ONE_TIME = 0 347 | ANNUALLY = 1 348 | BI_ANNUALLY = 2 349 | QUARTERLY = 4 350 | MONTHLY = 12 351 | 352 | 353 | # Stock dividend Type - References 354 | class DividendType(enum.Enum): 355 | """ 356 | the type of dividend. Dividends that have been paid and/or are expected to be paid on consistent schedules 357 | are denoted as CD. Special Cash dividends that have been paid that are infrequent or unusual, and/or can not be 358 | expected to occur in the future are denoted as SC. Used for method ``ReferenceClient.get_stock_dividends`` 359 | """ 360 | 361 | CD = "CD" 362 | SC = "SC" 363 | LT = "LT" 364 | ST = "ST" 365 | 366 | 367 | # Stock Dividend Sort - References 368 | class DividendSort(enum.Enum): 369 | """ 370 | sort field used for ordering dividend results. used for method ``ReferenceClient.get_stock_dividends`` 371 | """ 372 | 373 | EX_DIVIDEND_DATE = "ex_dividend_date" 374 | PAY_DATE = "pay_date" 375 | DECLARATION_DATE = "declaration_date" 376 | RECORD_DATE = "record_date" 377 | CASH_AMOUNT = "cash_amount" 378 | TICKER = "ticker" 379 | 380 | 381 | # Forex Quotes Sort Type - Forex 382 | class ForexQuotesSort(enum.Enum): 383 | """ 384 | Sort field used for ordering Forex quotes. Used for method: ``ForexClient.get_quotes`` 385 | """ 386 | 387 | TIMESTAMP = "timestamp" 388 | 389 | 390 | # Crypto Trades Sort Type - Crypto 391 | class CryptoTradesSort(enum.Enum): 392 | """ 393 | Sort field used for ordering crypto trades. Used for method: ``CryptoClient.get_trades`` 394 | """ 395 | 396 | TIMESTAMP = "timestamp" 397 | 398 | 399 | # Stream Host - Common Websockets 400 | class StreamHost(enum.Enum): 401 | """ 402 | Host to be used for stream connections. WHY on earth would you use delayed if you're paying for polygon?? 403 | """ 404 | 405 | REAL_TIME = "socket.polygon.io" 406 | BUSINESS = "business.polygon.io" 407 | DELAYED = "delayed.polygon.io" 408 | 409 | 410 | # Stream Service Prefix - Websockets 411 | class StreamServicePrefix(enum.Enum): 412 | """ 413 | Service Prefix for Stream endpoints. To be used for method: ``AsyncStreamClient.async change_handler()`` 414 | """ 415 | 416 | STOCK_TRADES = "T" 417 | STOCK_QUOTES = "Q" 418 | STOCK_MINUTE_AGGREGATES = "AM" 419 | STOCK_SECOND_AGGREGATES = "A" 420 | STOCK_LULD = "LULD" 421 | STOCK_IMBALANCES = "NOI" 422 | FOREX_QUOTES = "C" 423 | FOREX_MINUTE_AGGREGATES = "CA" 424 | CRYPTO_TRADES = "XT" 425 | CRYPTO_QUOTES = "XQ" 426 | CRYPTO_LEVEL2 = "XL2" 427 | CRYPTO_MINUTE_AGGREGATES = "XA" 428 | STATUS = "status" 429 | OPTION_TRADES = "T" 430 | OPTION_QUOTES = "Q" 431 | OPTION_MINUTE_AGGREGATES = "AM" 432 | OPTION_SECOND_AGGREGATES = "A" 433 | FAIR_MARKET_VALUE = "FMV" 434 | INDICES_MINUTE_AGGREGATES = "AM" 435 | INDICES_SECOND_AGGREGATES = "A" 436 | INDICES_VALUE = "V" 437 | 438 | 439 | # Timespan - common 440 | class Timespan(enum.Enum): 441 | """ 442 | The timespan values. Usually meant for aggregates endpoints. It is best to consult the relevant docs before using 443 | any value on an endpoint. 444 | """ 445 | 446 | SECOND = "second" 447 | MINUTE = "minute" 448 | MIN = "minute" 449 | HOUR = "hour" 450 | DAY = "day" 451 | WEEK = "week" 452 | MONTH = "month" 453 | QUARTER = "quarter" 454 | YEAR = "year" 455 | 456 | 457 | # Option Symbol Format - options 458 | class OptionSymbolFormat(enum.Enum): 459 | """ 460 | Option symbol formats supported by the library. To be used with functions to build or parse option symbols 461 | """ 462 | 463 | POLYGON = "polygon" 464 | TDA = "tda" 465 | TD_AMERITRADE = "tda" 466 | TOS = "tos" 467 | THINK_OR_SWIM = "tos" 468 | TRADIER = "tradier" 469 | TRADE_STATION = "trade_station" 470 | IB = "ibkr" 471 | IBKR = "ibkr" 472 | INTERACTIVE_BROKERAGE = "ibkr" 473 | 474 | 475 | # INDICATORS 476 | # Indicator Series Type - Common 477 | class SeriesType(enum.Enum): 478 | """ 479 | Series Type to be used for Indicators calculations 480 | """ 481 | 482 | CLOSE = "close" 483 | OPEN = "OPEN" 484 | HIGH = "HIGH" 485 | LOW = "LOW" 486 | 487 | 488 | # ========================================================= # 489 | 490 | if __name__ == "__main__": 491 | pass 492 | 493 | # ========================================================= # 494 | -------------------------------------------------------------------------------- /docs/Async-Streaming.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _async_streaming_header: 3 | 4 | Async Streaming 5 | =============== 6 | 7 | A convenient wrapper around the `Streaming API `__ 8 | 9 | **IMPORTANT** Polygon.io allows one simultaneous connection to one cluster at a time (clusters: stocks, options, forex, crypto). 10 | which means 4 total concurrent streams (Of course you need to have subscriptions for them). 11 | 12 | **Connecting to a cluster which already has an existing stream connected to it would result in existing connection getting dropped and new connection would be established** 13 | 14 | Note that This page describes the asyncio based streaming client. 15 | If you're looking for callback based streaming client, See :ref:`callback_streaming_header` 16 | 17 | Also note that async client has a reconnection mechanism built into it already. It is very basic at the moment. It resubscribes to the same set of services it already had 18 | before the disconnection and restores the handlers when reconnection establishes. More info in starting the stream below. 19 | 20 | It also exposes a few methods which you could use to create your own reconnect mechanism. Method :meth:`polygon.streaming.async_streaming.AsyncStreamClient.reconnect` is one of them 21 | 22 | Have a reconnect mechanism to share? Share in `discussions `__ or on the `wiki `__. 23 | 24 | Creating the client 25 | ------------------- 26 | 27 | Creating a client is just creating an instance of ``polygon.AsyncStreamClient``. Note that this expects a few arguments where most of them have default values. 28 | 29 | This is how the initializer looks like: 30 | 31 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.__init__ 32 | :noindex: 33 | 34 | Example use: 35 | 36 | .. code-block:: python 37 | 38 | import polygon 39 | 40 | stream_client = polygon.AsyncStreamClient('KEY', 'stocks') # in the simplest form 41 | 42 | Note that you don't have to call login methods as the library does it internally itself. 43 | 44 | Starting the Stream 45 | ------------------- 46 | 47 | Once you have a stream client, you MUST subscribe to streams before you start the main stream loop. Note that you can alter your subscriptions from other coroutines easily even after 48 | starting the main stream loop. See subscriptions methods below this section to know how to subscribe to streams. 49 | 50 | AFTER you have called your initial subscription methods, you have two ways to start the main stream loop. 51 | 52 | Without using the built-in reconnect functionality 53 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 54 | 55 | In this case you'd need to have your own while loop, like so: 56 | 57 | .. code-block:: python 58 | 59 | # assuming we create the client and sub to stream here already. 60 | while 1: 61 | await stream_client.handle_messages() 62 | 63 | and that's basically it. handle_message would take care of receiving messages and calling appropriate handlers (see below section for info on that aspect). 64 | You may want to implement your own reconnect mechanism here. 65 | 66 | If that's your use case, you can basically ignore the below section completely. 67 | 68 | Using the built-in reconnect functionality 69 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 70 | 71 | here you don't need any outer while loop of your own. The lib has inner while loops and mechanisms to trap disconnection errors and will attempt to reconnect. 72 | 73 | Note that this function is basic and not perfect yet and will continue to improve as we move ahead. If you figure out a way to implement reconnection, feel free to share that 74 | in `discussions `__ or on the `wiki `__. 75 | 76 | simple use example 77 | 78 | .. code-block:: python 79 | 80 | # assuming we already have a client subscribed to streams 81 | await stream_client.handle_messages(reconnect=True) 82 | 83 | That's it. This should be enough for most users. For those who need more control over the behavior here; this is how the method definition looks like: 84 | 85 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.handle_messages 86 | :noindex: 87 | 88 | Subscribing/Unsubscribing to Streams 89 | ------------------------------------ 90 | 91 | All subscription methods have names in pattern ``subscribe_service_name`` and ``unsubscribe_service_name``. 92 | 93 | Symbols names must be specified as a list of symbols: ``['AMD', 'NVDA', 'LOL']`` is the correct way to specify symbols. 94 | Not specifying a list of symbols results in the action being applied to ``ALL`` tickers in that service. 95 | Note that either of ``[]``, ``None``, ``['*']`` or ``'all'`` as value of symbols would also results in ALL tickers. 96 | 97 | The library allows specifying a string for symbol argument (that string is sent exactly as it is without processing), 98 | but only do that if you have the absolute need to. Most people should just specify a list. Note that a list of single 99 | ticker is accepted. 100 | 101 | **Options and Crypto stream endpoints expect prefixes ``O:, X:`` respectively in front of every ticker. The library handles this for you** 102 | so you can pass symbols with or without those prefixes. 103 | 104 | The Second argument on all unsubscribe methods is the ``handler_function`` which represents the handler function you'd like the library to call when a message from that service is 105 | received. You can have one handler for multiple services. Not supplying a handler results in the library using the default message handler. 106 | 107 | All methods are async coroutines which need to be awaited. 108 | 109 | ``await stream_client.subscribe_stock_trades(['AMD', 'NVDA'], handler_function=my_handler_function)`` 110 | 111 | By default, the library will also enforce upper case for all symbols being passed. To disable this enforcement, just 112 | pass in ``force_uppercase_symbols=False`` when subscribing in the methods below. 113 | 114 | Handling Messages 115 | ----------------- 116 | 117 | your handler functions should accept one argument which indicates the message. 118 | 119 | .. code-block:: python 120 | 121 | async def sample_handler(msg): 122 | print(f'Look at me! I am the handler now. {msg}') 123 | 124 | Note that you can also use a sync function as handler 125 | 126 | .. code-block:: python 127 | 128 | def sample_handler(msg): 129 | print(f'I am also a handler. But sync.. {msg}') 130 | 131 | In async streaming, **the library does the json decoding for you internally, and you will always receive a list/dict python object** (a list 99.99% of the time except the initial status 132 | messages). **You don't have to do** ``json decoding`` **yourself**. Internally it is already done using ``json.loads(msg)`` 133 | 134 | Once you have the message in your callback handler function, you can process it the way you want. print it out, write it to a file, push it to a redis queue, write to a database, 135 | offload to a multi-threaded queue. Just whatever. 136 | 137 | The default handler for the messages is ``_default_process_message``. 138 | 139 | Changing message handler functions while stream is running 140 | ---------------------------------------------------------- 141 | 142 | Library allows you to change your handlers after your main stream loop has started running. 143 | 144 | The function you'd need is: 145 | 146 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.change_handler 147 | :noindex: 148 | 149 | Note that you should never need to change handler for ``status`` ( which handles ``ev`` messages) unless you know you got a situation. Service prefixes just indicate which service (e.g. stock trades? options aggregates?) 150 | you want to change the handler. 151 | 152 | Closing the Stream 153 | ------------------ 154 | 155 | To turn off the streamer and shut down the websockets connection gracefully, it is advised to ``await stream_client.close_stream()`` 156 | when closing the application. Not an absolute necessity but a good software practice. 157 | 158 | **Streams** 159 | 160 | Common Streams 161 | -------------- 162 | 163 | these streams are available in 4 clusters (stocks, options, forex, crypto) EXCEPT indices 164 | 165 | Fair Market Value (FMV) 166 | ~~~~~~~~~~~~~~~~~~~~~~~ 167 | 168 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_fair_market_value 169 | :noindex: 170 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_fair_market_value 171 | :noindex: 172 | 173 | Stock Streams 174 | ------------- 175 | 176 | Stock Trades 177 | ~~~~~~~~~~~~ 178 | 179 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_stock_trades 180 | :noindex: 181 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_stock_trades 182 | :noindex: 183 | 184 | Stock Quotes 185 | ~~~~~~~~~~~~ 186 | 187 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_stock_quotes 188 | :noindex: 189 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_stock_quotes 190 | :noindex: 191 | 192 | Stock Minute Aggregates (OCHLV) 193 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 194 | 195 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_stock_minute_aggregates 196 | :noindex: 197 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_stock_minute_aggregates 198 | :noindex: 199 | 200 | Stock Second Aggregates (OCHLV) 201 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 202 | 203 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_stock_second_aggregates 204 | :noindex: 205 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_stock_second_aggregates 206 | :noindex: 207 | 208 | Stock Limit Up Limit Down (LULD) 209 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 210 | 211 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_stock_limit_up_limit_down 212 | :noindex: 213 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_stock_limit_up_limit_down 214 | :noindex: 215 | 216 | Stock Imbalances 217 | ~~~~~~~~~~~~~~~~ 218 | 219 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_stock_imbalances 220 | :noindex: 221 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_stock_imbalances 222 | :noindex: 223 | 224 | Options Streams 225 | --------------- 226 | 227 | Options Trades 228 | ~~~~~~~~~~~~~~ 229 | 230 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_option_trades 231 | :noindex: 232 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_option_trades 233 | :noindex: 234 | 235 | Options Quotes 236 | ~~~~~~~~~~~~~~ 237 | 238 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_option_quotes 239 | :noindex: 240 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_option_quotes 241 | :noindex: 242 | 243 | Options Minute Aggregates (OCHLV) 244 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 245 | 246 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_option_minute_aggregates 247 | :noindex: 248 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_option_minute_aggregates 249 | :noindex: 250 | 251 | Options Second Aggregates (OCHLV) 252 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 253 | 254 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_option_second_aggregates 255 | :noindex: 256 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_option_second_aggregates 257 | :noindex: 258 | 259 | 260 | Forex Streams 261 | ------------- 262 | 263 | Forex Quotes 264 | ~~~~~~~~~~~~ 265 | 266 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_forex_quotes 267 | :noindex: 268 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_forex_quotes 269 | :noindex: 270 | 271 | Forex Minute Aggregates (OCHLV) 272 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 273 | 274 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_forex_minute_aggregates 275 | :noindex: 276 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_forex_minute_aggregates 277 | :noindex: 278 | 279 | 280 | Forex Minute Aggregates (OCHLV) 281 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 282 | 283 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_forex_second_aggregates 284 | :noindex: 285 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_forex_second_aggregates 286 | :noindex: 287 | 288 | Crypto Streams 289 | -------------- 290 | 291 | Crypto Trades 292 | ~~~~~~~~~~~~~ 293 | 294 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_crypto_trades 295 | :noindex: 296 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_crypto_trades 297 | :noindex: 298 | 299 | Crypto Quotes 300 | ~~~~~~~~~~~~~ 301 | 302 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_crypto_quotes 303 | :noindex: 304 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_crypto_quotes 305 | :noindex: 306 | 307 | Crypto Minute Aggregates (OCHLV) 308 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 309 | 310 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_crypto_minute_aggregates 311 | :noindex: 312 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_crypto_minute_aggregates 313 | :noindex: 314 | 315 | Crypto Second Aggregates (OCHLV) 316 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 317 | 318 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_crypto_second_aggregates 319 | :noindex: 320 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_crypto_second_aggregates 321 | :noindex: 322 | 323 | Crypto Level 2 Book 324 | ~~~~~~~~~~~~~~~~~~~ 325 | 326 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_crypto_level2_book 327 | :noindex: 328 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_crypto_level2_book 329 | :noindex: 330 | 331 | 332 | Indices Streams 333 | --------------- 334 | 335 | Minute Aggregates 336 | ~~~~~~~~~~~~~~~~~ 337 | 338 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_indices_minute_aggregates 339 | :noindex: 340 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_indices_minute_aggregates 341 | :noindex: 342 | 343 | Second Aggregates 344 | ~~~~~~~~~~~~~~~~~ 345 | 346 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_indices_second_aggregates 347 | :noindex: 348 | .. automethod:: polygon.streaming.streaming.StreamClient.unsubscribe_indices_second_aggregates 349 | :noindex: 350 | 351 | Value 352 | ~~~~~~~~~~~~~~~~~ 353 | 354 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.subscribe_index_value 355 | :noindex: 356 | .. automethod:: polygon.streaming.async_streaming.AsyncStreamClient.unsubscribe_indices_value 357 | :noindex: 358 | 359 | 360 | -------------------------------------------------------------------------------- /docs/Options.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _options_header: 3 | 4 | Options 5 | ======= 6 | 7 | Read this page to know everything you need to know about using the various Options HTTP endpoints. 8 | 9 | See :ref:`async_support_header` for asynchronous use cases. 10 | 11 | Docs below assume you have already read getting started page and know how to create the client. 12 | If you do not know how to create the client, first see :ref:`create_and_use_header` and create client as below. As always you can have all 5 different clients together. 13 | 14 | .. code-block:: python 15 | 16 | import polygon 17 | 18 | options_client = polygon.OptionsClient('KEY') # for usual sync client 19 | async_options_client = polygon.OptionsClient('KEY', True) # for an async client 20 | 21 | here is how the client initializer looks like: 22 | 23 | .. autofunction:: polygon.options.options.OptionsClient 24 | 25 | **NOTE:** if you don't want to use the option symbol helper functions, then you can just go to the desired endpoint documentation from the list to left 26 | 27 | .. _option_symbols_header: 28 | 29 | Working with Option Symbols 30 | --------------------------- 31 | 32 | So when you're working with options (rest/websockets), you'll certainly need the option symbols which contain the information about their underlying symbol, expiry, call_or_put and the 33 | strike price in a certain format. There are many formats to represent them and every data source/brokerage uses a 34 | different format to represent them. 35 | 36 | for example Polygon.io tends to use `This Format `__ . For those who want to understand how this formatting works, 37 | `Here is a guide `__ (thanks to Ian from polygon support team). 38 | 39 | The library is equipped with a few functions to make it easier for you to **build, parse, convert, and detect 40 | format** of option symbols without worrying about how the structure works. 41 | 42 | This section has been written again following many changes in v1.0.8. If you were using option symbology in v1.0.7 or 43 | older, the documentation for that version is available [here](https://polygon.readthedocs.io/en/1.0.7/) although I'd 44 | suggest upgrading and making required (small) changes 45 | 46 | The library supports the following symbol formats at the moment 47 | 48 | =================== ==================== 49 | Full Name Shorthand String 50 | =================== ==================== 51 | Polygon.io polygon 52 | Tradier tradier 53 | Trade Station trade_station 54 | Interactive Brokers ibkr 55 | TD Ameritrade tda 56 | Think Or Swim tos 57 | =================== ==================== 58 | 59 | This section on option symbols is divided into these sections below. 60 | 61 | 1. **Creating** Option symbols from info as underlying, expiry, strike price, option type 62 | #. **Parsing** Option symbols to **extract** info as underlying, expiry, strike price, option type 63 | #. **Converting** an option symbol from one format to another. Works between all supported formats. 64 | #. **Detecting** format of an option symbol. Basic detection based on some simple rules. 65 | 66 | Creating Option Symbols 67 | ~~~~~~~~~~~~~~~~~~~~~~~ 68 | 69 | The function in this sub-section helps you to build option symbols from info as underlying symbol, expiry, strike 70 | price & option type (call/put). The function to use is ``polygon.build_option_symbol`` 71 | 72 | - Since the default format is polygon.io you don't need to specify a format if you're only working with polygon 73 | option symbols. 74 | - Polygon has a rest endpoint in reference client to get all active contracts which you can filter based on 75 | many values such as underlying symbol and expiry dates. 76 | - In polygon format, If you wonder whether you need to worry about the ``O:`` prefix which some/all option endpoints 77 | expect, then to your ease, the library handles that for you (So you can pass a symbol without prefix to let's say 78 | Option Snapshot function and the prefix will be added internally). If you want to be explicit, just pass 79 | ``prefix_o=True`` when building symbol. 80 | - Note that both tradier and polygon happen to use the exact same symbol format and hence can be used interchangeably. 81 | 82 | Example Code & Output for polygon/tradier format 83 | 84 | .. code-block:: python 85 | 86 | import polygon 87 | 88 | symbol1 = polygon.build_option_symbol('AMD', datetime.date(2022, 6, 28), 'call', 546.56) 89 | symbol2 = polygon.build_option_symbol('TSLA', '220628', 'c', 546, _format='polygon') 90 | symbol3 = polygon.build_option_symbol('A', '220628', 'put', 66.01, prefix_o=True) 91 | 92 | # Outputs 93 | # symbol1 -> AMD220628C00546560 94 | # symbol2 -> TSLA220628C00546000 95 | # symbol3 -> O:A220628P00066010 96 | 97 | 98 | The same function can be used to create option symbols for any of the supported formats, just pass in the format you 99 | need, either as a shorthand string from the table above, or use an enum from :class:`polygon.enums.OptionSymbolFormat` 100 | 101 | - Using enums (like ``OptionSymbolFormat.POLYGON`` in example below) is a good way to ensure you only pass in 102 | correct shorthand strings. Your IDE auto completion would make your life much easier when working with enums. 103 | 104 | Example code & outputs for multiple formats 105 | 106 | .. code-block:: python 107 | 108 | from polygon import build_option_symbol # you can import the way you like, just showing the alternates 109 | from polygon.enums import OptionSymbolFormat # optional, you can pass in shorthand strings too 110 | 111 | symbol1 = polygon.build_option_symbol('AMD', datetime.date(2022, 6, 28), 'call', 546.56, _format='tda') 112 | symbol2 = polygon.build_option_symbol('NVDA', '220628', 'c', 546, _format='tos') 113 | symbol3 = polygon.build_option_symbol('TSLA', datetime.date(2022, 6, 28), 'put', 46.01, _format='tradier') 114 | symbol4 = polygon.build_option_symbol('A', datetime.date(2022, 6, 28), 'p', 46.1, _format='ibkr') 115 | symbol5 = polygon.build_option_symbol('AB', datetime.date(2022, 6, 28), 'p', 46.01, _format='trade_station') 116 | symbol6 = polygon.build_option_symbol('PTON', '220628', 'p', 46, _format=OptionSymbolFormat.POLYGON) # using enum 117 | 118 | # outputs 119 | # symbol1 -> AMD_062822C546.56 120 | # symbol2 -> .NVDA062822C546 121 | # symbol3 -> TSLA220628P00046010 122 | # symbol4 -> A 220628P00046100 123 | # symbol5 -> AB 220628P46.01 124 | # symbol5 -> PTON220628P00046000 125 | 126 | For those who want more control, here is how the function signature and arguments look 127 | 128 | .. autofunction:: polygon.options.options.build_option_symbol 129 | :noindex: 130 | 131 | Parsing Option Symbols 132 | ~~~~~~~~~~~~~~~~~~~~~~ 133 | 134 | The function in this sub-section helps you to extract info as underlying symbol, expiry, strike price & option type 135 | (call/put) from an existing option symbol. Parsing is available on all supported formats. The function to use is 136 | ``polygon.build_option_symbol`` 137 | 138 | - Since the default format is ``polygon``, you don't need to specify a format if you're only working with polygon 139 | option symbols. 140 | - Polygon symbols can be passed in with or without the prefix ``O:``. Library will handle both internally 141 | - Note that both tradier and polygon happen to use the exact same symbol format and hence can be used interchangeably. 142 | - It is observed that some option symbols as returned by polygon endpoints happen to have a **correction number** 143 | within the symbol. The additional number is always between the underlying symbol and expiry. 144 | **The lib handles that for you** & parses the symbol accordingly. 145 | - An example of the corrected polygon symbol could be ``XY1221015C00234000``. Notice the extra 1 after ``XY`` and 146 | before expiry ``221015``. The library would parse this symbol as ``XY221015C00234000``. The number could be any 147 | number according to a response from polygon support team. 148 | 149 | **NOTE:** The parse function takes another optional argument, ``output_format``, defaulting to ``'object'``. 150 | Here is what it is for and how you can use it to your advantage. 151 | 152 | Output Format 153 | The library provides 3 possible output formats when getting parsed info from an option symbol. They are 154 | 155 | - An object of class :class:`polygon.options.options.OptionSymbol` (Default). You can access info as 156 | 157 | * ``obj.strike_price`` 158 | * ``obj.underlying_symbol`` 159 | * ``obj.expiry`` 160 | * ``obj.call_or_put`` 161 | * ``obj.option_symbol`` 162 | 163 | - As a list having elements: ``[underlying_symbol, expiry, call_or_put, strike_price, option_symbol]`` in this fixed 164 | order 165 | - As a dict having the following keys: 166 | 167 | * ``underlying_symbol`` 168 | * ``expiry`` 169 | * ``call_or_put`` 170 | * ``strike_price`` 171 | * ``option_symbol`` 172 | 173 | 174 | Example code and output for polygon/tradier formats 175 | 176 | .. code-block:: python 177 | 178 | import polygon 179 | 180 | parsed_details1 = polygon.parse_option_symbol('AMD211205C00156000') 181 | parsed_details2 = polygon.parse_option_symbol('AMD211205C00156000', output_format=list) 182 | parsed_details3 = polygon.parse_option_symbol('AMD211205C00156000', output_format=dict) 183 | 184 | # outputs 185 | # parsed_details1 would be an object having info as attributes as described in output format sub-section above 186 | # parsed_details2 -> ['AMD', dt.date(2021, 12, 5), 'C', 156, 'AMD211205C00156000'] 187 | # parsed_details3 -> {'underlying_symbol': 'AMD', 'expiry': dt.date(2021, 12, 5), 'call_or_put': 'C', 'strike_price': 156, 'option_symbol': 'AMD211205C00156000'} 188 | 189 | The same function can be used to parse option symbols in any of the supported formats, just pass in the format you 190 | need, either as a shorthand string from the table above, or use an enum from :class:`polygon.enums.OptionSymbolFormat` 191 | 192 | - Using enums (like ``OptionSymbolFormat.POLYGON`` in example below) is a good way to ensure you only pass in 193 | correct shorthand strings. Your IDE auto completion would make your life much easier when working with enums. 194 | 195 | Example code & outputs for multiple formats 196 | 197 | .. code-block:: python 198 | 199 | import polygon 200 | 201 | parsed_details1 = polygon.parse_option_symbol('AMD211205C00156000', _format='tradier') 202 | parsed_details2 = polygon.parse_option_symbol('AMD_062822P587.56', _format='tda', output_format=list) 203 | parsed_details3 = polygon.parse_option_symbol('AB 220628P46.01', _format='trade_station', output_format=dict) 204 | 205 | # outputs 206 | # parsed_details1 would be an object having info as attributes as described in output format sub-section above 207 | # parsed_details2 -> ['AMD', dt.date(2022, 6, 28), 'P', 587.56, 'AMD_062822P587.56'] 208 | # parsed_details3 -> {'underlying_symbol': 'AB', 'expiry': dt.date(2022, 6, 28), 'call_or_put': 'P', 'strike_price': 46.01, 'option_symbol': 'AB 220628P46.01'} 209 | 210 | For those who want more control, here is how the function signature and arguments look 211 | 212 | .. autofunction:: polygon.options.options.parse_option_symbol 213 | :noindex: 214 | 215 | Converting Option Symbol Formats 216 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 217 | 218 | The function in this sub-section helps you to convert an option symbol from one format to another. So if you want to 219 | convert a polygon option symbol to TD Ameritrade symbol (say to place an order), pass the symbol in this function, 220 | specify the formats and the library will do the conversions for you. 221 | 222 | Example code and outputs 223 | 224 | .. code-block:: python 225 | 226 | import polygon 227 | 228 | symbol1 = polygon.convert_option_symbol_formats('AMD220628P00096050', from_format='polygon', to_format='tda') 229 | symbol2 = polygon.convert_option_symbol_formats('AB 220628P46.01', from_format='trade_station', to_format='polygon') 230 | symbol2 = polygon.convert_option_symbol_formats('NVDA220628C00546000', 'tradier', 'tos') 231 | 232 | # outputs 233 | # symbol1 -> AMD_062822P96.05 234 | # symbol2 -> AB220628P00046010 235 | # symbol3 -> .NVDA062822C546 236 | 237 | For those who want more control, here is how the function signature and arguments look 238 | 239 | .. autofunction:: polygon.options.options.convert_option_symbol_formats 240 | :noindex: 241 | 242 | Detecting Option Symbol Format 243 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 244 | 245 | The function in this sub-section helps you to detect the symbol format of an option symbol programmatically. The 246 | function does basic detection according to some simple rules so test well before using this in production setting. It 247 | is almost always recommended to be explicit about formats. 248 | 249 | Example code and outputs 250 | 251 | .. code-block:: python 252 | 253 | import polygon 254 | 255 | format1 = polygon.detect_option_symbol_format('AMD_062822P96.05') 256 | format2 = polygon.detect_option_symbol_format('AB220628P00046010') 257 | format3 = polygon.detect_option_symbol_format('.NVDA062822C546') 258 | format4 = polygon.detect_option_symbol_format('AB 220628P46.01') 259 | format5 = polygon.detect_option_symbol_format('AB 220628P00046045') 260 | 261 | # outputs 262 | # format1 -> 'tda' 263 | # format2 -> 'polygon' # this also means tradier since both use exact same format 264 | # format3 -> 'tos' 265 | # format4 -> 'trade_station' 266 | # format5 -> ['ibkr', 'trade_station'] 267 | 268 | For those who want more control, here is how the function signature and arguments look 269 | 270 | .. autofunction:: polygon.options.options.detect_option_symbol_format 271 | :noindex: 272 | 273 | .. _option_endpoints_header: 274 | 275 | 276 | **Endpoints:** 277 | 278 | To use any of the below method, simply call it on the client you created above. so if you named your client ``client``, 279 | you'd call the methods as ``client.get_trades`` and so on. Async methods will need to be awaited, see :ref:`async_support_header`. 280 | 281 | SMA 282 | --- 283 | 284 | Simple Moving Average. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 285 | 286 | .. automethod:: polygon.options.options.SyncOptionsClient.get_sma 287 | :noindex: 288 | 289 | EMA 290 | --- 291 | 292 | Exponential Moving Average. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 293 | 294 | .. automethod:: polygon.options.options.SyncOptionsClient.get_ema 295 | :noindex: 296 | 297 | RSI 298 | --- 299 | 300 | Relative Strength Index. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 301 | 302 | .. automethod:: polygon.options.options.SyncOptionsClient.get_rsi 303 | :noindex: 304 | 305 | MACD 306 | ---- 307 | 308 | Moving Average Convergence/Divergence. This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 309 | 310 | .. automethod:: polygon.options.options.SyncOptionsClient.get_macd 311 | :noindex: 312 | 313 | Get Trades 314 | ---------- 315 | 316 | This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 317 | 318 | .. automethod:: polygon.options.options.SyncOptionsClient.get_trades 319 | :noindex: 320 | 321 | Get Quotes 322 | ---------- 323 | 324 | This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 325 | 326 | .. automethod:: polygon.options.options.SyncOptionsClient.get_quotes 327 | :noindex: 328 | 329 | Get Last Trade 330 | -------------- 331 | 332 | .. automethod:: polygon.options.options.SyncOptionsClient.get_last_trade 333 | :noindex: 334 | 335 | Get Daily Open Close 336 | -------------------- 337 | 338 | .. automethod:: polygon.options.options.SyncOptionsClient.get_daily_open_close 339 | :noindex: 340 | 341 | Get Aggregate Bars 342 | ------------------ 343 | 344 | The library added a better aggregate function if you're looking to get data for large time frames at minute/hour granularity. 345 | 346 | (for example 15 years historical data , 1 minute candles) 347 | 348 | See :ref:`better_aggs_header` for complete details on how to use it well and control how it behaves. 349 | 350 | .. automethod:: polygon.options.options.SyncOptionsClient.get_aggregate_bars 351 | :noindex: 352 | 353 | Get Previous Close 354 | ------------------ 355 | 356 | .. automethod:: polygon.options.options.SyncOptionsClient.get_previous_close 357 | :noindex: 358 | 359 | Get Snapshot 360 | ------------ 361 | 362 | This endpoint supports pagination. Passing ``all_pages=True`` enables it. See :ref:`pagination_header` for better info 363 | 364 | .. automethod:: polygon.options.options.SyncOptionsClient.get_snapshot 365 | :noindex: 366 | -------------------------------------------------------------------------------- /docs/Getting-Started.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _getting_started_header: 3 | 4 | Getting Started 5 | =============== 6 | 7 | Welcome to ``polygon``. Read this page to quickly install and configure this library to write your first Polygon 8 | Python application. 9 | 10 | **It is highly recommended to read this page for everyone since it contains everything you need to get started with the library** 11 | 12 | You can see some examples on the `github repository `__ after you have done 13 | the initial steps. And maybe join our `Discord Server `__ while you're at it :D 14 | 15 | What you need to have 16 | --------------------- 17 | 18 | 1. A `polygon.io account `__ and your ``API key``. Find your api key on `Your Dashboard `__ 19 | #. Python version 3.6 or higher. Don't have it installed? `Install python `__ 20 | 21 | Once you have these, Proceed to the installation of the library. Skip if already done. 22 | 23 | Installing ``polygon`` 24 | ---------------------- 25 | 26 | The recommended method of installation for all users is to install using ``pip`` from PyPi. A virtual environment is highly recommended but not a necessity. 27 | 28 | run the below command in terminal (same for all OS) 29 | 30 | .. code-block:: shell 31 | 32 | pip install polygon 33 | 34 | To confirm the install worked, try importing the package as such 35 | 36 | .. code-block:: python 37 | 38 | import polygon 39 | 40 | If this doesn't throw any errors, the install worked. You may proceed to next steps now. 41 | 42 | .. _create_and_use_header: 43 | 44 | General guide for clients & functions 45 | ------------------------------------- 46 | This section would provide general guidance on the clients without going into specific endpoints as stocks or options. 47 | 48 | As you already know polygon.io has two major classes of APIs. The ``REST`` APIs and ``websockets`` streaming APIs. 49 | 50 | This library implements all of them. 51 | 52 | - For `REST HTTP endpoints `__ 53 | 54 | + Regular client is implemented for all endpoints. 55 | + Support for ``async`` client is also provided. See :ref:`async_support_header` for more. 56 | 57 | - For `websocket streaming endpoints `__ 58 | 59 | + a ``callback`` based stream client is implemented. See :ref:`callback_streaming_header` 60 | + an async based stream client is also implemented. See :ref:`async_streaming_header` 61 | 62 | Be sure to check out our special section :ref:`enums_header` for info on ``enums`` which will be used in many functions in this library to avoid passing error prone data. 63 | 64 | Functions which are standalone (not attached to client objects) are all available at the top level as ``polygon.function_name``. 65 | 66 | **A detailed description of how to use the streaming endpoints is provided in the streamer docs linked above.** 67 | 68 | Need examples? The `github repository `__ has a few you could use. 69 | 70 | **also feel free to join in our** `Discord Server `__ **to ask a question or just chat with interesting people** 71 | 72 | Creating and Using REST HTTP clients 73 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 74 | This section aims to outline the general procedure to create and use the http clients in both regular and async programming methods. 75 | 76 | First up, you'd import the library. There are many ways to import names from a library and it is highly recommended to complete fundamental python if you're not aware of them. 77 | 78 | .. code-block:: python 79 | 80 | import polygon 81 | 82 | # OR import the name you need 83 | from polygon import StocksClient 84 | 85 | # OR import the names you need 86 | from polygon import (StocksClient, ForexClient, StreamClient, build_option_symbol) 87 | 88 | Now creating a client is as simple as (using stocks and forex clients as examples here) 89 | 90 | 1. Regular client: ``stocks_client = polygon.StocksClient('API_KEY')`` 91 | #. Async client: ``forex_client = polygon.ForexClient('API_KEY', True)`` 92 | 93 | Note that It is NOT recommended to hard code your API key or other credentials into your code unless you really have a use case. 94 | Instead preferably do one of the following: 95 | 96 | 1. create a separate python file with credentials, import that file into main file and reference using variable names. 97 | #. Use environment variables. 98 | 99 | Request timeouts and limits configuration (optional) 100 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 101 | 102 | **section Only meant for advanced use cases**. For most people, default timeouts would be enough. 103 | 104 | You can also specify timeouts on requests. By default the timeout is set to 10 seconds for connection, read, write and pool timeouts. 105 | 106 | **write timeout and pool timeout are only available for async rest client (which is httpx based)**. They'll be ignored if used with normal client 107 | 108 | If you're unsure of what this implies, you probably don't need to change them. 109 | 110 | **Limits config** 111 | 112 | Only meant for async rest client (httpx based). 113 | 114 | You also have the ability to change httpx connection pool settings when you work with async based rest client. This allows you to better control 115 | the behavior of underlying httpx pool, especially in cases where you need highly concurrent async applications. 116 | Using `uvloop `__ is also a good option in those case 117 | 118 | You can change the below configs: 119 | 120 | * **max_connections**: the max number of connections in the pool. Defaults to No Limit in the lib. 121 | * **max_keepalive**: max number of keepalive connections in the pool. Defaults to 30. 122 | 123 | Example uses: 124 | 125 | .. code-block:: python 126 | 127 | # client with a custom timeout. Default is 10 seconds 128 | client = polygon.StocksClient('api_key', connect_timeout=15) 129 | 130 | # another one 131 | client = polygon.StocksClient('api_key', connect_timeout=5, read_timeout=5) 132 | 133 | # An async one now 134 | client = polygon.StocksClient('key', True, read_timeout=5, connect_timeout=15) 135 | 136 | # another async one 137 | client = polygon.StocksClient('key', True, connect_timeout=15, max_connections=200) 138 | 139 | 140 | Now that you have a client, simply call its methods to get data from the API 141 | 142 | .. code-block:: python 143 | 144 | current_price = stocks_client.get_current_price('AMD') 145 | print(f'Current price for AMD is {current_price}') 146 | 147 | 148 | **Note that you can have instances of all 5 different types of http clients together**. So you can create client for each one of the stocks, options and other APIs 149 | 150 | All the clients in the lib support context managers 151 | 152 | .. code-block:: python 153 | 154 | with polygon.StocksClient('KEY') as client: 155 | last_quote = client.get_last_quote('AMD) 156 | print(f'Last quote for AMD: {last_quote}') 157 | 158 | # OR for async 159 | async with polygon.StocksClient('key', True) as client: 160 | last_quote = await client.get_last_quote('AMD') 161 | print(last_quote) 162 | 163 | 164 | Using context managers ensures that the connections opened up to make requests are closed properly. 165 | 166 | You can manually close the connections if you're not using context managers: 167 | 168 | 1. for regular non-async: ``client.close()`` 169 | #. for async: ``await client.close()`` 170 | 171 | This is not an absolute necessity but rather a good software practice to close out resources when you don't need them. 172 | 173 | Calling the methods/functions 174 | ----------------------------- 175 | 176 | Most methods and functions have sane default values which can be customized as needed. Required parameters need to be 177 | supplied as positional arguments (which just means that the order of arguments matter when passing more than one). 178 | 179 | Some options, crypto and forex endpoints expect you to append prefixes ``O:, C:, X:`` respectively in front of tickers (on options symbols, 180 | forex pairs and crypto pairs). **the library handles this for you** so you can pass in those with or without the prefix. 181 | 182 | **Parameters which have special values are supplied as python enums**. You can however always pass in your own values 183 | but it is recommended to use enums as they mitigate the possibilities of an error. 184 | 185 | All enums are available in the module ``polygon.enums`` and can be imported the way you like. 186 | 187 | If you're still unsure about enums, see our dedicated section: :ref:`enums_header` 188 | 189 | Passing dates, datetime values or timestamps 190 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 191 | 192 | The library allows you to specify your datetime or date values as ``datetime.date``, ``datetime.datetime`` objects or as 193 | string ``YYYY-MM-DD``. Some endpoints also accept millisecond/nanosecond timestamps (docs will mention this wherever necessary) 194 | 195 | - If an endpoint accepts a timestamp, you can either pass a timestamp or a datetime or date object. The lib will do the conversions for you 196 | internally 197 | 198 | - When you pass a timestamp, library will NOT do any conversions and pass it as is. So make sure you are passing the correct timestamps. 199 | 200 | - If you pass a ``datetime`` object, and the endpoint accepts a timestamp, the lib will convert internally to a timestamp. If there is no 201 | timezone info attached to the object, ``UTC`` will be used. 202 | 203 | - If you come across situations where the returned data results are not complete or missing some values (for e.g. on aggregate bars endpoint), 204 | just pass your values as ``datetime`` values (if possible as a timestamp or with timezone information at least) 205 | 206 | - The lib makes its best efforts parsing what the supplied datetime/timestamp/date could mean in context of the relevant endpoint. The behavior is of course 207 | different between for example aggs and trades. If you want absolute control, just pass as a unix timestamp or a ``datetime`` object having timezone information 208 | 209 | Here are some **best practices when passing datetime or dates or timestamps** 210 | 211 | - If you want complete control over what's passed, pass a timestamp since epoch. The accuracy (i.e milli second or nano second) 212 | depends on the endpoint itself (mentioned in the docs of course). Default timestamp accuracy is ``ms`` 213 | - Passing ``datetime`` objects is also a good way to pass absolute values and is recommended. Even better if the object has timezone info. 214 | If no timezone info is provided, lib assumes UTC. It doesn't make a difference in most cases, but should be taken care of in fine tuning and accurate filtering scenarios 215 | 216 | 217 | Return Values 218 | ------------- 219 | 220 | Most methods would by default return a dictionary/list object containing the data from the API. If you need the underlying response object 221 | you need to pass in ``raw_response=True`` in the function call. It might be useful for checking ``status_code`` or inspecting ``headers``. 222 | 223 | For 99% users, the default should be good enough. 224 | 225 | The underlying response object returned is ``requests.models.Response`` for regular client and ``httpx.Response`` for async client. 226 | Using ``.json()`` on the response object gets you the data dict/list 227 | 228 | Once you have the response, you can utilize the data in any way that you like. You can push it to a database, 229 | `create a pandas dataframe `__, save it to a file 230 | or process it the way you like. 231 | 232 | Every method's documentation contains a direct link to the corresponding official documentation page where you can see what the keys in the response mean. 233 | 234 | .. _pagination_header: 235 | 236 | Pagination Support 237 | ------------------ 238 | 239 | So quite a few endpoints implement pagination for large responses and hence the library implements a very simple and convenient way to 240 | get all the pages and merge responses internally to give you a single response with all the results in it. 241 | 242 | The behavior is exactly the same for ALL endpoints which support pagination (docs will mention when an endpoint is paginated). Knowing 243 | the functions and parameters once is enough for all endpoints. 244 | 245 | **To enable pagination** 246 | 247 | you simply need to pass ``all_pages=True`` to enable pagination for the concerned endpoint. You can also pass ``max_pages=an integer`` to limit how many pages the lib will fetch 248 | internally. The default behavior is to fetch all available pages. 249 | 250 | You can pass ``verbose=True`` if you want to know what's happening behind the scenes. It will print out status 251 | messages about the pagination process. 252 | 253 | You can further customize what kinda output you want to get. **you have three possible options to make use of pagination abilities** in the 254 | library 255 | 256 | Get a Single Merged Response (recommended) 257 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 258 | 259 | Recommended for most users. Using this method will give you all the pages, **merged into one single response** internally for your convenience, and you will get 260 | all the results from all pages in one single list. 261 | 262 | To use, simply pass ``all_pages=True``. you can optionally provide ``max_pages`` number too to limit how many pages to get. 263 | 264 | for example, below examples will do the merging of responses internally for you 265 | 266 | .. code-block:: python 267 | 268 | # assuming client is created already 269 | 270 | # This will pull ALL available tickers from reference APIs and merge them into a single list 271 | data = client.get_tickers(market='stocks', limit=1000, all_pages=True) 272 | 273 | # This will pull up to 4 available pages of tickers from reference APIs and merge them into a 274 | # single list 275 | data = client.get_tickers(market='stocks', limit=1000, all_pages=True, max_pages=5) 276 | 277 | 278 | Get a List of all pages 279 | ~~~~~~~~~~~~~~~~~~~~~~~ 280 | 281 | Only for people who know they need it. what this method does is provide you with a list of all pages, WITHOUT merging them. so you'll basically get a list of all pages like so 282 | ``[page1_data, page2_data, page3_data]``. 283 | 284 | By default each page element is the corresponding page's data itself. You can also customize it to get the underlying response objects (meant for advanced use cases) 285 | 286 | To enable, as usual you'd pass in ``all_pages=True``. But this time you'll ask the lib not to merge the pages using ``merge_all_pages=False``. That's it. 287 | as described above, to get underlying response objects, pass an additional ``raw_page_responses=True`` too. 288 | 289 | See examples below 290 | 291 | .. code-block:: python 292 | 293 | # assuming client is created already 294 | 295 | # will fetch all available pages, won't merge them and return a list of responses 296 | data = client.get_tickers(market='stocks', limit=1000, all_pages=True, merge_all_pages=False) 297 | 298 | # will fetch all available pages, won't merge them and return a list of response objects 299 | data = client.get_tickers(market='stocks', limit=1000, all_pages=True, merge_all_pages=False, 300 | raw_page_responses=True) 301 | 302 | # will fetch up to 5 available pages, won't merge them and return a list of responses 303 | data = client.get_tickers(market='stocks', limit=1000, all_pages=True, merge_all_pages=False, 304 | max_pages=5) 305 | 306 | Paginate Manually 307 | ~~~~~~~~~~~~~~~~~ 308 | 309 | Only meant for people who really need more manual control over pagination, yet want to make use of available functionality. 310 | 311 | Every client has a few core methods which can be used to get next or previous pages by passing in the last response you have. 312 | 313 | Note that while using these methods, you'd need to use your own mechanism to combine pages or process them. 314 | If any of these methods return False, it means no more pages are available. 315 | 316 | **Examples Use** 317 | 318 | .. code-block:: python 319 | 320 | # assuming a client is created already 321 | data = client.get_trades() 322 | 323 | next_page_of_data = client.get_next_page(data) # getting NEXT page 324 | previous_page_of_data = client.get_previous_page(data) # getting PREVIOUS page 325 | 326 | # ASYNC examples 327 | await client.get_next_page(data) 328 | await client.get_previous_page(data) 329 | 330 | # It's wise to check if the value returned is not False. 331 | 332 | **In practice, to get all pages (either next or previous), you'll need a while loop** An example: 333 | 334 | .. code-block:: python 335 | 336 | all_responses = [] 337 | 338 | response = client.get_trades_vx() # using get_trades as example. you can use it on all methods which support pagination 339 | all_responses.append(response) # using a list to store all the pages of response. You can use your own approach here. 340 | 341 | while 1: 342 | response = client.get_next_page(response) # change to get_previous_page for previous pages. 343 | 344 | if not response: 345 | break 346 | 347 | all_responses.append(response) # adding further responses to our list. you can use your own approach. 348 | 349 | print(f'all pages received. total pages: {len(all_responses)}') 350 | 351 | .. _async_support_header: 352 | 353 | Async Support for REST endpoints 354 | -------------------------------- 355 | 356 | As you saw above in the example, the clients have methods for each endpoint. The usual client is a sync client. 357 | However support for async is also provided for all the endpoints on all the clients. 358 | 359 | Here is how to make use of it (**This info is applicable to ALL rest clients**) 360 | 361 | First up, you'd create a client. Earlier you created a client by passing in just your API key. Here you'd create the client 362 | with an additional argument. 363 | 364 | so instead of something like: ``StocksClient('API_KEY')``, you'd do 365 | 366 | .. code-block:: python 367 | 368 | client = StocksClient('KEY', True) # or use_async=True for second parameter 369 | 370 | This gives you an async client. Similar to sync, you can have all 5 different clients together. You can also pass in your timeout values like you 371 | did above here too. 372 | 373 | **ALL the methods you'd use for async client have the same names as their sync counterpart names.** 374 | 375 | So if a method is named ``get_trades()`` in usual client, in async client you'd have it as ``get_trades()`` as well 376 | and this behavior is true for all methods 377 | 378 | Here is how you can use it grab the current price of a symbol 379 | 380 | .. code-block:: python 381 | 382 | import polygon 383 | 384 | async def main(): 385 | stocks_client = polygon.StocksClient('API_KEY', True) 386 | 387 | current_price = await stocks_client.get_current_price('AMD') 388 | await stocks_client.close() # close the client when you're done 389 | print(current_price) 390 | 391 | if __name__ == '__main__': 392 | import asyncio 393 | asyncio.run(main()) 394 | 395 | 396 | UVLOOP integration 397 | ------------------ 398 | 399 | (for async streamer and async rest client) 400 | 401 | unix based Operating systems only, `uvloop doesn't have windows support yet `__ 402 | 403 | If your use case demands better performance on async streamer or async based applications using rest client than what the usual ``asyncio`` has to offer, 404 | consider using `uvloop `__, a ``libuv`` based event loop which provides faster execution. 405 | 406 | Using it is very simple, install using ``pip install uvloop`` and then **at the very top of your program**, right below your imports, add: 407 | 408 | .. code-block:: python 409 | 410 | import uvloop 411 | 412 | asyncio.set_event_loop_policy(uvloop.EventLoopPolicy()) 413 | 414 | That's it. asyncio will now use uvloop's event loop policy instead of the default one. 415 | 416 | Special Points 417 | -------------- 418 | 419 | * Any method/endpoint having ``vX`` in its name is deemed experimental by polygon and its name and underlying URL path will be changed to a 420 | version number in the future. If you do use one of these, be aware of that name change which is reflected in the docs. If you find the lib 421 | doesn't have the changes reflected, let me know through any means mentioned in the help page. 422 | * You would notice some parameters having ``lt``, ``lte``, ``gt`` and ``gte`` in their names. Those parameters are supposed to be filters for 423 | ``less than``, ``less than or equal to``, ``greater than``, ``greater than or equal to`` respectively. To know more see heading **Query Filter Extensions** 424 | in `This blog post by polygon `__ 425 | To explain: imagine a parameter: ``fill_date_lt``. now the date you'll supply would be a filter for values less than the given value and hence you'd get results which have fill_date 426 | less than your specified value, which in this case is a date. 427 | * Some endpoints may not return a dictionary and instead return a ``list``. The number of such endpoints is very low. Similarly get current price returns a float/integer. 428 | I'm working towards reflecting the same in individual method's docs. 429 | * It is highly recommended to use the polygon.io documentation website's quick test functionality to play around with the endpoints. 430 | * Type hinting in function/method definitions indicate what data type does that parameter is supposed to be. If you think the type hinting is incomplete/incorrect, let me know. 431 | For example you might ses: ``cost: int`` which means this parameter ``cost`` is supposed to be an integer. ``adjusted: bool`` is another example for a boolean (either ``True`` or ``False``) 432 | * You'll notice some type hints having ``Union`` in them followed by two or more types inside a square bracket. That simply means the parameter could be of any type from that list in bracket 433 | . For example: ``price: Union[str, float, int]`` means the parameter ``price`` could be either a string, a float or an integer. You'd notice Union type hints more on return types 434 | of the functions/methods. 435 | 436 | **so far so good? Start by taking a look at the complete docs for endpoints you need. Here is a quick list** 437 | 438 | * :ref:`stocks_header` 439 | * :ref:`options_header` 440 | * :ref:`forex_and_crypto_header` 441 | * :ref:`callback_streaming_header` and :ref:`async_streaming_header` 442 | * :ref:`bulk_data_download_header` 443 | * :ref:`enums_header` 444 | -------------------------------------------------------------------------------- /polygon/streaming/streaming.py: -------------------------------------------------------------------------------- 1 | # ========================================================= # 2 | import logging 3 | import threading 4 | import time 5 | from typing import Union 6 | import websocket as ws_client 7 | from enum import Enum 8 | 9 | from polygon.streaming.constants import STREAM_CLUSTER_PREFIX_MAP 10 | 11 | # ========================================================= # 12 | 13 | 14 | HOST = "socket.polygon.io" 15 | DELAYED_HOST = "delayed.polygon.io" 16 | 17 | 18 | # ========================================================= # 19 | 20 | 21 | def get_logger(): 22 | return logging.getLogger(__name__) 23 | 24 | 25 | # ========================================================= # 26 | 27 | 28 | class StreamClient: 29 | """ 30 | These docs are not meant for general users. These are library API references. The actual docs will be 31 | available on the index page when they are prepared. 32 | 33 | Note that this is callback based stream client which is suitable for threaded/multi-processed applications. If 34 | you need to stream using an ``asyncio`` based stream client, see :ref:`async_streamer_client_interface_header`. 35 | 36 | This class implements all the websocket endpoints. Note that you should always import names from top level. 37 | e.g.: ``from polygon import StreamClient`` or ``import polygon`` (which allows you to access all names easily) 38 | 39 | Creating the client is as simple as: ``client = StreamClient('MY_API_KEY', 'other_options')`` 40 | 41 | Once you have the client, you can call its methods to subscribe/unsubscribe to streams, change handlers and 42 | process messages. All methods have sane default values and almost everything can be customized. 43 | 44 | Type Hinting tells you what data type a parameter is supposed to be. You should always use ``enums`` for most 45 | parameters to avoid supplying error prone values. 46 | 47 | Take a look at the `Official documentation `__ 48 | to get an idea of the stream, data formatting for messages and related useful stuff. 49 | """ 50 | 51 | def __init__( 52 | self, 53 | api_key: str, 54 | cluster, 55 | host=HOST, 56 | on_message=None, 57 | on_close=None, 58 | on_error=None, 59 | enable_connection_logs: bool = False, 60 | ): 61 | """ 62 | Initializes the callback function based stream client 63 | `Official Docs `__ 64 | 65 | :param api_key: Your API Key. Visit your dashboard to get yours. 66 | :param cluster: Which market/cluster to connect to. See :class:`polygon.enums.StreamCluster` for choices. 67 | NEVER connect to the same cluster again if there is an existing stream connected to it. 68 | The existing connection would be dropped and new one will be established. You can have up to 4 69 | concurrent streams connected to 4 different clusters. 70 | :param host: Host url to connect to. Default is real time. See :class:`polygon.enums.StreamHost` for choices. 71 | :param on_message: The function to be called when data is received. This is primary function you'll write to 72 | process the data from the stream. The function should accept one and only one ``arg`` 73 | (message). Default handler is :meth:`_default_on_msg`. 74 | :param on_close: The function to be called when stream is closed. Function should accept two args ( 75 | close_status_code, close_message). Default handler is :meth:`_default_on_close` 76 | :param on_error: Function to be called when an error is encountered. Function should accept one arg ( 77 | exception object). Default handler is :meth:`_default_on_error` 78 | :param enable_connection_logs: whether to print debug info related to the stream connection. 79 | Helpful for debugging. 80 | """ 81 | 82 | if enable_connection_logs: # enable connection logs if requested. 83 | ws_client.enableTrace(True) 84 | 85 | self._host, self.KEY, self._cluster = self._change_enum(host, str), api_key, self._change_enum(cluster, str) 86 | 87 | self._url, self._re, self._attempts = f"wss://{self._host}/{self._cluster}", None, 0 88 | 89 | self._subs = [] 90 | 91 | self._ping_interval, self._ping_timeout, self._ping_payload = None, None, None 92 | 93 | self._skip_utf8_validation, self._enable_connection_logs = None, enable_connection_logs 94 | 95 | self.WS = ws_client.WebSocketApp( 96 | self._url, 97 | on_message=self._default_on_msg, 98 | on_close=self._default_on_close, 99 | on_error=self._default_on_error, 100 | on_open=self._default_on_open, 101 | ) 102 | 103 | self.WS.on_close = on_close if on_close else self._default_on_close 104 | self.WS.on_error = on_error if on_error else self._default_on_error 105 | self.WS.on_message = on_message if on_message else self._default_on_msg 106 | 107 | self._auth = threading.Event() # to ensure we are logged in before sending any communication. 108 | 109 | self._run_in_thread: Union[threading.Thread, None] = None 110 | 111 | # Context managers 112 | def __enter__(self): 113 | return self 114 | 115 | def __exit__(self, exc_type, exc_val, exc_tb): 116 | self.WS.close() 117 | return 118 | 119 | def _start_stream( 120 | self, ping_interval: int = 21, ping_timeout: int = 20, ping_payload: str = "", skip_utf8_validation: bool = True 121 | ): 122 | """ 123 | Starts the Stream Event Loop. The loop is infinite and will continue to run until the stream is 124 | terminated, either manually or due to an exception. This method is for internal use only. you should always 125 | use :meth:`start_stream_thread` to start the stream. 126 | 127 | :param ping_interval: client would send a ``ping`` every specified number of seconds to server to keep 128 | connection alive. Set to 0 to disable pinging. Defaults to 21 seconds 129 | :param ping_timeout: Timeout in seconds if a ``pong`` (response to ping from server) is not received. The Stream 130 | is terminated as it is considered to be dead if no pong is received within the specified 131 | timeout. default: 20 seconds 132 | :param ping_payload: The option message to be sent with the ping. Better to leave it empty string. 133 | :param skip_utf8_validation: Whether to skip utf validation of messages. Defaults to True. Setting it to 134 | False may result in `performance downgrade 135 | `__ 137 | :return: None 138 | """ 139 | 140 | self._ping_interval, self._ping_timeout, self._ping_payload = ping_interval, ping_timeout, ping_payload 141 | 142 | self._skip_utf8_validation = skip_utf8_validation 143 | 144 | self.WS.run_forever( 145 | ping_interval=self._ping_interval, 146 | ping_timeout=self._ping_timeout, 147 | ping_payload=self._ping_payload, 148 | skip_utf8_validation=self._skip_utf8_validation, 149 | ) 150 | 151 | def start_stream_thread( 152 | self, ping_interval: int = 21, ping_timeout: int = 20, ping_payload: str = "", skip_utf8_validation: bool = True 153 | ): 154 | """ 155 | Starts the Stream. This will not block the main thread and it spawns the streamer in its own thread. 156 | 157 | :param ping_interval: client would send a ``ping`` every specified number of seconds to server to keep 158 | connection alive. Set to 0 to disable pinging. Defaults to 21 seconds 159 | :param ping_timeout: Timeout in seconds if a ``pong`` (response to ping from server) is not received. The Stream 160 | is terminated as it is considered to be dead if no pong is received within the specified 161 | timeout. default: 20 seconds 162 | :param ping_payload: The option message to be sent with the ping. Better to leave it empty string. 163 | :param skip_utf8_validation: Whether to skip utf validation of messages. Defaults to True. Setting it to 164 | False may result in `performance downgrade 165 | `__ 167 | :return: None 168 | """ 169 | 170 | try: 171 | self._run_in_thread = threading.Thread( 172 | target=self._start_stream, args=(ping_interval, ping_timeout, ping_payload, skip_utf8_validation) 173 | ) 174 | self._run_in_thread.start() 175 | 176 | except Exception as exc: 177 | print(f"error encountered: {str(exc)}") 178 | 179 | def close_stream(self, *args, **kwargs): 180 | """ 181 | Close the websocket connection. Wait for thread to finish if running. 182 | """ 183 | 184 | get_logger().info("Terminating Stream...") 185 | 186 | self.WS.close() 187 | 188 | if self._run_in_thread: 189 | self._run_in_thread.join() 190 | 191 | get_logger().info("Terminated") 192 | 193 | def _authenticate(self): 194 | """ 195 | Authenticates the client with the server using API key. Internal function, not meant to be called directly 196 | by users. 197 | 198 | :return: None 199 | """ 200 | 201 | _payload = '{"action":"auth","params":"%s"}' % self.KEY # f-strings were trippin' here. 202 | 203 | self.WS.send(_payload) 204 | 205 | time.sleep(1) 206 | 207 | self._auth.set() 208 | 209 | def _modify_sub(self, symbols=None, action="subscribe", _prefix="T.", force_uppercase_symbols: bool = True): 210 | """ 211 | Internal Function to send subscribe or unsubscribe requests to websocket. You should prefer using the 212 | corresponding methods to subscribe or unsubscribe to stream. 213 | 214 | :param symbols: The list of symbols to apply the actions to. 215 | :param action: Defaults to subscribe which subscribes to requested stream. Change to unsubscribe to remove an 216 | existing subscription. 217 | :param _prefix: prefix of the stream service. See :class:`polygon.enums.StreamServicePrefix` for choices. 218 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 219 | :return: None 220 | """ 221 | 222 | if symbols in [None, [], "all"]: 223 | symbols = _prefix + "*" 224 | 225 | elif isinstance(symbols, str): 226 | pass 227 | 228 | else: 229 | if force_uppercase_symbols: 230 | symbols = [x.upper() for x in symbols] 231 | 232 | if self._cluster in ["stocks", "forex", "crypto"]: # These do not require a symbol prefix 233 | symbols = ",".join([_prefix + symbol for symbol in symbols]) 234 | else: 235 | cluster_prefix = STREAM_CLUSTER_PREFIX_MAP[self._cluster] 236 | symbols = ",".join([f"{_prefix}{ensure_prefix(symbol, _prefix=cluster_prefix)}" for symbol in symbols]) 237 | 238 | self._subs.append((symbols, action)) 239 | _payload = '{"action":"%s", "params":"%s"}' % (action.lower(), symbols) 240 | 241 | try: 242 | # Ensuring we are logged in and the socket is open to receive subscription messages 243 | self._auth.wait() 244 | 245 | self.WS.send(_payload) 246 | 247 | except ws_client._exceptions.WebSocketConnectionClosedException: 248 | get_logger().error("Login Failed. Please recheck your API key and try again.") 249 | return 250 | 251 | except Exception: 252 | raise 253 | 254 | # COMMON Streams 255 | def subscribe_fair_market_value(self, symbols: list = None, force_uppercase_symbols: bool = True): 256 | """ 257 | Stream real-time Fair Market Value for given symbols. 258 | This method can be used to subscribe to any asset classes between stocks, options, crypto and forex. 259 | 260 | :param symbols: A list of symbols. Defaults to ALL symbols using `*` notation. 261 | You can pass in the symbols with or without their class prefix (O:, I:) 262 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 263 | :return: None 264 | """ 265 | 266 | _prefix = "FMV." 267 | 268 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 269 | 270 | def unsubscribe_fair_market_value(self, symbols: list = None): 271 | """ 272 | Stream real-time Fair Market Value for given symbols 273 | This method can be used to unsubscribe from any asset classes between stocks, options, crypto and forex. 274 | 275 | :param symbols: A list of symbols. Defaults to ALL symbols using `*` notation. 276 | You can pass in the symbols with or without their class prefix (O:, I:) 277 | :return: None 278 | """ 279 | 280 | _prefix = "FMV." 281 | 282 | self._modify_sub(symbols, "unsubscribe", _prefix) 283 | 284 | # STOCKS Streams 285 | def subscribe_stock_trades(self, symbols: list = None, force_uppercase_symbols: bool = True): 286 | """ 287 | Stream real-time trades for given stock ticker symbol(s). 288 | 289 | :param symbols: A list of tickers. Default is ``*`` which subscribes to ALL tickers in the market 290 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 291 | :return: None 292 | """ 293 | 294 | _prefix = "T." 295 | 296 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 297 | 298 | def unsubscribe_stock_trades(self, symbols: list = None): 299 | """Unsubscribe from the stream service for the symbols specified. Defaults to all symbols.""" 300 | 301 | _prefix = "T." 302 | 303 | self._modify_sub(symbols, "unsubscribe", _prefix) 304 | 305 | def subscribe_stock_quotes(self, symbols: list = None, force_uppercase_symbols: bool = True): 306 | """ 307 | Stream real-time Quotes for given stock ticker symbol(s). 308 | 309 | :param symbols: A list of tickers. Default is * which subscribes to ALL tickers in the market 310 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 311 | :return: None 312 | """ 313 | 314 | _prefix = "Q." 315 | 316 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 317 | 318 | def unsubscribe_stock_quotes(self, symbols: list = None): 319 | """Unsubscribe from the stream service for the symbols specified. Defaults to all symbols.""" 320 | 321 | _prefix = "Q." 322 | 323 | self._modify_sub(symbols, "unsubscribe", _prefix) 324 | 325 | def subscribe_stock_minute_aggregates(self, symbols: list = None, force_uppercase_symbols: bool = True): 326 | """ 327 | Stream real-time minute aggregates for given stock ticker symbol(s). 328 | 329 | :param symbols: A list of tickers. Default is * which subscribes to ALL tickers in the market 330 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 331 | :return: None 332 | """ 333 | 334 | _prefix = "AM." 335 | 336 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 337 | 338 | def unsubscribe_stock_minute_aggregates(self, symbols: list = None): 339 | """Unsubscribe from the stream service for the symbols specified. Defaults to all symbols.""" 340 | 341 | _prefix = "AM." 342 | 343 | self._modify_sub(symbols, "unsubscribe", _prefix) 344 | 345 | def subscribe_stock_second_aggregates(self, symbols: list = None, force_uppercase_symbols: bool = True): 346 | """ 347 | Stream real-time second aggregates for given stock ticker symbol(s). 348 | 349 | :param symbols: A list of tickers. Default is * which subscribes to ALL tickers in the market 350 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 351 | :return: None 352 | """ 353 | 354 | _prefix = "A." 355 | 356 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 357 | 358 | def unsubscribe_stock_second_aggregates(self, symbols: list = None): 359 | """Unsubscribe from the stream service for the symbols specified. Defaults to all symbols.""" 360 | 361 | _prefix = "A." 362 | 363 | self._modify_sub(symbols, "unsubscribe", _prefix) 364 | 365 | def subscribe_stock_limit_up_limit_down(self, symbols: list = None, force_uppercase_symbols: bool = True): 366 | """ 367 | Stream real-time LULD events for given stock ticker symbol(s). 368 | 369 | :param symbols: A list of tickers. Default is * which subscribes to ALL tickers in the market 370 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 371 | :return: None 372 | """ 373 | 374 | _prefix = "LULD." 375 | 376 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 377 | 378 | def unsubscribe_stock_limit_up_limit_down(self, symbols: list = None): 379 | """Unsubscribe from the stream service for the symbols specified. Defaults to all symbols.""" 380 | 381 | _prefix = "LULD." 382 | 383 | self._modify_sub(symbols, "unsubscribe", _prefix) 384 | 385 | def subscribe_stock_imbalances(self, symbols: list = None, force_uppercase_symbols: bool = True): 386 | """ 387 | Stream real-time Imbalance Events for given stock ticker symbol(s). 388 | 389 | :param symbols: A list of tickers. Default is * which subscribes to ALL tickers in the market 390 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 391 | :return: None 392 | """ 393 | 394 | _prefix = "NOI." 395 | 396 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 397 | 398 | def unsubscribe_stock_imbalances(self, symbols: list = None): 399 | """Unsubscribe from the stream service for the symbols specified. Defaults to all symbols.""" 400 | 401 | _prefix = "NOI." 402 | 403 | self._modify_sub(symbols, "unsubscribe", _prefix) 404 | 405 | # OPTIONS Streams 406 | def subscribe_option_trades(self, symbols: list = None, force_uppercase_symbols: bool = True): 407 | """ 408 | Stream real-time Options Trades for given Options contract. 409 | 410 | :param symbols: A list of symbols. Default is * which subscribes to ALL symbols in the market. you can pass 411 | **with or without** the prefix ``O:`` 412 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 413 | :return: None 414 | """ 415 | 416 | _prefix = "T." 417 | 418 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 419 | 420 | def unsubscribe_option_trades(self, symbols: list = None): 421 | """ 422 | Unsubscribe real-time Options Trades for given Options contract. 423 | 424 | :param symbols: A list of symbols. Default is * which subscribes to ALL symbols in the market. you can pass 425 | **with or without** the prefix ``O:`` 426 | :return: None 427 | """ 428 | 429 | _prefix = "T." 430 | 431 | self._modify_sub(symbols, "unsubscribe", _prefix) 432 | 433 | def subscribe_option_quotes(self, symbols: list = None, force_uppercase_symbols: bool = True): 434 | """ 435 | Stream real-time Options Quotes for given Options contract. 436 | 437 | :param symbols: A list of symbols. Default is * which subscribes to ALL symbols in the market. you can pass 438 | **with or without** the prefix ``O:`` 439 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 440 | :return: None 441 | """ 442 | 443 | _prefix = "Q." 444 | 445 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 446 | 447 | def unsubscribe_option_quotes(self, symbols: list = None): 448 | """ 449 | Unsubscribe real-time Options Quotes for given Options contract. 450 | 451 | :param symbols: A list of symbols. Default is * which subscribes to ALL symbols in the market. you can pass 452 | **with or without** the prefix ``O:`` 453 | :return: None 454 | """ 455 | 456 | _prefix = "Q." 457 | 458 | self._modify_sub(symbols, "unsubscribe", _prefix) 459 | 460 | def subscribe_option_minute_aggregates(self, symbols: list = None, force_uppercase_symbols: bool = True): 461 | """ 462 | Stream real-time Options Minute Aggregates for given Options contract(s). 463 | 464 | :param symbols: A list of symbols. Default is * which subscribes to ALL tickers in the market. you can pass 465 | **with or without** the prefix ``O:`` 466 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 467 | :return: None 468 | """ 469 | 470 | _prefix = "AM." 471 | 472 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 473 | 474 | def unsubscribe_option_minute_aggregates(self, symbols: list = None): 475 | """ 476 | Unsubscribe real-time Options Minute aggregates for given Options contract. 477 | 478 | :param symbols: A list of symbols. Default is * which subscribes to ALL symbols in the market. you can pass 479 | **with or without** the prefix ``O:`` 480 | :return: None 481 | """ 482 | 483 | _prefix = "AM." 484 | 485 | self._modify_sub(symbols, "unsubscribe", _prefix) 486 | 487 | def subscribe_option_second_aggregates(self, symbols: list = None, force_uppercase_symbols: bool = True): 488 | """ 489 | Stream real-time Options Second Aggregates for given Options contract(s). 490 | 491 | :param symbols: A list of symbols. Default is * which subscribes to ALL tickers in the market. you can pass 492 | **with or without** the prefix ``O:`` 493 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 494 | :return: None 495 | """ 496 | 497 | _prefix = "A." 498 | 499 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 500 | 501 | def unsubscribe_option_second_aggregates(self, symbols: list = None): 502 | """ 503 | Unsubscribe real-time Options Second Aggregates for given Options contract. 504 | 505 | :param symbols: A list of symbols. Default is * which subscribes to ALL symbols in the market. you can pass 506 | **with or without** the prefix ``O:`` 507 | :return: None 508 | """ 509 | 510 | _prefix = "A." 511 | 512 | self._modify_sub(symbols, "unsubscribe", _prefix) 513 | 514 | # FOREX Streams 515 | def subscribe_forex_quotes(self, symbols: list = None, force_uppercase_symbols: bool = True): 516 | """ 517 | Stream real-time forex quotes for given forex pair(s). 518 | 519 | :param symbols: A list of forex tickers. Default is * which subscribes to ALL tickers in the market. 520 | each Ticker must be in format: ``from/to``. For example: ``USD/CNH``. 521 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 522 | :return: None 523 | """ 524 | 525 | _prefix = "C." 526 | 527 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 528 | 529 | def unsubscribe_forex_quotes(self, symbols: list = None): 530 | """ 531 | Unsubscribe from the stream service for the symbols specified. Defaults to all symbols. 532 | 533 | :param symbols: A list of forex tickers. Default is * which unsubscribes to ALL tickers in the market. 534 | each Ticker must be in format: ``from/to``. For example: ``USD/CNH``. 535 | """ 536 | 537 | _prefix = "C." 538 | 539 | self._modify_sub(symbols, "unsubscribe", _prefix) 540 | 541 | def subscribe_forex_minute_aggregates(self, symbols: list = None, force_uppercase_symbols: bool = True): 542 | """ 543 | Stream real-time forex Minute Aggregates for given forex pair(s). 544 | 545 | :param symbols: A list of forex tickers. Default is * which subscribes to ALL tickers in the market. 546 | each Ticker must be in format: ``from/to``. For example: ``USD/CNH``. 547 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 548 | :return: None 549 | """ 550 | 551 | _prefix = "CA." 552 | 553 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 554 | 555 | def unsubscribe_forex_minute_aggregates(self, symbols: list = None): 556 | """ 557 | Unsubscribe from the stream service for the symbols specified. Defaults to all symbols. 558 | 559 | :param symbols: A list of forex tickers. Default is * which subscribes to ALL tickers in the market. 560 | each Ticker must be in format: ``from/to``. For example: ``USD/CNH``. 561 | """ 562 | 563 | _prefix = "CA." 564 | 565 | self._modify_sub(symbols, "unsubscribe", _prefix) 566 | 567 | def subscribe_forex_second_aggregates(self, symbols: list = None, force_uppercase_symbols: bool = True): 568 | """ 569 | Stream real-time forex Second Aggregates for given forex pair(s). 570 | 571 | :param symbols: A list of forex tickers. Default is * which subscribes to ALL tickers in the market. 572 | each Ticker must be in format: ``from/to``. For example, ``USD/CNH``. 573 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 574 | :return: None 575 | """ 576 | 577 | _prefix = "CAS." 578 | 579 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 580 | 581 | def unsubscribe_forex_second_aggregates(self, symbols: list = None): 582 | """ 583 | Unsubscribe from the stream service for the symbols specified. Defaults to all symbols. 584 | 585 | :param symbols: A list of forex tickers. Default is * which subscribes to ALL tickers in the market. 586 | each Ticker must be in format: ``from/to``. For example, ``USD/CNH``. 587 | """ 588 | 589 | _prefix = "CAS." 590 | 591 | self._modify_sub(symbols, "unsubscribe", _prefix) 592 | 593 | # CRYPTO Streams 594 | def subscribe_crypto_trades(self, symbols: list = None, force_uppercase_symbols: bool = True): 595 | """ 596 | Stream real-time Trades for given cryptocurrency pair(s). 597 | 598 | :param symbols: A list of Crypto tickers. Default is * which subscribes to ALL tickers in the market. 599 | each Ticker must be in format: ``from-to``. For example: ``BTC-USD``. you can pass symbols 600 | with or without the prefix ``X:`` 601 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 602 | :return: None 603 | """ 604 | 605 | _prefix = "XT." 606 | 607 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 608 | 609 | def unsubscribe_crypto_trades(self, symbols: list = None): 610 | """ 611 | Unsubscribe real-time trades for given cryptocurrency pair(s). 612 | 613 | :param symbols: A list of Crypto tickers. Default is * which subscribes to ALL tickers in the market. 614 | each Ticker must be in format: ``from-to``. For example: ``BTC-USD``. you can pass symbols 615 | with or without the prefix ``X:`` 616 | :return: None 617 | """ 618 | 619 | _prefix = "XT." 620 | 621 | self._modify_sub(symbols, "unsubscribe", _prefix) 622 | 623 | def subscribe_crypto_quotes(self, symbols: list = None, force_uppercase_symbols: bool = True): 624 | """ 625 | Stream real-time Quotes for given cryptocurrency pair(s). 626 | 627 | :param symbols: A list of Crypto tickers. Default is * which subscribes to ALL tickers in the market. 628 | each Ticker must be in format: ``from-to``. For example: ``BTC-USD``. you can pass symbols 629 | with or without the prefix ``X:`` 630 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 631 | :return: None 632 | """ 633 | 634 | _prefix = "XQ." 635 | 636 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 637 | 638 | def unsubscribe_crypto_quotes(self, symbols: list = None): 639 | """ 640 | Unsubscribe real-time quotes for given cryptocurrency pair(s). 641 | 642 | :param symbols: A list of Crypto tickers. Default is * which subscribes to ALL tickers in the market. 643 | each Ticker must be in format: ``from-to``. For example: ``BTC-USD``. you can pass symbols 644 | with or without the prefix ``X:`` 645 | :return: None 646 | """ 647 | 648 | _prefix = "XQ." 649 | 650 | self._modify_sub(symbols, "unsubscribe", _prefix) 651 | 652 | def subscribe_crypto_minute_aggregates(self, symbols: list = None, force_uppercase_symbols: bool = True): 653 | """ 654 | Stream real-time Minute Aggregates for given cryptocurrency pair(s). 655 | 656 | :param symbols: A list of Crypto tickers. Default is * which subscribes to ALL tickers in the market. 657 | each Ticker must be in format: ``from-to``. For example: ``BTC-USD``. you can pass symbols 658 | with or without the prefix ``X:`` 659 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 660 | :return: None 661 | """ 662 | 663 | _prefix = "XA." 664 | 665 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 666 | 667 | def unsubscribe_crypto_minute_aggregates(self, symbols: list = None): 668 | """ 669 | Unsubscribe real-time minute aggregates for given cryptocurrency pair(s). 670 | 671 | :param symbols: A list of Crypto tickers. Default is * which subscribes to ALL tickers in the market. 672 | each Ticker must be in format: ``from-to``. For example: ``BTC-USD``. you can pass symbols 673 | with or without the prefix ``X:`` 674 | :return: None 675 | """ 676 | 677 | _prefix = "XA." 678 | 679 | self._modify_sub(symbols, "unsubscribe", _prefix) 680 | 681 | def subscribe_crypto_second_aggregates(self, symbols: list = None, force_uppercase_symbols: bool = True): 682 | """ 683 | Stream real-time Second Aggregates for given cryptocurrency pair(s). 684 | 685 | :param symbols: A list of Crypto tickers. Default is * which subscribes to ALL tickers in the market. 686 | each Ticker must be in format: ``from-to``. For example: ``BTC-USD``. you can pass symbols 687 | with or without the prefix ``X:`` 688 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 689 | :return: None 690 | """ 691 | 692 | _prefix = "XAS." 693 | 694 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 695 | 696 | def unsubscribe_crypto_second_aggregates(self, symbols: list = None): 697 | """ 698 | Unsubscribe real-time Second aggregates for given cryptocurrency pair(s). 699 | 700 | :param symbols: A list of Crypto tickers. Default is * which subscribes to ALL tickers in the market. 701 | each Ticker must be in format: ``from-to``. For example: ``BTC-USD``. you can pass symbols 702 | with or without the prefix ``X:`` 703 | :return: None 704 | """ 705 | 706 | _prefix = "XAS." 707 | 708 | self._modify_sub(symbols, "unsubscribe", _prefix) 709 | 710 | def subscribe_crypto_level2_book(self, symbols: list = None, force_uppercase_symbols: bool = True): 711 | """ 712 | Stream real-time level 2 book data for given cryptocurrency pair(s). 713 | 714 | :param symbols: A list of Crypto tickers. Default is * which subscribes to ALL tickers in the market. 715 | each Ticker must be in format: ``from-to``. For example: ``BTC-USD``. you can pass symbols 716 | with or without the prefix ``X:`` 717 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 718 | :return: None 719 | """ 720 | 721 | _prefix = "XL2." 722 | 723 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 724 | 725 | def unsubscribe_crypto_level2_book(self, symbols: list = None): 726 | """ 727 | Unsubscribe real-time level 2 book data for given cryptocurrency pair(s). 728 | 729 | :param symbols: A list of Crypto tickers. Default is * which subscribes to ALL tickers in the market. 730 | each Ticker must be in format: ``from-to``. For example: ``BTC-USD``. you can pass symbols 731 | with or without the prefix ``X:`` 732 | :return: None 733 | """ 734 | 735 | _prefix = "XL2." 736 | 737 | self._modify_sub(symbols, "unsubscribe", _prefix) 738 | 739 | # INDICES Streams 740 | def subscribe_indices_minute_aggregates(self, symbols: list = None, force_uppercase_symbols: bool = True): 741 | """ 742 | Stream real-time minute aggregates for given index ticker symbol(s). 743 | 744 | :param symbols: A list of tickers. Default is * which subscribes to ALL tickers in the market. 745 | You can pass the symbols with or without the prefix ``I:`` 746 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 747 | :return: None 748 | """ 749 | 750 | _prefix = "AM." 751 | 752 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 753 | 754 | def unsubscribe_indices_minute_aggregates(self, symbols: list = None): 755 | """Unsubscribe from the stream service for the symbols specified. Defaults to all symbols.""" 756 | 757 | _prefix = "AM." 758 | 759 | self._modify_sub(symbols, "unsubscribe", _prefix) 760 | 761 | def subscribe_indices_second_aggregates(self, symbols: list = None, force_uppercase_symbols: bool = True): 762 | """ 763 | Stream real-time second aggregates for given index ticker symbol(s). 764 | 765 | :param symbols: A list of tickers. Default is * which subscribes to ALL tickers in the market. 766 | You can pass the symbols with or without the prefix ``I:`` 767 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 768 | :return: None 769 | """ 770 | 771 | _prefix = "A." 772 | 773 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 774 | 775 | def unsubscribe_indices_second_aggregates(self, symbols: list = None): 776 | """Unsubscribe from the stream service for the symbols specified. Defaults to all symbols.""" 777 | 778 | _prefix = "A." 779 | 780 | self._modify_sub(symbols, "unsubscribe", _prefix) 781 | 782 | def subscribe_index_value(self, symbols: list = None, force_uppercase_symbols: bool = True): 783 | """ 784 | Stream real-time Value for given index ticker symbol 785 | 786 | :param symbols: A list of symbols. Defaults to ALL symbols using `*` notation. 787 | You can pass in the symbols with or without the prefix ``I:`` 788 | :param force_uppercase_symbols: Set to ``False`` if you don't want the library to make all symbols upper case 789 | :return: None 790 | """ 791 | if self._cluster != "indices": 792 | raise ValueError(f"This method is only available on Indices stream.") 793 | 794 | _prefix = "V." 795 | 796 | self._modify_sub(symbols, "subscribe", _prefix, force_uppercase_symbols=force_uppercase_symbols) 797 | 798 | def unsubscribe_indices_value(self, symbols: list = None): 799 | """ 800 | Stream real-time Fair Market Value for given symbols 801 | 802 | :param symbols: A list of symbols. Defaults to ALL symbols using `*` notation. 803 | You can pass in the symbols with or without the prefix ``I:`` 804 | :return: None 805 | """ 806 | if self._cluster != "indices": 807 | raise ValueError(f"This method is only available on Indices stream.") 808 | 809 | _prefix = "V." 810 | 811 | self._modify_sub(symbols, "unsubscribe", _prefix) 812 | 813 | @staticmethod 814 | def _default_on_msg(_ws: ws_client.WebSocketApp, msg): 815 | """ 816 | Default handler for message processing 817 | 818 | :param msg: The message as received from the server 819 | :return: None 820 | """ 821 | 822 | print("message received:\n", str(msg)) 823 | 824 | @staticmethod 825 | def _default_on_close(_ws: ws_client.WebSocketApp, close_code, msg): 826 | """ 827 | THe default function to be called when stream is closed. 828 | 829 | :param close_code: The close code as received from server 830 | :param msg: The close message as received from server 831 | :return: 832 | """ 833 | 834 | if close_code is None: 835 | return 836 | 837 | print( 838 | f'Closed. Close Code: {close_code} || Args: {None if msg == "" else msg}\nMost common reason for ' 839 | f"stream to be closed is incorrect API key OR internet issues" 840 | ) 841 | 842 | @staticmethod 843 | def _default_on_error(_ws: ws_client.WebSocketApp, error, *args): 844 | """ 845 | Default function to be called when an error is encountered. 846 | 847 | :param error: The exception object as supplied by the handler 848 | :return: None 849 | """ 850 | 851 | print("Error Encountered:\n", str(error)) 852 | 853 | def _default_on_open(self, _ws: ws_client.WebSocketApp, *args): 854 | """ 855 | Default function to be called when stream client is initialized. Takes care of the authentication. 856 | 857 | :param args: Any args supplied by the handler 858 | :return: None 859 | """ 860 | 861 | self._authenticate() 862 | 863 | @staticmethod 864 | def _change_enum(val: Union[str, Enum, float, int], allowed_type=str): 865 | if isinstance(val, Enum): 866 | try: 867 | return val.value 868 | 869 | except AttributeError: 870 | raise ValueError( 871 | f"The value supplied: ({val}) does not match the required type: ({allowed_type}). " 872 | f"Please consider using the specified enum in the docs for this function or recheck " 873 | f"the value supplied." 874 | ) 875 | 876 | if isinstance(allowed_type, list): 877 | if type(val) in allowed_type: 878 | return val 879 | 880 | raise ValueError( 881 | f"The value supplied: ({val}) does not match the required type: ({allowed_type}). " 882 | f"Please consider using the specified enum in the docs for this function or recheck " 883 | f"the value supplied." 884 | ) 885 | 886 | if isinstance(val, allowed_type) or val is None: 887 | return val 888 | 889 | 890 | # ========================================================= # 891 | 892 | 893 | def ensure_prefix(symbol: str, _prefix: str = "O:"): 894 | """ 895 | ensuring prefixes in symbol names. to be used internally by forex, crypto and options 896 | 897 | :param symbol: the symbol to check 898 | :param _prefix: which prefix to check for. defaults to ``O:`` which is for options 899 | :return: capitalized prefixed symbol. 900 | """ 901 | 902 | if symbol.upper().startswith(_prefix) or symbol == "*": 903 | return symbol.upper() 904 | 905 | return f"{_prefix}{symbol.upper()}" 906 | 907 | 908 | # ========================================================= # 909 | 910 | 911 | if __name__ == "__main__": 912 | print("Don't You Dare Running Lib Files Directly") 913 | 914 | # ========================================================= # 915 | --------------------------------------------------------------------------------