{"id":37064838,"url":"https://github.com/obendidi/pstock","last_synced_at":"2026-01-14T07:35:00.640Z","repository":{"id":38329016,"uuid":"446075088","full_name":"obendidi/pstock","owner":"obendidi","description":"Async yahoo-finance python api with pydantic models.","archived":false,"fork":false,"pushed_at":"2023-09-07T23:52:29.000Z","size":1460,"stargazers_count":18,"open_issues_count":9,"forks_count":1,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-09-25T04:57:44.861Z","etag":null,"topics":["api","chart","finviz","httpx","pandas-dataframe","stock","stock-data","stock-market","stock-markets","stocks","stocks-prices","yahoo-finance"],"latest_commit_sha":null,"homepage":"https://obendidi.github.io/pstock/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/obendidi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2022-01-09T11:57:50.000Z","updated_at":"2025-04-21T15:10:29.000Z","dependencies_parsed_at":"2023-02-13T04:15:22.034Z","dependency_job_id":null,"html_url":"https://github.com/obendidi/pstock","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":"obendidi/python-lib-template","purl":"pkg:github/obendidi/pstock","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obendidi%2Fpstock","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obendidi%2Fpstock/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obendidi%2Fpstock/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obendidi%2Fpstock/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/obendidi","download_url":"https://codeload.github.com/obendidi/pstock/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/obendidi%2Fpstock/sbom","scorecard":{"id":700834,"data":{"date":"2025-08-11","repo":{"name":"github.com/obendidi/pstock","commit":"fff22e00506e5a819ebb0c44e18b7e4d36d28aed"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.8,"checks":[{"name":"Code-Review","score":0,"reason":"Found 1/23 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/docs.yml:1","Warn: no topLevel permission defined: .github/workflows/publish-pypi.yml:1","Warn: no topLevel permission defined: .github/workflows/test.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/docs.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/obendidi/pstock/docs.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/docs.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/obendidi/pstock/docs.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/docs.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/obendidi/pstock/docs.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/docs.yml:32: update your workflow using https://app.stepsecurity.io/secureworkflow/obendidi/pstock/docs.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/docs.yml:51: update your workflow using https://app.stepsecurity.io/secureworkflow/obendidi/pstock/docs.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish-pypi.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/obendidi/pstock/publish-pypi.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/publish-pypi.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/obendidi/pstock/publish-pypi.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/publish-pypi.yml:24: update your workflow using https://app.stepsecurity.io/secureworkflow/obendidi/pstock/publish-pypi.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/publish-pypi.yml:38: update your workflow using https://app.stepsecurity.io/secureworkflow/obendidi/pstock/publish-pypi.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:20: update your workflow using https://app.stepsecurity.io/secureworkflow/obendidi/pstock/test.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:22: update your workflow using https://app.stepsecurity.io/secureworkflow/obendidi/pstock/test.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test.yml:29: update your workflow using https://app.stepsecurity.io/secureworkflow/obendidi/pstock/test.yml/main?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:39: update your workflow using https://app.stepsecurity.io/secureworkflow/obendidi/pstock/test.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test.yml:63: update your workflow using https://app.stepsecurity.io/secureworkflow/obendidi/pstock/test.yml/main?enable=pin","Info:   0 out of   8 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   6 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 8 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"19 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: PYSEC-2024-48 / GHSA-fj7x-q9j7-g6q6","Warn: Project is vulnerable to: PYSEC-2024-230 / GHSA-248v-346w-9cwc","Warn: Project is vulnerable to: PYSEC-2022-42986 / GHSA-43fp-rhv2-5gv8","Warn: Project is vulnerable to: PYSEC-2023-135 / GHSA-xqr8-7jwr-rhp7","Warn: Project is vulnerable to: GHSA-vqfr-h8mv-ghfj","Warn: Project is vulnerable to: GHSA-h8pj-cxx2-jfg2","Warn: Project is vulnerable to: PYSEC-2024-60 / GHSA-jjg7-2v4v-x38h","Warn: Project is vulnerable to: GHSA-cpwx-vrp4-4pq7","Warn: Project is vulnerable to: GHSA-gmj6-6f8f-6699","Warn: Project is vulnerable to: GHSA-h5c8-rqwp-cp95","Warn: Project is vulnerable to: GHSA-h75v-3vvj-5mfj","Warn: Project is vulnerable to: GHSA-q2x7-8rv6-6q7h","Warn: Project is vulnerable to: PYSEC-2022-230 / GHSA-wrxv-2j5q-m38w","Warn: Project is vulnerable to: PYSEC-2022-42969","Warn: Project is vulnerable to: GHSA-mr82-8j83-vxmv","Warn: Project is vulnerable to: PYSEC-2023-117 / GHSA-mrwq-x4v8-fh7p","Warn: Project is vulnerable to: GHSA-jh85-wwv9-24hv","Warn: Project is vulnerable to: PYSEC-2024-187 / GHSA-rqc4-2hc7-8c8v","Warn: Project is vulnerable to: GHSA-jfmj-5v4g-7637"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-22T05:10:40.340Z","repository_id":38329016,"created_at":"2025-08-22T05:10:40.340Z","updated_at":"2025-08-22T05:10:40.340Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28413424,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-14T05:26:33.345Z","status":"ssl_error","status_checked_at":"2026-01-14T05:21:57.251Z","response_time":107,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","chart","finviz","httpx","pandas-dataframe","stock","stock-data","stock-market","stock-markets","stocks","stocks-prices","yahoo-finance"],"created_at":"2026-01-14T07:35:00.083Z","updated_at":"2026-01-14T07:35:00.626Z","avatar_url":"https://github.com/obendidi.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Pstock\n\n## Disclaimer\n\n**You should refer to Yahoo!'s terms of use**\n([here](https://policies.yahoo.com/us/en/yahoo/terms/product-atos/apiforydn/index.htm),\n[here](https://legal.yahoo.com/us/en/yahoo/terms/otos/index.html), and\n[here](https://policies.yahoo.com/us/en/yahoo/terms/index.htm)) **for\ndetails on your rights to use the actual data downloaded. Remember - the\nproject is intended for personal use only.**\n\n**Pstock** is an open source tool/project that is not affiliated in any way to yahoo-finance. Nothing in this project should be considered investment advice.\n\n---\n[![codecov](https://codecov.io/gh/obendidi/pstock/branch/main/graph/badge.svg?token=WU1E3ISBDK)](https://codecov.io/gh/obendidi/pstock)\n\u003ca target=\"new\" href=\"https://pypi.python.org/pypi/pstock-python\"\u003e\u003cimg border=0 src=\"https://img.shields.io/pypi/v/pstock-python.svg?maxAge=60%\" alt=\"PyPi version\"\u003e\u003c/a\u003e\n\u003ca href=\"https://pypi.org/project/pstock-python\" target=\"_blank\"\u003e\n\u003cimg src=\"https://img.shields.io/pypi/pyversions/pstock-python.svg?color=%2334D058\" alt=\"Supported Python versions\"\u003e\u003c/a\u003e\n\u003ca target=\"new\" href=\"https://pypi.python.org/pypi/pstock-python\"\u003e\u003cimg border=0 src=\"https://img.shields.io/pypi/status/pstock-python.svg?maxAge=60\" alt=\"PyPi status\"\u003e\u003c/a\u003e\n\u003ca target=\"new\" href=\"https://pypi.python.org/pypi/pstock-python\"\u003e\u003cimg border=0 src=\"https://img.shields.io/pypi/dm/pstock-python.svg?maxAge=2592000\u0026label=installs\u0026color=%2327B1FF\" alt=\"PyPi downloads\"\u003e\u003c/a\u003e\n![example workflow](https://github.com/obendidi/pstock/actions/workflows/test.yml/badge.svg)\n![example workflow](https://github.com/obendidi/pstock/actions/workflows/docs.yml/badge.svg)\n\n---\n\n**Documentation**: \u003ca href=\"https://obendidi.github.io/pstock\" target=\"_blank\"\u003ehttps://obendidi.github.io/pstock\u003c/a\u003e\n\n**Source Code**: \u003ca href=\"https://github.com/obendidi/pstock\" target=\"_blank\"\u003ehttps://github.com/obendidi/pstock\u003c/a\u003e\n\n\n- [Pstock](#pstock)\n  - [Disclaimer](#disclaimer)\n  - [Requirements](#requirements)\n  - [Installation](#installation)\n  - [Quickstart](#quickstart)\n  - [User Guide](#user-guide)\n    - [Assets](#assets)\n    - [Trends](#trends)\n    - [Earnings](#earnings)\n    - [Income Statement](#income-statement)\n    - [News](#news)\n    - [Bars (Historical price data)](#bars-historical-price-data)\n    - [BarsMulti](#barsmulti)\n  - [Sans-I/O protocol](#sans-io-protocol)\n  - [Contributors](#contributors)\n\n---\n\n**Pstock** is *yet* another python unoficial API for getting yahoo-finance data.\n\nThe key features are:\n\n- Async first\n- Data validation using pydantic\n- Fully typed, with great editor support\n- Easily extensible: Parse the yahoo-finance quote dict and extract any type of info you want.\n- Follows the Sans-IO design pattern: Use your favourite http library (sync/async) and let `pstock` parse your response to get `Assets` or `Bars`\n\n## Requirements\n\nPython 3.8+ (support for 3.6/3.7 may be added later, contributions are welcome)\n\nPstock depends mainly on:\n\n- [pydantic](https://pydantic-docs.helpmanual.io/): For data validation\n- [pandas](https://pandas.pydata.org/docs/): For structuring data in nice dataframes\n- [httpx](https://www.python-httpx.org/): For the main async IO interface\n\n## Installation\n\n\u003cdiv class=\"termy\"\u003e\n\n```console\n$ pip install pstock-python\n\n---\u003e 100%\n```\n\n\u003c/div\u003e\n\n## Quickstart\n\n- Download an asset:\n\n```Python\nimport asyncio\nfrom pstock import Asset\n\nasset = asyncio.run(Asset.get(\"TSLA\"))\nprint(asset)\n# symbol='TSLA' name='Tesla, Inc.' asset_type='EQUITY' currency='USD' latest_price=920.0 sector='Consumer Cyclical' industry='Auto Manufacturers'\n```\n\n- Download a list of assets:\n\n```Python\nimport asyncio\nfrom pstock import Assets\n\nassets = asyncio.run(Assets.get([\"TSLA\", \"AAPL\", \"GME\"]))\nprint(assets)\n# __root__=[Asset(symbol='TSLA', name='Tesla, Inc.', asset_type='EQUITY', currency='USD', latest_price=918.97, sector='Consumer Cyclical', industry='Auto Manufacturers'), Asset(symbol='AAPL', name='Apple Inc.', asset_type='EQUITY', currency='USD', latest_price=172.345, sector='Technology', industry='Consumer Electronics'), Asset(symbol='GME', name='GameStop Corp.', asset_type='EQUITY', currency='USD', latest_price=125.0, sector='Consumer Cyclical', industry='Specialty Retail')]\n\nprint(assets[0])\n# Asset(symbol='TSLA', name='Tesla, Inc.', asset_type='EQUITY', currency='USD', latest_price=918.97, sector='Consumer Cyclical', industry='Auto Manufacturers')\n\nprint(assets.df)\n                  name asset_type currency  ...                                           earnings                                             trends                                   income_statement\nsymbol                                      ...\nAAPL        Apple Inc.     EQUITY      USD  ...  [{'quarter': '1Q2021', 'estimate': 0.99, 'actu...  [{'date': 2021-11-17, 'strong_buy': 13, 'buy':...  [{'date': 2021-09-25, 'ebit': 108949000000.0, ...\nGME     GameStop Corp.     EQUITY      USD  ...  [{'quarter': '1Q2021', 'estimate': 1.35, 'actu...  [{'date': 2021-11-17, 'strong_buy': 2, 'buy': ...  [{'date': 2021-01-30, 'ebit': -249300000.0, 't...\nTSLA       Tesla, Inc.     EQUITY      USD  ...  [{'quarter': '1Q2021', 'estimate': 0.79, 'actu...  [{'date': 2021-11-17, 'strong_buy': 4, 'buy': ...  [{'date': 2021-12-31, 'ebit': 6523000000.0, 't...\n```\n\n- Download historical bars:\n\n```Python\nimport asyncio\nfrom pstock import Bars\n\nbars = asyncio.run(Bars.get(\"TSLA\"))\nprint(bars)\n# __root__=[Bar(date=datetime.datetime(2010, 7, 1, 4, 0, tzinfo=datetime.timezone.utc), open=5.0, high=5.184000015258789, low=2.996000051498413, close=3.98799991607666, adj_close=3.98799991607666, volume=322879000.0, interval=Duration(months=1)), Bar(date=datetime.datetime(2010, 8, 1, 4, 0, tzinfo=datetime.timezone.utc), open=4.099999904632568, high=4.435999870300293, low=3.4779999256134033, close=3.8959999084472656, adj_close=3.8959999084472656, volume=75191000.0, interval=Duration(months=1)), Bar(date=datetime.datetime(2010, 9, 1, 4, 0, tzinfo=datetime.timezone.utc), open=3.9240000247955322, high=4.631999969482422, low=3.9000000953674316, close=4.081999778747559, adj_close=4.081999778747559, volume=90229500.0, interval=Duration(months=1)), Bar(date=datetime.datetime(2010, 10, 1, 4, 0, tzinfo=datetime.timezone.utc), open=4.138000011444092, high=4.374000072479248, low=4.0, close=4.368000030517578, adj_close=4.368000030517578, volume=32739000.0, interval=Duration(months=1)), ....]\n\nprint(bars.df)\n                   open         high         low        close    adj_close       volume interval\ndate\n2010-07-01     5.000000     5.184000    2.996000     3.988000     3.988000  322879000.0  30 days\n2010-08-01     4.100000     4.436000    3.478000     3.896000     3.896000   75191000.0  30 days\n2010-09-01     3.924000     4.632000    3.900000     4.082000     4.082000   90229500.0  30 days\n2010-10-01     4.138000     4.374000    4.000000     4.368000     4.368000   32739000.0  30 days\n2010-11-01     4.388000     7.200000    4.210000     7.066000     7.066000  141575500.0  30 days\n...                 ...          ...         ...          ...          ...          ...      ...\n2021-11-01  1145.000000  1243.489990  978.599976  1144.760010  1144.760010  648671800.0  30 days\n2021-12-01  1160.699951  1172.839966  886.119995  1056.780029  1056.780029  509945100.0  30 days\n2022-01-01  1147.750000  1208.000000  792.010010   936.719971   936.719971  638471400.0  30 days\n2022-02-01   935.210022   947.770020  850.700012   875.760010   875.760010  223112600.0  30 days\n2022-02-15   900.000000   923.000000  893.377380   922.429993   922.429993   19085243.0  30 days\n\n[141 rows x 7 columns]\n```\n\n- Download stock news:\n\n```Python\nimport asyncio\nfrom pstock import News\n\nnews = asyncio.run(News.get(\"TSLA\"))\nprint(news.df)\n                                                                       title                                            url                                            summary\ndate\n2022-02-15 12:11:46+00:00  Retail investor: 'I'm being careful just in ca...  https://finance.yahoo.com/news/retail-investor...  Some retail investors are being more cautious ...\n2022-02-15 12:23:00+00:00  Tesla’s Elon Musk Gave Away $5.7 Billion. But ...  https://finance.yahoo.com/m/d342cd56-d5bb-3957...  Tesla CEO Elon Musk gave away more than 5 mill...\n2022-02-15 13:07:02+00:00                      Company News for Feb 15, 2022  https://finance.yahoo.com/news/company-news-fe...    Companies In The News Are: IFS, OLK, THS, TSLA.\n....\n2022-02-15 19:23:43+00:00  Australia's Syrah Resources to expand Louisian...  https://finance.yahoo.com/news/australias-syra...  Australian industrial materials firm Syrah Res...\n2022-02-15 20:31:30+00:00       Biggest Companies in the World by Market Cap  https://finance.yahoo.com/m/8aead0a5-ef35-3d90...  The world's biggest companies by market cap op...\n```\n\n## User Guide\n\n### Assets\n\nAn `Asset` in `pstock` terms is any ticker symbol supported by yahoo-finance. If the asset exists in yahoo-finance, you should be able to get it's quote summary  using `pstock`.\n\n```Python\nimport asyncio\nfrom pstock import Asset\n\nasset = asyncio.run(Asset.get(\"TSLA\"))\nprint(asset)\n# symbol='TSLA' name='Tesla, Inc.' asset_type='EQUITY' currency='USD' latest_price=920.0 sector='Consumer Cyclical' industry='Auto Manufacturers'\n```\n\nAn `Asset` will always have a:\n\n- `symbol`: The ticker symbol of the asset\n- `name`: The long/short name of the asset (depending on which is found, the long name takes priority)\n- `asset_type`: Type of the asset, can be one of: `EQUITY`, `CURRENCY`, `CRYPTOCURRENCY`, `ETF`, `FUTURE`, `INDEX`\n- `currency`: Currency of the asset, `USD` for US stocks\n- `latest_price`: Latest price of the asset known by yahoo-finance, takes into account the pre-post market prices. Can be `numpy.nan` if no proce data is found.\n\n\u003e _Note: if an `asset_type` exists in yahoo-finance but is not one of the above, feel free to open an issue or PR. In the meantime you can subclass the `Asset` object and override the type of `asset_type` and add the missing asset type_\n\nThe other fields are optional and can be filled depending on the `asset_type`, currently there are only fields for the `EQUITY` (stocks) asset_type:\n\n- `sector`\n- `industry`\n- [trends](#trends)\n- [earnings](#earnings)\n- [income_statement](#income-statement)\n\nIn addition to getting data about a single `Asset`, there is also the possibily to query multiple assets at the same time using `Assets`. The main benefit is that it provides the ability to directly convert the resulting list of assets into a pandas dataframe.\n\n```Python\nimport asyncio\nfrom pstock import Asset\n\nassets = asyncio.run(Assets.get([\"TSLA\", \"AAPL\", \"GME\"]))\n\nprint(assets.df)\n                  name asset_type currency  ...                                           earnings                                             trends                                   income_statement\nsymbol                                      ...\nAAPL        Apple Inc.     EQUITY      USD  ...  [{'quarter': '1Q2021', 'estimate': 0.99, 'actu...  [{'date': 2021-11-17, 'strong_buy': 13, 'buy':...  [{'date': 2021-09-25, 'ebit': 108949000000.0, ...\nGME     GameStop Corp.     EQUITY      USD  ...  [{'quarter': '1Q2021', 'estimate': 1.35, 'actu...  [{'date': 2021-11-17, 'strong_buy': 2, 'buy': ...  [{'date': 2021-01-30, 'ebit': -249300000.0, 't...\nTSLA       Tesla, Inc.     EQUITY      USD  ...  [{'quarter': '1Q2021', 'estimate': 0.79, 'actu...  [{'date': 2021-11-17, 'strong_buy': 4, 'buy': ...  [{'date': 2021-12-31, 'ebit': 6523000000.0, 't...\n```\n\n\u003e _Note 1: `Assets` is also a pydantic model that will validate data that it pulls from yahoo-finance._\n\n\u003e _Note 2: The generated pandas Dataframe is cached into a private `._df` attribute and is computed only the first time it is accessed via the property `.df`._\n\n\u003e _Note 3: Most if not all data objects in `pstock` have a `.df` property, and it's the recommended way to view and manipulate data when possible._\n\n\u003e _Note 4: `Assets`, `Bars`, `Earnings`, `News`, ... can also be iterated over and support indexing and behave like a `typing.List[Asset]`, `typing.List[Bar]`, ..._\n### Trends\n\nThere are 2 ways to get the trends of a symbol.\n\n- via `Asset`:\n\n```Python\nimport asyncio\nfrom pstock import Asset\n\nasset = asyncio.run(Asset.get(\"TSLA\"))\nprint(asset.trends.df)\n\n            strong_buy  buy  hold  sell  strong_sell  score recomendation\ndate\n2021-11-17           4    4     8     6            0   2.73          HOLD\n2021-12-17          11    6    13     6            0   2.39           BUY\n2022-01-16          11    6    13     6            0   2.39           BUY\n2022-02-15           4    4     8     6            0   2.73          HOLD\n```\n\n- Directly via `Trends`\n\n```Python\nimport asyncio\nfrom pstock import Trends\n\ntrends = asyncio.run(Trends.get(\"TSLA\"))\nprint(trends.df)\n\n            strong_buy  buy  hold  sell  strong_sell  score recomendation\ndate\n2021-11-17           4    4     8     6            0   2.73          HOLD\n2021-12-17          11    6    13     6            0   2.39           BUY\n2022-01-16          11    6    13     6            0   2.39           BUY\n2022-02-15           4    4     8     6            0   2.73          HOLD\n```\n\n### Earnings\n\nThere are 2 ways to get the earnings of a symbol.\n\n- via `Asset`:\n\n```Python\nimport asyncio\nfrom pstock import Asset\n\nasset = asyncio.run(Asset.get(\"TSLA\"))\nprint(asset.earnings.df)\n\n         estimate  actual status       revenue      earnings\nquarter\n1Q2021       0.79    0.93   Beat  1.038900e+10  4.380000e+08\n2Q2021       0.98    1.45   Beat  1.195800e+10  1.142000e+09\n3Q2021       1.59    1.86   Beat  1.375700e+10  1.618000e+09\n4Q2021       2.37    2.54   Beat  1.771900e+10  2.321000e+09\n1Q2022       2.25     NaN   None           NaN           NaN\n```\n\n- Directly via `Earnings`\n\n```Python\nimport asyncio\nfrom pstock import Earnings\n\nearnings = asyncio.run(Earnings.get(\"TSLA\"))\nprint(earnings.df)\n\n         estimate  actual status       revenue      earnings\nquarter\n1Q2021       0.79    0.93   Beat  1.038900e+10  4.380000e+08\n2Q2021       0.98    1.45   Beat  1.195800e+10  1.142000e+09\n3Q2021       1.59    1.86   Beat  1.375700e+10  1.618000e+09\n4Q2021       2.37    2.54   Beat  1.771900e+10  2.321000e+09\n1Q2022       2.25     NaN   None           NaN           NaN\n```\n\n\u003e _Note: The last earning have `NaN`/`None` values since we only have analysts estimates and revenue isn't reported yet. The specific earnings call date can be extracted from the `QuoteSummary`._\n\n### Income Statement\n\nThere are 2 ways to get the income statement of a symbol.\n\n\u003e _Note: The current extracted statement is very limited/minimaliste, contributions are welcome to extract more data from the `QuoteSummary`._\n\n- via `Asset`:\n\n```Python\nimport asyncio\nfrom pstock import Asset\n\nasset = asyncio.run(Asset.get(\"TSLA\"))\nprint(asset.income_statement.df)\n\n                    ebit  total_revenue  gross_profit\ndate\n2018-12-31 -2.530000e+08   2.146100e+10  4.042000e+09\n2019-12-31  8.000000e+07   2.457800e+10  4.069000e+09\n2020-12-31  1.951000e+09   3.153600e+10  6.630000e+09\n2021-12-31  6.523000e+09   5.382300e+10  1.360600e+10\n```\n\n\u003e _Note: `asset.income_statement` can be `None` for all assets that are not of type `EQUITY`._\n\n- Directly via `IncomeStatements`\n\n```Python\nimport asyncio\nfrom pstock import IncomeStatements\n\nincome_statement = asyncio.run(IncomeStatements.get(\"TSLA\"))\nprint(income_statement.df)\n\n                    ebit  total_revenue  gross_profit\ndate\n2018-12-31 -2.530000e+08   2.146100e+10  4.042000e+09\n2019-12-31  8.000000e+07   2.457800e+10  4.069000e+09\n2020-12-31  1.951000e+09   3.153600e+10  6.630000e+09\n2021-12-31  6.523000e+09   5.382300e+10  1.360600e+10\n```\n\n\u003e _Note: You can also use `QuarterlyIncomeStatements` for (as the name says) quarterly income stamenets_.\n\n### News\n\nGettings yahoo-finance news about a symbol also follows the same pattern.\n\n```Python\nimport asyncio\nfrom pstock import News\n\nnews = asyncio.run(News.get(\"TSLA\"))\nprint(news.df)\n                                                                       title                                            url                                            summary\ndate\n2022-02-15 12:11:46+00:00  Retail investor: 'I'm being careful just in ca...  https://finance.yahoo.com/news/retail-investor...  Some retail investors are being more cautious ...\n2022-02-15 12:23:00+00:00  Tesla’s Elon Musk Gave Away $5.7 Billion. But ...  https://finance.yahoo.com/m/d342cd56-d5bb-3957...  Tesla CEO Elon Musk gave away more than 5 mill...\n2022-02-15 13:07:02+00:00                      Company News for Feb 15, 2022  https://finance.yahoo.com/news/company-news-fe...    Companies In The News Are: IFS, OLK, THS, TSLA.\n....\n2022-02-15 19:23:43+00:00  Australia's Syrah Resources to expand Louisian...  https://finance.yahoo.com/news/australias-syra...  Australian industrial materials firm Syrah Res...\n2022-02-15 20:31:30+00:00       Biggest Companies in the World by Market Cap  https://finance.yahoo.com/m/8aead0a5-ef35-3d90...  The world's biggest companies by market cap op...\n```\n\n### Bars (Historical price data)\n\nA `Bar` in `pstock` is a pydantic model with the following fields:\n\n```Python\nclass Bar(BaseModel):\n    date: datetime\n    open: float\n    high: float\n    low: float\n    close: float\n    adj_close: float\n    volume: float\n    interval: timedelta\n```\n\n\u003e _Note: The `interval` is the time between bar `open` and `close`._\n\nTo get `Bars` there are a couple of arguments that can be specified:\n\n- `interval`: one of `1m`, `2m`, `5m`, `15m`, `30m`, `1h`, `1d`, `5d`, `1mo`, `3mo`, defaults to `None`\n- `period`: one of `1d`, `5d`, `1mo`, `3mo`, `6mo`, `1y`, `2y`, `5y`, `10y`, `ytd`, `max`, defaults to `None`\n- `start`: Any `date`/`datetime` [supported by pydnatic](https://pydantic-docs.helpmanual.io/usage/types/#datetime-types), defaults to `None`\n- `end`: Any `date`/`datetime` [supported by pydnatic](https://pydantic-docs.helpmanual.io/usage/types/#datetime-types), defaults to `None`\n- `events`: one of `div`, `split`, `div,splits`, defaults to `div,splits`\n- `include_prepost`: Bool, include Pre and Post market bars, default to `False`\n\n\nBy default, if no argument is provided, the `period` is set to `max` and the interval to `3mo`, example:\n\n\u003e _**Note**: It is possible for yahoo-finance to return bars of different interval than what was specified in the request (example below, requested `3mo` interval bars, got an interval of `1mo` because `TSLA` is a relatively new stock and it's max period is around ~10 years by the time of writing)._\n\n```Python\nimport asyncio\nfrom pstock import Bars\n\nbars = asyncio.run(Bars.get(\"TSLA\"))\nprint(bars.df)\n\n                   open         high         low        close    adj_close       volume interval\ndate\n2010-07-01     5.000000     5.184000    2.996000     3.988000     3.988000  322879000.0  30 days\n2010-08-01     4.100000     4.436000    3.478000     3.896000     3.896000   75191000.0  30 days\n2010-09-01     3.924000     4.632000    3.900000     4.082000     4.082000   90229500.0  30 days\n2010-10-01     4.138000     4.374000    4.000000     4.368000     4.368000   32739000.0  30 days\n2010-11-01     4.388000     7.200000    4.210000     7.066000     7.066000  141575500.0  30 days\n...                 ...          ...         ...          ...          ...          ...      ...\n2021-11-01  1145.000000  1243.489990  978.599976  1144.760010  1144.760010  648671800.0  30 days\n2021-12-01  1160.699951  1172.839966  886.119995  1056.780029  1056.780029  509945100.0  30 days\n2022-01-01  1147.750000  1208.000000  792.010010   936.719971   936.719971  638471400.0  30 days\n2022-02-01   935.210022   947.770020  850.700012   875.760010   875.760010  223112600.0  30 days\n2022-02-15   900.000000   923.000000  893.377380   922.429993   922.429993   19085243.0  30 days\n\n[141 rows x 7 columns]\n```\n\n\u003e _**Note 1**: Yahoo-finance limits the `interval` of data we can fetch based on how old the data is. For example we can't get `1m` bars for a period (or start/end) older than 7 days._\n\n\u003cdetails markdown=\"1\"\u003e\n\u003csummary\u003eExample of an interval error ...\u003c/summary\u003e\n\n```Python\nimport asyncio\nfrom pstock import Bars\n\nbars = asyncio.run(Bars.get(\"TSLA\", period=\"1mo\", interval=\"1m\"))\nprint(bars.df)\n\nTraceback (most recent call last):\n  File \"pstock/bar.py\", line 243, in \u003cmodule\u003e\n    bars = asyncio.run(Bars.get(\"TSLA\", period=\"1mo\", interval=\"1m\"))\n  File \"user/.pyenv/versions/3.8.12/lib/python3.8/asyncio/runners.py\", line 44, in run\n    return loop.run_until_complete(main)\n  File \"user/.pyenv/versions/3.8.12/lib/python3.8/asyncio/base_events.py\", line 616, in run_until_complete\n    return future.result()\n  File \"pstock/bar.py\", line 196, in get\n    return cls.load(response=response)\n  File \"pstock/bar.py\", line 169, in load\n    return cls.parse_obj(get_ohlc_from_chart(data))\n  File \"user/git/pstock/pstock/utils/chart.py\", line 18, in get_ohlc_from_chart\n    raise ValueError(f\"Yahoo-finance responded with an error:\\n{error}\")\nValueError: Yahoo-finance responded with an error:\n{'code': 'Unprocessable Entity', 'description': '1m data not available for startTime=1642289894 and endTime=1644968294. Only 7 days worth of 1m granularity data are allowed to be fetched per request.'}\n```\n\u003e \u003c/details\u003e\n\n\u003e _**Note2** By leaving the `interval` parameter empty (=`None`), `pstock` automatically tries to find the lowest `interval` possible based on how old the data requested is._\n\n```Python\nimport asyncio\nfrom pstock import Bars\n\nbars = asyncio.run(Bars.get(\"TSLA\", period=\"1mo\"))\nprint(bars.df)\n\n# Automatically finds that the lowest interval for a period of `1mo` is `2m`\n\n                                  open         high          low        close    adj_close     volume        interval\ndate\n2022-01-18 14:30:00+00:00  1028.000000  1030.000000  1023.000000  1023.983582  1023.983582  1125597.0 0 days 00:02:00\n2022-01-18 14:32:00+00:00  1023.230103  1032.000000  1023.230103  1029.807983  1029.807983   228889.0 0 days 00:02:00\n2022-01-18 14:34:00+00:00  1029.949951  1029.949951  1023.700012  1025.000000  1025.000000   248188.0 0 days 00:02:00\n2022-01-18 14:36:00+00:00  1024.319946  1025.999878  1018.000000  1021.000000  1021.000000   289773.0 0 days 00:02:00\n2022-01-18 14:38:00+00:00  1021.669922  1024.000000  1018.440002  1020.150024  1020.150024   183713.0 0 days 00:02:00\n...                                ...          ...          ...          ...          ...        ...             ...\n2022-02-15 20:52:00+00:00   919.640015   920.989990   919.171570   919.179993   919.179993   189152.0 0 days 00:02:00\n2022-02-15 20:54:00+00:00   919.320007   920.770020   918.869995   920.075012   920.075012   178398.0 0 days 00:02:00\n2022-02-15 20:56:00+00:00   920.010010   921.000000   919.859985   920.940002   920.940002   207078.0 0 days 00:02:00\n2022-02-15 20:58:00+00:00   920.900024   923.000000   920.750000   922.260010   922.260010   382232.0 0 days 00:02:00\n2022-02-15 21:00:00+00:00   922.429993   922.429993   922.429993   922.429993   922.429993        0.0 0 days 00:02:00\n\n[4093 rows x 7 columns]\n```\n\n\u003e _**Note3** Instead of using `period` it is also possible to set a specific `start` and optioally `end` value. If `end` is not set, it defaults to current UTC time._\n\n### BarsMulti\n\nSometimes we'll want to get bars for multiple symbols at the same time.\n\n```Python\nimport asyncio\nfrom pstock import BarsMulti\n\nbars = asyncio.run(BarsMulti.get([\"TSLA\", \"AAPL\"], period=\"5d\", interval=\"1d\"))\nprint(bars.df)\n\n                  TSLA                                                                             AAPL\n                  open        high         low       close   adj_close      volume interval        open        high         low       close   adj_close      volume interval\ndate\n2022-02-09  935.000000  946.270020  920.000000  932.000000  932.000000  17419800.0   1 days  176.050003  176.649994  174.899994  176.279999  176.279999  71285000.0   1 days\n2022-02-10  908.369995  943.809998  896.700012  904.549988  904.549988  22042300.0   1 days  174.139999  175.479996  171.550003  172.119995  172.119995  90865900.0   1 days\n2022-02-11  909.630005  915.960022  850.700012  860.000000  860.000000  26492700.0   1 days  172.330002  173.080002  168.039993  168.639999  168.639999  98566000.0   1 days\n2022-02-14  861.570007  898.880005  853.150024  875.760010  875.760010  22515100.0   1 days  167.369995  169.580002  166.559998  168.880005  168.880005  86062800.0   1 days\n2022-02-15  900.000000  923.000000  893.377380  922.429993  922.429993  19085243.0   1 days  170.970001  172.949997  170.250000  172.789993  172.789993  62512704.0   1 days\n```\n\n\u003e _**Note** Bars of a specific symbol can be accessed by using the sumbol as key:\n\u003e `bars[\"TSLA\"].df == bars.df[\"TSLA\"] == Bars.get(\"TSLA\").df`_\n\n## Sans-I/O protocol\n\n\u003e An I/O-free protocol implementation (colloquially referred to as a “sans-IO” implementation) is an implementation of a network protocol that contains no code that does any form of network I/O or any form of asynchronous flow control. Put another way, a sans-IO protocol implementation is one that is defined entirely in terms of synchronous functions returning synchronous results, and that does not block or wait for any form of I/O.\n\u003e ............\n\u003e By keeping async flow control and I/O out of your protocol implementation, it provides the ability to use that implementation across all forms of flow control. This means that the core of the protocol implementation is divorced entirely from the way I/O is done or the way the API is designed.\n\n-\u003e [https://sans-io.readthedocs.io](https://sans-io.readthedocs.io/)\n\nAlthough `pstock` provides an async IO interface to get data from yahoo-finance, It is still extremly easy to use it with other http libraries or other ways to get data.\n\nA simple example is using the popular `requests` library:\n\n```python\nimport requests\nfrom pstock import Asset, rdm_user_agent_value\n\nurl = Asset.uri(\"TSLA\")\nheaders = {\"User-Agent\": rdm_user_agent_value()}\n\nresponse = requests.get(url, headers=headers)\n\nasset = Asset.load(response=response)\n```\n\nThe `response` object can be an `str` or `bytes` content of the response. Or it can even be the whole response object (should have a `.read()` method that returns content).\n\nThe same can be done for generating `Bars`\n\n```python\nimport requests\nfrom pstock import Bars, rdm_user_agent_value\n\nurl = Bars.uri(\"TSLA\", interval=\"1m\", period=\"1d\")\nheaders = {\"User-Agent\": rdm_user_agent_value()}\n\nresponse = requests.get(url, headers=headers)\n\nbars = Bars.load(response=response)\n```\n\n\n\n## Contributors\n\nFeel free to contribute !\n\n\u003ca href = \"https://github.com/obendidi/pstock/graphs/contributors\"\u003e\n\u003cimg src = \"https://contrib.rocks/image?repo=obendidi/pstock\"/\u003e\n\u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fobendidi%2Fpstock","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fobendidi%2Fpstock","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fobendidi%2Fpstock/lists"}