From e16345ed59df857a15f2cc97fabb94fa1cd1566c Mon Sep 17 00:00:00 2001 From: R5dan Date: Thu, 23 Jan 2025 20:51:12 +0000 Subject: [PATCH 01/15] Update search --- yfinance/search.py | 155 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 126 insertions(+), 29 deletions(-) diff --git a/yfinance/search.py b/yfinance/search.py index 7e834233c..154ad6e1d 100644 --- a/yfinance/search.py +++ b/yfinance/search.py @@ -24,9 +24,73 @@ from . import utils from .const import _BASE_URL_ from .data import YfData +from typing import TypedDict +import typing as t + +SEARCH_CACHE = TypedDict('SEARCH_CACHE', { + "query": str, + "fields": list[str], + "results": dict +}) + +class SearchCache: + data = YfData() + logger = utils.get_yf_logger() + def __init__(self): + self.cache = {} + + def get(self, query:'tuple[str, list[str]]') -> 't.Union[dict, None]': + if query in self.cache: + return self.cache[query] + return None + + def set(self, query:'tuple[str, list[str]]', data:'dict') -> 'None': + self.cache[query] = data + + def fetch(self, query:'str', fields:'list[str]', session=None, proxy=None, timeout=30, **kwargs:'dict') -> 'dict': + if res := self.get((query, fields)): + return res + + params = { + "q": query, + "enableFuzzyQuery": "enable_fuzzy_query" in fields, + "quotesQueryId": "tss_match_phrase_query", + "newsQueryId": "news_cie_vespa", + "enableCb": "cb" in fields, + "enableNavLinks": "nav_links" in fields, + "enableResearchReports": "research" in fields, + "enableCulturalAssets": "cultural_assets" in fields, + } + + + if "quotes" in fields: + params["quotesCount"] = kwargs.get("max_results", 8) + params["recommendedCount"] = kwargs.get("recommended", 8) + if "news" in fields: + params["newsCount"] = kwargs.get("news_count", 8) + if "lists" in fields: + params["listsCount"] = kwargs.get("lists_count", 8) + + url = f"{_BASE_URL_}/v1/finance/search" + data = self.data.cache_get(url=url, params=params, proxy=proxy, timeout=timeout, session=session) + if data is None or "Will be right back" in data.text: + raise RuntimeError("*** YAHOO! FINANCE IS CURRENTLY DOWN! ***\n" + "Our engineers are working quickly to resolve " + "the issue. Thank you for your patience.") + try: + data = data.json() + self.set((query, fields), data) + except _json.JSONDecodeError: + self.logger.error(f"{query}: Failed to retrieve search results and received faulty response instead.") + data = {} + return data + + + class Search: + cache = SearchCache() def __init__(self, query, max_results=8, news_count=8, lists_count=8, include_cb=True, include_nav_links=False, include_research=False, include_cultural_assets=False, enable_fuzzy_query=False, recommended=8, session=None, proxy=None, timeout=30, raise_errors=True): @@ -49,6 +113,7 @@ def __init__(self, query, max_results=8, news_count=8, lists_count=8, include_cb timeout: Request timeout in seconds (default 30). raise_errors: Raise exceptions on error (default True). """ + self.fields = ["quotes" if max_results else "", "news" if news_count else "", "lists" if lists_count else "", "cb" if include_cb else "", "nav_links" if include_nav_links else "", "research" if include_research else "", "cultural_assets" if include_cultural_assets else ""] self.query = query self.max_results = max_results self.enable_fuzzy_query = enable_fuzzy_query @@ -80,34 +145,9 @@ def __init__(self, query, max_results=8, news_count=8, lists_count=8, include_cb def search(self) -> 'Search': """Search using the query parameters defined in the constructor.""" - url = f"{_BASE_URL_}/v1/finance/search" - params = { - "q": self.query, - "quotesCount": self.max_results, - "enableFuzzyQuery": self.enable_fuzzy_query, - "newsCount": self.news_count, - "quotesQueryId": "tss_match_phrase_query", - "newsQueryId": "news_cie_vespa", - "listsCount": self.lists_count, - "enableCb": self.include_cb, - "enableNavLinks": self.nav_links, - "enableResearchReports": self.enable_research, - "enableCulturalAssets": self.enable_cultural_assets, - "recommendedCount": self.recommended - } - - self._logger.debug(f'{self.query}: Yahoo GET parameters: {str(dict(params))}') + self._logger.debug(f'{self.query}: Fields: {self.fields}') - data = self._data.cache_get(url=url, params=params, proxy=self.proxy, timeout=self.timeout) - if data is None or "Will be right back" in data.text: - raise RuntimeError("*** YAHOO! FINANCE IS CURRENTLY DOWN! ***\n" - "Our engineers are working quickly to resolve " - "the issue. Thank you for your patience.") - try: - data = data.json() - except _json.JSONDecodeError: - self._logger.error(f"{self.query}: Failed to retrieve search results and received faulty response instead.") - data = {} + data = self.cache.fetch(self.query, self.fields, session=self.session, proxy=self.proxy, timeout=self.timeout) self._response = data # Filter quotes to only include symbols @@ -117,9 +157,66 @@ def search(self) -> 'Search': self._research = data.get("researchReports", []) self._nav = data.get("nav", []) - self._all = {"quotes": self._quotes, "news": self._news, "lists": self._lists, "research": self._research, - "nav": self._nav} + self._all = { + "quotes": self._quotes, + "news": self._news, + "lists": self._lists, + "research": self._research, + "nav": self._nav + } + + return self + + + + def search_quotes(self) -> 'Search': + """Search using the query parameters defined in the constructor, but only return the quotes.""" + self._logger.debug(f'{self.query}: Fields: [quotes]') + data = self.cache.fetch(self.query, ["quotes"], session=self.session, proxy=self.proxy, timeout=self.timeout) + + self._quotes = data.get("quotes", []) + self._response = data + self._all["quotes"] = self._quotes + return self + def search_news(self) -> 'Search': + """Search using the query parameters defined in the constructor, but only return the news.""" + self._logger.debug(f'{self.query}: Fields: [news]') + data = self.cache.fetch(self.query, ["news"], session=self.session, proxy=self.proxy, timeout=self.timeout) + + self._news = data.get("news", []) + self._response = data + self._all["news"] = self._news + return self + + def search_lists(self) -> 'Search': + """Search using the query parameters defined in the constructor, but only return the lists.""" + self._logger.debug(f'{self.query}: Fields: [lists]') + data = self.cache.fetch(self.query, ["lists"], session=self.session, proxy=self.proxy, timeout=self.timeout) + + self._lists = data.get("lists", []) + self._response = data + self._all["lists"] = self._lists + return self + + def search_research(self) -> 'Search': + """Search using the query parameters defined in the constructor, but only return the research reports.""" + self._logger.debug(f'{self.query}: Fields: [research]') + data = self.cache.fetch(self.query, ["research"], session=self.session, proxy=self.proxy, timeout=self.timeout) + + self._research = data.get("researchReports", []) + self._response = data + self._all["research"] = self._research + return self + + def search_nav(self) -> 'Search': + """Search using the query parameters defined in the constructor, but only return the navigation links.""" + self._logger.debug(f'{self.query}: Fields: [nav]') + data = self.cache.fetch(self.query, ["nav"], session=self.session, proxy=self.proxy, timeout=self.timeout) + + self._nav = data.get("nav", []) + self._response = data + self._all["nav"] = self._nav return self @property From 25eb653460baee7616833bc1c94086088cf079db Mon Sep 17 00:00:00 2001 From: R5dan Date: Thu, 23 Jan 2025 20:54:04 +0000 Subject: [PATCH 02/15] Change search_x to return results --- yfinance/search.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/yfinance/search.py b/yfinance/search.py index 154ad6e1d..4180e4c27 100644 --- a/yfinance/search.py +++ b/yfinance/search.py @@ -169,7 +169,7 @@ def search(self) -> 'Search': - def search_quotes(self) -> 'Search': + def search_quotes(self) -> 'list': """Search using the query parameters defined in the constructor, but only return the quotes.""" self._logger.debug(f'{self.query}: Fields: [quotes]') data = self.cache.fetch(self.query, ["quotes"], session=self.session, proxy=self.proxy, timeout=self.timeout) @@ -177,9 +177,9 @@ def search_quotes(self) -> 'Search': self._quotes = data.get("quotes", []) self._response = data self._all["quotes"] = self._quotes - return self + return self.quotes - def search_news(self) -> 'Search': + def search_news(self) -> 'list': """Search using the query parameters defined in the constructor, but only return the news.""" self._logger.debug(f'{self.query}: Fields: [news]') data = self.cache.fetch(self.query, ["news"], session=self.session, proxy=self.proxy, timeout=self.timeout) @@ -187,9 +187,9 @@ def search_news(self) -> 'Search': self._news = data.get("news", []) self._response = data self._all["news"] = self._news - return self + return self.news - def search_lists(self) -> 'Search': + def search_lists(self) -> 'list': """Search using the query parameters defined in the constructor, but only return the lists.""" self._logger.debug(f'{self.query}: Fields: [lists]') data = self.cache.fetch(self.query, ["lists"], session=self.session, proxy=self.proxy, timeout=self.timeout) @@ -197,9 +197,9 @@ def search_lists(self) -> 'Search': self._lists = data.get("lists", []) self._response = data self._all["lists"] = self._lists - return self + return self.lists - def search_research(self) -> 'Search': + def search_research(self) -> 'list': """Search using the query parameters defined in the constructor, but only return the research reports.""" self._logger.debug(f'{self.query}: Fields: [research]') data = self.cache.fetch(self.query, ["research"], session=self.session, proxy=self.proxy, timeout=self.timeout) @@ -207,9 +207,9 @@ def search_research(self) -> 'Search': self._research = data.get("researchReports", []) self._response = data self._all["research"] = self._research - return self + return self.research - def search_nav(self) -> 'Search': + def search_nav(self) -> 'list': """Search using the query parameters defined in the constructor, but only return the navigation links.""" self._logger.debug(f'{self.query}: Fields: [nav]') data = self.cache.fetch(self.query, ["nav"], session=self.session, proxy=self.proxy, timeout=self.timeout) @@ -217,7 +217,7 @@ def search_nav(self) -> 'Search': self._nav = data.get("nav", []) self._response = data self._all["nav"] = self._nav - return self + return self.nav @property def quotes(self) -> 'list': From 368d3fbbf1d43d99d9d22630507561cfe1693c25 Mon Sep 17 00:00:00 2001 From: R5dan Date: Thu, 23 Jan 2025 20:59:47 +0000 Subject: [PATCH 03/15] Remove YfData from Search --- yfinance/search.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/yfinance/search.py b/yfinance/search.py index 4180e4c27..5ae1c607a 100644 --- a/yfinance/search.py +++ b/yfinance/search.py @@ -130,7 +130,6 @@ def __init__(self, query, max_results=8, news_count=8, lists_count=8, include_cb self.enable_cultural_assets = include_cultural_assets self.recommended = recommended - self._data = YfData(session=self.session) self._logger = utils.get_yf_logger() self._response = {} @@ -166,9 +165,9 @@ def search(self) -> 'Search': } return self - - + + def search_quotes(self) -> 'list': """Search using the query parameters defined in the constructor, but only return the quotes.""" self._logger.debug(f'{self.query}: Fields: [quotes]') From b62348a71c8798bb40778e1fe71085bc37b556b5 Mon Sep 17 00:00:00 2001 From: sshcli Date: Mon, 17 Feb 2025 01:16:52 +0000 Subject: [PATCH 04/15] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cbc656f42..cbdcf78b6 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ Yahoo! finance API is intended for personal use only.** - `Ticker`: single ticker data - `Tickers`: multiple tickers' data - `download`: download market data for multiple tickers -- `Market`: get infomation about a market +- `Market`: get information about a market - `Search`: quotes and news from search - `Sector` and `Industry`: sector and industry information - `EquityQuery` and `Screener`: build query to screen market @@ -58,7 +58,7 @@ The list of changes can be found in the [Changelog](https://github.com/ranarouss ## Developers: want to contribute? -`yfinance` relies on community to investigate bugs, review code, and contribute code. Developer guide: https://github.com/ranaroussi/yfinance/discussions/1084 +`yfinance` relies on the community to investigate bugs, review code, and contribute code. Developer guide: https://github.com/ranaroussi/yfinance/discussions/1084 --- From 27a5e9241cd2d73b66b93a7172f9d1beb3c3544a Mon Sep 17 00:00:00 2001 From: Ran Aroussi Date: Sat, 22 Feb 2025 18:57:12 +0000 Subject: [PATCH 05/15] yfinance "logo" --- doc/yfinance-gh-icon-dark.webp | Bin 0 -> 1252 bytes doc/yfinance-gh-icon-light.webp | Bin 0 -> 1292 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/yfinance-gh-icon-dark.webp create mode 100644 doc/yfinance-gh-icon-light.webp diff --git a/doc/yfinance-gh-icon-dark.webp b/doc/yfinance-gh-icon-dark.webp new file mode 100644 index 0000000000000000000000000000000000000000..613f7207e2ca609fb9ade2d0fe5c14df82f9e8ea GIT binary patch literal 1252 zcmWIYbaT7I!oU#j>J$(bU=hK^z`!5?#K##Jv>6#3eF8k{m>3us%NK0xRWYq9KQCce z|4UHN;HCTR`(9mJT_&u`-JE59X2mC$ph(%sJlo>f1Jh>iwDXUd=~z@c@5UohgU>NX zBR8j~)oMvxthdNh_MCKM`gVzI!L|P!kG9;|`0>&1?AxmzwEgSo$XV~A{ddx)WW`&> zn&wf?b^m-%2yG~yB(?6zuZ0t=*1WTy#TxP2^>Y8#@KUL4mr~|zpRZ!CCwry2T&#U@ zbawLQhgNbO9X4-Lc27v@%GxwFvmny-o6n_!kh51mdS6=HogE;ud*{0hxv<1q@wY3E z{#v=}_^-8DM}95OIw%x+TSZS=f8XwHYq|1X^mm;2=CvhgQ@q$BTmSF~-iVj$RgS}4 zqIfE>{pw%$%?#OlGk$ISw#qNLcST-8@5*~Zk#*mWEI5?F5-QU(gXbW}Nr9dTItNcI zEvP!Skwtm>qnDD$gnDASmZwVu8+|9vA&X0GG=6K(6@9b#_l0ir<7weO6>_4$bg5tgOobC< z8Rjx-onX*mw43NL&r5Zwvf{Gxn;sj4I8*Z;mh>@5u6_AzMxARO!?QJ8qEmm~+j4Y! z&nI(_<)4j>^+kOqPYn$X4P2@t6FGC{%o*;h&a#)6mzO#8rWhN`-k$n>%8aLKk9MU6 z_px6vk2yVSiTmn|yDaLZmb;%XajyItGieG7zkSxjWP@1IS)Yywu3h+6_3QV}U(PCj zJl$>2$R6BV#mrFUHX}MD{?42OWyY0fb9C}=%(--YX3Xh@N{VZjwKVQ}7RxEf>)?8z zw|`=Zf^uZQPoO)>BX=)r6L}&DWMTz93=IFiKjB)>Jo*3sD7*isb>FVJT{?AL zrD@xp?UO1WdhC9&Yy0J;^M5MD-?`G^Tkt=t!1VLM-uKM$)_Kow&xo5ZbA!LNBJgtC z-T%#ter-9{c>G{?i%Zv4d3QiMw-k{+kH-OzgaKQVEJ8G{~Dj3m!IBp|JlGvBG7;6!&{z1ir+_CZEyKCF3;D-K)h-|M!EB%tPVeIZ_Ds@nRL#}#OVXo@Yfu!sx$bBlR$+Y??Wo22sjA2N zt!l*jr)t3xRof&k8!x`Qwyg?o=#PlV_DZx;vR@XWJx^Cy4Or=~B*zl4bCMdadd9H? zBbVao8O9QfT#Bb>7*jCvFig)VreNe@n4VEg!N|ihJ%gBnk%wh^1~COA56kon68z89 zGCheb)04zB z$yER$*$p5f9})y)(D5z6PGbV>O(wu@mQQT|%O|#D<`dgv^NH=s`GofIj6yqqMv>nu za*F)!0%JX_lBKe?1?@VRN*Tr`kFNV3b6}T_4)tLvR58nUHUL3IG4CAAjYKw59Py?Y?cg%GW%a z!){y2Jn*Dl^j%u(N~bX5CyDg22!udiz}L?PH@ppe?Yp0DVS0RW-xw7kQ%$H^RL(#9 zLHp8|*>}DRTp}bo(eBF*GXxR|zl$ z0xZ@){Pn@&Xvuz&dW%DpIYk+}-1)S#o&WqGJ1}r4gSSpN?G#rN;? z|2$Jp+aSKE4SWp~v!3h=sX4hA;OFQ665LA!=0000~ CT537~ literal 0 HcmV?d00001 From 437401e68aeeb2a102dd219b4be3052a2f070ff0 Mon Sep 17 00:00:00 2001 From: Ran Aroussi Date: Sat, 22 Feb 2025 19:06:11 +0000 Subject: [PATCH 06/15] yfinance "logo" --- doc/yfinance-gh-logo-dark.webp | Bin 0 -> 5904 bytes doc/yfinance-gh-logo-light.webp | Bin 0 -> 6332 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/yfinance-gh-logo-dark.webp create mode 100644 doc/yfinance-gh-logo-light.webp diff --git a/doc/yfinance-gh-logo-dark.webp b/doc/yfinance-gh-logo-dark.webp new file mode 100644 index 0000000000000000000000000000000000000000..040ac7165f1c951bfc953e1459f6d971fa1f1fb0 GIT binary patch literal 5904 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 Date: Sat, 22 Feb 2025 19:25:06 +0000 Subject: [PATCH 07/15] Minor design changes to readme file --- README.md | 50 +++++++++++++++++++++++--------------------------- 1 file changed, 23 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index cbdcf78b6..8f8f57b99 100644 --- a/README.md +++ b/README.md @@ -1,38 +1,36 @@ -# Download market data from Yahoo! Finance's API + + -
+# Download market data from Yahoo! Finance's API -#### \*\*\* IMPORTANT LEGAL DISCLAIMER \*\*\* +Python version +PyPi version +PyPi status +PyPi downloads +Star this repo +Follow me on twitter ---- -**Yahoo!, Y!Finance, and Yahoo! finance are registered trademarks of -Yahoo, Inc.** -yfinance is **not** affiliated, endorsed, or vetted by Yahoo, Inc. It's -an open-source tool that uses Yahoo's publicly available APIs, and is -intended for research and educational purposes. +**yfinance** offers a Pythonic way to fetch financial & market data from [Yahoo!Ⓡ finance](https://finance.yahoo.com). -**You should refer to Yahoo!'s terms of use** -([here](https://policies.yahoo.com/us/en/yahoo/terms/product-atos/apiforydn/index.htm), -[here](https://legal.yahoo.com/us/en/yahoo/terms/otos/index.html), and -[here](https://policies.yahoo.com/us/en/yahoo/terms/index.htm)) **for -details on your rights to use the actual data downloaded. Remember - the -Yahoo! finance API is intended for personal use only.** +--- -
+> [!IMPORTANT] +> **Yahoo!, Y!Finance, and Yahoo! finance are registered trademarks of Yahoo, Inc.** +> +> yfinance is **not** affiliated, endorsed, or vetted by Yahoo, Inc. It's an open-source tool that uses Yahoo's publicly available APIs, and is intended for research and educational purposes. +> +> **You should refer to Yahoo!'s terms of use** ([here](https://policies.yahoo.com/us/en/yahoo/terms/product-atos/apiforydn/index.htm), [here](https://legal.yahoo.com/us/en/yahoo/terms/otos/index.html), and [here](https://policies.yahoo.com/us/en/yahoo/terms/index.htm)) **for details on your rights to use the actual data downloaded. +> +> Remember - the Yahoo! finance API is intended for personal use only.** --- -
Python version -PyPi version -PyPi status -PyPi downloads -CodeFactor -Star this repo -Follow me on twitter - -**yfinance** offers a Pythonic way to fetch financial & market data from [Yahoo!Ⓡ finance](https://finance.yahoo.com). +> [!TIP] +> THE NEW DOCUMENTATION WEBSITE IS NOW LIVE! 🤘 +> +> Visit [**ranaroussi.github.io/yfinance**](https://ranaroussi.github.io/yfinance/index.html) › ## Main components @@ -44,8 +42,6 @@ Yahoo! finance API is intended for personal use only.** - `Sector` and `Industry`: sector and industry information - `EquityQuery` and `Screener`: build query to screen market -## **NEW DOCUMENTATION WEBSITE**: [ranaroussi.github.io/yfinance](https://ranaroussi.github.io/yfinance/index.html) - ## Installation Install `yfinance` from PYPI using `pip`: From 0edf69392253806b1ddf3480285d0453cde9761d Mon Sep 17 00:00:00 2001 From: Ran Aroussi Date: Sat, 22 Feb 2025 19:26:14 +0000 Subject: [PATCH 08/15] Delete .DS_Store --- .DS_Store | Bin 6148 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 .DS_Store diff --git a/.DS_Store b/.DS_Store deleted file mode 100644 index 9b786ce52aa00e90336160999621dda530c39633..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 6148 zcmeH~J!%6%427R!7lt%jrkutH$PET#pTHLg*pSB9U`XmYdY*ooY+RcqJc0B^niaeI z6+0^cw);B20~3G^-4$C8Gc)EZoN>eH`*^=zZr4v%yb8QT%#4)@v;EqZh=2%)fCz|y z2rP&|p5oZNF6f!`C?X&N%OK$2hemhpr6V;y9Sku7P}eMnaUHV+wRwTsOGhdzG^^>s zs?}l)@p`mVTV2;nM{2giYWT3av-uQ5vuuYoCN%3I3L+o^GXks3CqMrW^hfjmtVO8^ zh`>K1VC(&HzvD~Q+4|@8y#7&DUk^GpE@$}l6Trle;x~F2_nR-My>z6qLeq~xU{DZ& HrxN%9njH~; From 7ccedb58a884513c263ef9ec786b1dea705c53bb Mon Sep 17 00:00:00 2001 From: Ran Aroussi Date: Sat, 22 Feb 2025 22:10:50 +0000 Subject: [PATCH 09/15] Set docs domain to yfinance-python.org --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 8f8f57b99..2f774ec46 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ > [!TIP] > THE NEW DOCUMENTATION WEBSITE IS NOW LIVE! 🤘 > -> Visit [**ranaroussi.github.io/yfinance**](https://ranaroussi.github.io/yfinance/index.html) › +> Visit [**yfinance-python.org**](https://yfinance-python.org/) › ## Main components From 9e00b811b80c18b1ea72cc7cdc8caeb1d3f16eec Mon Sep 17 00:00:00 2001 From: Ran Aroussi Date: Sat, 22 Feb 2025 22:16:13 +0000 Subject: [PATCH 10/15] Added docs logo --- doc/source/_static/logo-dark.webp | Bin 0 -> 3238 bytes doc/source/_static/logo-light.webp | Bin 0 -> 3472 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 doc/source/_static/logo-dark.webp create mode 100644 doc/source/_static/logo-light.webp diff --git a/doc/source/_static/logo-dark.webp b/doc/source/_static/logo-dark.webp new file mode 100644 index 0000000000000000000000000000000000000000..af9065272dd443b54eb0f764210cd308d09d73e5 GIT binary patch literal 3238 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 literal 0 HcmV?d00001 From 0ecaf96ccb1018aac1aea6f80c2e7725e5272e98 Mon Sep 17 00:00:00 2001 From: Ran Aroussi Date: Sat, 22 Feb 2025 22:17:21 +0000 Subject: [PATCH 11/15] Update conf.py --- doc/source/conf.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index a869680f9..b778c83d1 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -10,8 +10,8 @@ # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information -project = 'yfinance - market data downloader' -copyright = '2017-2019 Ran Aroussi' +project = 'yfinance / Pythonic access to market data' +copyright = '2017-2025 Ran Aroussi' author = 'Ran Aroussi' # -- General configuration --------------------------------------------------- @@ -41,6 +41,10 @@ html_theme_options = { "github_url": "https://github.com/ranaroussi/yfinance", "navbar_align": "left" + "logo": { + "image_light": "_static/logo-light.webp", + "image_dark": "_static/logo-dark.webp", + } } html_static_path = ['_static'] html_css_files = ['yfinance.css'] From 01c8c206dc04577b99617b85b21b384e7bc849aa Mon Sep 17 00:00:00 2001 From: Ran Aroussi Date: Sat, 22 Feb 2025 22:21:27 +0000 Subject: [PATCH 12/15] Update conf.py --- doc/source/conf.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/doc/source/conf.py b/doc/source/conf.py index b778c83d1..f2c99c5e1 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -40,10 +40,10 @@ html_theme = 'pydata_sphinx_theme' html_theme_options = { "github_url": "https://github.com/ranaroussi/yfinance", - "navbar_align": "left" + "navbar_align": "left", "logo": { "image_light": "_static/logo-light.webp", - "image_dark": "_static/logo-dark.webp", + "image_dark": "_static/logo-dark.webp" } } html_static_path = ['_static'] From 0fd51d3203398c636074d1b15eca71875c7394da Mon Sep 17 00:00:00 2001 From: Ran Aroussi Date: Sun, 23 Feb 2025 21:33:26 +0000 Subject: [PATCH 13/15] added star history :) --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 2f774ec46..b42f69f75 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,8 @@ > > Visit [**yfinance-python.org**](https://yfinance-python.org/) › +--- + ## Main components - `Ticker`: single ticker data @@ -58,6 +60,10 @@ The list of changes can be found in the [Changelog](https://github.com/ranarouss --- +![Star History Chart](https://api.star-history.com/svg?repos=ranaroussi/yfinance) + +--- + ### Legal Stuff **yfinance** is distributed under the **Apache Software License**. See From eb78798ee024439c94a8b3303cac1b39c1c41465 Mon Sep 17 00:00:00 2001 From: R5dan Date: Tue, 25 Feb 2025 12:35:17 +0000 Subject: [PATCH 14/15] Revert "Merge branch 'ranaroussi:main' into search" This reverts commit 5ef1311a7ea7d6d5fe2aaf7c13ca34abf9b56a9b, reversing changes made to 4eea297dcd3352008c204120c897fb53bc394ccc. --- .DS_Store | Bin 0 -> 6148 bytes .github/workflows/pytest.yml.disabled | 35 - CHANGELOG.rst | 39 +- README.md | 58 +- doc/source/_static/logo-dark.webp | Bin 3238 -> 0 bytes doc/source/_static/logo-light.webp | Bin 3472 -> 0 bytes doc/source/conf.py | 13 +- doc/source/reference/index.rst | 14 +- doc/source/reference/yfinance.functions.rst | 19 + doc/source/reference/yfinance.market.rst | 33 +- doc/source/reference/yfinance.screener.rst | 27 - doc/yfinance-gh-icon-dark.webp | Bin 1252 -> 0 bytes doc/yfinance-gh-icon-light.webp | Bin 1292 -> 0 bytes doc/yfinance-gh-logo-dark.webp | Bin 5904 -> 0 bytes doc/yfinance-gh-logo-light.webp | Bin 6332 -> 0 bytes meta.yaml | 2 +- requirements.txt | 2 + setup.py | 4 +- tests/context.py | 34 +- tests/data/SCR-TO-1d-bad-div-fixed.csv | 1072 +++++++++---------- tests/test_cache.py | 93 -- tests/test_price_repair.py | 15 +- tests/test_prices.py | 8 +- tests/test_screener.py | 143 ++- tests/test_ticker.py | 48 +- tests/test_utils.py | 68 ++ yfinance/__init__.py | 10 +- yfinance/base.py | 125 ++- yfinance/const.py | 154 +-- yfinance/data.py | 40 +- yfinance/domain/market.py | 14 +- yfinance/multi.py | 13 +- yfinance/scrapers/history.py | 97 +- yfinance/scrapers/holders.py | 16 +- yfinance/scrapers/quote.py | 64 +- yfinance/screener/__init__.py | 6 +- yfinance/screener/query.py | 218 ---- yfinance/screener/screener.py | 391 ++++--- yfinance/screener/screener_query.py | 145 +++ yfinance/utils.py | 148 +-- yfinance/version.py | 2 +- 41 files changed, 1474 insertions(+), 1696 deletions(-) create mode 100644 .DS_Store delete mode 100644 .github/workflows/pytest.yml.disabled delete mode 100644 doc/source/_static/logo-dark.webp delete mode 100644 doc/source/_static/logo-light.webp delete mode 100644 doc/source/reference/yfinance.screener.rst delete mode 100644 doc/yfinance-gh-icon-dark.webp delete mode 100644 doc/yfinance-gh-icon-light.webp delete mode 100644 doc/yfinance-gh-logo-dark.webp delete mode 100644 doc/yfinance-gh-logo-light.webp delete mode 100644 tests/test_cache.py delete mode 100644 yfinance/screener/query.py create mode 100644 yfinance/screener/screener_query.py diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000000000000000000000000000000000000..9b786ce52aa00e90336160999621dda530c39633 GIT binary patch literal 6148 zcmeH~J!%6%427R!7lt%jrkutH$PET#pTHLg*pSB9U`XmYdY*ooY+RcqJc0B^niaeI z6+0^cw);B20~3G^-4$C8Gc)EZoN>eH`*^=zZr4v%yb8QT%#4)@v;EqZh=2%)fCz|y z2rP&|p5oZNF6f!`C?X&N%OK$2hemhpr6V;y9Sku7P}eMnaUHV+wRwTsOGhdzG^^>s zs?}l)@p`mVTV2;nM{2giYWT3av-uQ5vuuYoCN%3I3L+o^GXks3CqMrW^hfjmtVO8^ zh`>K1VC(&HzvD~Q+4|@8y#7&DUk^GpE@$}l6Trle;x~F2_nR-My>z6qLeq~xU{DZ& HrxN%9njH~; literal 0 HcmV?d00001 diff --git a/.github/workflows/pytest.yml.disabled b/.github/workflows/pytest.yml.disabled deleted file mode 100644 index 2e733ce42..000000000 --- a/.github/workflows/pytest.yml.disabled +++ /dev/null @@ -1,35 +0,0 @@ -name: Pytest - -on: - pull_request: - branches: - - master - - main - - dev - -jobs: - test: - runs-on: ubuntu-latest - - steps: - - name: Checkout code - uses: actions/checkout@v3 - - - name: Set up Python - uses: actions/setup-python@v4 - with: - python-version: "3.12" - cache: 'pip' - - - name: Install dependencies - run: | - python -m pip install --upgrade pip - pip install -r requirements.txt pytest - - - name: Run non-cache tests - run: pytest tests/ --ignore tests/test_cache.py --ignore tests/test_price_repair.py - - - name: Run cache tests - run: | - pytest tests/test_cache.py::TestCache - pytest tests/test_cache.py::TestCacheNoPermission diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 6e6057cdb..04d1a829a 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,49 +1,14 @@ Change Log =========== -0.2.54 ------- -Hotfix user-agent #2277 - -0.2.53 ------- -Fixes: -- Fix: Failed to parse holders JSON data #2234 -- Fix: Bad data in Holders #2244 -- Stop CSRF-cookie-fetch fail killing yfinance #2249 -- Fix Market Docs #2250 -- Fix: Broken "See also" links in documentation #2253 -- Fix: Interval check and error message formatting in multi.py #2256 -Improve: -- Add pre- / post-stock prices (and other useful information) #2212 -- Warn user when use download() without specifying auto_adjust #2230 -- Refactor: Earnings Dates – Switch to API Fetching #2247 -- Improve prices div repair #2260 -Maintenance: -- Add GitHub Actions workflow and fix failing tests #2233 - -0.2.52 ------- -Features: -- Improve Screener & docs #2207 -- Add Market summary & status #2175 -- Support custom period in Ticker.history() #2192 -- raise YfRateLimitError if rate limited #2108 -- add more options to Search #2191 -Fixes: -- remove hardcoded keys in Analysis #2194 -- handle Yahoo changed Search response #2202 -Maintenance: -- add optional dependencies to requirements.txt #2199 - 0.2.51 ------ +Fixes: +- earnings_dates #2169 Features: - Screener tweaks #2168 - Search #2160 - get_news() expose count #2173 -Fixes: -- earnings_dates #2169 0.2.50 ------ diff --git a/README.md b/README.md index b42f69f75..cbc656f42 100644 --- a/README.md +++ b/README.md @@ -1,49 +1,51 @@ - - - # Download market data from Yahoo! Finance's API -Python version -PyPi version -PyPi status -PyPi downloads -Star this repo -Follow me on twitter +
+#### \*\*\* IMPORTANT LEGAL DISCLAIMER \*\*\* +--- -**yfinance** offers a Pythonic way to fetch financial & market data from [Yahoo!Ⓡ finance](https://finance.yahoo.com). +**Yahoo!, Y!Finance, and Yahoo! finance are registered trademarks of +Yahoo, Inc.** ---- +yfinance is **not** affiliated, endorsed, or vetted by Yahoo, Inc. It's +an open-source tool that uses Yahoo's publicly available APIs, and is +intended for research and educational purposes. + +**You should refer to Yahoo!'s terms of use** +([here](https://policies.yahoo.com/us/en/yahoo/terms/product-atos/apiforydn/index.htm), +[here](https://legal.yahoo.com/us/en/yahoo/terms/otos/index.html), and +[here](https://policies.yahoo.com/us/en/yahoo/terms/index.htm)) **for +details on your rights to use the actual data downloaded. Remember - the +Yahoo! finance API is intended for personal use only.** -> [!IMPORTANT] -> **Yahoo!, Y!Finance, and Yahoo! finance are registered trademarks of Yahoo, Inc.** -> -> yfinance is **not** affiliated, endorsed, or vetted by Yahoo, Inc. It's an open-source tool that uses Yahoo's publicly available APIs, and is intended for research and educational purposes. -> -> **You should refer to Yahoo!'s terms of use** ([here](https://policies.yahoo.com/us/en/yahoo/terms/product-atos/apiforydn/index.htm), [here](https://legal.yahoo.com/us/en/yahoo/terms/otos/index.html), and [here](https://policies.yahoo.com/us/en/yahoo/terms/index.htm)) **for details on your rights to use the actual data downloaded. -> -> Remember - the Yahoo! finance API is intended for personal use only.** +
--- -> [!TIP] -> THE NEW DOCUMENTATION WEBSITE IS NOW LIVE! 🤘 -> -> Visit [**yfinance-python.org**](https://yfinance-python.org/) › +Python version +PyPi version +PyPi status +PyPi downloads +CodeFactor +Star this repo +Follow me on twitter ---- +**yfinance** offers a Pythonic way to fetch financial & market data from [Yahoo!Ⓡ finance](https://finance.yahoo.com). ## Main components - `Ticker`: single ticker data - `Tickers`: multiple tickers' data - `download`: download market data for multiple tickers -- `Market`: get information about a market +- `Market`: get infomation about a market - `Search`: quotes and news from search - `Sector` and `Industry`: sector and industry information - `EquityQuery` and `Screener`: build query to screen market +## **NEW DOCUMENTATION WEBSITE**: [ranaroussi.github.io/yfinance](https://ranaroussi.github.io/yfinance/index.html) + ## Installation Install `yfinance` from PYPI using `pip`: @@ -56,11 +58,7 @@ The list of changes can be found in the [Changelog](https://github.com/ranarouss ## Developers: want to contribute? -`yfinance` relies on the community to investigate bugs, review code, and contribute code. Developer guide: https://github.com/ranaroussi/yfinance/discussions/1084 - ---- - -![Star History Chart](https://api.star-history.com/svg?repos=ranaroussi/yfinance) +`yfinance` relies on community to investigate bugs, review code, and contribute code. Developer guide: https://github.com/ranaroussi/yfinance/discussions/1084 --- diff --git a/doc/source/_static/logo-dark.webp b/doc/source/_static/logo-dark.webp deleted file mode 100644 index af9065272dd443b54eb0f764210cd308d09d73e5..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3238 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 diff --git a/doc/source/conf.py b/doc/source/conf.py index f2c99c5e1..e83733b3a 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -10,8 +10,8 @@ # -- Project information ----------------------------------------------------- # https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information -project = 'yfinance / Pythonic access to market data' -copyright = '2017-2025 Ran Aroussi' +project = 'yfinance - market data downloader' +copyright = '2017-2019 Ran Aroussi' author = 'Ran Aroussi' # -- General configuration --------------------------------------------------- @@ -29,8 +29,7 @@ autoclass_content = 'both' autosummary_generate = True autodoc_default_options = { - 'exclude-members': '__init__', - 'members': True, + 'exclude-members': '__init__' } # -- Options for HTML output ------------------------------------------------- @@ -40,11 +39,7 @@ html_theme = 'pydata_sphinx_theme' html_theme_options = { "github_url": "https://github.com/ranaroussi/yfinance", - "navbar_align": "left", - "logo": { - "image_light": "_static/logo-light.webp", - "image_dark": "_static/logo-dark.webp" - } + "navbar_align": "left" } html_static_path = ['_static'] html_css_files = ['yfinance.css'] diff --git a/doc/source/reference/index.rst b/doc/source/reference/index.rst index c907ed26c..5858a1a69 100644 --- a/doc/source/reference/index.rst +++ b/doc/source/reference/index.rst @@ -15,15 +15,13 @@ The following are the publicly available classes, and functions exposed by the ` - :attr:`Ticker `: Class for accessing single ticker data. - :attr:`Tickers `: Class for handling multiple tickers. -- :attr:`Market `: Class for accessing market summary. -- :attr:`download `: Function to download market data for multiple tickers. +- :attr:`MarketSummary `: Class for accessing market summary. - :attr:`Search `: Class for accessing search results. - :attr:`Sector `: Domain class for accessing sector information. - :attr:`Industry `: Domain class for accessing industry information. -- :attr:`Market `: Class for accessing market status & summary. -- :attr:`EquityQuery `: Class to build equity query filters. -- :attr:`FundQuery `: Class to build fund query filters. -- :attr:`screen `: Run equity/fund queries. +- :attr:`download `: Function to download market data for multiple tickers. +- :attr:`EquityQuery `: Class to build equity market query. +- :attr:`Screener `: Class to screen the market using defined query. - :attr:`enable_debug_mode `: Function to enable debug mode for logging. - :attr:`set_tz_cache_location `: Function to set the timezone cache location. @@ -34,13 +32,11 @@ The following are the publicly available classes, and functions exposed by the ` yfinance.ticker_tickers yfinance.stock - yfinance.market yfinance.financials yfinance.analysis - yfinance.market + yfinance.marketsummary yfinance.search yfinance.sector_industry - yfinance.screener yfinance.functions yfinance.funds_data diff --git a/doc/source/reference/yfinance.functions.rst b/doc/source/reference/yfinance.functions.rst index 5206e4415..ef83454b7 100644 --- a/doc/source/reference/yfinance.functions.rst +++ b/doc/source/reference/yfinance.functions.rst @@ -13,6 +13,25 @@ The `download` function allows you to retrieve market data for multiple tickers download +Query Market Data +~~~~~~~~~~~~~~~~~~~~~ +The `Sector` and `Industry` modules allow you to access the sector and industry information. + +.. autosummary:: + :toctree: api/ + + EquityQuery + Screener + +.. seealso:: + :attr:`EquityQuery.valid_operand_fields ` + supported operand values for query + :attr:`EquityQuery.valid_eq_operand_map ` + supported `EQ query operand parameters` + :attr:`Screener.predefined_bodies ` + supported predefined screens + + Enable Debug Mode ~~~~~~~~~~~~~~~~~ Enables logging of debug information for the `yfinance` package. diff --git a/doc/source/reference/yfinance.market.rst b/doc/source/reference/yfinance.market.rst index 58021ad09..a11a8e82c 100644 --- a/doc/source/reference/yfinance.market.rst +++ b/doc/source/reference/yfinance.market.rst @@ -1,41 +1,16 @@ ===================== -Market +Market Summary ===================== - .. currentmodule:: yfinance - - Class ------------ The `Market` class, allows you to access market data in a Pythonic way. - .. autosummary:: :toctree: api/ - Market Market Sample Code ------------------- - +-------------------------- +The `Market` class, allows you to access market summary data in a Pythonic way. .. literalinclude:: examples/market.py - :language: python - - -Markets ------------- -There are 8 different markets available in Yahoo Finance. - -* US -* GB - -\ - -* ASIA -* EUROPE - -\ - -* RATES -* COMMODITIES -* CURRENCIES -* CRYPTOCURRENCIES \ No newline at end of file + :language: python \ No newline at end of file diff --git a/doc/source/reference/yfinance.screener.rst b/doc/source/reference/yfinance.screener.rst deleted file mode 100644 index 74e8f2bed..000000000 --- a/doc/source/reference/yfinance.screener.rst +++ /dev/null @@ -1,27 +0,0 @@ -========================= -Screener & Query -========================= - -.. currentmodule:: yfinance - -Query Market Data -~~~~~~~~~~~~~~~~~~~~~ -The `Sector` and `Industry` modules allow you to access the sector and industry information. - -.. autosummary:: - :toctree: api/ - - EquityQuery - FundQuery - screen - -.. seealso:: - :attr:`EquityQuery.valid_fields ` - supported operand values for query - :attr:`EquityQuery.valid_values ` - supported `EQ query operand parameters` - :attr:`FundQuery.valid_fields ` - supported operand values for query - :attr:`FundQuery.valid_values ` - supported `EQ query operand parameters` - \ No newline at end of file diff --git a/doc/yfinance-gh-icon-dark.webp b/doc/yfinance-gh-icon-dark.webp deleted file mode 100644 index 613f7207e2ca609fb9ade2d0fe5c14df82f9e8ea..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1252 zcmWIYbaT7I!oU#j>J$(bU=hK^z`!5?#K##Jv>6#3eF8k{m>3us%NK0xRWYq9KQCce z|4UHN;HCTR`(9mJT_&u`-JE59X2mC$ph(%sJlo>f1Jh>iwDXUd=~z@c@5UohgU>NX zBR8j~)oMvxthdNh_MCKM`gVzI!L|P!kG9;|`0>&1?AxmzwEgSo$XV~A{ddx)WW`&> zn&wf?b^m-%2yG~yB(?6zuZ0t=*1WTy#TxP2^>Y8#@KUL4mr~|zpRZ!CCwry2T&#U@ zbawLQhgNbO9X4-Lc27v@%GxwFvmny-o6n_!kh51mdS6=HogE;ud*{0hxv<1q@wY3E z{#v=}_^-8DM}95OIw%x+TSZS=f8XwHYq|1X^mm;2=CvhgQ@q$BTmSF~-iVj$RgS}4 zqIfE>{pw%$%?#OlGk$ISw#qNLcST-8@5*~Zk#*mWEI5?F5-QU(gXbW}Nr9dTItNcI zEvP!Skwtm>qnDD$gnDASmZwVu8+|9vA&X0GG=6K(6@9b#_l0ir<7weO6>_4$bg5tgOobC< z8Rjx-onX*mw43NL&r5Zwvf{Gxn;sj4I8*Z;mh>@5u6_AzMxARO!?QJ8qEmm~+j4Y! z&nI(_<)4j>^+kOqPYn$X4P2@t6FGC{%o*;h&a#)6mzO#8rWhN`-k$n>%8aLKk9MU6 z_px6vk2yVSiTmn|yDaLZmb;%XajyItGieG7zkSxjWP@1IS)Yywu3h+6_3QV}U(PCj zJl$>2$R6BV#mrFUHX}MD{?42OWyY0fb9C}=%(--YX3Xh@N{VZjwKVQ}7RxEf>)?8z zw|`=Zf^uZQPoO)>BX=)r6L}&DWMTz93=IFiKjB)>Jo*3sD7*isb>FVJT{?AL zrD@xp?UO1WdhC9&Yy0J;^M5MD-?`G^Tkt=t!1VLM-uKM$)_Kow&xo5ZbA!LNBJgtC z-T%#ter-9{c>G{?i%Zv4d3QiMw-k{+kH-OzgaKQVEJ8G{~Dj3m!IBp|JlGvBG7;6!&{z1ir+_CZEyKCF3;D-K)h-|M!EB%tPVeIZ_Ds@nRL#}#OVXo@Yfu!sx$bBlR$+Y??Wo22sjA2N zt!l*jr)t3xRof&k8!x`Qwyg?o=#PlV_DZx;vR@XWJx^Cy4Or=~B*zl4bCMdadd9H? zBbVao8O9QfT#Bb>7*jCvFig)VreNe@n4VEg!N|ihJ%gBnk%wh^1~COA56kon68z89 zGCheb)04zB z$yER$*$p5f9})y)(D5z6PGbV>O(wu@mQQT|%O|#D<`dgv^NH=s`GofIj6yqqMv>nu za*F)!0%JX_lBKe?1?@VRN*Tr`kFNV3b6}T_4)tLvR58nUHUL3IG4CAAjYKw59Py?Y?cg%GW%a z!){y2Jn*Dl^j%u(N~bX5CyDg22!udiz}L?PH@ppe?Yp0DVS0RW-xw7kQ%$H^RL(#9 zLHp8|*>}DRTp}bo(eBF*GXxR|zl$ z0xZ@){Pn@&Xvuz&dW%DpIYk+}-1)S#o&WqGJ1}r4gSSpN?G#rN;? z|2$Jp+aSKE4SWp~v!3h=sX4hA;OFQ665LA!=0000~ CT537~ diff --git a/doc/yfinance-gh-logo-dark.webp b/doc/yfinance-gh-logo-dark.webp deleted file mode 100644 index 040ac7165f1c951bfc953e1459f6d971fa1f1fb0..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5904 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.3.0 numpy>=1.16.5 requests>=2.31 multitasking>=0.0.7 +lxml>=4.9.1 platformdirs>=2.0.0 pytz>=2022.5 frozendict>=2.3.4 beautifulsoup4>=4.11.1 +html5lib>=1.1 peewee>=3.16.2 requests_cache>=1.0 requests_ratelimiter>=0.3.1 diff --git a/setup.py b/setup.py index 7ec5c1748..9b0c073b4 100644 --- a/setup.py +++ b/setup.py @@ -61,9 +61,9 @@ packages=find_packages(exclude=['contrib', 'docs', 'tests', 'examples']), install_requires=['pandas>=1.3.0', 'numpy>=1.16.5', 'requests>=2.31', 'multitasking>=0.0.7', - 'platformdirs>=2.0.0', 'pytz>=2022.5', + 'lxml>=4.9.1', 'platformdirs>=2.0.0', 'pytz>=2022.5', 'frozendict>=2.3.4', 'peewee>=3.16.2', - 'beautifulsoup4>=4.11.1'], + 'beautifulsoup4>=4.11.1', 'html5lib>=1.1'], extras_require={ 'nospam': ['requests_cache>=1.0', 'requests_ratelimiter>=0.3.1'], 'repair': ['scipy>=1.6.3'], diff --git a/tests/context.py b/tests/context.py index cefd8a807..598cfa429 100644 --- a/tests/context.py +++ b/tests/context.py @@ -5,7 +5,9 @@ import sys import os import yfinance -from requests_ratelimiter import LimiterSession +from requests import Session +from requests_cache import CacheMixin, SQLiteCache +from requests_ratelimiter import LimiterMixin, MemoryQueueBucket from pyrate_limiter import Duration, RequestRate, Limiter _parent_dp = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) @@ -25,21 +27,19 @@ import shutil shutil.rmtree(testing_cache_dirpath) -# Setup a session to only rate-limit -history_rate = RequestRate(1, Duration.SECOND) + +# Setup a session to rate-limit and cache persistently: +class CachedLimiterSession(CacheMixin, LimiterMixin, Session): + pass +history_rate = RequestRate(1, Duration.SECOND*2) limiter = Limiter(history_rate) -session_gbl = LimiterSession(limiter=limiter) +cache_fp = os.path.join(testing_cache_dirpath, "unittests-cache") +session_gbl = CachedLimiterSession( + limiter=limiter, + bucket_class=MemoryQueueBucket, + backend=SQLiteCache(cache_fp, expire_after=_dt.timedelta(hours=1)), +) +# Use this instead if only want rate-limiting: +# from requests_ratelimiter import LimiterSession +# session_gbl = LimiterSession(limiter=limiter) -# Use this instead if you also want caching: -# from requests_cache import CacheMixin, SQLiteCache -# from requests_ratelimiter import LimiterMixin -# from requests import Session -# from pyrate_limiter import MemoryQueueBucket -# class CachedLimiterSession(CacheMixin, LimiterMixin, Session): -# pass -# cache_fp = os.path.join(testing_cache_dirpath, "unittests-cache") -# session_gbl = CachedLimiterSession( -# limiter=limiter, -# bucket_class=MemoryQueueBucket, -# backend=SQLiteCache(cache_fp, expire_after=_dt.timedelta(hours=1)), -# ) diff --git a/tests/data/SCR-TO-1d-bad-div-fixed.csv b/tests/data/SCR-TO-1d-bad-div-fixed.csv index f01a92b76..532a13a34 100644 --- a/tests/data/SCR-TO-1d-bad-div-fixed.csv +++ b/tests/data/SCR-TO-1d-bad-div-fixed.csv @@ -1,337 +1,337 @@ Datetime,Open,High,Low,Close,Adj Close,Volume,Dividends,Stock Splits,Repaired? -2022-01-04 00:00:00-05:00,3.829999923706055,4.269999980926514,3.829999923706055,4.0,3.944533314976542,559600,0.0,0.0,True -2022-01-05 00:00:00-05:00,4.050000190734863,4.199999809265137,4.039999961853027,4.050000190734863,3.993839960518446,467700,0.0,0.0,True -2022-01-06 00:00:00-05:00,4.150000095367432,4.179999828338623,4.050000190734863,4.090000152587891,4.03328527695197,393300,0.0,0.0,True -2022-01-07 00:00:00-05:00,4.130000114440918,4.230000019073486,4.070000171661377,4.159999847412109,4.102314998616687,860600,0.0,0.0,True -2022-01-10 00:00:00-05:00,4.199999809265137,4.199999809265137,4.119999885559082,4.199999809265137,4.1417598971441585,281900,0.0,0.0,True -2022-01-11 00:00:00-05:00,4.199999809265137,4.460000038146973,4.159999847412109,4.420000076293945,4.358709973340641,695900,0.0,0.0,True -2022-01-12 00:00:00-05:00,4.449999809265137,4.639999866485596,4.449999809265137,4.579999923706055,4.516490403262631,452500,0.0,0.0,True -2022-01-13 00:00:00-05:00,4.590000152587891,4.639999866485596,4.420000076293945,4.46999979019165,4.40801578307044,373700,0.0,0.0,True -2022-01-14 00:00:00-05:00,4.480000019073486,4.590000152587891,4.429999828338623,4.559999942779541,4.496767745045869,339600,0.0,0.0,True -2022-01-17 00:00:00-05:00,4.570000171661377,4.760000228881836,4.519999980926514,4.679999828338623,4.6151041122524905,317900,0.0,0.0,True -2022-01-18 00:00:00-05:00,4.75,4.78000020980835,4.650000095367432,4.659999847412109,4.595381036129677,317400,0.0,0.0,True -2022-01-19 00:00:00-05:00,4.71999979019165,4.730000019073486,4.489999771118164,4.519999980926514,4.457322428612345,642600,0.0,0.0,True -2022-01-20 00:00:00-05:00,4.400000095367432,4.639999866485596,4.320000171661377,4.539999961853027,4.477045922641211,780900,0.0,0.0,True -2022-01-21 00:00:00-05:00,4.460000038146973,4.579999923706055,4.369999885559082,4.420000076293945,4.358709973340641,426200,0.0,0.0,True -2022-01-24 00:00:00-05:00,4.309999942779541,4.400000095367432,4.070000171661377,4.380000114440918,4.3192642390010665,391900,0.0,0.0,True -2022-01-25 00:00:00-05:00,4.400000095367432,4.639999866485596,4.309999942779541,4.579999923706055,4.516490403262631,461500,0.0,0.0,True -2022-01-26 00:00:00-05:00,4.699999809265137,4.75,4.550000190734863,4.570000171661377,4.506629492060302,229400,0.0,0.0,True -2022-01-27 00:00:00-05:00,4.590000152587891,4.699999809265137,4.429999828338623,4.480000019073486,4.417877530084874,1782700,0.0,0.0,True -2022-01-28 00:00:00-05:00,4.539999961853027,4.699999809265137,4.53000020980835,4.690000057220459,4.62496502345482,340300,0.0,0.0,True -2022-01-31 00:00:00-05:00,4.670000076293945,4.960000038146973,4.670000076293945,4.889999866485596,4.82219244143454,341600,0.0,0.0,True -2022-02-01 00:00:00-05:00,4.900000095367432,4.900000095367432,4.75,4.809999942779541,4.743301390661442,245000,0.0,0.0,True -2022-02-02 00:00:00-05:00,4.789999961853027,4.880000114440918,4.659999847412109,4.75,4.684133416011156,335900,0.0,0.0,True -2022-02-03 00:00:00-05:00,4.71999979019165,4.800000190734863,4.579999923706055,4.730000019073486,4.6644107577943945,567100,0.0,0.0,True -2022-02-04 00:00:00-05:00,4.760000228881836,4.980000019073486,4.760000228881836,4.880000114440918,4.8123306944201065,728600,0.0,0.0,True -2022-02-07 00:00:00-05:00,4.800000190734863,4.849999904632568,4.639999866485596,4.670000076293945,4.605243201050161,509100,0.0,0.0,True -2022-02-08 00:00:00-05:00,4.650000095367432,4.650000095367432,4.360000133514404,4.460000038146973,4.398154871868112,520500,0.0,0.0,True -2022-02-09 00:00:00-05:00,4.46999979019165,4.619999885559082,4.449999809265137,4.550000190734863,4.48690683384354,225400,0.0,0.0,True -2022-02-10 00:00:00-05:00,4.519999980926514,4.610000133514404,4.449999809265137,4.510000228881836,4.447461935316068,225300,0.0,0.0,True -2022-02-11 00:00:00-05:00,4.5,4.630000114440918,4.489999771118164,4.630000114440918,4.565797884616639,380600,0.0,0.0,True -2022-02-14 00:00:00-05:00,4.5,4.550000190734863,4.400000095367432,4.510000228881836,4.447461935316068,507600,0.0,0.0,True -2022-02-15 00:00:00-05:00,4.420000076293945,4.71999979019165,4.420000076293945,4.690000057220459,4.62496502345482,342800,0.0,0.0,True -2022-02-16 00:00:00-05:00,4.699999809265137,4.800000190734863,4.539999961853027,4.579999923706055,4.516490403262631,508700,0.0,0.0,True -2022-02-17 00:00:00-05:00,4.599999904632568,4.659999847412109,4.519999980926514,4.570000171661377,4.506629492060302,309900,0.0,0.0,True -2022-02-18 00:00:00-05:00,4.510000228881836,4.559999942779541,4.380000114440918,4.420000076293945,4.358709973340641,191700,0.0,0.0,True -2022-02-22 00:00:00-05:00,4.460000038146973,4.599999904632568,4.429999828338623,4.53000020980835,4.467184175626778,1063700,0.0,0.0,True -2022-02-23 00:00:00-05:00,4.590000152587891,4.739999771118164,4.559999942779541,4.679999828338623,4.6151041122524905,256600,0.0,0.0,True -2022-02-24 00:00:00-05:00,4.699999809265137,4.820000171661377,4.559999942779541,4.670000076293945,4.605243201050161,392200,0.0,0.0,True -2022-02-25 00:00:00-05:00,4.659999847412109,4.880000114440918,4.630000114440918,4.849999904632568,4.782746707094965,264400,0.0,0.0,True -2022-02-28 00:00:00-05:00,4.880000114440918,5.099999904632568,4.869999885559082,5.079999923706055,5.0095572765877225,543200,0.0,0.0,True -2022-03-01 00:00:00-05:00,5.159999847412109,5.28000020980835,5.03000020980835,5.179999828338623,5.108170567671532,481700,0.0,0.0,True -2022-03-02 00:00:00-05:00,5.239999771118164,5.309999942779541,5.079999923706055,5.179999828338623,5.108170567671532,232200,0.0,0.0,True -2022-03-03 00:00:00-05:00,5.21999979019165,5.230000019073486,4.949999809265137,4.96999979019165,4.901082656395535,234500,0.0,0.0,True -2022-03-04 00:00:00-05:00,5.03000020980835,5.389999866485596,5.03000020980835,5.360000133514404,5.285675327434491,1110400,0.0,0.0,True -2022-03-07 00:00:00-05:00,5.570000171661377,5.849999904632568,5.440000057220459,5.650000095367432,5.571653453671484,738400,0.0,0.0,True -2022-03-08 00:00:00-05:00,5.829999923706055,5.889999866485596,5.46999979019165,5.679999828338623,5.601237023090574,733300,0.0,0.0,True -2022-03-09 00:00:00-05:00,5.300000190734863,5.639999866485596,5.199999809265137,5.21999979019165,5.147615466199004,796500,0.0,0.0,True -2022-03-10 00:00:00-05:00,5.360000133514404,5.449999809265137,5.239999771118164,5.309999942779541,5.2363678460804834,454800,0.0,0.0,True -2022-03-11 00:00:00-05:00,5.289999961853027,5.329999923706055,5.110000133514404,5.25,5.177200289336249,222100,0.0,0.0,True -2022-03-14 00:00:00-04:00,5.050000190734863,5.099999904632568,4.559999942779541,4.789999961853027,4.72357873244468,642400,0.0,0.0,True -2022-03-15 00:00:00-04:00,4.53000020980835,4.889999866485596,4.420000076293945,4.610000133514404,4.546074808493825,594600,0.0,0.0,True -2022-03-16 00:00:00-04:00,4.579999923706055,4.829999923706055,4.579999923706055,4.679999828338623,4.6151041122524905,583800,0.0,0.0,True -2022-03-17 00:00:00-04:00,4.789999961853027,4.960000038146973,4.739999771118164,4.800000190734863,4.733440479459113,654300,0.0,0.0,True -2022-03-18 00:00:00-04:00,4.71999979019165,4.920000076293945,4.710000038146973,4.71999979019165,4.654549428686014,284100,0.0,0.0,True -2022-03-21 00:00:00-04:00,4.829999923706055,5.010000228881836,4.820000171661377,4.980000019073486,4.910944403409967,344500,0.0,0.0,True -2022-03-22 00:00:00-04:00,4.96999979019165,4.96999979019165,4.820000171661377,4.940000057220459,4.871498669070392,374000,0.0,0.0,True -2022-03-23 00:00:00-04:00,5.010000228881836,5.099999904632568,4.940000057220459,4.940000057220459,4.871498669070392,535800,0.0,0.0,True -2022-03-24 00:00:00-04:00,5.0,5.0,4.840000152587891,4.900000095367432,4.832053770542921,385800,0.0,0.0,True -2022-03-25 00:00:00-04:00,4.849999904632568,5.21999979019165,4.840000152587891,5.179999828338623,5.108170567671532,821200,0.0,0.0,True -2022-03-28 00:00:00-04:00,4.900000095367432,5.110000133514404,4.900000095367432,5.070000171661377,4.999696365385395,338100,0.0,0.0,True -2022-03-29 00:00:00-04:00,4.940000057220459,5.230000019073486,4.809999942779541,5.210000038146973,5.137754554996675,628200,0.0,0.0,True -2022-03-30 00:00:00-04:00,5.269999980926514,5.400000095367432,5.269999980926514,5.369999885559082,5.295536238636821,448200,0.0,0.0,True -2022-03-31 00:00:00-04:00,5.300000190734863,5.409999847412109,5.260000228881836,5.309999942779541,5.2363678460804834,308000,0.0,0.0,True -2022-04-01 00:00:00-04:00,5.210000038146973,5.400000095367432,5.210000038146973,5.28000020980835,5.206784276661393,279000,0.0,0.0,True -2022-04-04 00:00:00-04:00,5.349999904632568,5.429999828338623,5.260000228881836,5.300000190734863,5.226506934878154,298100,0.0,0.0,True -2022-04-05 00:00:00-04:00,5.329999923706055,5.420000076293945,5.199999809265137,5.21999979019165,5.147615466199004,308800,0.0,0.0,True -2022-04-06 00:00:00-04:00,5.179999828338623,5.309999942779541,5.090000152587891,5.119999885559082,5.049002593021247,395100,0.0,0.0,True -2022-04-07 00:00:00-04:00,5.159999847412109,5.230000019073486,5.03000020980835,5.179999828338623,5.108170567671532,277200,0.0,0.0,True -2022-04-08 00:00:00-04:00,5.230000019073486,5.400000095367432,5.190000057220459,5.349999904632568,5.275813162514007,281000,0.0,0.0,True -2022-04-11 00:00:00-04:00,5.389999866485596,5.389999866485596,5.210000038146973,5.309999942779541,5.2363678460804834,474300,0.0,0.0,True -2022-04-12 00:00:00-04:00,5.400000095367432,5.5,5.300000190734863,5.329999923706055,5.256090922203297,440400,0.0,0.0,True -2022-04-13 00:00:00-04:00,5.400000095367432,5.46999979019165,5.309999942779541,5.360000133514404,5.285675327434491,553200,0.0,0.0,True -2022-04-14 00:00:00-04:00,5.369999885559082,5.510000228881836,5.349999904632568,5.429999828338623,5.354703795381053,399900,0.0,0.0,True -2022-04-18 00:00:00-04:00,5.460000038146973,5.639999866485596,5.400000095367432,5.550000190734863,5.473040162587675,412700,0.0,0.0,True -2022-04-19 00:00:00-04:00,5.489999771118164,5.489999771118164,5.21999979019165,5.329999923706055,5.256090922203297,375600,0.0,0.0,True -2022-04-20 00:00:00-04:00,5.329999923706055,5.400000095367432,5.25,5.28000020980835,5.206784276661393,245400,0.0,0.0,True -2022-04-21 00:00:00-04:00,5.289999961853027,5.389999866485596,5.0,5.059999942779541,4.9898350362770145,441300,0.0,0.0,True -2022-04-22 00:00:00-04:00,5.059999942779541,5.059999942779541,4.820000171661377,4.829999923706055,4.763024048878203,444800,0.0,0.0,True -2022-04-25 00:00:00-04:00,4.610000133514404,4.800000190734863,4.5,4.739999771118164,4.674271668996724,598100,0.0,0.0,True -2022-04-26 00:00:00-04:00,4.78000020980835,4.929999828338623,4.730000019073486,4.820000171661377,4.753162719769822,362000,0.0,0.0,True -2022-04-27 00:00:00-04:00,4.820000171661377,4.909999847412109,4.710000038146973,4.880000114440918,4.8123306944201065,306800,0.0,0.0,True -2022-04-28 00:00:00-04:00,4.920000076293945,4.989999771118164,4.800000190734863,4.949999809265137,4.881359998178772,337000,0.0,0.0,True -2022-04-29 00:00:00-04:00,4.960000038146973,5.0,4.769999980926514,4.820000171661377,4.753162719769822,312400,0.0,0.0,True -2022-05-02 00:00:00-04:00,4.710000038146973,4.829999923706055,4.630000114440918,4.730000019073486,4.6644107577943945,438800,0.0,0.0,True -2022-05-03 00:00:00-04:00,4.710000038146973,5.03000020980835,4.710000038146973,4.96999979019165,4.901082656395535,675000,0.0,0.0,True -2022-05-04 00:00:00-04:00,5.0,5.079999923706055,4.900000095367432,5.050000190734863,4.979973289262582,1268500,0.0,0.0,True -2022-05-05 00:00:00-04:00,5.099999904632568,5.150000095367432,4.860000133514404,5.03000020980835,4.96025063104582,356000,0.0,0.0,True -2022-05-06 00:00:00-04:00,4.96999979019165,5.139999866485596,4.880000114440918,4.940000057220459,4.871498669070392,250600,0.0,0.0,True -2022-05-09 00:00:00-04:00,4.78000020980835,4.78000020980835,4.460000038146973,4.579999923706055,4.516490403262631,587200,0.0,0.0,True -2022-05-10 00:00:00-04:00,4.650000095367432,4.75,4.440000057220459,4.539999961853027,4.477045922641211,359400,0.0,0.0,True -2022-05-11 00:00:00-04:00,4.670000076293945,4.670000076293945,4.21999979019165,4.329999923706055,4.26995759345916,709200,0.0,0.0,True -2022-05-12 00:00:00-04:00,4.349999904632568,4.489999771118164,4.25,4.380000114440918,4.3192642390010665,564300,0.0,0.0,True -2022-05-13 00:00:00-04:00,4.429999828338623,4.840000152587891,4.429999828338623,4.769999980926514,4.703856074227918,800600,0.0,0.0,True -2022-05-16 00:00:00-04:00,4.769999980926514,5.010000228881836,4.760000228881836,4.920000076293945,4.851775592947579,430900,0.0,0.0,True -2022-05-17 00:00:00-04:00,5.0,5.159999847412109,4.989999771118164,5.130000114440918,5.058864340035679,491800,0.0,0.0,True -2022-05-18 00:00:00-04:00,5.239999771118164,5.28000020980835,4.949999809265137,5.059999942779541,4.9898350362770145,526000,0.0,0.0,True -2022-05-19 00:00:00-04:00,4.940000057220459,5.28000020980835,4.940000057220459,5.230000019073486,5.15747804902554,440200,0.0,0.0,True -2022-05-20 00:00:00-04:00,5.179999828338623,5.400000095367432,5.179999828338623,5.349999904632568,5.275813162514007,510600,0.0,0.0,True -2022-05-24 00:00:00-04:00,5.320000171661377,5.579999923706055,5.300000190734863,5.570000171661377,5.492762820804438,522100,0.0,0.0,True -2022-05-25 00:00:00-04:00,5.599999904632568,5.760000228881836,5.550000190734863,5.690000057220459,5.611098770105007,634300,0.0,0.0,True -2022-05-26 00:00:00-04:00,5.849999904632568,5.849999904632568,5.610000133514404,5.610000133514404,5.532207719331908,492900,0.0,0.0,True -2022-05-27 00:00:00-04:00,5.619999885559082,5.78000020980835,5.590000152587891,5.78000020980835,5.699850314174381,746000,0.0,0.0,True -2022-05-30 00:00:00-04:00,5.840000152587891,6.139999866485596,5.840000152587891,6.139999866485596,6.054858579982144,430100,0.0,0.0,True -2022-05-31 00:00:00-04:00,6.150000095367432,6.170000076293945,5.710000038146973,5.840000152587891,5.759019124636771,3694200,0.0,0.0,True -2022-06-01 00:00:00-04:00,5.96999979019165,6.099999904632568,5.849999904632568,5.949999809265137,5.867493744828961,478200,0.0,0.0,True -2022-06-02 00:00:00-04:00,5.949999809265137,6.070000171661377,5.860000133514404,6.0,5.916800808276918,243400,0.0,0.0,True -2022-06-03 00:00:00-04:00,5.960000038146973,6.210000038146973,5.889999866485596,6.190000057220459,6.104165643430101,758200,0.0,0.0,True -2022-06-06 00:00:00-04:00,6.300000190734863,6.369999885559082,6.039999961853027,6.369999885559082,6.281669149474904,489200,0.0,0.0,True -2022-06-07 00:00:00-04:00,6.369999885559082,6.679999828338623,6.269999980926514,6.570000171661377,6.478896567454624,647300,0.0,0.0,True -2022-06-08 00:00:00-04:00,6.699999809265137,6.71999979019165,6.380000114440918,6.460000038146973,6.370421111450331,727300,0.0,0.0,True -2022-06-09 00:00:00-04:00,6.46999979019165,6.46999979019165,6.28000020980835,6.28000020980835,6.192918023311579,508200,0.0,0.0,True -2022-06-10 00:00:00-04:00,6.28000020980835,6.309999942779541,6.050000190734863,6.170000076293945,6.084442985213339,448700,0.0,0.0,True -2022-06-13 00:00:00-04:00,6.0,6.079999923706055,5.710000038146973,6.070000171661377,5.985829276223479,462500,0.0,0.0,True -2022-06-14 00:00:00-04:00,6.199999809265137,6.199999809265137,5.670000076293945,5.690000057220459,5.611098770105007,506000,0.0,0.0,True -2022-06-15 00:00:00-04:00,5.75,5.789999961853027,5.449999809265137,5.519999980926514,5.443455757356482,632600,0.0,0.0,True -2022-06-16 00:00:00-04:00,5.260000228881836,5.409999847412109,5.119999885559082,5.130000114440918,5.058864340035679,745300,0.0,0.0,True -2022-06-17 00:00:00-04:00,5.150000095367432,5.25,4.5,4.599999904632568,4.536213479385443,2540000,0.0,0.0,True -2022-06-20 00:00:00-04:00,4.579999923706055,4.739999771118164,4.519999980926514,4.690000057220459,4.62496502345482,273900,0.0,0.0,True -2022-06-21 00:00:00-04:00,4.800000190734863,4.949999809265137,4.710000038146973,4.769999980926514,4.703856074227918,592700,0.0,0.0,True -2022-06-22 00:00:00-04:00,4.449999809265137,4.460000038146973,4.300000190734863,4.309999942779541,4.250234517336348,809900,0.0,0.0,True -2022-06-23 00:00:00-04:00,4.329999923706055,4.389999866485596,3.740000009536743,3.849999904632568,3.796612960444777,1175400,0.0,0.0,True -2022-06-24 00:00:00-04:00,3.910000085830689,4.170000076293945,3.880000114440918,3.9700000286102295,3.9149493276513994,708700,0.0,0.0,True -2022-06-27 00:00:00-04:00,4.070000171661377,4.159999847412109,3.930000066757202,4.099999904632568,4.0431461881542985,638900,0.0,0.0,True -2022-06-28 00:00:00-04:00,4.199999809265137,4.400000095367432,4.179999828338623,4.309999942779541,4.250234517336348,998100,0.0,0.0,True -2022-06-29 00:00:00-04:00,4.349999904632568,4.400000095367432,4.090000152587891,4.099999904632568,4.0431461881542985,623400,0.0,0.0,True -2022-06-30 00:00:00-04:00,4.0,4.110000133514404,3.849999904632568,3.9800000190734863,3.92481065675978,788400,0.0,0.0,True -2022-07-04 00:00:00-04:00,4.019999980926514,4.050000190734863,3.890000104904175,4.03000020980835,3.9741177202077367,501500,0.0,0.0,True -2022-07-05 00:00:00-04:00,3.900000095367432,3.930000066757202,3.680000066757202,3.799999952316284,3.7473067328089247,1068800,0.0,0.0,True -2022-07-06 00:00:00-04:00,3.7100000381469727,3.849999904632568,3.380000114440918,3.470000028610229,3.421882872232358,785800,0.0,0.0,True -2022-07-07 00:00:00-04:00,3.640000104904175,3.7899999618530273,3.640000104904175,3.7300000190734863,3.67827742905026,537500,0.0,0.0,True -2022-07-08 00:00:00-04:00,3.75,3.880000114440918,3.640000104904175,3.799999952316284,3.7473067328089247,380000,0.0,0.0,True -2022-07-11 00:00:00-04:00,3.740000009536743,3.890000104904175,3.640000104904175,3.829999923706055,3.776890720134068,1113200,0.0,0.0,True -2022-07-12 00:00:00-04:00,3.7100000381469727,3.7899999618530273,3.5199999809265137,3.539999961853028,3.4909119670379978,693900,0.0,0.0,True -2022-07-13 00:00:00-04:00,3.4600000381469727,3.5799999237060547,3.440000057220459,3.509999990463257,3.4613279797128547,537100,0.0,0.0,True -2022-07-14 00:00:00-04:00,3.380000114440918,3.4600000381469727,3.259999990463257,3.440000057220459,3.3922988849072158,877700,0.0,0.0,True -2022-07-15 00:00:00-04:00,3.5199999809265137,3.609999895095825,3.390000104904175,3.5299999713897705,3.4810506379296164,565800,0.0,0.0,True -2022-07-18 00:00:00-04:00,3.5799999237060547,3.809999942779541,3.559999942779541,3.7699999809265137,3.717722745483783,1215000,0.0,0.0,True -2022-07-19 00:00:00-04:00,3.759999990463257,3.880000114440918,3.740000009536743,3.849999904632568,3.796612960444777,861800,0.0,0.0,True -2022-07-20 00:00:00-04:00,3.819999933242798,3.890000104904175,3.7300000190734863,3.859999895095825,3.8064742895531585,397100,0.0,0.0,True -2022-07-21 00:00:00-04:00,3.740000009536743,3.799999952316284,3.619999885559082,3.7100000381469727,3.658554770833498,481600,0.0,0.0,True -2022-07-22 00:00:00-04:00,3.740000009536743,3.7899999618530273,3.630000114440918,3.630000114440918,3.579664137966451,547400,0.0,0.0,True -2022-07-25 00:00:00-04:00,3.650000095367432,3.890000104904175,3.609999895095825,3.839999914169312,3.7867520492424487,617400,0.0,0.0,True -2022-07-26 00:00:00-04:00,3.900000095367432,3.9800000190734863,3.7899999618530273,3.869999885559082,3.8163360365675905,538400,0.0,0.0,True -2022-07-27 00:00:00-04:00,3.849999904632568,4.03000020980835,3.849999904632568,4.0,3.944533314976542,607300,0.0,0.0,True -2022-07-28 00:00:00-04:00,4.059999942779541,4.190000057220459,4.019999980926514,4.090000152587891,4.03328527695197,850200,0.0,0.0,True -2022-07-29 00:00:00-04:00,4.190000057220459,4.369999885559082,4.130000114440918,4.289999961853027,4.230512277025638,953100,0.0,0.0,True -2022-08-02 00:00:00-04:00,4.239999771118164,4.239999771118164,4.03000020980835,4.059999942779541,4.003700871720775,471000,0.0,0.0,True -2022-08-03 00:00:00-04:00,4.090000152587891,4.110000133514404,3.839999914169312,3.930000066757202,3.8755044291239273,677200,0.0,0.0,True -2022-08-04 00:00:00-04:00,3.859999895095825,3.880000114440918,3.680000066757202,3.680000066757202,3.628970783508355,809500,0.0,0.0,True -2022-08-05 00:00:00-04:00,3.609999895095825,3.890000104904175,3.609999895095825,3.849999904632568,3.796612960444777,380700,0.0,0.0,True -2022-08-08 00:00:00-04:00,3.799999952316284,3.940000057220459,3.759999990463257,3.940000057220459,3.885365340326257,429300,0.0,0.0,True -2022-08-09 00:00:00-04:00,4.0,4.03000020980835,3.950000047683716,4.010000228881836,3.954394644084923,328300,0.0,0.0,True -2022-08-10 00:00:00-04:00,4.039999961853027,4.039999961853027,3.900000095367432,3.990000009536743,3.9346724037742127,848100,0.0,0.0,True -2022-08-11 00:00:00-04:00,4.03000020980835,4.190000057220459,3.990000009536743,4.159999847412109,4.102314998616687,4875600,0.0,0.0,True -2022-08-12 00:00:00-04:00,4.150000095367432,4.420000076293945,4.110000133514404,4.300000190734863,4.2403736061340185,1629200,0.0,0.0,True -2022-08-15 00:00:00-04:00,4.110000133514404,4.369999885559082,4.03000020980835,4.300000190734863,4.2403736061340185,712300,0.0,0.0,True -2022-08-16 00:00:00-04:00,4.369999885559082,4.489999771118164,4.21999979019165,4.289999961853027,4.230512277025638,596600,0.0,0.0,True -2022-08-17 00:00:00-04:00,4.269999980926514,4.389999866485596,4.21999979019165,4.28000020980835,4.220651365823309,404100,0.0,0.0,True -2022-08-18 00:00:00-04:00,4.349999904632568,4.639999866485596,4.349999904632568,4.550000190734863,4.48690683384354,1213700,0.0,0.0,True -2022-08-19 00:00:00-04:00,4.610000133514404,4.650000095367432,4.489999771118164,4.5,4.437600188301636,348900,0.0,0.0,True -2022-08-22 00:00:00-04:00,4.460000038146973,4.519999980926514,4.349999904632568,4.510000228881836,4.447461935316068,589300,0.0,0.0,True -2022-08-23 00:00:00-04:00,4.550000190734863,4.78000020980835,4.550000190734863,4.699999809265137,4.634826352563199,526400,0.0,0.0,True -2022-08-24 00:00:00-04:00,4.730000019073486,4.960000038146973,4.730000019073486,4.929999828338623,4.861637339962012,472800,0.0,0.0,True -2022-08-25 00:00:00-04:00,4.96999979019165,5.090000152587891,4.960000038146973,5.059999942779541,4.9898350362770145,453900,0.0,0.0,True -2022-08-26 00:00:00-04:00,5.059999942779541,5.170000076293945,5.010000228881836,5.010000228881836,4.9405283907351105,342300,0.0,0.0,True -2022-08-29 00:00:00-04:00,4.949999809265137,5.199999809265137,4.909999847412109,5.130000114440918,5.058864340035679,319600,0.0,0.0,True -2022-08-30 00:00:00-04:00,5.070000171661377,5.070000171661377,4.900000095367432,4.940000057220459,4.871498669070392,335300,0.0,0.0,True -2022-08-31 00:00:00-04:00,4.849999904632568,5.050000190734863,4.78000020980835,4.880000114440918,4.8123306944201065,517200,0.0,0.0,True -2022-09-01 00:00:00-04:00,4.880000114440918,4.880000114440918,4.570000171661377,4.619999885559082,4.555935719696154,587000,0.0,0.0,True -2022-09-02 00:00:00-04:00,4.840000152587891,4.869999885559082,4.690000057220459,4.699999809265137,4.634826352563199,392000,0.0,0.0,True -2022-09-06 00:00:00-04:00,4.800000190734863,4.860000133514404,4.579999923706055,4.670000076293945,4.605243201050161,545600,0.0,0.0,True -2022-09-07 00:00:00-04:00,4.539999961853027,4.559999942779541,4.400000095367432,4.449999809265137,4.388292706947627,412100,0.0,0.0,True -2022-09-08 00:00:00-04:00,4.449999809265137,4.539999961853027,4.409999847412109,4.480000019073486,4.417877530084874,369200,0.0,0.0,True -2022-09-09 00:00:00-04:00,4.559999942779541,4.809999942779541,4.559999942779541,4.78000020980835,4.7137178212423505,513000,0.0,0.0,True -2022-09-12 00:00:00-04:00,4.789999961853027,4.880000114440918,4.739999771118164,4.829999923706055,4.763024048878203,285000,0.0,0.0,True -2022-09-13 00:00:00-04:00,4.800000190734863,4.849999904632568,4.71999979019165,4.760000228881836,4.693995163025589,225800,0.0,0.0,True -2022-09-14 00:00:00-04:00,4.809999942779541,4.989999771118164,4.78000020980835,4.869999885559082,4.802468947405675,1021100,0.0,0.0,True -2022-09-15 00:00:00-04:00,4.809999942779541,4.920000076293945,4.739999771118164,4.75,4.684133416011156,352500,0.0,0.0,True -2022-09-16 00:00:00-04:00,4.730000019073486,4.730000019073486,4.550000190734863,4.659999847412109,4.595381036129677,702500,0.0,0.0,True -2022-09-19 00:00:00-04:00,4.5,4.659999847412109,4.389999866485596,4.639999866485596,4.575658795818967,537500,0.0,0.0,True -2022-09-20 00:00:00-04:00,4.639999866485596,4.639999866485596,4.429999828338623,4.480000019073486,4.417877530084874,400900,0.0,0.0,True -2022-09-21 00:00:00-04:00,4.519999980926514,4.559999942779541,4.309999942779541,4.320000171661377,4.260095846444729,364600,0.0,0.0,True -2022-09-22 00:00:00-04:00,4.389999866485596,4.449999809265137,4.099999904632568,4.130000114440918,4.072731011291545,515800,0.0,0.0,True -2022-09-23 00:00:00-04:00,4.0,4.0,3.5999999046325684,3.700000047683716,3.6486934417251167,960400,0.0,0.0,True -2022-09-26 00:00:00-04:00,3.690000057220459,3.75,3.3299999237060547,3.369999885559082,3.3232693721955235,683500,0.0,0.0,True -2022-09-27 00:00:00-04:00,3.440000057220459,3.470000028610229,3.3399999141693115,3.380000114440918,3.3331309102569295,931200,0.0,0.0,True -2022-09-28 00:00:00-04:00,3.380000114440918,3.660000085830689,3.359999895095825,3.660000085830689,3.609248125291594,541000,0.0,0.0,True -2022-09-29 00:00:00-04:00,3.5899999141693115,3.75,3.4800000190734863,3.740000009536743,3.688138758158641,640300,0.0,0.0,True -2022-09-30 00:00:00-04:00,3.670000076293945,3.7699999809265137,3.569999933242798,3.700000047683716,3.6486934417251167,536300,0.0,0.0,True -2022-10-03 00:00:00-04:00,3.809999942779541,3.940000057220459,3.7699999809265137,3.900000095367432,3.845920441798786,656400,0.0,0.0,True -2022-10-04 00:00:00-04:00,3.9800000190734863,4.119999885559082,3.9800000190734863,4.010000228881836,3.954394644084923,638800,0.0,0.0,True -2022-10-05 00:00:00-04:00,4.019999980926514,4.269999980926514,3.990000009536743,4.170000076293945,4.112176327725068,615400,0.0,0.0,True -2022-10-06 00:00:00-04:00,4.139999866485596,4.409999847412109,4.139999866485596,4.380000114440918,4.3192642390010665,418100,0.0,0.0,True -2022-10-07 00:00:00-04:00,4.360000133514404,4.440000057220459,4.21999979019165,4.269999980926514,4.210789200902825,673400,0.0,0.0,True -2022-10-11 00:00:00-04:00,4.090000152587891,4.099999904632568,3.859999895095825,3.990000009536743,3.9346724037742127,307800,0.0,0.0,True -2022-10-12 00:00:00-04:00,3.940000057220459,3.9800000190734863,3.839999914169312,3.9700000286102295,3.9149493276513994,371100,0.0,0.0,True -2022-10-13 00:00:00-04:00,3.910000085830689,4.099999904632568,3.910000085830689,4.039999961853027,3.9839790493161167,625900,0.0,0.0,True -2022-10-14 00:00:00-04:00,4.010000228881836,4.070000171661377,3.829999923706055,3.839999914169312,3.7867520492424487,353500,0.0,0.0,True -2022-10-17 00:00:00-04:00,3.890000104904175,3.9700000286102295,3.849999904632568,3.900000095367432,3.845920441798786,546400,0.0,0.0,True -2022-10-18 00:00:00-04:00,3.930000066757202,3.990000009536743,3.829999923706055,3.910000085830689,3.8557817709071665,377200,0.0,0.0,True -2022-10-19 00:00:00-04:00,3.900000095367432,4.0,3.869999885559082,3.990000009536743,3.9346724037742127,379500,0.0,0.0,True -2022-10-20 00:00:00-04:00,4.0,4.130000114440918,3.9600000381469727,3.990000009536743,3.9346724037742127,453900,0.0,0.0,True -2022-10-21 00:00:00-04:00,3.9800000190734863,4.039999961853027,3.930000066757202,3.950000047683716,3.89522708734069,396900,0.0,0.0,True -2022-10-24 00:00:00-04:00,3.9800000190734863,4.059999942779541,3.910000085830689,4.0,3.944533314976542,496100,0.0,0.0,True -2022-10-25 00:00:00-04:00,3.9700000286102295,4.079999923706055,3.9700000286102295,4.059999942779541,4.003700871720775,532500,0.0,0.0,True -2022-10-26 00:00:00-04:00,4.050000190734863,4.230000019073486,4.050000190734863,4.210000038146973,4.151621644158592,877200,0.0,0.0,True -2022-10-27 00:00:00-04:00,4.21999979019165,4.300000190734863,4.130000114440918,4.170000076293945,4.112176327725068,474000,0.0,0.0,True -2022-10-28 00:00:00-04:00,4.119999885559082,4.199999809265137,4.03000020980835,4.070000171661377,4.013563454547312,363900,0.0,0.0,True -2022-10-31 00:00:00-04:00,4.010000228881836,4.230000019073486,4.010000228881836,4.110000133514404,4.053008353074783,628500,0.0,0.0,True -2022-11-01 00:00:00-04:00,4.230000019073486,4.25,4.139999866485596,4.179999828338623,4.122037238927397,319700,0.0,0.0,True -2022-11-02 00:00:00-04:00,4.170000076293945,4.340000152587891,4.110000133514404,4.21999979019165,4.16148255536092,481300,0.0,0.0,True -2022-11-03 00:00:00-04:00,4.190000057220459,4.340000152587891,4.179999828338623,4.289999961853027,4.230512277025638,279400,0.0,0.0,True -2022-11-04 00:00:00-04:00,4.360000133514404,4.590000152587891,4.340000152587891,4.550000190734863,4.48690683384354,741800,0.0,0.0,True -2022-11-07 00:00:00-05:00,4.559999942779541,4.599999904632568,4.5,4.579999923706055,4.516490403262631,366700,0.0,0.0,True -2022-11-08 00:00:00-05:00,4.590000152587891,4.599999904632568,4.460000038146973,4.510000228881836,4.447461935316068,426500,0.0,0.0,True -2022-11-09 00:00:00-05:00,4.099999904632568,4.130000114440918,3.509999990463257,3.5799999237060547,3.5303570745184945,3261400,0.0,0.0,True -2022-11-10 00:00:00-05:00,3.609999895095825,3.609999895095825,3.240000009536743,3.5199999809265137,3.4711897267272875,2489900,0.0,0.0,True -2022-11-11 00:00:00-05:00,3.549999952316284,3.549999952316284,3.369999885559082,3.4800000190734863,3.4317442013407384,1531900,0.0,0.0,True -2022-11-14 00:00:00-05:00,3.4100000858306885,3.619999885559082,3.380000114440918,3.5199999809265137,3.4711897267272875,1636500,0.0,0.0,True -2022-11-15 00:00:00-05:00,3.549999952316284,3.650000095367432,3.509999990463257,3.619999885559082,3.5698023909520185,613200,0.0,0.0,True -2022-11-16 00:00:00-05:00,3.619999885559082,3.619999885559082,3.440000057220459,3.450000047683716,3.4021597961095438,1095300,0.0,0.0,True -2022-11-17 00:00:00-05:00,3.4200000762939453,3.4200000762939453,3.220000028610229,3.359999895095825,3.313407834134116,1058500,0.0,0.0,True -2022-11-18 00:00:00-05:00,3.299999952316284,3.3499999046325684,3.2300000190734863,3.3299999237060547,3.2838238468089744,1005000,0.0,0.0,True -2022-11-21 00:00:00-05:00,3.289999961853028,3.3299999237060547,3.130000114440918,3.289999961853028,3.244378739328476,1701700,0.0,0.0,True -2022-11-22 00:00:00-05:00,3.309999942779541,3.450000047683716,3.309999942779541,3.4100000858306885,3.3627146886290467,668000,0.0,0.0,True -2022-11-23 00:00:00-05:00,3.3399999141693115,3.559999942779541,3.299999952316284,3.4600000381469727,3.412021543123977,626600,0.0,0.0,True -2022-11-24 00:00:00-05:00,3.450000047683716,3.4600000381469727,3.380000114440918,3.430000066757202,3.382437346845809,213400,0.0,0.0,True -2022-11-25 00:00:00-05:00,3.450000047683716,3.4800000190734863,3.369999885559082,3.380000114440918,3.3331309102569295,404100,0.0,0.0,True -2022-11-28 00:00:00-05:00,3.309999942779541,3.359999895095825,3.259999990463257,3.299999952316284,3.2542398594838313,472800,0.0,0.0,True -2022-11-29 00:00:00-05:00,3.3299999237060547,3.4800000190734863,3.309999942779541,3.400000095367432,3.3528533595206658,782700,0.0,0.0,True -2022-11-30 00:00:00-05:00,3.5899999141693115,3.5899999141693115,3.400000095367432,3.400000095367432,3.3528533595206658,1510300,0.0,0.0,True -2022-12-01 00:00:00-05:00,3.4600000381469727,3.549999952316284,3.359999895095825,3.369999885559082,3.3232693721955235,570700,0.0,0.0,True -2022-12-02 00:00:00-05:00,3.369999885559082,3.450000047683716,3.3299999237060547,3.3499999046325684,3.3035469229317878,319600,0.0,0.0,True -2022-12-05 00:00:00-05:00,3.400000095367432,3.470000028610229,3.259999990463257,3.299999952316284,3.2542398594838313,1100300,0.0,0.0,True -2022-12-06 00:00:00-05:00,3.289999961853028,3.3499999046325684,3.0799999237060547,3.0799999237060547,3.037290619099453,1268000,0.0,0.0,True -2022-12-07 00:00:00-05:00,3.0799999237060547,3.180000066757202,2.9800000190734863,3.0899999141693115,3.0471521571608595,769100,0.0,0.0,True -2022-12-08 00:00:00-05:00,3.190000057220459,3.190000057220459,2.990000009536743,3.0299999713897705,2.987984182510575,618300,0.0,0.0,True -2022-12-09 00:00:00-05:00,3.0199999809265137,3.059999942779541,2.950000047683716,3.059999942779541,3.0175681698357177,779100,0.0,0.0,True -2022-12-12 00:00:00-05:00,3.059999942779541,3.0899999141693115,2.950000047683716,2.970000028610229,2.92881620786029,1015200,0.0,0.0,True -2022-12-13 00:00:00-05:00,3.059999942779541,3.130000114440918,2.930000066757202,3.049999952316284,3.007706840727337,1585100,0.0,0.0,True -2022-12-14 00:00:00-05:00,3.0799999237060547,3.119999885559082,3.009999990463257,3.0999999046325684,3.057013277316215,508600,0.0,0.0,True -2022-12-15 00:00:00-05:00,3.049999952316284,3.0799999237060547,2.970000028610229,3.0799999237060547,3.037290619099453,802900,0.0,0.0,True -2022-12-16 00:00:00-05:00,3.009999990463257,3.0299999713897705,2.890000104904175,2.940000057220459,2.8992322205351466,1059300,0.0,0.0,True -2022-12-19 00:00:00-05:00,2.9100000858306885,2.930000066757202,2.680000066757202,2.740000009536743,2.7020054294145046,2117800,0.0,0.0,True -2022-12-20 00:00:00-05:00,2.740000009536743,2.859999895095825,2.7100000381469727,2.8299999237060547,2.790757600342958,988400,0.0,0.0,True -2022-12-21 00:00:00-05:00,2.8399999141693115,3.059999942779541,2.8399999141693115,3.0299999713897705,2.987984182510575,796100,0.0,0.0,True -2022-12-22 00:00:00-05:00,3.049999952316284,3.059999942779541,2.890000104904175,2.9200000762939453,2.8795095623183853,1115000,0.0,0.0,True -2022-12-23 00:00:00-05:00,2.970000028610229,3.190000057220459,2.950000047683716,3.1700000762939453,3.1260427900279066,1357700,0.0,0.0,True -2022-12-28 00:00:00-05:00,3.109999895095825,3.119999885559082,2.9200000762939453,2.940000057220459,2.8992322205351466,1075500,0.0,0.0,True -2022-12-29 00:00:00-05:00,2.9200000762939453,3.009999990463257,2.9200000762939453,2.990000009536743,2.9485386571240255,471300,0.0,0.0,True -2022-12-30 00:00:00-05:00,2.9600000381469727,3.0299999713897705,2.9600000381469727,3.0,2.958400404138459,573100,0.0,0.0,True -2023-01-03 00:00:00-05:00,2.970000028610229,3.0,2.75,2.7699999809265137,2.7315894167396477,766300,0.0,0.0,True -2023-01-04 00:00:00-05:00,2.7699999809265137,2.7799999713897705,2.680000066757202,2.7100000381469727,2.672421442089362,735100,0.0,0.0,True -2023-01-05 00:00:00-05:00,2.690000057220459,2.7699999809265137,2.680000066757202,2.7100000381469727,2.672421442089362,716200,0.0,0.0,True -2023-01-06 00:00:00-05:00,2.7300000190734863,2.809999942779541,2.7300000190734863,2.799999952316284,2.7611734040647895,333100,0.0,0.0,True -2023-01-09 00:00:00-05:00,2.859999895095825,2.950000047683716,2.819999933242798,2.880000114440918,2.8400642458848626,491400,0.0,0.0,True -2023-01-10 00:00:00-05:00,2.859999895095825,2.9100000858306885,2.809999942779541,2.890000104904175,2.8499251570871906,418900,0.0,0.0,True -2023-01-11 00:00:00-05:00,2.890000104904175,2.990000009536743,2.890000104904175,2.9200000762939453,2.8795095623183853,808900,0.0,0.0,True -2023-01-12 00:00:00-05:00,2.970000028610229,3.0799999237060547,2.950000047683716,3.039999961853028,2.997845093712904,900700,0.0,0.0,True -2023-01-13 00:00:00-05:00,3.039999961853028,3.0999999046325684,2.9800000190734863,3.0299999713897705,2.987984182510575,625000,0.0,0.0,True -2023-01-16 00:00:00-05:00,3.0299999713897705,3.039999961853028,3.0,3.009999990463257,2.968261315340787,360400,0.0,0.0,True -2023-01-17 00:00:00-05:00,3.059999942779541,3.1700000762939453,3.0,3.150000095367432,3.1063201318111444,699200,0.0,0.0,True -2023-01-18 00:00:00-05:00,3.190000057220459,3.289999961853028,3.130000114440918,3.130000114440918,3.0865976825474095,707500,0.0,0.0,True -2023-01-19 00:00:00-05:00,3.130000114440918,3.140000104904175,3.0299999713897705,3.119999885559082,3.0767359355329766,291600,0.0,0.0,True -2023-01-20 00:00:00-05:00,3.109999895095825,3.1600000858306885,3.0799999237060547,3.119999885559082,3.0767359355329766,191000,0.0,0.0,True -2023-01-23 00:00:00-05:00,3.140000104904175,3.180000066757202,3.069999933242798,3.109999895095825,3.0668746064245958,329700,0.0,0.0,True -2023-01-24 00:00:00-05:00,3.059999942779541,3.0899999141693115,3.009999990463257,3.0199999809265137,2.9781228534021937,496300,0.0,0.0,True -2023-01-25 00:00:00-05:00,3.009999990463257,3.049999952316284,2.930000066757202,3.049999952316284,3.007706840727337,415700,0.0,0.0,True -2023-01-26 00:00:00-05:00,3.049999952316284,3.0899999141693115,2.990000009536743,3.039999961853028,2.997845093712904,243700,0.0,0.0,True -2023-01-27 00:00:00-05:00,3.0299999713897705,3.069999933242798,2.9600000381469727,3.0199999809265137,2.9781228534021937,432400,0.0,0.0,True -2023-01-30 00:00:00-05:00,2.9800000190734863,2.9800000190734863,2.869999885559082,2.890000104904175,2.8499251570871906,427200,0.0,0.0,True -2023-01-31 00:00:00-05:00,2.859999895095825,2.9600000381469727,2.809999942779541,2.9600000381469727,2.918954878751909,428900,0.0,0.0,True -2023-02-01 00:00:00-05:00,2.9600000381469727,3.0,2.880000114440918,2.940000057220459,2.8992322205351466,800000,0.0,0.0,True -2023-02-02 00:00:00-05:00,2.970000028610229,2.970000028610229,2.8499999046325684,2.880000114440918,2.8400642458848626,552400,0.0,0.0,True -2023-02-03 00:00:00-05:00,2.869999885559082,2.950000047683716,2.859999895095825,2.900000095367432,2.8597866951485984,468600,0.0,0.0,True -2023-02-06 00:00:00-05:00,2.900000095367432,2.9200000762939453,2.8299999237060547,2.8399999141693115,2.8006185115452866,214400,0.0,0.0,True -2023-02-07 00:00:00-05:00,2.869999885559082,3.0899999141693115,2.859999895095825,3.0899999141693115,3.0471521571608595,736000,0.0,0.0,True -2023-02-08 00:00:00-05:00,3.0999999046325684,3.109999895095825,3.0,3.0,2.958400404138459,293100,0.0,0.0,True -2023-02-09 00:00:00-05:00,2.970000028610229,3.039999961853028,2.970000028610229,3.0199999809265137,2.9781228534021937,290000,0.0,0.0,True -2023-02-10 00:00:00-05:00,3.009999990463257,3.0899999141693115,3.009999990463257,3.049999952316284,3.007706840727337,319600,0.0,0.0,True -2023-02-13 00:00:00-05:00,3.0899999141693115,3.0899999141693115,2.970000028610229,3.0,2.958400404138459,494600,0.0,0.0,True -2023-02-14 00:00:00-05:00,2.990000009536743,3.009999990463257,2.950000047683716,3.0,2.958400404138459,354700,0.0,0.0,True -2023-02-15 00:00:00-05:00,2.970000028610229,2.990000009536743,2.890000104904175,2.970000028610229,2.92881620786029,301400,0.0,0.0,True -2023-02-16 00:00:00-05:00,2.940000057220459,3.0,2.9200000762939453,2.990000009536743,2.9485386571240255,212600,0.0,0.0,True -2023-02-17 00:00:00-05:00,2.930000066757202,2.930000066757202,2.759999990463257,2.7799999713897705,2.7414505368950017,823900,0.0,0.0,True -2023-02-21 00:00:00-05:00,2.809999942779541,2.8299999237060547,2.7100000381469727,2.720000028610229,2.682282562244717,352700,0.0,0.0,True -2023-02-22 00:00:00-05:00,2.740000009536743,2.740000009536743,2.640000104904175,2.6600000858306885,2.623114796547458,343700,0.0,0.0,True -2023-02-23 00:00:00-05:00,2.700000047683716,2.7799999713897705,2.6600000858306885,2.75,2.7118667585228855,292200,0.0,0.0,True -2023-02-24 00:00:00-05:00,2.700000047683716,2.799999952316284,2.700000047683716,2.7799999713897705,2.7414505368950017,322100,0.0,0.0,True -2023-02-27 00:00:00-05:00,2.809999942779541,2.9100000858306885,2.75,2.880000114440918,2.8400642458848626,268200,0.0,0.0,True -2023-02-28 00:00:00-05:00,2.880000114440918,2.9200000762939453,2.819999933242798,2.8499999046325684,2.8104802585597204,917800,0.0,0.0,True -2023-03-01 00:00:00-05:00,2.859999895095825,2.9800000190734863,2.859999895095825,2.9800000190734863,2.938677328015644,327600,0.0,0.0,True -2023-03-02 00:00:00-05:00,3.0,3.0299999713897705,2.9200000762939453,2.9600000381469727,2.918954878751909,287600,0.0,0.0,True -2023-03-03 00:00:00-05:00,2.9100000858306885,3.0799999237060547,2.9100000858306885,3.049999952316284,3.007706840727337,289700,0.0,0.0,True -2023-03-06 00:00:00-05:00,3.059999942779541,3.059999942779541,2.970000028610229,3.009999990463257,2.968261315340787,232100,0.0,0.0,True -2023-03-07 00:00:00-05:00,2.9800000190734863,3.0,2.880000114440918,2.9100000858306885,2.8696482332100053,279700,0.0,0.0,True -2023-03-08 00:00:00-05:00,2.970000028610229,3.059999942779541,2.900000095367432,2.9600000381469727,2.918954878751909,455000,0.0,0.0,True -2023-03-09 00:00:00-05:00,3.0,3.180000066757202,2.990000009536743,3.009999990463257,2.968261315340787,336300,0.0,0.0,True -2023-03-10 00:00:00-05:00,3.009999990463257,3.059999942779541,2.9100000858306885,2.950000047683716,2.909093340690502,350400,0.0,0.0,True -2023-03-13 00:00:00-04:00,2.8299999237060547,2.9100000858306885,2.75,2.900000095367432,2.8597866951485984,435800,0.0,0.0,True -2023-03-14 00:00:00-04:00,2.869999885559082,2.950000047683716,2.8399999141693115,2.880000114440918,2.8443894812602815,231900,0.00441,0.0,True -2023-03-15 00:00:00-04:00,2.75,2.759999990463257,2.470000028610229,2.630000114440918,2.597480557521533,1133800,0.0,0.0,True -2023-03-16 00:00:00-04:00,2.650000095367432,2.7300000190734863,2.569999933242798,2.720000028610229,2.6863676068156948,420000,0.0,0.0,True +2022-01-04 00:00:00-05:00,3.8299999237060547,4.269999980926514,3.8299999237060547,4.0,3.3497861392076005,559600,0.0,0.0,True +2022-01-05 00:00:00-05:00,4.050000190734863,4.199999809265137,4.039999961853027,4.050000190734863,3.3916584482029357,467700,0.0,0.0,True +2022-01-06 00:00:00-05:00,4.150000095367432,4.179999828338623,4.050000190734863,4.090000152587891,3.4251562953992045,393300,0.0,0.0,True +2022-01-07 00:00:00-05:00,4.130000114440918,4.230000019073486,4.070000171661377,4.159999847412109,3.4837778828878645,860600,0.0,0.0,True +2022-01-10 00:00:00-05:00,4.199999809265137,4.199999809265137,4.119999885559082,4.199999809265137,3.5172753751889427,281900,0.0,0.0,True +2022-01-11 00:00:00-05:00,4.199999809265137,4.460000038146973,4.159999847412109,4.420000076293945,3.701514244558799,695900,0.0,0.0,True +2022-01-12 00:00:00-05:00,4.449999809265137,4.639999866485596,4.449999809265137,4.579999923706055,3.8355049235534926,452500,0.0,0.0,True +2022-01-13 00:00:00-05:00,4.590000152587891,4.639999866485596,4.420000076293945,4.46999979019165,3.743385843763754,373700,0.0,0.0,True +2022-01-14 00:00:00-05:00,4.480000019073486,4.590000152587891,4.429999828338623,4.559999942779541,3.818755999955358,339600,0.0,0.0,True +2022-01-17 00:00:00-05:00,4.570000171661377,4.760000228881836,4.519999980926514,4.679999828338623,3.919249896439353,317900,0.0,0.0,True +2022-01-18 00:00:00-05:00,4.75,4.78000020980835,4.650000095367432,4.659999847412109,3.9025006179460293,317400,0.0,0.0,True +2022-01-19 00:00:00-05:00,4.71999979019165,4.730000019073486,4.489999771118164,4.519999980926514,3.7852581527590896,642600,0.0,0.0,True +2022-01-20 00:00:00-05:00,4.400000095367432,4.639999866485596,4.320000171661377,4.539999961853027,3.8020077861476045,780900,0.0,0.0,True +2022-01-21 00:00:00-05:00,4.460000038146973,4.579999923706055,4.369999885559082,4.420000076293945,3.701514244558799,426200,0.0,0.0,True +2022-01-24 00:00:00-05:00,4.309999942779541,4.400000095367432,4.070000171661377,4.380000114440918,3.6680160424673405,391900,0.0,0.0,True +2022-01-25 00:00:00-05:00,4.400000095367432,4.639999866485596,4.309999942779541,4.579999923706055,3.8355049235534926,461500,0.0,0.0,True +2022-01-26 00:00:00-05:00,4.699999809265137,4.75,4.550000190734863,4.570000171661377,3.8271308166496154,229400,0.0,0.0,True +2022-01-27 00:00:00-05:00,4.590000152587891,4.699999809265137,4.429999828338623,4.480000019073486,3.7517606604580114,1782700,0.0,0.0,True +2022-01-28 00:00:00-05:00,4.539999961853027,4.699999809265137,4.53000020980835,4.690000057220459,3.927624003343231,340300,0.0,0.0,True +2022-01-31 00:00:00-05:00,4.670000076293945,4.960000038146973,4.670000076293945,4.889999866485596,4.095113949114952,341600,0.0,0.0,True +2022-02-01 00:00:00-05:00,4.900000095367432,4.900000095367432,4.75,4.809999942779541,4.028117899827226,245000,0.0,0.0,True +2022-02-02 00:00:00-05:00,4.789999961853027,4.880000114440918,4.659999847412109,4.75,3.977871129032823,335900,0.0,0.0,True +2022-02-03 00:00:00-05:00,4.71999979019165,4.800000190734863,4.579999923706055,4.730000019073486,3.961122205434689,567100,0.0,0.0,True +2022-02-04 00:00:00-05:00,4.760000228881836,4.980000019073486,4.760000228881836,4.880000114440918,4.086739132420695,728600,0.0,0.0,True +2022-02-07 00:00:00-05:00,4.800000190734863,4.849999904632568,4.639999866485596,4.670000076293945,3.9108757895354764,509100,0.0,0.0,True +2022-02-08 00:00:00-05:00,4.650000095367432,4.650000095367432,4.360000133514404,4.460000038146973,3.735011736859877,520500,0.0,0.0,True +2022-02-09 00:00:00-05:00,4.46999979019165,4.619999885559082,4.449999809265137,4.550000190734863,3.8103818930514812,225400,0.0,0.0,True +2022-02-10 00:00:00-05:00,4.519999980926514,4.610000133514404,4.449999809265137,4.510000228881836,3.776884400750403,225300,0.0,0.0,True +2022-02-11 00:00:00-05:00,4.5,4.630000114440918,4.489999771118164,4.630000114440918,3.8773779423392076,380600,0.0,0.0,True +2022-02-14 00:00:00-05:00,4.5,4.550000190734863,4.400000095367432,4.510000228881836,3.776884400750403,507600,0.0,0.0,True +2022-02-15 00:00:00-05:00,4.420000076293945,4.71999979019165,4.420000076293945,4.690000057220459,3.927624003343231,342800,0.0,0.0,True +2022-02-16 00:00:00-05:00,4.699999809265137,4.800000190734863,4.539999961853027,4.579999923706055,3.8355049235534926,508700,0.0,0.0,True +2022-02-17 00:00:00-05:00,4.599999904632568,4.659999847412109,4.519999980926514,4.570000171661377,3.8271308166496154,309900,0.0,0.0,True +2022-02-18 00:00:00-05:00,4.510000228881836,4.559999942779541,4.380000114440918,4.420000076293945,3.701514244558799,191700,0.0,0.0,True +2022-02-22 00:00:00-05:00,4.460000038146973,4.599999904632568,4.429999828338623,4.53000020980835,3.793632969453347,1063700,0.0,0.0,True +2022-02-23 00:00:00-05:00,4.590000152587891,4.739999771118164,4.559999942779541,4.679999828338623,3.919249896439353,256600,0.0,0.0,True +2022-02-24 00:00:00-05:00,4.699999809265137,4.820000171661377,4.559999942779541,4.670000076293945,3.9108757895354764,392200,0.0,0.0,True +2022-02-25 00:00:00-05:00,4.659999847412109,4.880000114440918,4.630000114440918,4.849999904632568,4.061615747023494,264400,0.0,0.0,True +2022-02-28 00:00:00-05:00,4.880000114440918,5.099999904632568,4.869999885559082,5.079999923706055,4.254228368402038,543200,0.0,0.0,True +2022-03-01 00:00:00-05:00,5.159999847412109,5.28000020980835,5.03000020980835,5.179999828338623,4.337972986392709,481700,0.0,0.0,True +2022-03-02 00:00:00-05:00,5.239999771118164,5.309999942779541,5.079999923706055,5.179999828338623,4.337972986392709,232200,0.0,0.0,True +2022-03-03 00:00:00-05:00,5.21999979019165,5.230000019073486,4.949999809265137,4.96999979019165,4.1621092886122995,234500,0.0,0.0,True +2022-03-04 00:00:00-05:00,5.03000020980835,5.389999866485596,5.03000020980835,5.360000133514404,4.488714008566296,1110400,0.0,0.0,True +2022-03-07 00:00:00-05:00,5.570000171661377,5.849999904632568,5.440000057220459,5.650000095367432,4.731573045844052,738400,0.0,0.0,True +2022-03-08 00:00:00-05:00,5.829999923706055,5.889999866485596,5.46999979019165,5.679999828338623,4.7566960763460635,733300,0.0,0.0,True +2022-03-09 00:00:00-05:00,5.300000190734863,5.639999866485596,5.199999809265137,5.21999979019165,4.371470478693786,796500,0.0,0.0,True +2022-03-10 00:00:00-05:00,5.360000133514404,5.449999809265137,5.239999771118164,5.309999942779541,4.446840989780581,454800,0.0,0.0,True +2022-03-11 00:00:00-05:00,5.289999961853027,5.329999923706055,5.110000133514404,5.25,4.3965945738813685,222100,0.0,0.0,True +2022-03-14 00:00:00-04:00,5.050000190734863,5.099999904632568,4.559999942779541,4.789999961853027,4.011368976229091,642400,0.0,0.0,True +2022-03-15 00:00:00-04:00,4.53000020980835,4.889999866485596,4.420000076293945,4.610000133514404,3.8606286638458838,594600,0.0,0.0,True +2022-03-16 00:00:00-04:00,4.579999923706055,4.829999923706055,4.579999923706055,4.679999828338623,3.919249896439353,583800,0.0,0.0,True +2022-03-17 00:00:00-04:00,4.789999961853027,4.960000038146973,4.739999771118164,4.800000190734863,4.019743792923348,654300,0.0,0.0,True +2022-03-18 00:00:00-04:00,4.71999979019165,4.920000076293945,4.710000038146973,4.71999979019165,3.9527477436356215,284100,0.0,0.0,True +2022-03-21 00:00:00-04:00,4.829999923706055,5.010000228881836,4.820000171661377,4.980000019073486,4.170484105306556,344500,0.0,0.0,True +2022-03-22 00:00:00-04:00,4.96999979019165,4.96999979019165,4.820000171661377,4.940000057220459,4.136985903215098,374000,0.0,0.0,True +2022-03-23 00:00:00-04:00,5.010000228881836,5.099999904632568,4.940000057220459,4.940000057220459,4.136985903215098,535800,0.0,0.0,True +2022-03-24 00:00:00-04:00,5.0,5.0,4.840000152587891,4.900000095367432,4.10348841091402,385800,0.0,0.0,True +2022-03-25 00:00:00-04:00,4.849999904632568,5.21999979019165,4.840000152587891,5.179999828338623,4.337972986392709,821200,0.0,0.0,True +2022-03-28 00:00:00-04:00,4.900000095367432,5.110000133514404,4.900000095367432,5.070000171661377,4.2458542614981605,338100,0.0,0.0,True +2022-03-29 00:00:00-04:00,4.940000057220459,5.230000019073486,4.809999942779541,5.210000038146973,4.36309637178991,628200,0.0,0.0,True +2022-03-30 00:00:00-04:00,5.269999980926514,5.400000095367432,5.269999980926514,5.369999885559082,4.497088115470174,448200,0.0,0.0,True +2022-03-31 00:00:00-04:00,5.300000190734863,5.409999847412109,5.260000228881836,5.309999942779541,4.446840989780581,308000,0.0,0.0,True +2022-04-01 00:00:00-04:00,5.210000038146973,5.400000095367432,5.210000038146973,5.28000020980835,4.42171795927857,279000,0.0,0.0,True +2022-04-04 00:00:00-04:00,5.349999904632568,5.429999828338623,5.260000228881836,5.300000190734863,4.438466882876704,298100,0.0,0.0,True +2022-04-05 00:00:00-04:00,5.329999923706055,5.420000076293945,5.199999809265137,5.21999979019165,4.371470478693786,308800,0.0,0.0,True +2022-04-06 00:00:00-04:00,5.179999828338623,5.309999942779541,5.090000152587891,5.119999885559082,4.287726215598306,395100,0.0,0.0,True +2022-04-07 00:00:00-04:00,5.159999847412109,5.230000019073486,5.03000020980835,5.179999828338623,4.337972986392709,277200,0.0,0.0,True +2022-04-08 00:00:00-04:00,5.230000019073486,5.400000095367432,5.190000057220459,5.349999904632568,4.480338836976849,281000,0.0,0.0,True +2022-04-11 00:00:00-04:00,5.389999866485596,5.389999866485596,5.210000038146973,5.309999942779541,4.446840989780581,474300,0.0,0.0,True +2022-04-12 00:00:00-04:00,5.400000095367432,5.5,5.300000190734863,5.329999923706055,4.463590268273905,440400,0.0,0.0,True +2022-04-13 00:00:00-04:00,5.400000095367432,5.46999979019165,5.309999942779541,5.360000133514404,4.488714008566296,553200,0.0,0.0,True +2022-04-14 00:00:00-04:00,5.369999885559082,5.510000228881836,5.349999904632568,5.429999828338623,4.547334531369386,399900,0.0,0.0,True +2022-04-18 00:00:00-04:00,5.460000038146973,5.639999866485596,5.400000095367432,5.550000190734863,4.647828427853381,412700,0.0,0.0,True +2022-04-19 00:00:00-04:00,5.489999771118164,5.489999771118164,5.21999979019165,5.329999923706055,4.463590268273905,375600,0.0,0.0,True +2022-04-20 00:00:00-04:00,5.329999923706055,5.400000095367432,5.25,5.28000020980835,4.42171795927857,245400,0.0,0.0,True +2022-04-21 00:00:00-04:00,5.289999961853027,5.389999866485596,5.0,5.059999942779541,4.237479799699093,441300,0.0,0.0,True +2022-04-22 00:00:00-04:00,5.059999942779541,5.059999942779541,4.820000171661377,4.829999923706055,4.04486682342536,444800,0.0,0.0,True +2022-04-25 00:00:00-04:00,4.610000133514404,4.800000190734863,4.5,4.739999771118164,3.969496312338566,598100,0.0,0.0,True +2022-04-26 00:00:00-04:00,4.78000020980835,4.929999828338623,4.730000019073486,4.820000171661377,4.036492361626292,362000,0.0,0.0,True +2022-04-27 00:00:00-04:00,4.820000171661377,4.909999847412109,4.710000038146973,4.880000114440918,4.086739132420695,306800,0.0,0.0,True +2022-04-28 00:00:00-04:00,4.920000076293945,4.989999771118164,4.800000190734863,4.949999809265137,4.145360365014165,337000,0.0,0.0,True +2022-04-29 00:00:00-04:00,4.960000038146973,5.0,4.769999980926514,4.820000171661377,4.036492361626292,312400,0.0,0.0,True +2022-05-02 00:00:00-04:00,4.710000038146973,4.829999923706055,4.630000114440918,4.730000019073486,3.961122205434689,438800,0.0,0.0,True +2022-05-03 00:00:00-04:00,4.710000038146973,5.03000020980835,4.710000038146973,4.96999979019165,4.1621092886122995,675000,0.0,0.0,True +2022-05-04 00:00:00-04:00,5.0,5.079999923706055,4.900000095367432,5.050000190734863,4.229104983004836,1268500,0.0,0.0,True +2022-05-05 00:00:00-04:00,5.099999904632568,5.150000095367432,4.860000133514404,5.03000020980835,4.212356059406702,356000,0.0,0.0,True +2022-05-06 00:00:00-04:00,4.96999979019165,5.139999866485596,4.880000114440918,4.940000057220459,4.136985903215098,250600,0.0,0.0,True +2022-05-09 00:00:00-04:00,4.78000020980835,4.78000020980835,4.460000038146973,4.579999923706055,3.8355049235534926,587200,0.0,0.0,True +2022-05-10 00:00:00-04:00,4.650000095367432,4.75,4.440000057220459,4.539999961853027,3.8020077861476045,359400,0.0,0.0,True +2022-05-11 00:00:00-04:00,4.670000076293945,4.670000076293945,4.21999979019165,4.329999923706055,3.626143733472005,709200,0.0,0.0,True +2022-05-12 00:00:00-04:00,4.349999904632568,4.489999771118164,4.25,4.380000114440918,3.6680160424673405,564300,0.0,0.0,True +2022-05-13 00:00:00-04:00,4.429999828338623,4.840000152587891,4.429999828338623,4.769999980926514,3.994620052630957,800600,0.0,0.0,True +2022-05-16 00:00:00-04:00,4.769999980926514,5.010000228881836,4.760000228881836,4.920000076293945,4.120236624721774,430900,0.0,0.0,True +2022-05-17 00:00:00-04:00,5.0,5.159999847412109,4.989999771118164,5.130000114440918,4.296101032292563,491800,0.0,0.0,True +2022-05-18 00:00:00-04:00,5.239999771118164,5.28000020980835,4.949999809265137,5.059999942779541,4.237479799699093,526000,0.0,0.0,True +2022-05-19 00:00:00-04:00,4.940000057220459,5.28000020980835,4.940000057220459,5.230000019073486,4.3798460051784245,440200,0.0,0.0,True +2022-05-20 00:00:00-04:00,5.179999828338623,5.400000095367432,5.179999828338623,5.349999904632568,4.480338836976849,510600,0.0,0.0,True +2022-05-24 00:00:00-04:00,5.320000171661377,5.579999923706055,5.300000190734863,5.570000171661377,4.664577351451515,522100,0.0,0.0,True +2022-05-25 00:00:00-04:00,5.599999904632568,5.760000228881836,5.550000190734863,5.690000057220459,4.7650708930403205,634300,0.0,0.0,True +2022-05-26 00:00:00-04:00,5.849999904632568,5.849999904632568,5.610000133514404,5.610000133514404,4.698074843752594,492900,0.0,0.0,True +2022-05-27 00:00:00-04:00,5.619999885559082,5.78000020980835,5.590000152587891,5.78000020980835,4.840440694336735,746000,0.0,0.0,True +2022-05-30 00:00:00-04:00,5.840000152587891,6.139999866485596,5.840000152587891,6.139999866485596,5.141921673998341,430100,0.0,0.0,True +2022-05-31 00:00:00-04:00,6.150000095367432,6.170000076293945,5.710000038146973,5.840000152587891,4.890688174921517,3694200,0.0,0.0,True +2022-06-01 00:00:00-04:00,5.96999979019165,6.099999904632568,5.849999904632568,5.949999809265137,4.982807254711255,478200,0.0,0.0,True +2022-06-02 00:00:00-04:00,5.949999809265137,6.070000171661377,5.860000133514404,6.0,5.024679918601781,243400,0.0,0.0,True +2022-06-03 00:00:00-04:00,5.960000038146973,6.210000038146973,5.889999866485596,6.190000057220459,5.183794337888866,758200,0.0,0.0,True +2022-06-06 00:00:00-04:00,6.300000190734863,6.369999885559082,6.039999961853027,6.369999885559082,5.334534295376884,489200,0.0,0.0,True +2022-06-07 00:00:00-04:00,6.369999885559082,6.679999828338623,6.269999980926514,6.570000171661377,5.5020242411486056,647300,0.0,0.0,True +2022-06-08 00:00:00-04:00,6.699999809265137,6.71999979019165,6.380000114440918,6.460000038146973,5.409904451568487,727300,0.0,0.0,True +2022-06-09 00:00:00-04:00,6.46999979019165,6.46999979019165,6.28000020980835,6.28000020980835,5.259164848975659,508200,0.0,0.0,True +2022-06-10 00:00:00-04:00,6.28000020980835,6.309999942779541,6.050000190734863,6.170000076293945,5.167045414290732,448700,0.0,0.0,True +2022-06-13 00:00:00-04:00,6.0,6.079999923706055,5.710000038146973,6.070000171661377,5.08330044140487,462500,0.0,0.0,True +2022-06-14 00:00:00-04:00,6.199999809265137,6.199999809265137,5.670000076293945,5.690000057220459,4.7650708930403205,506000,0.0,0.0,True +2022-06-15 00:00:00-04:00,5.75,5.789999961853027,5.449999809265137,5.519999980926514,4.62270468756099,632600,0.0,0.0,True +2022-06-16 00:00:00-04:00,5.260000228881836,5.409999847412109,5.119999885559082,5.130000114440918,4.296101032292563,745300,0.0,0.0,True +2022-06-17 00:00:00-04:00,5.150000095367432,5.25,4.5,4.599999904632568,3.852254202046817,2540000,0.0,0.0,True +2022-06-20 00:00:00-04:00,4.579999923706055,4.739999771118164,4.519999980926514,4.690000057220459,3.927624003343231,273900,0.0,0.0,True +2022-06-21 00:00:00-04:00,4.800000190734863,4.949999809265137,4.710000038146973,4.769999980926514,3.994620052630957,592700,0.0,0.0,True +2022-06-22 00:00:00-04:00,4.449999809265137,4.460000038146973,4.300000190734863,4.309999942779541,3.609394454978681,809900,0.0,0.0,True +2022-06-23 00:00:00-04:00,4.329999923706055,4.389999866485596,3.740000009536743,3.8499999046325684,3.224168857326404,1175400,0.0,0.0,True +2022-06-24 00:00:00-04:00,3.9100000858306885,4.170000076293945,3.880000114440918,3.9700000286102295,3.324662753810399,708700,0.0,0.0,True +2022-06-27 00:00:00-04:00,4.070000171661377,4.159999847412109,3.930000066757202,4.099999904632568,3.4335304023030813,638900,0.0,0.0,True +2022-06-28 00:00:00-04:00,4.199999809265137,4.400000095367432,4.179999828338623,4.309999942779541,3.609394454978681,998100,0.0,0.0,True +2022-06-29 00:00:00-04:00,4.349999904632568,4.400000095367432,4.090000152587891,4.099999904632568,3.4335304023030813,623400,0.0,0.0,True +2022-06-30 00:00:00-04:00,4.0,4.110000133514404,3.8499999046325684,3.9800000190734863,3.3330372156094663,788400,0.0,0.0,True +2022-07-04 00:00:00-04:00,4.019999980926514,4.050000190734863,3.890000104904175,4.03000020980835,3.3749098794999917,501500,0.0,0.0,True +2022-07-05 00:00:00-04:00,3.9000000953674316,3.930000066757202,3.680000066757202,3.799999952316284,3.1822969032262587,1068800,0.0,0.0,True +2022-07-06 00:00:00-04:00,3.7100000381469727,3.8499999046325684,3.380000114440918,3.4700000286102295,2.9059396638570445,785800,0.0,0.0,True +2022-07-07 00:00:00-04:00,3.640000104904175,3.7899999618530273,3.640000104904175,3.7300000190734863,3.123675670632789,537500,0.0,0.0,True +2022-07-08 00:00:00-04:00,3.75,3.880000114440918,3.640000104904175,3.799999952316284,3.1822969032262587,380000,0.0,0.0,True +2022-07-11 00:00:00-04:00,3.740000009536743,3.890000104904175,3.640000104904175,3.8299999237060547,3.2074202886234597,1113200,0.0,0.0,True +2022-07-12 00:00:00-04:00,3.7100000381469727,3.7899999618530273,3.5199999809265137,3.5399999618530273,2.964560719002919,693900,0.0,0.0,True +2022-07-13 00:00:00-04:00,3.4600000381469727,3.5799999237060547,3.440000057220459,3.509999990463257,2.9394373336057176,537100,0.0,0.0,True +2022-07-14 00:00:00-04:00,3.380000114440918,3.4600000381469727,3.259999990463257,3.440000057220459,2.880816278459843,877700,0.0,0.0,True +2022-07-15 00:00:00-04:00,3.5199999809265137,3.609999895095825,3.390000104904175,3.5299999713897705,2.9561862572038518,565800,0.0,0.0,True +2022-07-18 00:00:00-04:00,3.5799999237060547,3.809999942779541,3.559999942779541,3.7699999809265137,3.157173517829057,1215000,0.0,0.0,True +2022-07-19 00:00:00-04:00,3.759999990463257,3.880000114440918,3.740000009536743,3.8499999046325684,3.224168857326404,861800,0.0,0.0,True +2022-07-20 00:00:00-04:00,3.819999933242798,3.890000104904175,3.7300000190734863,3.859999895095825,3.232543319125471,397100,0.0,0.0,True +2022-07-21 00:00:00-04:00,3.740000009536743,3.799999952316284,3.619999885559082,3.7100000381469727,3.1069267470346547,481600,0.0,0.0,True +2022-07-22 00:00:00-04:00,3.740000009536743,3.7899999618530273,3.630000114440918,3.630000114440918,3.0399310526421175,547400,0.0,0.0,True +2022-07-25 00:00:00-04:00,3.6500000953674316,3.890000104904175,3.609999895095825,3.8399999141693115,3.215794750422527,617400,0.0,0.0,True +2022-07-26 00:00:00-04:00,3.9000000953674316,3.9800000190734863,3.7899999618530273,3.869999885559082,3.2409181358197285,538400,0.0,0.0,True +2022-07-27 00:00:00-04:00,3.8499999046325684,4.03000020980835,3.8499999046325684,4.0,3.3497861392076005,607300,0.0,0.0,True +2022-07-28 00:00:00-04:00,4.059999942779541,4.190000057220459,4.019999980926514,4.090000152587891,3.4251562953992045,850200,0.0,0.0,True +2022-07-29 00:00:00-04:00,4.190000057220459,4.369999885559082,4.130000114440918,4.289999961853027,3.5926458862757364,953100,0.0,0.0,True +2022-08-02 00:00:00-04:00,4.239999771118164,4.239999771118164,4.03000020980835,4.059999942779541,3.4000325551068133,471000,0.0,0.0,True +2022-08-03 00:00:00-04:00,4.090000152587891,4.110000133514404,3.8399999141693115,3.930000066757202,3.2911652615093208,677200,0.0,0.0,True +2022-08-04 00:00:00-04:00,3.859999895095825,3.880000114440918,3.680000066757202,3.680000066757202,3.081803361637453,809500,0.0,0.0,True +2022-08-05 00:00:00-04:00,3.609999895095825,3.890000104904175,3.609999895095825,3.8499999046325684,3.224168857326404,380700,0.0,0.0,True +2022-08-08 00:00:00-04:00,3.799999952316284,3.940000057220459,3.759999990463257,3.940000057220459,3.2995393684131984,429300,0.0,0.0,True +2022-08-09 00:00:00-04:00,4.0,4.03000020980835,3.950000047683716,4.010000228881836,3.3581606010066674,328300,0.0,0.0,True +2022-08-10 00:00:00-04:00,4.039999961853027,4.039999961853027,3.9000000953674316,3.990000009536743,3.3414120323037233,848100,0.0,0.0,True +2022-08-11 00:00:00-04:00,4.03000020980835,4.190000057220459,3.990000009536743,4.159999847412109,3.4837778828878645,4875600,0.0,0.0,True +2022-08-12 00:00:00-04:00,4.150000095367432,4.420000076293945,4.110000133514404,4.300000190734863,3.6010203480748033,1629200,0.0,0.0,True +2022-08-15 00:00:00-04:00,4.110000133514404,4.369999885559082,4.03000020980835,4.300000190734863,3.6010203480748033,712300,0.0,0.0,True +2022-08-16 00:00:00-04:00,4.369999885559082,4.489999771118164,4.21999979019165,4.289999961853027,3.5926458862757364,596600,0.0,0.0,True +2022-08-17 00:00:00-04:00,4.269999980926514,4.389999866485596,4.21999979019165,4.28000020980835,3.5842717793718593,404100,0.0,0.0,True +2022-08-18 00:00:00-04:00,4.349999904632568,4.639999866485596,4.349999904632568,4.550000190734863,3.8103818930514812,1213700,0.0,0.0,True +2022-08-19 00:00:00-04:00,4.610000133514404,4.650000095367432,4.489999771118164,4.5,3.7685095840561456,348900,0.0,0.0,True +2022-08-22 00:00:00-04:00,4.460000038146973,4.519999980926514,4.349999904632568,4.510000228881836,3.776884400750403,589300,0.0,0.0,True +2022-08-23 00:00:00-04:00,4.550000190734863,4.78000020980835,4.550000190734863,4.699999809265137,3.9359984651422977,526400,0.0,0.0,True +2022-08-24 00:00:00-04:00,4.730000019073486,4.960000038146973,4.730000019073486,4.929999828338623,4.128611441416031,472800,0.0,0.0,True +2022-08-25 00:00:00-04:00,4.96999979019165,5.090000152587891,4.960000038146973,5.059999942779541,4.237479799699093,453900,0.0,0.0,True +2022-08-26 00:00:00-04:00,5.059999942779541,5.170000076293945,5.010000228881836,5.010000228881836,4.1956074907037575,342300,0.0,0.0,True +2022-08-29 00:00:00-04:00,4.949999809265137,5.199999809265137,4.909999847412109,5.130000114440918,4.296101032292563,319600,0.0,0.0,True +2022-08-30 00:00:00-04:00,5.070000171661377,5.070000171661377,4.900000095367432,4.940000057220459,4.136985903215098,335300,0.0,0.0,True +2022-08-31 00:00:00-04:00,4.849999904632568,5.050000190734863,4.78000020980835,4.880000114440918,4.086739132420695,517200,0.0,0.0,True +2022-09-01 00:00:00-04:00,4.880000114440918,4.880000114440918,4.570000171661377,4.619999885559082,3.869002770749761,587000,0.0,0.0,True +2022-09-02 00:00:00-04:00,4.840000152587891,4.869999885559082,4.690000057220459,4.699999809265137,3.9359984651422977,392000,0.0,0.0,True +2022-09-06 00:00:00-04:00,4.800000190734863,4.860000133514404,4.579999923706055,4.670000076293945,3.9108757895354764,545600,0.0,0.0,True +2022-09-07 00:00:00-04:00,4.539999961853027,4.559999942779541,4.400000095367432,4.449999809265137,3.72663656527043,412100,0.0,0.0,True +2022-09-08 00:00:00-04:00,4.449999809265137,4.539999961853027,4.409999847412109,4.480000019073486,3.7517606604580114,369200,0.0,0.0,True +2022-09-09 00:00:00-04:00,4.559999942779541,4.809999942779541,4.559999942779541,4.78000020980835,4.002994869325215,513000,0.0,0.0,True +2022-09-12 00:00:00-04:00,4.789999961853027,4.880000114440918,4.739999771118164,4.829999923706055,4.04486682342536,285000,0.0,0.0,True +2022-09-13 00:00:00-04:00,4.800000190734863,4.849999904632568,4.71999979019165,4.760000228881836,3.9862459457270805,225800,0.0,0.0,True +2022-09-14 00:00:00-04:00,4.809999942779541,4.989999771118164,4.78000020980835,4.869999885559082,4.078364315726438,1021100,0.0,0.0,True +2022-09-15 00:00:00-04:00,4.809999942779541,4.920000076293945,4.739999771118164,4.75,3.977871129032823,352500,0.0,0.0,True +2022-09-16 00:00:00-04:00,4.730000019073486,4.730000019073486,4.550000190734863,4.659999847412109,3.9025006179460293,702500,0.0,0.0,True +2022-09-19 00:00:00-04:00,4.5,4.659999847412109,4.389999866485596,4.639999866485596,3.8857520492430853,537500,0.0,0.0,True +2022-09-20 00:00:00-04:00,4.639999866485596,4.639999866485596,4.429999828338623,4.480000019073486,3.7517606604580114,400900,0.0,0.0,True +2022-09-21 00:00:00-04:00,4.519999980926514,4.559999942779541,4.309999942779541,4.320000171661377,3.617768916777748,364600,0.0,0.0,True +2022-09-22 00:00:00-04:00,4.389999866485596,4.449999809265137,4.099999904632568,4.130000114440918,3.458654497490663,515800,0.0,0.0,True +2022-09-23 00:00:00-04:00,4.0,4.0,3.5999999046325684,3.700000047683716,3.0985522852355873,960400,0.0,0.0,True +2022-09-26 00:00:00-04:00,3.690000057220459,3.75,3.3299999237060547,3.369999885559082,2.8221948684187783,683500,0.0,0.0,True +2022-09-27 00:00:00-04:00,3.440000057220459,3.4700000286102295,3.3399999141693115,3.380000114440918,2.8305695076654405,931200,0.0,0.0,True +2022-09-28 00:00:00-04:00,3.380000114440918,3.6600000858306885,3.359999895095825,3.6600000858306885,3.065054438039319,541000,0.0,0.0,True +2022-09-29 00:00:00-04:00,3.5899999141693115,3.75,3.4800000190734863,3.740000009536743,3.1320501324318557,640300,0.0,0.0,True +2022-09-30 00:00:00-04:00,3.6700000762939453,3.7699999809265137,3.569999933242798,3.700000047683716,3.0985522852355873,536300,0.0,0.0,True +2022-10-03 00:00:00-04:00,3.809999942779541,3.940000057220459,3.7699999809265137,3.9000000953674316,3.2660418761121193,656400,0.0,0.0,True +2022-10-04 00:00:00-04:00,3.9800000190734863,4.119999885559082,3.9800000190734863,4.010000228881836,3.3581606010066674,638800,0.0,0.0,True +2022-10-05 00:00:00-04:00,4.019999980926514,4.269999980926514,3.990000009536743,4.170000076293945,3.4921523446869314,615400,0.0,0.0,True +2022-10-06 00:00:00-04:00,4.139999866485596,4.409999847412109,4.139999866485596,4.380000114440918,3.6680160424673405,418100,0.0,0.0,True +2022-10-07 00:00:00-04:00,4.360000133514404,4.440000057220459,4.21999979019165,4.269999980926514,3.5758966077824126,673400,0.0,0.0,True +2022-10-11 00:00:00-04:00,4.090000152587891,4.099999904632568,3.859999895095825,3.990000009536743,3.3414120323037233,307800,0.0,0.0,True +2022-10-12 00:00:00-04:00,3.940000057220459,3.9800000190734863,3.8399999141693115,3.9700000286102295,3.324662753810399,371100,0.0,0.0,True +2022-10-13 00:00:00-04:00,3.9100000858306885,4.099999904632568,3.9100000858306885,4.039999961853027,3.383284341299059,625900,0.0,0.0,True +2022-10-14 00:00:00-04:00,4.010000228881836,4.070000171661377,3.8299999237060547,3.8399999141693115,3.215794750422527,353500,0.0,0.0,True +2022-10-17 00:00:00-04:00,3.890000104904175,3.9700000286102295,3.8499999046325684,3.9000000953674316,3.2660418761121193,546400,0.0,0.0,True +2022-10-18 00:00:00-04:00,3.930000066757202,3.990000009536743,3.8299999237060547,3.9100000858306885,3.2744163379111866,377200,0.0,0.0,True +2022-10-19 00:00:00-04:00,3.9000000953674316,4.0,3.869999885559082,3.990000009536743,3.3414120323037233,379500,0.0,0.0,True +2022-10-20 00:00:00-04:00,4.0,4.130000114440918,3.9600000381469727,3.990000009536743,3.3414120323037233,453900,0.0,0.0,True +2022-10-21 00:00:00-04:00,3.9800000190734863,4.039999961853027,3.930000066757202,3.950000047683716,3.307914185107455,396900,0.0,0.0,True +2022-10-24 00:00:00-04:00,3.9800000190734863,4.059999942779541,3.9100000858306885,4.0,3.3497861392076005,496100,0.0,0.0,True +2022-10-25 00:00:00-04:00,3.9700000286102295,4.079999923706055,3.9700000286102295,4.059999942779541,3.4000325551068133,532500,0.0,0.0,True +2022-10-26 00:00:00-04:00,4.050000190734863,4.230000019073486,4.050000190734863,4.210000038146973,3.5256501918831997,877200,0.0,0.0,True +2022-10-27 00:00:00-04:00,4.21999979019165,4.300000190734863,4.130000114440918,4.170000076293945,3.4921523446869314,474000,0.0,0.0,True +2022-10-28 00:00:00-04:00,4.119999885559082,4.199999809265137,4.03000020980835,4.070000171661377,3.4084080815914506,363900,0.0,0.0,True +2022-10-31 00:00:00-04:00,4.010000228881836,4.230000019073486,4.010000228881836,4.110000133514404,3.441905573892529,628500,0.0,0.0,True +2022-11-01 00:00:00-04:00,4.230000019073486,4.25,4.139999866485596,4.179999828338623,3.5005264515908086,319700,0.0,0.0,True +2022-11-02 00:00:00-04:00,4.170000076293945,4.340000152587891,4.110000133514404,4.21999979019165,3.534024298787077,481300,0.0,0.0,True +2022-11-03 00:00:00-04:00,4.190000057220459,4.340000152587891,4.179999828338623,4.289999961853027,3.5926458862757364,279400,0.0,0.0,True +2022-11-04 00:00:00-04:00,4.360000133514404,4.590000152587891,4.340000152587891,4.550000190734863,3.8103818930514812,741800,0.0,0.0,True +2022-11-07 00:00:00-05:00,4.559999942779541,4.599999904632568,4.5,4.579999923706055,3.8355049235534926,366700,0.0,0.0,True +2022-11-08 00:00:00-05:00,4.590000152587891,4.599999904632568,4.460000038146973,4.510000228881836,3.776884400750403,426500,0.0,0.0,True +2022-11-09 00:00:00-05:00,4.099999904632568,4.130000114440918,3.509999990463257,3.5799999237060547,2.9980583887515926,3261400,0.0,0.0,True +2022-11-10 00:00:00-05:00,3.609999895095825,3.609999895095825,3.240000009536743,3.5199999809265137,2.9478121502999746,2489900,0.0,0.0,True +2022-11-11 00:00:00-05:00,3.549999952316284,3.549999952316284,3.369999885559082,3.4800000190734863,2.9143141256561114,1531900,0.0,0.0,True +2022-11-14 00:00:00-05:00,3.4100000858306885,3.619999885559082,3.380000114440918,3.5199999809265137,2.9478121502999746,1636500,0.0,0.0,True +2022-11-15 00:00:00-05:00,3.549999952316284,3.6500000953674316,3.509999990463257,3.619999885559082,3.031556235947861,613200,0.0,0.0,True +2022-11-16 00:00:00-05:00,3.619999885559082,3.619999885559082,3.440000057220459,3.450000047683716,2.8891903853637197,1095300,0.0,0.0,True +2022-11-17 00:00:00-05:00,3.4200000762939453,3.4200000762939453,3.2200000286102295,3.359999895095825,2.813820229172116,1058500,0.0,0.0,True +2022-11-18 00:00:00-05:00,3.299999952316284,3.3499999046325684,3.2300000190734863,3.3299999237060547,2.7886968437749147,1005000,0.0,0.0,True +2022-11-21 00:00:00-05:00,3.2899999618530273,3.3299999237060547,3.130000114440918,3.2899999618530273,2.755199174026241,1701700,0.0,0.0,True +2022-11-22 00:00:00-05:00,3.309999942779541,3.450000047683716,3.309999942779541,3.4100000858306885,2.8556927156150467,668000,0.0,0.0,True +2022-11-23 00:00:00-05:00,3.3399999141693115,3.559999942779541,3.299999952316284,3.4600000381469727,2.897565202057977,626600,0.0,0.0,True +2022-11-24 00:00:00-05:00,3.450000047683716,3.4600000381469727,3.380000114440918,3.430000066757202,2.872441639213181,213400,0.0,0.0,True +2022-11-25 00:00:00-05:00,3.450000047683716,3.4800000190734863,3.369999885559082,3.380000114440918,2.8305695076654405,404100,0.0,0.0,True +2022-11-28 00:00:00-05:00,3.309999942779541,3.359999895095825,3.259999990463257,3.299999952316284,2.763573458377713,472800,0.0,0.0,True +2022-11-29 00:00:00-05:00,3.3299999237060547,3.4800000190734863,3.309999942779541,3.4000000953674316,2.8473182538159794,782700,0.0,0.0,True +2022-11-30 00:00:00-05:00,3.5899999141693115,3.5899999141693115,3.4000000953674316,3.4000000953674316,2.8473182538159794,1510300,0.0,0.0,True +2022-12-01 00:00:00-05:00,3.4600000381469727,3.549999952316284,3.359999895095825,3.369999885559082,2.8221948684187783,570700,0.0,0.0,True +2022-12-02 00:00:00-05:00,3.369999885559082,3.450000047683716,3.3299999237060547,3.3499999046325684,2.805446122268239,319600,0.0,0.0,True +2022-12-05 00:00:00-05:00,3.4000000953674316,3.4700000286102295,3.259999990463257,3.299999952316284,2.763573458377713,1100300,0.0,0.0,True +2022-12-06 00:00:00-05:00,3.2899999618530273,3.3499999046325684,3.0799999237060547,3.0799999237060547,2.579335298798237,1268000,0.0,0.0,True +2022-12-07 00:00:00-05:00,3.0799999237060547,3.180000066757202,2.9800000190734863,3.0899999141693115,2.5877099380448993,769100,0.0,0.0,True +2022-12-08 00:00:00-05:00,3.190000057220459,3.190000057220459,2.990000009536743,3.0299999713897705,2.537463167250497,618300,0.0,0.0,True +2022-12-09 00:00:00-05:00,3.0199999809265137,3.059999942779541,2.950000047683716,3.059999942779541,2.5625865526476983,779100,0.0,0.0,True +2022-12-12 00:00:00-05:00,3.059999942779541,3.0899999141693115,2.950000047683716,2.9700000286102295,2.4872163964560943,1015200,0.0,0.0,True +2022-12-13 00:00:00-05:00,3.059999942779541,3.130000114440918,2.930000066757202,3.049999952316284,2.554212090848631,1585100,0.0,0.0,True +2022-12-14 00:00:00-05:00,3.0799999237060547,3.119999885559082,3.009999990463257,3.0999999046325684,2.5960842223963714,508600,0.0,0.0,True +2022-12-15 00:00:00-05:00,3.049999952316284,3.0799999237060547,2.9700000286102295,3.0799999237060547,2.579335298798237,802900,0.0,0.0,True +2022-12-16 00:00:00-05:00,3.009999990463257,3.0299999713897705,2.890000104904175,2.940000057220459,2.4620930110588928,1059300,0.0,0.0,True +2022-12-19 00:00:00-05:00,2.9100000858306885,2.930000066757202,2.680000066757202,2.740000009536743,2.2946035976299557,2117800,0.0,0.0,True +2022-12-20 00:00:00-05:00,2.740000009536743,2.859999895095825,2.7100000381469727,2.8299999237060547,2.369973931269155,988400,0.0,0.0,True +2022-12-21 00:00:00-05:00,2.8399999141693115,3.059999942779541,2.8399999141693115,3.0299999713897705,2.537463167250497,796100,0.0,0.0,True +2022-12-22 00:00:00-05:00,3.049999952316284,3.059999942779541,2.890000104904175,2.9200000762939453,2.4453440874607586,1115000,0.0,0.0,True +2022-12-23 00:00:00-05:00,2.9700000286102295,3.190000057220459,2.950000047683716,3.1700000762939453,2.654705632437436,1357700,0.0,0.0,True +2022-12-28 00:00:00-05:00,3.109999895095825,3.119999885559082,2.9200000762939453,2.940000057220459,2.4620930110588928,1075500,0.0,0.0,True +2022-12-29 00:00:00-05:00,2.9200000762939453,3.009999990463257,2.9200000762939453,2.990000009536743,2.503965142606633,471300,0.0,0.0,True +2022-12-30 00:00:00-05:00,2.9600000381469727,3.0299999713897705,2.9600000381469727,3.0,2.5123399593008906,573100,0.0,0.0,True +2023-01-03 00:00:00-05:00,2.9700000286102295,3.0,2.75,2.7699999809265137,2.319726983027157,766300,0.0,0.0,True +2023-01-04 00:00:00-05:00,2.7699999809265137,2.7799999713897705,2.680000066757202,2.7100000381469727,2.269480212232754,735100,0.0,0.0,True +2023-01-05 00:00:00-05:00,2.690000057220459,2.7699999809265137,2.680000066757202,2.7100000381469727,2.269480212232754,716200,0.0,0.0,True +2023-01-06 00:00:00-05:00,2.7300000190734863,2.809999942779541,2.7300000190734863,2.799999952316284,2.3448503684243582,333100,0.0,0.0,True +2023-01-09 00:00:00-05:00,2.859999895095825,2.950000047683716,2.819999933242798,2.880000114440918,2.4118462402644902,491400,0.0,0.0,True +2023-01-10 00:00:00-05:00,2.859999895095825,2.9100000858306885,2.809999942779541,2.890000104904175,2.4202203471683674,418900,0.0,0.0,True +2023-01-11 00:00:00-05:00,2.890000104904175,2.990000009536743,2.890000104904175,2.9200000762939453,2.4453440874607586,808900,0.0,0.0,True +2023-01-12 00:00:00-05:00,2.9700000286102295,3.0799999237060547,2.950000047683716,3.0399999618530273,2.5458372741543736,900700,0.0,0.0,True +2023-01-13 00:00:00-05:00,3.0399999618530273,3.0999999046325684,2.9800000190734863,3.0299999713897705,2.537463167250497,625000,0.0,0.0,True +2023-01-16 00:00:00-05:00,3.0299999713897705,3.0399999618530273,3.0,3.009999990463257,2.5207140662047673,360400,0.0,0.0,True +2023-01-17 00:00:00-05:00,3.059999942779541,3.1700000762939453,3.0,3.1500000953674316,2.6379567088393023,699200,0.0,0.0,True +2023-01-18 00:00:00-05:00,3.190000057220459,3.2899999618530273,3.130000114440918,3.130000114440918,2.6212079626887625,707500,0.0,0.0,True +2023-01-19 00:00:00-05:00,3.130000114440918,3.140000104904175,3.0299999713897705,3.119999885559082,2.6128331459945056,291600,0.0,0.0,True +2023-01-20 00:00:00-05:00,3.109999895095825,3.1600000858306885,3.0799999237060547,3.119999885559082,2.6128331459945056,191000,0.0,0.0,True +2023-01-23 00:00:00-05:00,3.140000104904175,3.180000066757202,3.069999933242798,3.109999895095825,2.6044586841954387,329700,0.0,0.0,True +2023-01-24 00:00:00-05:00,3.059999942779541,3.0899999141693115,3.009999990463257,3.0199999809265137,2.5290887054514295,496300,0.0,0.0,True +2023-01-25 00:00:00-05:00,3.009999990463257,3.049999952316284,2.930000066757202,3.049999952316284,2.554212090848631,415700,0.0,0.0,True +2023-01-26 00:00:00-05:00,3.049999952316284,3.0899999141693115,2.990000009536743,3.0399999618530273,2.5458372741543736,243700,0.0,0.0,True +2023-01-27 00:00:00-05:00,3.0299999713897705,3.069999933242798,2.9600000381469727,3.0199999809265137,2.5290887054514295,432400,0.0,0.0,True +2023-01-30 00:00:00-05:00,2.9800000190734863,2.9800000190734863,2.869999885559082,2.890000104904175,2.4202203471683674,427200,0.0,0.0,True +2023-01-31 00:00:00-05:00,2.859999895095825,2.9600000381469727,2.809999942779541,2.9600000381469727,2.478841934657027,428900,0.0,0.0,True +2023-02-01 00:00:00-05:00,2.9600000381469727,3.0,2.880000114440918,2.940000057220459,2.4620930110588928,800000,0.0,0.0,True +2023-02-02 00:00:00-05:00,2.9700000286102295,2.9700000286102295,2.8499999046325684,2.880000114440918,2.4118462402644902,552400,0.0,0.0,True +2023-02-03 00:00:00-05:00,2.869999885559082,2.950000047683716,2.859999895095825,2.9000000953674316,2.4285949864150296,468600,0.0,0.0,True +2023-02-06 00:00:00-05:00,2.9000000953674316,2.9200000762939453,2.8299999237060547,2.8399999141693115,2.3783480381730318,214400,0.0,0.0,True +2023-02-07 00:00:00-05:00,2.869999885559082,3.0899999141693115,2.859999895095825,3.0899999141693115,2.5877099380448993,736000,0.0,0.0,True +2023-02-08 00:00:00-05:00,3.0999999046325684,3.109999895095825,3.0,3.0,2.5123399593008906,293100,0.0,0.0,True +2023-02-09 00:00:00-05:00,2.9700000286102295,3.0399999618530273,2.9700000286102295,3.0199999809265137,2.5290887054514295,290000,0.0,0.0,True +2023-02-10 00:00:00-05:00,3.009999990463257,3.0899999141693115,3.009999990463257,3.049999952316284,2.554212090848631,319600,0.0,0.0,True +2023-02-13 00:00:00-05:00,3.0899999141693115,3.0899999141693115,2.9700000286102295,3.0,2.5123399593008906,494600,0.0,0.0,True +2023-02-14 00:00:00-05:00,2.990000009536743,3.009999990463257,2.950000047683716,3.0,2.5123399593008906,354700,0.0,0.0,True +2023-02-15 00:00:00-05:00,2.9700000286102295,2.990000009536743,2.890000104904175,2.9700000286102295,2.4872163964560943,301400,0.0,0.0,True +2023-02-16 00:00:00-05:00,2.940000057220459,3.0,2.9200000762939453,2.990000009536743,2.503965142606633,212600,0.0,0.0,True +2023-02-17 00:00:00-05:00,2.930000066757202,2.930000066757202,2.759999990463257,2.7799999713897705,2.328101267378629,823900,0.0,0.0,True +2023-02-21 00:00:00-05:00,2.809999942779541,2.8299999237060547,2.7100000381469727,2.7200000286102295,2.2778544965842267,352700,0.0,0.0,True +2023-02-22 00:00:00-05:00,2.740000009536743,2.740000009536743,2.640000104904175,2.6600000858306885,2.227607903237419,343700,0.0,0.0,True +2023-02-23 00:00:00-05:00,2.700000047683716,2.7799999713897705,2.6600000858306885,2.75,2.302978059429023,292200,0.0,0.0,True +2023-02-24 00:00:00-05:00,2.700000047683716,2.799999952316284,2.700000047683716,2.7799999713897705,2.328101267378629,322100,0.0,0.0,True +2023-02-27 00:00:00-05:00,2.809999942779541,2.9100000858306885,2.75,2.880000114440918,2.4118462402644902,268200,0.0,0.0,True +2023-02-28 00:00:00-05:00,2.880000114440918,2.9200000762939453,2.819999933242798,2.8499999046325684,2.3867228548672887,917800,0.0,0.0,True +2023-03-01 00:00:00-05:00,2.859999895095825,2.9800000190734863,2.859999895095825,2.9800000190734863,2.4955906808075663,327600,0.0,0.0,True +2023-03-02 00:00:00-05:00,3.0,3.0299999713897705,2.9200000762939453,2.9600000381469727,2.478841934657027,287600,0.0,0.0,True +2023-03-03 00:00:00-05:00,2.9100000858306885,3.0799999237060547,2.9100000858306885,3.049999952316284,2.554212090848631,289700,0.0,0.0,True +2023-03-06 00:00:00-05:00,3.059999942779541,3.059999942779541,2.9700000286102295,3.009999990463257,2.5207140662047673,232100,0.0,0.0,True +2023-03-07 00:00:00-05:00,2.9800000190734863,3.0,2.880000114440918,2.9100000858306885,2.4369696256616913,279700,0.0,0.0,True +2023-03-08 00:00:00-05:00,2.9700000286102295,3.059999942779541,2.9000000953674316,2.9600000381469727,2.478841934657027,455000,0.0,0.0,True +2023-03-09 00:00:00-05:00,3.0,3.180000066757202,2.990000009536743,3.009999990463257,2.5207140662047673,336300,0.0,0.0,True +2023-03-10 00:00:00-05:00,3.009999990463257,3.059999942779541,2.9100000858306885,2.950000047683716,2.470467295410365,350400,0.0,0.0,True +2023-03-13 00:00:00-04:00,2.8299999237060547,2.9100000858306885,2.75,2.9000000953674316,2.4285949864150296,435800,0.0,0.0,True +2023-03-14 00:00:00-04:00,2.869999885559082,2.950000047683716,2.8399999141693115,2.880000114440918,2.844389481260282,231900,0.441,0.0,True +2023-03-15 00:00:00-04:00,2.75,2.759999990463257,2.4700000286102295,2.630000114440918,2.597480557521533,1133800,0.0,0.0,True +2023-03-16 00:00:00-04:00,2.6500000953674316,2.7300000190734863,2.569999933242798,2.7200000286102295,2.6863676068156948,420000,0.0,0.0,True 2023-03-17 00:00:00-04:00,2.680000066757202,2.75,2.619999885559082,2.630000114440918,2.597480557521533,403800,0.0,0.0,True -2023-03-20 00:00:00-04:00,2.640000104904175,2.7300000190734863,2.619999885559082,2.720000028610229,2.6863676068156948,251300,0.0,0.0,True -2023-03-21 00:00:00-04:00,2.7699999809265137,2.8399999141693115,2.720000028610229,2.7699999809265137,2.735749498032002,311100,0.0,0.0,True -2023-03-22 00:00:00-04:00,2.759999990463257,2.789999961853028,2.6600000858306885,2.6600000858306885,2.627109869698912,162000,0.0,0.0,True +2023-03-20 00:00:00-04:00,2.640000104904175,2.7300000190734863,2.619999885559082,2.7200000286102295,2.6863676068156948,251300,0.0,0.0,True +2023-03-21 00:00:00-04:00,2.7699999809265137,2.8399999141693115,2.7200000286102295,2.7699999809265137,2.7357494980320016,311100,0.0,0.0,True +2023-03-22 00:00:00-04:00,2.759999990463257,2.7899999618530273,2.6600000858306885,2.6600000858306885,2.627109869698912,162000,0.0,0.0,True 2023-03-23 00:00:00-04:00,2.690000057220459,2.740000009536743,2.5899999141693115,2.640000104904175,2.6073571132123887,190900,0.0,0.0,True 2023-03-24 00:00:00-04:00,2.569999933242798,2.6600000858306885,2.569999933242798,2.630000114440918,2.597480557521533,301600,0.0,0.0,True -2023-03-27 00:00:00-04:00,2.630000114440918,2.720000028610229,2.559999942779541,2.7100000381469727,2.676491406020028,226600,0.0,0.0,True +2023-03-27 00:00:00-04:00,2.630000114440918,2.7200000286102295,2.559999942779541,2.7100000381469727,2.676491406020028,226600,0.0,0.0,True 2023-03-28 00:00:00-04:00,2.740000009536743,2.740000009536743,2.6600000858306885,2.7100000381469727,2.676491406020028,161900,0.0,0.0,True -2023-03-29 00:00:00-04:00,2.700000047683716,2.759999990463257,2.690000057220459,2.720000028610229,2.6863676068156948,202700,0.0,0.0,True -2023-03-30 00:00:00-04:00,2.700000047683716,2.75,2.6700000762939453,2.720000028610229,2.6863676068156948,118100,0.0,0.0,True -2023-03-31 00:00:00-04:00,2.75,2.799999952316284,2.75,2.7699999809265137,2.735749498032002,201700,0.0,0.0,True +2023-03-29 00:00:00-04:00,2.700000047683716,2.759999990463257,2.690000057220459,2.7200000286102295,2.6863676068156948,202700,0.0,0.0,True +2023-03-30 00:00:00-04:00,2.700000047683716,2.75,2.6700000762939453,2.7200000286102295,2.6863676068156948,118100,0.0,0.0,True +2023-03-31 00:00:00-04:00,2.75,2.799999952316284,2.75,2.7699999809265137,2.7357494980320016,201700,0.0,0.0,True 2023-04-03 00:00:00-04:00,2.7699999809265137,2.9600000381469727,2.7699999809265137,2.9600000381469727,2.9234003297587776,876600,0.0,0.0,True -2023-04-04 00:00:00-04:00,2.990000009536743,2.990000009536743,2.880000114440918,2.9200000762939453,2.8838949942333265,151100,0.0,0.0,True -2023-04-05 00:00:00-04:00,2.940000057220459,2.940000057220459,2.819999933242798,2.8399999141693115,2.8048839682872364,90400,0.0,0.0,True +2023-04-04 00:00:00-04:00,2.990000009536743,2.990000009536743,2.880000114440918,2.9200000762939453,2.8838949942333274,151100,0.0,0.0,True +2023-04-05 00:00:00-04:00,2.940000057220459,2.940000057220459,2.819999933242798,2.8399999141693115,2.804883968287236,90400,0.0,0.0,True 2023-04-06 00:00:00-04:00,2.880000114440918,2.880000114440918,2.7799999713897705,2.799999952316284,2.765378455314191,123900,0.0,0.0,True -2023-04-10 00:00:00-04:00,2.789999961853028,2.900000095367432,2.7799999713897705,2.789999961853028,2.7555024319661197,205200,0.0,0.0,True +2023-04-10 00:00:00-04:00,2.7899999618530273,2.9000000953674316,2.7799999713897705,2.7899999618530273,2.7555024319661197,205200,0.0,0.0,True 2023-04-11 00:00:00-04:00,2.7699999809265137,2.8299999237060547,2.7699999809265137,2.809999942779541,2.775255011005047,345000,0.0,0.0,True 2023-04-12 00:00:00-04:00,2.8299999237060547,2.8499999046325684,2.799999952316284,2.809999942779541,2.775255011005047,210200,0.0,0.0,True -2023-04-13 00:00:00-04:00,2.789999961853028,2.809999942779541,2.7699999809265137,2.789999961853028,2.7555024319661197,234700,0.0,0.0,True +2023-04-13 00:00:00-04:00,2.7899999618530273,2.809999942779541,2.7699999809265137,2.7899999618530273,2.7555024319661197,234700,0.0,0.0,True 2023-04-14 00:00:00-04:00,2.799999952316284,2.8299999237060547,2.740000009536743,2.75,2.715996918993074,545200,0.0,0.0,True -2023-04-17 00:00:00-04:00,2.789999961853028,2.789999961853028,2.720000028610229,2.75,2.715996918993074,171800,0.0,0.0,True +2023-04-17 00:00:00-04:00,2.7899999618530273,2.7899999618530273,2.7200000286102295,2.75,2.715996918993074,171800,0.0,0.0,True 2023-04-18 00:00:00-04:00,2.75,2.75,2.680000066757202,2.7100000381469727,2.676491406020028,194200,0.0,0.0,True 2023-04-19 00:00:00-04:00,2.7100000381469727,2.7100000381469727,2.619999885559082,2.6600000858306885,2.627109869698912,269500,0.0,0.0,True 2023-04-20 00:00:00-04:00,2.640000104904175,2.640000104904175,2.569999933242798,2.619999885559082,2.5876043567258664,833900,0.0,0.0,True -2023-04-21 00:00:00-04:00,2.619999885559082,2.650000095367432,2.5999999046325684,2.650000095367432,2.61723349145565,174500,0.0,0.0,True +2023-04-21 00:00:00-04:00,2.619999885559082,2.6500000953674316,2.5999999046325684,2.6500000953674316,2.61723349145565,174500,0.0,0.0,True 2023-04-24 00:00:00-04:00,2.609999895095825,2.6600000858306885,2.569999933242798,2.6600000858306885,2.627109869698912,255300,0.0,0.0,True -2023-04-25 00:00:00-04:00,2.619999885559082,2.650000095367432,2.569999933242798,2.5899999141693115,2.557975044548487,406500,0.0,0.0,True +2023-04-25 00:00:00-04:00,2.619999885559082,2.6500000953674316,2.569999933242798,2.5899999141693115,2.557975044548487,406500,0.0,0.0,True 2023-04-26 00:00:00-04:00,2.569999933242798,2.619999885559082,2.4800000190734863,2.4800000190734863,2.4493354162153973,293400,0.0,0.0,True 2023-04-27 00:00:00-04:00,2.5,2.5299999713897705,2.450000047683716,2.4800000190734863,2.4493354162153973,251700,0.0,0.0,True 2023-04-28 00:00:00-04:00,2.5299999713897705,2.549999952316284,2.4800000190734863,2.5,2.469087995254325,405600,0.0,0.0,True -2023-05-01 00:00:00-04:00,2.4800000190734863,2.5799999237060547,2.4800000190734863,2.539999961853028,2.508593508227371,138100,0.0,0.0,True +2023-05-01 00:00:00-04:00,2.4800000190734863,2.5799999237060547,2.4800000190734863,2.5399999618530273,2.5085935082273703,138100,0.0,0.0,True 2023-05-02 00:00:00-04:00,2.549999952316284,2.549999952316284,2.299999952316284,2.3299999237060547,2.301189920014072,846200,0.0,0.0,True 2023-05-03 00:00:00-04:00,2.309999942779541,2.3499999046325684,2.240000009536743,2.3499999046325684,2.3209424990529994,555600,0.0,0.0,True 2023-05-04 00:00:00-04:00,2.3499999046325684,2.380000114440918,2.299999952316284,2.3499999046325684,2.3209424990529994,359300,0.0,0.0,True @@ -340,23 +340,23 @@ Datetime,Open,High,Low,Close,Adj Close,Volume,Dividends,Stock Splits,Repaired? 2023-05-09 00:00:00-04:00,2.549999952316284,2.549999952316284,2.490000009536743,2.5299999713897705,2.498717129984109,120400,0.0,0.0,True 2023-05-10 00:00:00-04:00,2.549999952316284,2.549999952316284,2.430000066757202,2.4800000190734863,2.4493354162153973,236300,0.0,0.0,True 2023-05-11 00:00:00-04:00,2.4800000190734863,2.5199999809265137,2.380000114440918,2.380000114440918,2.350572166125569,433000,0.0,0.0,True -2023-05-12 00:00:00-04:00,2.430000066757202,2.549999952316284,2.400000095367432,2.5299999713897705,2.498717129984109,510700,0.0,0.0,True -2023-05-15 00:00:00-04:00,2.539999961853028,2.630000114440918,2.5299999713897705,2.619999885559082,2.5876043567258664,230800,0.0,0.0,True +2023-05-12 00:00:00-04:00,2.430000066757202,2.549999952316284,2.4000000953674316,2.5299999713897705,2.498717129984109,510700,0.0,0.0,True +2023-05-15 00:00:00-04:00,2.5399999618530273,2.630000114440918,2.5299999713897705,2.619999885559082,2.5876043567258664,230800,0.0,0.0,True 2023-05-16 00:00:00-04:00,2.619999885559082,2.6700000762939453,2.440000057220459,2.4800000190734863,2.4493354162153973,579000,0.0,0.0,True 2023-05-17 00:00:00-04:00,2.4800000190734863,2.509999990463257,2.4100000858306885,2.4800000190734863,2.4493354162153973,196000,0.0,0.0,True -2023-05-18 00:00:00-04:00,2.4600000381469727,2.539999961853028,2.440000057220459,2.5,2.469087995254325,233000,0.0,0.0,True -2023-05-19 00:00:00-04:00,2.559999942779541,2.5799999237060547,2.470000028610229,2.509999990463257,2.478964550945181,229000,0.0,0.0,True +2023-05-18 00:00:00-04:00,2.4600000381469727,2.5399999618530273,2.440000057220459,2.5,2.469087995254325,233000,0.0,0.0,True +2023-05-19 00:00:00-04:00,2.559999942779541,2.5799999237060547,2.4700000286102295,2.509999990463257,2.478964550945181,229000,0.0,0.0,True 2023-05-23 00:00:00-04:00,2.4600000381469727,2.609999895095825,2.4600000381469727,2.559999942779541,2.528346087266298,240100,0.0,0.0,True -2023-05-24 00:00:00-04:00,2.5199999809265137,2.559999942779541,2.440000057220459,2.470000028610229,2.439459037972136,199100,0.0,0.0,True -2023-05-25 00:00:00-04:00,2.5,2.5,2.380000114440918,2.400000095367432,2.3703247451644964,287100,0.0,0.0,True -2023-05-26 00:00:00-04:00,2.400000095367432,2.470000028610229,2.369999885559082,2.400000095367432,2.3703247451644964,150100,0.0,0.0,True -2023-05-29 00:00:00-04:00,2.400000095367432,2.4800000190734863,2.400000095367432,2.4600000381469727,2.4295826597288745,58700,0.0,0.0,True +2023-05-24 00:00:00-04:00,2.5199999809265137,2.559999942779541,2.440000057220459,2.4700000286102295,2.439459037972136,199100,0.0,0.0,True +2023-05-25 00:00:00-04:00,2.5,2.5,2.380000114440918,2.4000000953674316,2.3703247451644964,287100,0.0,0.0,True +2023-05-26 00:00:00-04:00,2.4000000953674316,2.4700000286102295,2.369999885559082,2.4000000953674316,2.3703247451644964,150100,0.0,0.0,True +2023-05-29 00:00:00-04:00,2.4000000953674316,2.4800000190734863,2.4000000953674316,2.4600000381469727,2.4295826597288745,58700,0.0,0.0,True 2023-05-30 00:00:00-04:00,2.440000057220459,2.440000057220459,2.3299999237060547,2.390000104904175,2.36044818947364,281300,0.0,0.0,True 2023-05-31 00:00:00-04:00,2.3299999237060547,2.4600000381469727,2.259999990463257,2.430000066757202,2.3999537024466853,708800,0.0,0.0,True 2023-06-01 00:00:00-04:00,2.390000104904175,2.4100000858306885,2.299999952316284,2.3299999237060547,2.301189920014072,490100,0.0,0.0,True 2023-06-02 00:00:00-04:00,2.3299999237060547,2.549999952316284,2.3299999237060547,2.549999952316284,2.518469886470632,1196900,0.0,0.0,True 2023-06-05 00:00:00-04:00,2.509999990463257,2.619999885559082,2.509999990463257,2.549999952316284,2.518469886470632,317400,0.0,0.0,True -2023-06-06 00:00:00-04:00,2.569999933242798,2.5799999237060547,2.470000028610229,2.490000009536743,2.459211617011064,401600,0.0,0.0,True +2023-06-06 00:00:00-04:00,2.569999933242798,2.5799999237060547,2.4700000286102295,2.490000009536743,2.459211617011064,401600,0.0,0.0,True 2023-06-07 00:00:00-04:00,2.4800000190734863,2.5199999809265137,2.4600000381469727,2.4800000190734863,2.4493354162153973,176900,0.0,0.0,True 2023-06-08 00:00:00-04:00,2.5,2.609999895095825,2.430000066757202,2.559999942779541,2.528346087266298,510900,0.0,0.0,True 2023-06-09 00:00:00-04:00,2.549999952316284,2.5999999046325684,2.5,2.5,2.469087995254325,178700,0.0,0.0,True @@ -366,205 +366,205 @@ Datetime,Open,High,Low,Close,Adj Close,Volume,Dividends,Stock Splits,Repaired? 2023-06-15 00:00:00-04:00,2.430000066757202,2.430000066757202,2.3399999141693115,2.4100000858306885,2.3845465390399636,92600,0.0,0.0,True 2023-06-16 00:00:00-04:00,2.4100000858306885,2.440000057220459,2.3399999141693115,2.369999885559082,2.344968795614638,407100,0.0,0.0,True 2023-06-19 00:00:00-04:00,2.4100000858306885,2.4100000858306885,2.359999895095825,2.369999885559082,2.344968795614638,69900,0.0,0.0,True -2023-06-20 00:00:00-04:00,2.359999895095825,2.359999895095825,2.2699999809265137,2.289999961853028,2.2658137448919837,404500,0.0,0.0,True -2023-06-21 00:00:00-04:00,2.289999961853028,2.289999961853028,2.2100000381469727,2.259999990463257,2.236130728074987,234900,0.0,0.0,True +2023-06-20 00:00:00-04:00,2.359999895095825,2.359999895095825,2.2699999809265137,2.2899999618530273,2.2658137448919833,404500,0.0,0.0,True +2023-06-21 00:00:00-04:00,2.2899999618530273,2.2899999618530273,2.2100000381469727,2.259999990463257,2.2361307280749867,234900,0.0,0.0,True 2023-06-22 00:00:00-04:00,2.25,2.259999990463257,2.119999885559082,2.130000114440918,2.107503788822673,366900,0.0,0.0,True 2023-06-23 00:00:00-04:00,2.1600000858306885,2.200000047683716,2.0799999237060547,2.0999999046325684,2.077820626629678,175300,0.0,0.0,True 2023-06-26 00:00:00-04:00,2.1600000858306885,2.1600000858306885,2.0899999141693115,2.0999999046325684,2.077820626629678,109500,0.0,0.0,True 2023-06-27 00:00:00-04:00,2.0899999141693115,2.130000114440918,2.059999942779541,2.059999942779541,2.038243028580351,165900,0.0,0.0,True 2023-06-28 00:00:00-04:00,2.0999999046325684,2.1600000858306885,2.0199999809265137,2.1600000858306885,2.1371868056396695,287900,0.0,0.0,True -2023-06-29 00:00:00-04:00,2.1600000858306885,2.2100000381469727,2.150000095367432,2.2100000381469727,2.1866588395453275,113900,0.0,0.0,True -2023-06-30 00:00:00-04:00,2.190000057220459,2.299999952316284,2.180000066757202,2.2699999809265137,2.2460251639313187,354000,0.0,0.0,True +2023-06-29 00:00:00-04:00,2.1600000858306885,2.2100000381469727,2.1500000953674316,2.2100000381469727,2.1866588395453275,113900,0.0,0.0,True +2023-06-30 00:00:00-04:00,2.190000057220459,2.299999952316284,2.180000066757202,2.2699999809265137,2.2460251639313182,354000,0.0,0.0,True 2023-07-04 00:00:00-04:00,2.319999933242798,2.380000114440918,2.25,2.359999895095825,2.3350745051343056,245600,0.0,0.0,True 2023-07-05 00:00:00-04:00,2.4600000381469727,2.4600000381469727,2.2100000381469727,2.2100000381469727,2.1866588395453275,475400,0.0,0.0,True 2023-07-06 00:00:00-04:00,2.2100000381469727,2.2699999809265137,2.190000057220459,2.200000047683716,2.1767644036889964,240200,0.0,0.0,True -2023-07-07 00:00:00-04:00,2.2100000381469727,2.380000114440918,2.2100000381469727,2.3299999237060547,2.305391197565312,222100,0.0,0.0,True +2023-07-07 00:00:00-04:00,2.2100000381469727,2.380000114440918,2.2100000381469727,2.3299999237060547,2.3053911975653114,222100,0.0,0.0,True 2023-07-10 00:00:00-04:00,2.309999942779541,2.3499999046325684,2.299999952316284,2.299999952316284,2.275708180748315,55700,0.0,0.0,True -2023-07-11 00:00:00-04:00,2.289999961853028,2.400000095367432,2.2799999713897705,2.400000095367432,2.374652248559631,238500,0.0,0.0,True -2023-07-12 00:00:00-04:00,2.450000047683716,2.4600000381469727,2.390000104904175,2.440000057220459,2.41422955585696,241500,0.0,0.0,True -2023-07-13 00:00:00-04:00,2.400000095367432,2.4600000381469727,2.390000104904175,2.440000057220459,2.41422955585696,153200,0.0,0.0,True -2023-07-14 00:00:00-04:00,2.3499999046325684,2.390000104904175,2.2799999713897705,2.289999961853028,2.2658137448919837,232100,0.0,0.0,True -2023-07-17 00:00:00-04:00,2.289999961853028,2.309999942779541,2.220000028610229,2.240000009536743,2.216342001738323,144600,0.0,0.0,True +2023-07-11 00:00:00-04:00,2.2899999618530273,2.4000000953674316,2.2799999713897705,2.4000000953674316,2.374652248559631,238500,0.0,0.0,True +2023-07-12 00:00:00-04:00,2.450000047683716,2.4600000381469727,2.390000104904175,2.440000057220459,2.4142295558569598,241500,0.0,0.0,True +2023-07-13 00:00:00-04:00,2.4000000953674316,2.4600000381469727,2.390000104904175,2.440000057220459,2.4142295558569598,153200,0.0,0.0,True +2023-07-14 00:00:00-04:00,2.3499999046325684,2.390000104904175,2.2799999713897705,2.2899999618530273,2.2658137448919833,232100,0.0,0.0,True +2023-07-17 00:00:00-04:00,2.2899999618530273,2.309999942779541,2.2200000286102295,2.240000009536743,2.216342001738323,144600,0.0,0.0,True 2023-07-18 00:00:00-04:00,2.2300000190734863,2.3499999046325684,2.2300000190734863,2.309999942779541,2.285602471228647,146700,0.0,0.0,True -2023-07-19 00:00:00-04:00,2.299999952316284,2.470000028610229,2.299999952316284,2.450000047683716,2.42412413708929,443000,0.0,0.0,True +2023-07-19 00:00:00-04:00,2.299999952316284,2.4700000286102295,2.299999952316284,2.450000047683716,2.42412413708929,443000,0.0,0.0,True 2023-07-20 00:00:00-04:00,2.4800000190734863,2.569999933242798,2.4800000190734863,2.5199999809265137,2.493384751955613,270100,0.0,0.0,True -2023-07-21 00:00:00-04:00,2.5799999237060547,2.5799999237060547,2.450000047683716,2.4800000190734863,2.4538070085302883,222600,0.0,0.0,True -2023-07-24 00:00:00-04:00,2.5,2.5299999713897705,2.470000028610229,2.490000009536743,2.463701589762618,197200,0.0,0.0,True -2023-07-25 00:00:00-04:00,2.470000028610229,2.490000009536743,2.4100000858306885,2.440000057220459,2.41422955585696,188700,0.0,0.0,True -2023-07-26 00:00:00-04:00,2.400000095367432,2.450000047683716,2.400000095367432,2.450000047683716,2.42412413708929,128100,0.0,0.0,True -2023-07-27 00:00:00-04:00,2.4800000190734863,2.4800000190734863,2.400000095367432,2.4100000858306885,2.3845465390399636,381600,0.0,0.0,True +2023-07-21 00:00:00-04:00,2.5799999237060547,2.5799999237060547,2.450000047683716,2.4800000190734863,2.453807008530288,222600,0.0,0.0,True +2023-07-24 00:00:00-04:00,2.5,2.5299999713897705,2.4700000286102295,2.490000009536743,2.463701589762618,197200,0.0,0.0,True +2023-07-25 00:00:00-04:00,2.4700000286102295,2.490000009536743,2.4100000858306885,2.440000057220459,2.4142295558569598,188700,0.0,0.0,True +2023-07-26 00:00:00-04:00,2.4000000953674316,2.450000047683716,2.4000000953674316,2.450000047683716,2.42412413708929,128100,0.0,0.0,True +2023-07-27 00:00:00-04:00,2.4800000190734863,2.4800000190734863,2.4000000953674316,2.4100000858306885,2.3845465390399636,381600,0.0,0.0,True 2023-07-28 00:00:00-04:00,2.450000047683716,2.549999952316284,2.380000114440918,2.5299999713897705,2.503279042435946,424500,0.0,0.0,True -2023-07-31 00:00:00-04:00,2.5,2.7300000190734863,2.5,2.720000028610229,2.6912723060742505,516500,0.0,0.0,True +2023-07-31 00:00:00-04:00,2.5,2.7300000190734863,2.5,2.7200000286102295,2.6912723060742505,516500,0.0,0.0,True 2023-08-01 00:00:00-04:00,2.740000009536743,2.759999990463257,2.3399999141693115,2.450000047683716,2.42412413708929,3980500,0.0,0.0,True 2023-08-02 00:00:00-04:00,2.4600000381469727,2.4600000381469727,2.3299999237060547,2.369999885559082,2.344968795614638,2111700,0.0,0.0,True -2023-08-03 00:00:00-04:00,2.359999895095825,2.450000047683716,2.359999895095825,2.440000057220459,2.41422955585696,814300,0.0,0.0,True -2023-08-04 00:00:00-04:00,2.470000028610229,2.539999961853028,2.4200000762939453,2.539999961853028,2.5131733329162786,1363900,0.0,0.0,True -2023-08-08 00:00:00-04:00,2.509999990463257,2.549999952316284,2.470000028610229,2.5299999713897705,2.503279042435946,776900,0.0,0.0,True +2023-08-03 00:00:00-04:00,2.359999895095825,2.450000047683716,2.359999895095825,2.440000057220459,2.4142295558569598,814300,0.0,0.0,True +2023-08-04 00:00:00-04:00,2.4700000286102295,2.5399999618530273,2.4200000762939453,2.5399999618530273,2.5131733329162786,1363900,0.0,0.0,True +2023-08-08 00:00:00-04:00,2.509999990463257,2.549999952316284,2.4700000286102295,2.5299999713897705,2.503279042435946,776900,0.0,0.0,True 2023-08-09 00:00:00-04:00,2.549999952316284,2.559999942779541,2.5,2.5199999809265137,2.493384751955613,932100,0.0,0.0,True -2023-08-10 00:00:00-04:00,2.5199999809265137,2.5299999713897705,2.470000028610229,2.490000009536743,2.463701589762618,389700,0.0,0.0,True +2023-08-10 00:00:00-04:00,2.5199999809265137,2.5299999713897705,2.4700000286102295,2.490000009536743,2.463701589762618,389700,0.0,0.0,True 2023-08-11 00:00:00-04:00,2.4800000190734863,2.509999990463257,2.4800000190734863,2.509999990463257,2.483490461475281,280800,0.0,0.0,True -2023-08-14 00:00:00-04:00,2.509999990463257,2.509999990463257,2.400000095367432,2.430000066757202,2.4043352653766275,361600,0.0,0.0,True +2023-08-14 00:00:00-04:00,2.509999990463257,2.509999990463257,2.4000000953674316,2.430000066757202,2.4043352653766275,361600,0.0,0.0,True 2023-08-15 00:00:00-04:00,2.4200000762939453,2.440000057220459,2.2699999809265137,2.319999933242798,2.2954970524609775,1139100,0.0,0.0,True -2023-08-16 00:00:00-04:00,2.289999961853028,2.359999895095825,2.2300000190734863,2.259999990463257,2.236130728074987,474700,0.0,0.0,True +2023-08-16 00:00:00-04:00,2.2899999618530273,2.359999895095825,2.2300000190734863,2.259999990463257,2.2361307280749867,474700,0.0,0.0,True 2023-08-17 00:00:00-04:00,2.259999990463257,2.309999942779541,2.25,2.309999942779541,2.285602471228647,1188900,0.0,0.0,True 2023-08-18 00:00:00-04:00,2.2699999809265137,2.390000104904175,2.240000009536743,2.359999895095825,2.3350745051343056,554900,0.0,0.0,True -2023-08-21 00:00:00-04:00,2.380000114440918,2.400000095367432,2.3299999237060547,2.3299999237060547,2.305391197565312,211200,0.0,0.0,True -2023-08-22 00:00:00-04:00,2.3499999046325684,2.369999885559082,2.25,2.2699999809265137,2.2460251639313187,336200,0.0,0.0,True -2023-08-23 00:00:00-04:00,2.240000009536743,2.259999990463257,2.200000047683716,2.220000028610229,2.19655313002566,368100,0.0,0.0,True +2023-08-21 00:00:00-04:00,2.380000114440918,2.4000000953674316,2.3299999237060547,2.3299999237060547,2.3053911975653114,211200,0.0,0.0,True +2023-08-22 00:00:00-04:00,2.3499999046325684,2.369999885559082,2.25,2.2699999809265137,2.2460251639313182,336200,0.0,0.0,True +2023-08-23 00:00:00-04:00,2.240000009536743,2.259999990463257,2.200000047683716,2.2200000286102295,2.19655313002566,368100,0.0,0.0,True 2023-08-24 00:00:00-04:00,2.2100000381469727,2.2100000381469727,2.130000114440918,2.1600000858306885,2.1371868056396695,270700,0.0,0.0,True 2023-08-25 00:00:00-04:00,2.1600000858306885,2.190000057220459,2.0,2.109999895095825,2.0877147717340114,706100,0.0,0.0,True -2023-08-28 00:00:00-04:00,2.150000095367432,2.190000057220459,2.130000114440918,2.150000095367432,2.1272926605353355,655500,0.0,0.0,True -2023-08-29 00:00:00-04:00,2.1600000858306885,2.200000047683716,2.150000095367432,2.190000057220459,2.1668701132086636,245600,0.0,0.0,True -2023-08-30 00:00:00-04:00,2.180000066757202,2.220000028610229,2.1700000762939453,2.180000066757202,2.1569756773523325,211200,0.0,0.0,True +2023-08-28 00:00:00-04:00,2.1500000953674316,2.190000057220459,2.130000114440918,2.1500000953674316,2.127292660535336,655500,0.0,0.0,True +2023-08-29 00:00:00-04:00,2.1600000858306885,2.200000047683716,2.1500000953674316,2.190000057220459,2.1668701132086636,245600,0.0,0.0,True +2023-08-30 00:00:00-04:00,2.180000066757202,2.2200000286102295,2.1700000762939453,2.180000066757202,2.1569756773523325,211200,0.0,0.0,True 2023-08-31 00:00:00-04:00,2.190000057220459,2.299999952316284,2.190000057220459,2.2799999713897705,2.255919454411651,1133800,0.0,0.0,True 2023-09-01 00:00:00-04:00,2.299999952316284,2.369999885559082,2.299999952316284,2.359999895095825,2.3350745051343056,761300,0.0,0.0,True 2023-09-05 00:00:00-04:00,2.4200000762939453,2.4200000762939453,2.2699999809265137,2.390000104904175,2.3647578127032993,1434000,0.0,0.0,True -2023-09-06 00:00:00-04:00,2.380000114440918,2.400000095367432,2.3299999237060547,2.400000095367432,2.374652248559631,352700,0.0,0.0,True +2023-09-06 00:00:00-04:00,2.380000114440918,2.4000000953674316,2.3299999237060547,2.4000000953674316,2.374652248559631,352700,0.0,0.0,True 2023-09-07 00:00:00-04:00,2.359999895095825,2.390000104904175,2.319999933242798,2.3499999046325684,2.325180069277974,501700,0.0,0.0,True 2023-09-08 00:00:00-04:00,2.3499999046325684,2.359999895095825,2.3299999237060547,2.359999895095825,2.3350745051343056,405100,0.0,0.0,True 2023-09-11 00:00:00-04:00,2.390000104904175,2.4200000762939453,2.3299999237060547,2.3499999046325684,2.325180069277974,740800,0.0,0.0,True 2023-09-12 00:00:00-04:00,2.3499999046325684,2.440000057220459,2.3499999046325684,2.430000066757202,2.4043352653766275,696100,0.0,0.0,True -2023-09-13 00:00:00-04:00,2.440000057220459,2.4600000381469727,2.400000095367432,2.430000066757202,2.4043352653766275,328600,0.0,0.0,True +2023-09-13 00:00:00-04:00,2.440000057220459,2.4600000381469727,2.4000000953674316,2.430000066757202,2.4043352653766275,328600,0.0,0.0,True 2023-09-14 00:00:00-04:00,2.450000047683716,2.5199999809265137,2.430000066757202,2.5199999809265137,2.497917890548706,553500,0.00441,0.0,False 2023-09-15 00:00:00-04:00,2.5,2.640000104904175,2.4800000190734863,2.569999933242798,2.5474798679351807,770400,0.0,0.0,False 2023-09-18 00:00:00-04:00,2.569999933242798,2.640000104904175,2.5299999713897705,2.559999942779541,2.537567377090454,753200,0.0,0.0,False 2023-09-19 00:00:00-04:00,2.569999933242798,2.569999933242798,2.490000009536743,2.5299999713897705,2.5078303813934326,289600,0.0,0.0,False -2023-09-20 00:00:00-04:00,2.569999933242798,2.5799999237060547,2.470000028610229,2.470000028610229,2.4483561515808105,311700,0.0,0.0,False +2023-09-20 00:00:00-04:00,2.569999933242798,2.5799999237060547,2.4700000286102295,2.4700000286102295,2.4483561515808105,311700,0.0,0.0,False 2023-09-21 00:00:00-04:00,2.440000057220459,2.5,2.3399999141693115,2.359999895095825,2.339319944381714,598900,0.0,0.0,False -2023-09-22 00:00:00-04:00,2.400000095367432,2.4800000190734863,2.3499999046325684,2.4800000190734863,2.458268404006958,554600,0.0,0.0,False +2023-09-22 00:00:00-04:00,2.4000000953674316,2.4800000190734863,2.3499999046325684,2.4800000190734863,2.458268404006958,554600,0.0,0.0,False 2023-09-25 00:00:00-04:00,2.4600000381469727,2.4600000381469727,2.3399999141693115,2.359999895095825,2.339319944381714,317300,0.0,0.0,False 2023-09-26 00:00:00-04:00,2.3399999141693115,2.4200000762939453,2.3399999141693115,2.369999885559082,2.3492321968078613,411400,0.0,0.0,False -2023-09-27 00:00:00-04:00,2.400000095367432,2.430000066757202,2.2699999809265137,2.289999961853028,2.269933223724365,1153300,0.0,0.0,False +2023-09-27 00:00:00-04:00,2.4000000953674316,2.430000066757202,2.2699999809265137,2.2899999618530273,2.2699332237243652,1153300,0.0,0.0,False 2023-09-28 00:00:00-04:00,2.25,2.3299999237060547,2.200000047683716,2.240000009536743,2.2203714847564697,1060800,0.0,0.0,False 2023-09-29 00:00:00-04:00,2.2100000381469727,2.240000009536743,2.130000114440918,2.140000104904175,2.1212480068206787,1289400,0.0,0.0,False -2023-10-02 00:00:00-04:00,2.150000095367432,2.1600000858306885,1.9800000190734863,2.0,1.9824745655059812,977300,0.0,0.0,False -2023-10-03 00:00:00-04:00,1.9900000095367432,2.0,1.8600000143051147,1.919999957084656,1.9031755924224851,2986000,0.0,0.0,False -2023-10-04 00:00:00-04:00,1.919999957084656,1.940000057220459,1.8600000143051147,1.940000057220459,1.9230003356933596,608300,0.0,0.0,False -2023-10-05 00:00:00-04:00,29.850000381469727,30.479999542236328,29.0,29.959999084472656,29.69746780395508,16100,0.0,0.0,False -2023-10-06 00:00:00-04:00,29.71999931335449,30.049999237060547,29.13999938964844,29.13999938964844,28.884653091430664,41400,0.0,0.0,False -2023-10-10 00:00:00-04:00,29.0,29.350000381469727,28.36000061035156,28.81999969482422,28.567459106445312,198800,0.0,0.0,False +2023-10-02 00:00:00-04:00,2.1500000953674316,2.1600000858306885,1.9800000190734863,2.0,1.9824745655059814,977300,0.0,0.0,False +2023-10-03 00:00:00-04:00,1.9900000095367432,2.0,1.8600000143051147,1.9199999570846558,1.9031755924224854,2986000,0.0,0.0,False +2023-10-04 00:00:00-04:00,1.9199999570846558,1.940000057220459,1.8600000143051147,1.940000057220459,1.9230003356933594,608300,0.0,0.0,False +2023-10-05 00:00:00-04:00,29.850000381469727,30.479999542236328,29.0,29.959999084472656,29.697467803955078,16100,0.0,0.0,False +2023-10-06 00:00:00-04:00,29.719999313354492,30.049999237060547,29.139999389648438,29.139999389648438,28.884653091430664,41400,0.0,0.0,False +2023-10-10 00:00:00-04:00,29.0,29.350000381469727,28.360000610351562,28.81999969482422,28.567459106445312,198800,0.0,0.0,False 2023-10-11 00:00:00-04:00,28.850000381469727,29.0,28.729999542236328,28.729999542236328,28.478246688842773,28400,0.0,0.0,False -2023-10-12 00:00:00-04:00,28.76000022888184,28.76000022888184,28.25,28.299999237060547,28.0520133972168,42300,0.0,0.0,False +2023-10-12 00:00:00-04:00,28.760000228881836,28.760000228881836,28.25,28.299999237060547,28.052013397216797,42300,0.0,0.0,False 2023-10-13 00:00:00-04:00,28.31999969482422,29.0,28.309999465942383,28.989999771118164,28.73596954345703,50700,0.0,0.0,False -2023-10-16 00:00:00-04:00,29.420000076293945,29.420000076293945,28.76000022888184,29.229999542236328,28.973865509033203,23900,0.0,0.0,False -2023-10-17 00:00:00-04:00,29.25,29.450000762939453,28.88999938964844,28.950000762939453,28.696319580078125,40100,0.0,0.0,False -2023-10-18 00:00:00-04:00,28.899999618530277,28.96999931335449,28.350000381469727,28.739999771118164,28.4881591796875,31800,0.0,0.0,False -2023-10-19 00:00:00-04:00,28.690000534057617,28.700000762939453,28.11000061035156,28.350000381469727,28.101577758789062,40800,0.0,0.0,False -2023-10-20 00:00:00-04:00,28.5,29.399999618530277,27.65999984741211,27.82999992370605,27.58613395690918,46600,0.0,0.0,False -2023-10-23 00:00:00-04:00,27.739999771118164,27.799999237060547,27.46999931335449,27.530000686645508,27.28876304626465,29400,0.0,0.0,False +2023-10-16 00:00:00-04:00,29.420000076293945,29.420000076293945,28.760000228881836,29.229999542236328,28.973865509033203,23900,0.0,0.0,False +2023-10-17 00:00:00-04:00,29.25,29.450000762939453,28.889999389648438,28.950000762939453,28.696319580078125,40100,0.0,0.0,False +2023-10-18 00:00:00-04:00,28.899999618530273,28.969999313354492,28.350000381469727,28.739999771118164,28.4881591796875,31800,0.0,0.0,False +2023-10-19 00:00:00-04:00,28.690000534057617,28.700000762939453,28.110000610351562,28.350000381469727,28.101577758789062,40800,0.0,0.0,False +2023-10-20 00:00:00-04:00,28.5,29.399999618530273,27.65999984741211,27.829999923706055,27.58613395690918,46600,0.0,0.0,False +2023-10-23 00:00:00-04:00,27.739999771118164,27.799999237060547,27.469999313354492,27.530000686645508,27.28876304626465,29400,0.0,0.0,False 2023-10-24 00:00:00-04:00,27.09000015258789,27.3700008392334,26.700000762939453,26.75,26.515596389770508,34000,0.0,0.0,False -2023-10-25 00:00:00-04:00,26.84000015258789,27.21999931335449,26.65999984741211,27.18000030517578,26.941829681396484,27200,0.0,0.0,False -2023-10-26 00:00:00-04:00,27.5,27.780000686645508,27.26000022888184,27.63999938964844,27.397798538208008,29700,0.0,0.0,False -2023-10-27 00:00:00-04:00,27.25,27.76000022888184,26.950000762939453,27.309999465942383,27.070690155029297,20700,0.0,0.0,False -2023-10-30 00:00:00-04:00,27.07999992370605,27.729999542236328,26.96999931335449,27.309999465942383,27.070690155029297,17700,0.0,0.0,False +2023-10-25 00:00:00-04:00,26.84000015258789,27.219999313354492,26.65999984741211,27.18000030517578,26.941829681396484,27200,0.0,0.0,False +2023-10-26 00:00:00-04:00,27.5,27.780000686645508,27.260000228881836,27.639999389648438,27.397798538208008,29700,0.0,0.0,False +2023-10-27 00:00:00-04:00,27.25,27.760000228881836,26.950000762939453,27.309999465942383,27.070690155029297,20700,0.0,0.0,False +2023-10-30 00:00:00-04:00,27.079999923706055,27.729999542236328,26.969999313354492,27.309999465942383,27.070690155029297,17700,0.0,0.0,False 2023-10-31 00:00:00-04:00,27.209999084472656,27.420000076293945,26.770000457763672,27.15999984741211,26.92200469970703,12800,0.0,0.0,False -2023-11-01 00:00:00-04:00,27.13999938964844,27.190000534057617,26.799999237060547,27.190000534057617,26.95174217224121,27700,0.0,0.0,False +2023-11-01 00:00:00-04:00,27.139999389648438,27.190000534057617,26.799999237060547,27.190000534057617,26.95174217224121,27700,0.0,0.0,False 2023-11-02 00:00:00-04:00,27.040000915527344,27.790000915527344,27.0,27.600000381469727,27.3581485748291,12200,0.0,0.0,False -2023-11-03 00:00:00-04:00,27.34000015258789,27.670000076293945,26.71999931335449,26.799999237060547,26.56515884399414,25300,0.0,0.0,False -2023-11-06 00:00:00-05:00,27.01000022888184,27.18000030517578,25.43000030517578,25.75,25.52436065673828,39600,0.0,0.0,False -2023-11-07 00:00:00-05:00,25.899999618530277,25.899999618530277,24.36000061035156,24.3799991607666,24.166364669799805,45100,0.0,0.0,False -2023-11-08 00:00:00-05:00,24.43000030517578,24.540000915527344,23.309999465942383,23.43000030517578,23.224689483642575,42600,0.0,0.0,False -2023-11-09 00:00:00-05:00,23.43000030517578,23.6299991607666,22.75,22.86000061035156,22.65968513488769,51500,0.0,0.0,False -2023-11-10 00:00:00-05:00,22.899999618530277,23.290000915527344,22.530000686645508,22.71999931335449,22.520910263061523,27200,0.0,0.0,False +2023-11-03 00:00:00-04:00,27.34000015258789,27.670000076293945,26.719999313354492,26.799999237060547,26.56515884399414,25300,0.0,0.0,False +2023-11-06 00:00:00-05:00,27.010000228881836,27.18000030517578,25.43000030517578,25.75,25.52436065673828,39600,0.0,0.0,False +2023-11-07 00:00:00-05:00,25.899999618530273,25.899999618530273,24.360000610351562,24.3799991607666,24.166364669799805,45100,0.0,0.0,False +2023-11-08 00:00:00-05:00,24.43000030517578,24.540000915527344,23.309999465942383,23.43000030517578,23.224689483642578,42600,0.0,0.0,False +2023-11-09 00:00:00-05:00,23.43000030517578,23.6299991607666,22.75,22.860000610351562,22.659685134887695,51500,0.0,0.0,False +2023-11-10 00:00:00-05:00,22.899999618530273,23.290000915527344,22.530000686645508,22.719999313354492,22.520910263061523,27200,0.0,0.0,False 2023-11-13 00:00:00-05:00,22.979999542236328,23.549999237060547,22.34000015258789,23.239999771118164,23.036354064941406,43600,0.0,0.0,False -2023-11-14 00:00:00-05:00,23.5,23.5,22.450000762939453,22.649999618530277,22.45152473449707,36800,0.0,0.0,False -2023-11-15 00:00:00-05:00,22.299999237060547,22.57999992370605,22.100000381469727,22.459999084472656,22.2631893157959,39000,0.0,0.0,False -2023-11-16 00:00:00-05:00,22.809999465942383,22.809999465942383,21.600000381469727,21.950000762939453,21.75765991210937,90300,0.0,0.0,False +2023-11-14 00:00:00-05:00,23.5,23.5,22.450000762939453,22.649999618530273,22.45152473449707,36800,0.0,0.0,False +2023-11-15 00:00:00-05:00,22.299999237060547,22.579999923706055,22.100000381469727,22.459999084472656,22.2631893157959,39000,0.0,0.0,False +2023-11-16 00:00:00-05:00,22.809999465942383,22.809999465942383,21.600000381469727,21.950000762939453,21.757659912109375,90300,0.0,0.0,False 2023-11-17 00:00:00-05:00,22.1299991607666,22.90999984741211,22.1299991607666,22.540000915527344,22.34248924255371,36600,0.0,0.0,False -2023-11-20 00:00:00-05:00,23.299999237060547,23.709999084472656,22.149999618530277,23.670000076293945,23.462587356567383,56100,0.0,0.0,False -2023-11-21 00:00:00-05:00,23.200000762939453,23.36000061035156,22.899999618530277,23.13999938964844,22.937231063842773,23300,0.0,0.0,False +2023-11-20 00:00:00-05:00,23.299999237060547,23.709999084472656,22.149999618530273,23.670000076293945,23.462587356567383,56100,0.0,0.0,False +2023-11-21 00:00:00-05:00,23.200000762939453,23.360000610351562,22.899999618530273,23.139999389648438,22.937231063842773,23300,0.0,0.0,False 2023-11-22 00:00:00-05:00,22.75,22.8799991607666,21.979999542236328,22.190000534057617,21.995555877685547,72300,0.0,0.0,False -2023-11-23 00:00:00-05:00,23.38999938964844,23.38999938964844,22.020000457763672,22.299999237060547,22.104591369628903,47600,0.0,0.0,False +2023-11-23 00:00:00-05:00,23.389999389648438,23.389999389648438,22.020000457763672,22.299999237060547,22.104591369628906,47600,0.0,0.0,False 2023-11-24 00:00:00-05:00,22.75,22.75,22.489999771118164,22.670000076293945,22.471349716186523,11900,0.0,0.0,False -2023-11-27 00:00:00-05:00,23.11000061035156,23.459999084472656,22.61000061035156,22.940000534057617,22.738983154296875,22100,0.0,0.0,False -2023-11-28 00:00:00-05:00,22.90999984741211,22.90999984741211,22.459999084472656,22.57999992370605,22.382137298583984,15400,0.0,0.0,False -2023-11-29 00:00:00-05:00,22.700000762939453,22.84000015258789,22.399999618530277,22.600000381469727,22.40196228027344,15700,0.0,0.0,False -2023-11-30 00:00:00-05:00,22.739999771118164,22.950000762939453,22.11000061035156,22.299999237060547,22.104591369628903,48200,0.0,0.0,False -2023-12-01 00:00:00-05:00,22.21999931335449,22.76000022888184,22.21999931335449,22.399999618530277,22.20371437072754,20700,0.0,0.0,False +2023-11-27 00:00:00-05:00,23.110000610351562,23.459999084472656,22.610000610351562,22.940000534057617,22.738983154296875,22100,0.0,0.0,False +2023-11-28 00:00:00-05:00,22.90999984741211,22.90999984741211,22.459999084472656,22.579999923706055,22.382137298583984,15400,0.0,0.0,False +2023-11-29 00:00:00-05:00,22.700000762939453,22.84000015258789,22.399999618530273,22.600000381469727,22.401962280273438,15700,0.0,0.0,False +2023-11-30 00:00:00-05:00,22.739999771118164,22.950000762939453,22.110000610351562,22.299999237060547,22.104591369628906,48200,0.0,0.0,False +2023-12-01 00:00:00-05:00,22.219999313354492,22.760000228881836,22.219999313354492,22.399999618530273,22.20371437072754,20700,0.0,0.0,False 2023-12-04 00:00:00-05:00,22.530000686645508,22.93000030517578,22.25,22.420000076293945,22.223539352416992,22000,0.0,0.0,False -2023-12-05 00:00:00-05:00,22.440000534057617,22.5,21.71999931335449,21.88999938964844,21.698183059692383,24500,0.0,0.0,False +2023-12-05 00:00:00-05:00,22.440000534057617,22.5,21.719999313354492,21.889999389648438,21.698183059692383,24500,0.0,0.0,False 2023-12-06 00:00:00-05:00,22.020000457763672,22.209999084472656,20.90999984741211,20.989999771118164,20.80607032775879,105100,0.0,0.0,False -2023-12-07 00:00:00-05:00,20.950000762939453,21.020000457763672,20.15999984741211,20.399999618530277,20.221240997314453,51900,0.0,0.0,False -2023-12-08 00:00:00-05:00,20.96999931335449,21.200000762939453,20.690000534057617,20.8799991607666,20.6970329284668,59600,0.0,0.0,False +2023-12-07 00:00:00-05:00,20.950000762939453,21.020000457763672,20.15999984741211,20.399999618530273,20.221240997314453,51900,0.0,0.0,False +2023-12-08 00:00:00-05:00,20.969999313354492,21.200000762939453,20.690000534057617,20.8799991607666,20.697032928466797,59600,0.0,0.0,False 2023-12-11 00:00:00-05:00,21.09000015258789,21.18000030517578,20.5,21.06999969482422,20.88536834716797,29700,0.0,0.0,False -2023-12-12 00:00:00-05:00,20.989999771118164,21.18000030517578,20.899999618530277,21.18000030517578,20.99440574645996,69300,0.0,0.0,False -2023-12-13 00:00:00-05:00,20.790000915527344,21.21999931335449,20.440000534057617,21.21999931335449,21.034053802490234,35900,0.0,0.0,False -2023-12-14 00:00:00-05:00,22.01000022888184,22.100000381469727,21.420000076293945,21.88999938964844,21.698183059692383,22200,0.0,0.0,False -2023-12-15 00:00:00-05:00,21.940000534057617,21.940000534057617,21.32999992370605,21.690000534057617,21.49993705749512,25200,0.0,0.0,False -2023-12-18 00:00:00-05:00,21.899999618530277,22.3700008392334,21.770000457763672,22.290000915527344,22.09468078613281,59200,0.0,0.0,False -2023-12-19 00:00:00-05:00,22.030000686645508,22.950000762939453,22.030000686645508,22.82999992370605,22.62994766235352,62400,0.0,0.0,False +2023-12-12 00:00:00-05:00,20.989999771118164,21.18000030517578,20.899999618530273,21.18000030517578,20.99440574645996,69300,0.0,0.0,False +2023-12-13 00:00:00-05:00,20.790000915527344,21.219999313354492,20.440000534057617,21.219999313354492,21.034053802490234,35900,0.0,0.0,False +2023-12-14 00:00:00-05:00,22.010000228881836,22.100000381469727,21.420000076293945,21.889999389648438,21.698183059692383,22200,0.0,0.0,False +2023-12-15 00:00:00-05:00,21.940000534057617,21.940000534057617,21.329999923706055,21.690000534057617,21.499937057495117,25200,0.0,0.0,False +2023-12-18 00:00:00-05:00,21.899999618530273,22.3700008392334,21.770000457763672,22.290000915527344,22.094680786132812,59200,0.0,0.0,False +2023-12-19 00:00:00-05:00,22.030000686645508,22.950000762939453,22.030000686645508,22.829999923706055,22.629947662353516,62400,0.0,0.0,False 2023-12-20 00:00:00-05:00,23.0,23.31999969482422,22.670000076293945,23.09000015258789,22.88766860961914,89800,0.0,0.0,False -2023-12-21 00:00:00-05:00,23.290000915527344,23.559999465942383,23.07999992370605,23.420000076293945,23.21477699279785,47900,0.0,0.0,False -2023-12-22 00:00:00-05:00,23.5,23.81999969482422,22.76000022888184,22.790000915527344,22.59029769897461,185800,0.0,0.0,False -2023-12-27 00:00:00-05:00,23.190000534057617,23.190000534057617,22.280000686645508,22.290000915527344,22.09468078613281,49600,0.0,0.0,False -2023-12-28 00:00:00-05:00,22.100000381469727,22.57999992370605,21.799999237060547,21.84000015258789,21.648622512817383,8500,0.0,0.0,False -2023-12-29 00:00:00-05:00,21.899999618530277,22.040000915527344,21.350000381469727,21.43000030517578,21.24221611022949,43900,0.0,0.0,False +2023-12-21 00:00:00-05:00,23.290000915527344,23.559999465942383,23.079999923706055,23.420000076293945,23.21477699279785,47900,0.0,0.0,False +2023-12-22 00:00:00-05:00,23.5,23.81999969482422,22.760000228881836,22.790000915527344,22.59029769897461,185800,0.0,0.0,False +2023-12-27 00:00:00-05:00,23.190000534057617,23.190000534057617,22.280000686645508,22.290000915527344,22.094680786132812,49600,0.0,0.0,False +2023-12-28 00:00:00-05:00,22.100000381469727,22.579999923706055,21.799999237060547,21.84000015258789,21.648622512817383,8500,0.0,0.0,False +2023-12-29 00:00:00-05:00,21.899999618530273,22.040000915527344,21.350000381469727,21.43000030517578,21.242216110229492,43900,0.0,0.0,False 2024-01-02 00:00:00-05:00,21.709999084472656,22.68000030517578,21.540000915527344,22.459999084472656,22.2631893157959,34900,0.0,0.0,False -2024-01-03 00:00:00-05:00,22.540000915527344,22.600000381469727,22.36000061035156,22.57999992370605,22.382137298583984,25900,0.0,0.0,False -2024-01-04 00:00:00-05:00,22.51000022888184,22.81999969482422,22.100000381469727,22.420000076293945,22.223539352416992,21900,0.0,0.0,False +2024-01-03 00:00:00-05:00,22.540000915527344,22.600000381469727,22.360000610351562,22.579999923706055,22.382137298583984,25900,0.0,0.0,False +2024-01-04 00:00:00-05:00,22.510000228881836,22.81999969482422,22.100000381469727,22.420000076293945,22.223539352416992,21900,0.0,0.0,False 2024-01-05 00:00:00-05:00,22.3799991607666,22.440000534057617,22.100000381469727,22.229999542236328,22.03520393371582,17800,0.0,0.0,False -2024-01-08 00:00:00-05:00,22.63999938964844,22.63999938964844,21.799999237060547,22.399999618530277,22.20371437072754,21000,0.0,0.0,False -2024-01-09 00:00:00-05:00,22.3799991607666,22.479999542236328,22.030000686645508,22.36000061035156,22.164066314697266,11200,0.0,0.0,False -2024-01-10 00:00:00-05:00,22.1200008392334,22.88999938964844,22.1200008392334,22.5,22.302839279174805,76600,0.0,0.0,False -2024-01-11 00:00:00-05:00,22.18000030517578,22.649999618530277,22.18000030517578,22.51000022888184,22.31275177001953,7500,0.0,0.0,False -2024-01-12 00:00:00-05:00,22.670000076293945,23.200000762939453,22.51000022888184,22.96999931335449,22.76872062683105,31300,0.0,0.0,False -2024-01-15 00:00:00-05:00,23.0,24.25,23.0,23.649999618530277,23.442760467529297,19500,0.0,0.0,False +2024-01-08 00:00:00-05:00,22.639999389648438,22.639999389648438,21.799999237060547,22.399999618530273,22.20371437072754,21000,0.0,0.0,False +2024-01-09 00:00:00-05:00,22.3799991607666,22.479999542236328,22.030000686645508,22.360000610351562,22.164066314697266,11200,0.0,0.0,False +2024-01-10 00:00:00-05:00,22.1200008392334,22.889999389648438,22.1200008392334,22.5,22.302839279174805,76600,0.0,0.0,False +2024-01-11 00:00:00-05:00,22.18000030517578,22.649999618530273,22.18000030517578,22.510000228881836,22.31275177001953,7500,0.0,0.0,False +2024-01-12 00:00:00-05:00,22.670000076293945,23.200000762939453,22.510000228881836,22.969999313354492,22.768720626831055,31300,0.0,0.0,False +2024-01-15 00:00:00-05:00,23.0,24.25,23.0,23.649999618530273,23.442760467529297,19500,0.0,0.0,False 2024-01-16 00:00:00-05:00,23.549999237060547,24.31999969482422,23.440000534057617,23.6299991607666,23.422935485839844,36600,0.0,0.0,False -2024-01-17 00:00:00-05:00,23.649999618530277,23.71999931335449,22.979999542236328,23.020000457763672,22.818283081054688,7100,0.0,0.0,False +2024-01-17 00:00:00-05:00,23.649999618530273,23.719999313354492,22.979999542236328,23.020000457763672,22.818283081054688,7100,0.0,0.0,False 2024-01-18 00:00:00-05:00,23.0,24.489999771118164,22.989999771118164,24.25,24.037504196166992,140400,0.0,0.0,False -2024-01-19 00:00:00-05:00,24.149999618530277,24.57999992370605,23.88999938964844,24.350000381469727,24.136629104614254,37400,0.0,0.0,False -2024-01-22 00:00:00-05:00,24.649999618530277,24.65999984741211,23.729999542236328,23.88999938964844,23.6806583404541,13800,0.0,0.0,False -2024-01-23 00:00:00-05:00,24.0,24.0,23.81999969482422,23.989999771118164,23.77978134155273,32500,0.0,0.0,False -2024-01-24 00:00:00-05:00,23.88999938964844,24.11000061035156,23.850000381469727,24.01000022888184,23.79960823059082,21200,0.0,0.0,False -2024-01-25 00:00:00-05:00,24.01000022888184,24.5,24.01000022888184,24.479999542236328,24.26548767089844,30400,0.0,0.0,False -2024-01-26 00:00:00-05:00,24.8799991607666,24.8799991607666,23.899999618530277,24.25,24.037504196166992,48900,0.0,0.0,False -2024-01-29 00:00:00-05:00,23.959999084472656,24.21999931335449,23.950000762939453,24.0,23.789695739746094,16800,0.0,0.0,False -2024-01-30 00:00:00-05:00,24.36000061035156,24.36000061035156,23.989999771118164,24.0,23.789695739746094,36000,0.0,0.0,False -2024-01-31 00:00:00-05:00,23.950000762939453,23.96999931335449,23.670000076293945,23.71999931335449,23.512147903442383,30900,0.0,0.0,False -2024-02-01 00:00:00-05:00,23.799999237060547,24.1200008392334,23.76000022888184,23.799999237060547,23.59144592285156,31000,0.0,0.0,False -2024-02-02 00:00:00-05:00,23.989999771118164,24.32999992370605,23.690000534057617,24.06999969482422,23.859081268310547,48400,0.0,0.0,False +2024-01-19 00:00:00-05:00,24.149999618530273,24.579999923706055,23.889999389648438,24.350000381469727,24.136629104614258,37400,0.0,0.0,False +2024-01-22 00:00:00-05:00,24.649999618530273,24.65999984741211,23.729999542236328,23.889999389648438,23.6806583404541,13800,0.0,0.0,False +2024-01-23 00:00:00-05:00,24.0,24.0,23.81999969482422,23.989999771118164,23.779781341552734,32500,0.0,0.0,False +2024-01-24 00:00:00-05:00,23.889999389648438,24.110000610351562,23.850000381469727,24.010000228881836,23.79960823059082,21200,0.0,0.0,False +2024-01-25 00:00:00-05:00,24.010000228881836,24.5,24.010000228881836,24.479999542236328,24.265487670898438,30400,0.0,0.0,False +2024-01-26 00:00:00-05:00,24.8799991607666,24.8799991607666,23.899999618530273,24.25,24.037504196166992,48900,0.0,0.0,False +2024-01-29 00:00:00-05:00,23.959999084472656,24.219999313354492,23.950000762939453,24.0,23.789695739746094,16800,0.0,0.0,False +2024-01-30 00:00:00-05:00,24.360000610351562,24.360000610351562,23.989999771118164,24.0,23.789695739746094,36000,0.0,0.0,False +2024-01-31 00:00:00-05:00,23.950000762939453,23.969999313354492,23.670000076293945,23.719999313354492,23.512147903442383,30900,0.0,0.0,False +2024-02-01 00:00:00-05:00,23.799999237060547,24.1200008392334,23.760000228881836,23.799999237060547,23.591445922851562,31000,0.0,0.0,False +2024-02-02 00:00:00-05:00,23.989999771118164,24.329999923706055,23.690000534057617,24.06999969482422,23.859081268310547,48400,0.0,0.0,False 2024-02-05 00:00:00-05:00,24.489999771118164,24.75,24.15999984741211,24.729999542236328,24.51329803466797,68100,0.0,0.0,False -2024-02-06 00:00:00-05:00,24.76000022888184,24.950000762939453,24.1200008392334,24.200000762939453,23.987943649291992,44600,0.0,0.0,False -2024-02-07 00:00:00-05:00,24.299999237060547,24.299999237060547,22.46999931335449,22.75,22.550647735595703,78300,0.0,0.0,False -2024-02-08 00:00:00-05:00,22.61000061035156,22.979999542236328,22.450000762939453,22.739999771118164,22.540735244750977,40100,0.0,0.0,False +2024-02-06 00:00:00-05:00,24.760000228881836,24.950000762939453,24.1200008392334,24.200000762939453,23.987943649291992,44600,0.0,0.0,False +2024-02-07 00:00:00-05:00,24.299999237060547,24.299999237060547,22.469999313354492,22.75,22.550647735595703,78300,0.0,0.0,False +2024-02-08 00:00:00-05:00,22.610000610351562,22.979999542236328,22.450000762939453,22.739999771118164,22.540735244750977,40100,0.0,0.0,False 2024-02-09 00:00:00-05:00,22.75,22.809999465942383,22.540000915527344,22.670000076293945,22.471349716186523,31500,0.0,0.0,False -2024-02-12 00:00:00-05:00,22.63999938964844,23.26000022888184,22.600000381469727,23.1299991607666,22.92731666564941,14700,0.0,0.0,False -2024-02-13 00:00:00-05:00,23.3799991607666,23.540000915527344,22.76000022888184,22.90999984741211,22.70924568176269,31500,0.0,0.0,False -2024-02-14 00:00:00-05:00,23.170000076293945,24.13999938964844,22.96999931335449,23.979999542236328,23.769868850708008,29800,0.0,0.0,False -2024-02-15 00:00:00-05:00,24.21999931335449,25.75,24.209999084472656,25.190000534057617,24.96926689147949,75200,0.0,0.0,False -2024-02-16 00:00:00-05:00,25.290000915527344,25.459999084472656,24.649999618530277,24.700000762939453,24.483562469482425,42400,0.0,0.0,False +2024-02-12 00:00:00-05:00,22.639999389648438,23.260000228881836,22.600000381469727,23.1299991607666,22.927316665649414,14700,0.0,0.0,False +2024-02-13 00:00:00-05:00,23.3799991607666,23.540000915527344,22.760000228881836,22.90999984741211,22.709245681762695,31500,0.0,0.0,False +2024-02-14 00:00:00-05:00,23.170000076293945,24.139999389648438,22.969999313354492,23.979999542236328,23.769868850708008,29800,0.0,0.0,False +2024-02-15 00:00:00-05:00,24.219999313354492,25.75,24.209999084472656,25.190000534057617,24.969266891479492,75200,0.0,0.0,False +2024-02-16 00:00:00-05:00,25.290000915527344,25.459999084472656,24.649999618530273,24.700000762939453,24.483562469482422,42400,0.0,0.0,False 2024-02-20 00:00:00-05:00,24.5,24.700000762939453,24.31999969482422,24.520000457763672,24.305139541625977,11800,0.0,0.0,False -2024-02-21 00:00:00-05:00,24.040000915527344,25.739999771118164,24.040000915527344,24.959999084472656,24.74128150939941,19800,0.0,0.0,False -2024-02-22 00:00:00-05:00,24.76000022888184,24.770000457763672,23.649999618530277,23.84000015258789,23.6310977935791,57300,0.0,0.0,False -2024-02-23 00:00:00-05:00,23.950000762939453,23.950000762939453,23.399999618530277,23.46999931335449,23.26433753967285,11900,0.0,0.0,False +2024-02-21 00:00:00-05:00,24.040000915527344,25.739999771118164,24.040000915527344,24.959999084472656,24.741281509399414,19800,0.0,0.0,False +2024-02-22 00:00:00-05:00,24.760000228881836,24.770000457763672,23.649999618530273,23.84000015258789,23.6310977935791,57300,0.0,0.0,False +2024-02-23 00:00:00-05:00,23.950000762939453,23.950000762939453,23.399999618530273,23.469999313354492,23.26433753967285,11900,0.0,0.0,False 2024-02-26 00:00:00-05:00,23.18000030517578,24.200000762939453,22.8799991607666,23.93000030517578,23.720308303833008,27600,0.0,0.0,False -2024-02-27 00:00:00-05:00,23.21999931335449,23.96999931335449,23.18000030517578,23.600000381469727,23.393199920654297,19900,0.0,0.0,False -2024-02-28 00:00:00-05:00,23.540000915527344,23.799999237060547,23.07999992370605,23.190000534057617,22.986793518066406,20900,0.0,0.0,False -2024-02-29 00:00:00-05:00,22.96999931335449,23.700000762939453,22.96999931335449,23.6200008392334,23.41302490234375,29300,0.0,0.0,False -2024-03-01 00:00:00-05:00,23.61000061035156,24.350000381469727,23.61000061035156,23.88999938964844,23.6806583404541,13400,0.0,0.0,False -2024-03-04 00:00:00-05:00,23.93000030517578,25.049999237060547,23.93000030517578,25.049999237060547,24.830493927001957,32700,0.0,0.0,False -2024-03-05 00:00:00-05:00,24.63999938964844,25.290000915527344,24.63999938964844,25.290000915527344,25.06839179992676,47000,0.0,0.0,False -2024-03-06 00:00:00-05:00,25.479999542236328,25.5,25.040000915527344,25.309999465942383,25.088214874267575,30400,0.0,0.0,False -2024-03-07 00:00:00-05:00,25.450000762939453,25.450000762939453,25.100000381469727,25.149999618530277,24.929616928100582,14700,0.0,0.0,False +2024-02-27 00:00:00-05:00,23.219999313354492,23.969999313354492,23.18000030517578,23.600000381469727,23.393199920654297,19900,0.0,0.0,False +2024-02-28 00:00:00-05:00,23.540000915527344,23.799999237060547,23.079999923706055,23.190000534057617,22.986793518066406,20900,0.0,0.0,False +2024-02-29 00:00:00-05:00,22.969999313354492,23.700000762939453,22.969999313354492,23.6200008392334,23.41302490234375,29300,0.0,0.0,False +2024-03-01 00:00:00-05:00,23.610000610351562,24.350000381469727,23.610000610351562,23.889999389648438,23.6806583404541,13400,0.0,0.0,False +2024-03-04 00:00:00-05:00,23.93000030517578,25.049999237060547,23.93000030517578,25.049999237060547,24.830493927001953,32700,0.0,0.0,False +2024-03-05 00:00:00-05:00,24.639999389648438,25.290000915527344,24.639999389648438,25.290000915527344,25.068391799926758,47000,0.0,0.0,False +2024-03-06 00:00:00-05:00,25.479999542236328,25.5,25.040000915527344,25.309999465942383,25.088214874267578,30400,0.0,0.0,False +2024-03-07 00:00:00-05:00,25.450000762939453,25.450000762939453,25.100000381469727,25.149999618530273,24.929616928100586,14700,0.0,0.0,False 2024-03-08 00:00:00-05:00,25.31999969482422,25.3799991607666,24.6299991607666,24.8700008392334,24.65207290649414,14800,0.0,0.0,False 2024-03-11 00:00:00-04:00,25.299999237060547,25.299999237060547,24.84000015258789,25.020000457763672,24.800756454467773,6500,0.0,0.0,False -2024-03-12 00:00:00-04:00,25.290000915527344,26.239999771118164,25.200000762939453,25.850000381469727,25.623483657836918,98700,0.0,0.0,False -2024-03-13 00:00:00-04:00,26.030000686645508,26.799999237060547,26.030000686645508,26.729999542236328,26.49577140808105,70600,0.0,0.0,False +2024-03-12 00:00:00-04:00,25.290000915527344,26.239999771118164,25.200000762939453,25.850000381469727,25.623483657836914,98700,0.0,0.0,False +2024-03-13 00:00:00-04:00,26.030000686645508,26.799999237060547,26.030000686645508,26.729999542236328,26.495771408081055,70600,0.0,0.0,False 2024-03-14 00:00:00-04:00,27.0,27.5,26.75,27.190000534057617,26.95174217224121,50200,0.0,0.0,False 2024-03-15 00:00:00-04:00,27.549999237060547,27.549999237060547,26.68000030517578,26.709999084472656,26.4759464263916,118200,0.0,0.0,False -2024-03-18 00:00:00-04:00,27.36000061035156,27.61000061035156,26.8700008392334,27.489999771118164,27.249113082885746,58500,0.0,0.0,False -2024-03-19 00:00:00-04:00,27.690000534057617,28.5,27.399999618530277,28.3700008392334,28.12140274047852,100900,0.0,0.0,False -2024-03-20 00:00:00-04:00,28.40999984741211,29.190000534057617,28.0,29.07999992370605,28.825180053710938,46300,0.0,0.0,False -2024-03-21 00:00:00-04:00,29.350000381469727,29.700000762939453,28.8799991607666,29.280000686645508,29.02342796325684,52500,0.0,0.0,False -2024-03-22 00:00:00-04:00,29.520000457763672,29.520000457763672,28.82999992370605,29.15999984741211,28.90447807312012,42100,0.0,0.0,False -2024-03-25 00:00:00-04:00,29.15999984741211,29.989999771118164,29.15999984741211,29.88999938964844,29.628082275390625,32600,0.0,0.0,False +2024-03-18 00:00:00-04:00,27.360000610351562,27.610000610351562,26.8700008392334,27.489999771118164,27.249113082885742,58500,0.0,0.0,False +2024-03-19 00:00:00-04:00,27.690000534057617,28.5,27.399999618530273,28.3700008392334,28.121402740478516,100900,0.0,0.0,False +2024-03-20 00:00:00-04:00,28.40999984741211,29.190000534057617,28.0,29.079999923706055,28.825180053710938,46300,0.0,0.0,False +2024-03-21 00:00:00-04:00,29.350000381469727,29.700000762939453,28.8799991607666,29.280000686645508,29.023427963256836,52500,0.0,0.0,False +2024-03-22 00:00:00-04:00,29.520000457763672,29.520000457763672,28.829999923706055,29.15999984741211,28.904478073120117,42100,0.0,0.0,False +2024-03-25 00:00:00-04:00,29.15999984741211,29.989999771118164,29.15999984741211,29.889999389648438,29.628082275390625,32600,0.0,0.0,False 2024-03-26 00:00:00-04:00,29.989999771118164,30.06999969482422,29.15999984741211,29.18000030517578,28.924304962158203,54100,0.0,0.0,False -2024-03-27 00:00:00-04:00,29.170000076293945,29.170000076293945,28.26000022888184,28.290000915527344,28.042102813720703,63300,0.0,0.0,False -2024-03-28 00:00:00-04:00,28.51000022888184,28.690000534057617,27.6200008392334,28.420000076293945,28.17096328735352,42100,0.0,0.0,False -2024-04-01 00:00:00-04:00,28.420000076293945,31.440000534057617,28.420000076293945,31.200000762939453,30.926603317260746,75600,0.0,0.0,False +2024-03-27 00:00:00-04:00,29.170000076293945,29.170000076293945,28.260000228881836,28.290000915527344,28.042102813720703,63300,0.0,0.0,False +2024-03-28 00:00:00-04:00,28.510000228881836,28.690000534057617,27.6200008392334,28.420000076293945,28.170963287353516,42100,0.0,0.0,False +2024-04-01 00:00:00-04:00,28.420000076293945,31.440000534057617,28.420000076293945,31.200000762939453,30.926603317260742,75600,0.0,0.0,False 2024-04-02 00:00:00-04:00,31.200000762939453,31.520000457763672,30.959999084472656,31.520000457763672,31.243799209594727,109600,0.0,0.0,False -2024-04-03 00:00:00-04:00,31.690000534057617,31.799999237060547,31.32999992370605,31.790000915527344,31.51143455505371,69600,0.0,0.0,False -2024-04-04 00:00:00-04:00,32.099998474121094,32.099998474121094,31.229999542236328,31.700000762939453,31.42222213745117,112900,0.0,0.0,False +2024-04-03 00:00:00-04:00,31.690000534057617,31.799999237060547,31.329999923706055,31.790000915527344,31.51143455505371,69600,0.0,0.0,False +2024-04-04 00:00:00-04:00,32.099998474121094,32.099998474121094,31.229999542236328,31.700000762939453,31.422222137451172,112900,0.0,0.0,False 2024-04-05 00:00:00-04:00,31.780000686645508,33.349998474121094,31.75,33.029998779296875,32.74056625366211,59200,0.0,0.0,False 2024-04-08 00:00:00-04:00,33.25,34.130001068115234,32.81999969482422,33.77000045776367,33.474082946777344,67300,0.0,0.0,False 2024-04-09 00:00:00-04:00,33.70000076293945,33.90999984741211,33.40999984741211,33.849998474121094,33.55337905883789,58000,0.0,0.0,False @@ -573,7 +573,7 @@ Datetime,Open,High,Low,Close,Adj Close,Volume,Dividends,Stock Splits,Repaired? 2024-04-12 00:00:00-04:00,34.349998474121094,34.97999954223633,32.7400016784668,33.09000015258789,32.80004119873047,67100,0.0,0.0,False 2024-04-15 00:00:00-04:00,33.189998626708984,33.290000915527344,32.27000045776367,32.41999816894531,32.13591003417969,29900,0.0,0.0,False 2024-04-16 00:00:00-04:00,32.4900016784668,32.959999084472656,32.0,32.599998474121094,32.314334869384766,50700,0.0,0.0,False -2024-04-17 00:00:00-04:00,32.650001525878906,33.43000030517578,31.51000022888184,32.5099983215332,32.225120544433594,58200,0.0,0.0,False +2024-04-17 00:00:00-04:00,32.650001525878906,33.43000030517578,31.510000228881836,32.5099983215332,32.225120544433594,58200,0.0,0.0,False 2024-04-18 00:00:00-04:00,32.9900016784668,33.40999984741211,32.65999984741211,33.15999984741211,32.86942672729492,63300,0.0,0.0,False 2024-04-19 00:00:00-04:00,32.59000015258789,33.79999923706055,32.59000015258789,33.119998931884766,32.829776763916016,44300,0.0,0.0,False 2024-04-22 00:00:00-04:00,33.27000045776367,33.27000045776367,32.52000045776367,32.7400016784668,32.45310974121094,25300,0.0,0.0,False @@ -582,29 +582,29 @@ Datetime,Open,High,Low,Close,Adj Close,Volume,Dividends,Stock Splits,Repaired? 2024-04-25 00:00:00-04:00,32.52000045776367,33.529998779296875,32.18000030517578,33.380001068115234,33.087501525878906,21900,0.0,0.0,False 2024-04-26 00:00:00-04:00,33.349998474121094,33.349998474121094,32.900001525878906,33.060001373291016,32.77030563354492,11300,0.0,0.0,False 2024-04-29 00:00:00-04:00,32.56999969482422,32.75,32.33000183105469,32.70000076293945,32.41345977783203,16700,0.0,0.0,False -2024-04-30 00:00:00-04:00,32.84000015258789,32.84000015258789,31.709999084472656,31.81999969482422,31.541170120239254,17600,0.0,0.0,False -2024-05-01 00:00:00-04:00,31.809999465942383,31.81999969482422,30.100000381469727,30.5,30.23273658752441,43300,0.0,0.0,False +2024-04-30 00:00:00-04:00,32.84000015258789,32.84000015258789,31.709999084472656,31.81999969482422,31.541170120239258,17600,0.0,0.0,False +2024-05-01 00:00:00-04:00,31.809999465942383,31.81999969482422,30.100000381469727,30.5,30.232736587524414,43300,0.0,0.0,False 2024-05-02 00:00:00-04:00,30.1200008392334,31.3799991607666,30.1200008392334,31.040000915527344,30.76800537109375,21300,0.0,0.0,False -2024-05-03 00:00:00-04:00,31.1200008392334,31.1200008392334,30.01000022888184,31.049999237060547,30.777915954589844,23300,0.0,0.0,False +2024-05-03 00:00:00-04:00,31.1200008392334,31.1200008392334,30.010000228881836,31.049999237060547,30.777915954589844,23300,0.0,0.0,False 2024-05-06 00:00:00-04:00,31.209999084472656,31.959999084472656,30.81999969482422,31.540000915527344,31.26362419128418,62800,0.0,0.0,False 2024-05-07 00:00:00-04:00,30.459999084472656,31.65999984741211,30.459999084472656,31.190000534057617,30.916690826416016,26900,0.0,0.0,False -2024-05-08 00:00:00-04:00,30.86000061035156,31.21999931335449,30.59000015258789,30.88999938964844,30.619319915771484,14300,0.0,0.0,False -2024-05-09 00:00:00-04:00,31.09000015258789,31.36000061035156,30.75,30.76000022888184,30.490459442138672,15800,0.0,0.0,False +2024-05-08 00:00:00-04:00,30.860000610351562,31.219999313354492,30.59000015258789,30.889999389648438,30.619319915771484,14300,0.0,0.0,False +2024-05-09 00:00:00-04:00,31.09000015258789,31.360000610351562,30.75,30.760000228881836,30.490459442138672,15800,0.0,0.0,False 2024-05-10 00:00:00-04:00,30.670000076293945,31.190000534057617,30.170000076293945,30.31999969482422,30.05431365966797,14500,0.0,0.0,False -2024-05-13 00:00:00-04:00,30.649999618530277,30.649999618530277,30.1299991607666,30.51000022888184,30.24264907836914,25300,0.0,0.0,False -2024-05-14 00:00:00-04:00,30.299999237060547,30.540000915527344,30.049999237060547,30.450000762939453,30.18317604064941,13800,0.0,0.0,False +2024-05-13 00:00:00-04:00,30.649999618530273,30.649999618530273,30.1299991607666,30.510000228881836,30.24264907836914,25300,0.0,0.0,False +2024-05-14 00:00:00-04:00,30.299999237060547,30.540000915527344,30.049999237060547,30.450000762939453,30.183176040649414,13800,0.0,0.0,False 2024-05-15 00:00:00-04:00,30.020000457763672,32.15999984741211,30.020000457763672,32.04999923706055,31.769153594970703,187400,0.0,0.0,False -2024-05-16 00:00:00-04:00,32.5099983215332,34.029998779296875,32.25,33.959999084472656,33.66241836547852,146700,0.0,0.0,False +2024-05-16 00:00:00-04:00,32.5099983215332,34.029998779296875,32.25,33.959999084472656,33.662418365478516,146700,0.0,0.0,False 2024-05-17 00:00:00-04:00,34.0,35.63999938964844,34.0,35.04999923706055,34.74286651611328,121100,0.0,0.0,False 2024-05-21 00:00:00-04:00,35.4900016784668,35.7599983215332,34.81999969482422,35.459999084472656,35.14927291870117,110400,0.0,0.0,False 2024-05-22 00:00:00-04:00,35.599998474121094,35.599998474121094,34.34000015258789,34.90999984741211,34.60409164428711,66600,0.0,0.0,False -2024-05-23 00:00:00-04:00,35.25,35.25,33.900001525878906,34.0099983215332,33.71197891235352,42100,0.0,0.0,False +2024-05-23 00:00:00-04:00,35.25,35.25,33.900001525878906,34.0099983215332,33.711978912353516,42100,0.0,0.0,False 2024-05-24 00:00:00-04:00,34.15999984741211,34.77000045776367,34.040000915527344,34.599998474121094,34.296810150146484,29000,0.0,0.0,False 2024-05-27 00:00:00-04:00,34.5,34.5,34.0,34.33000183105469,34.029178619384766,2800,0.0,0.0,False 2024-05-28 00:00:00-04:00,34.4900016784668,34.70000076293945,34.459999084472656,34.70000076293945,34.39593505859375,49100,0.0,0.0,False 2024-05-29 00:00:00-04:00,34.869998931884766,34.869998931884766,33.900001525878906,34.70000076293945,34.39593505859375,30300,0.0,0.0,False -2024-05-30 00:00:00-04:00,34.97999954223633,37.68999862670898,34.959999084472656,36.650001525878906,36.32884979248047,147200,0.0,0.0,False -2024-05-31 00:00:00-04:00,36.650001525878906,36.68999862670898,35.869998931884766,36.68999862670898,36.36849594116211,28500,0.0,0.0,False +2024-05-30 00:00:00-04:00,34.97999954223633,37.689998626708984,34.959999084472656,36.650001525878906,36.32884979248047,147200,0.0,0.0,False +2024-05-31 00:00:00-04:00,36.650001525878906,36.689998626708984,35.869998931884766,36.689998626708984,36.36849594116211,28500,0.0,0.0,False 2024-06-03 00:00:00-04:00,36.91999816894531,37.0,34.0,34.150001525878906,33.85075378417969,77000,0.0,0.0,False 2024-06-04 00:00:00-04:00,34.130001068115234,34.15999984741211,32.400001525878906,33.290000915527344,32.998291015625,110500,0.0,0.0,False 2024-06-05 00:00:00-04:00,33.209999084472656,33.4900016784668,32.599998474121094,33.150001525878906,32.85951614379883,55100,0.0,0.0,False @@ -615,109 +615,109 @@ Datetime,Open,High,Low,Close,Adj Close,Volume,Dividends,Stock Splits,Repaired? 2024-06-12 00:00:00-04:00,33.13999938964844,33.2400016784668,32.16999816894531,32.849998474121094,32.56214141845703,29500,0.0,0.0,False 2024-06-13 00:00:00-04:00,32.689998626708984,32.689998626708984,30.670000076293945,31.09000015258789,30.817567825317383,41600,0.0,0.0,False 2024-06-14 00:00:00-04:00,31.09000015258789,31.239999771118164,30.8799991607666,31.100000381469727,30.82748031616211,32800,0.0,0.0,False -2024-06-17 00:00:00-04:00,31.26000022888184,31.6200008392334,30.57999992370605,31.5,31.223974227905277,36300,0.0,0.0,False +2024-06-17 00:00:00-04:00,31.260000228881836,31.6200008392334,30.579999923706055,31.5,31.223974227905273,36300,0.0,0.0,False 2024-06-18 00:00:00-04:00,31.5,32.22999954223633,31.5,32.18000030517578,31.89801597595215,74600,0.0,0.0,False 2024-06-19 00:00:00-04:00,32.18000030517578,32.18000030517578,31.5,31.790000915527344,31.51143455505371,6500,0.0,0.0,False -2024-06-20 00:00:00-04:00,32.9900016784668,32.9900016784668,31.63999938964844,31.709999084472656,31.432132720947266,18000,0.0,0.0,False -2024-06-21 00:00:00-04:00,31.780000686645508,31.780000686645508,30.600000381469727,31.170000076293945,30.89686584472656,34300,0.0,0.0,False +2024-06-20 00:00:00-04:00,32.9900016784668,32.9900016784668,31.639999389648438,31.709999084472656,31.432132720947266,18000,0.0,0.0,False +2024-06-21 00:00:00-04:00,31.780000686645508,31.780000686645508,30.600000381469727,31.170000076293945,30.896865844726562,34300,0.0,0.0,False 2024-06-24 00:00:00-04:00,31.520000457763672,33.20000076293945,31.5,33.0,32.71083068847656,30700,0.0,0.0,False 2024-06-25 00:00:00-04:00,32.779998779296875,32.95000076293945,31.8799991607666,32.63999938964844,32.35398483276367,12200,0.0,0.0,False 2024-06-26 00:00:00-04:00,32.119998931884766,32.72999954223633,31.770000457763672,32.70000076293945,32.41345977783203,10300,0.0,0.0,False 2024-06-27 00:00:00-04:00,32.869998931884766,32.9900016784668,32.47999954223633,32.619998931884766,32.33415985107422,20900,0.0,0.0,False 2024-06-28 00:00:00-04:00,32.52000045776367,33.09000015258789,32.029998779296875,32.22999954223633,31.94757652282715,80900,0.0,0.0,False 2024-07-02 00:00:00-04:00,33.0,33.93000030517578,32.08000183105469,33.630001068115234,33.33531188964844,55800,0.0,0.0,False -2024-07-03 00:00:00-04:00,33.529998779296875,33.720001220703125,31.899999618530277,32.68000030517578,32.39363479614258,15800,0.0,0.0,False +2024-07-03 00:00:00-04:00,33.529998779296875,33.720001220703125,31.899999618530273,32.68000030517578,32.39363479614258,15800,0.0,0.0,False 2024-07-04 00:00:00-04:00,32.77000045776367,33.04999923706055,32.529998779296875,32.97999954223633,32.69100570678711,3000,0.0,0.0,False -2024-07-05 00:00:00-04:00,32.25,32.36000061035156,31.299999237060547,31.399999618530277,31.12485122680664,40700,0.0,0.0,False -2024-07-08 00:00:00-04:00,31.479999542236328,31.950000762939453,30.76000022888184,31.950000762939453,31.670032501220703,24700,0.0,0.0,False -2024-07-09 00:00:00-04:00,31.700000762939453,31.700000762939453,30.6200008392334,30.82999992370605,30.559844970703125,26400,0.0,0.0,False -2024-07-10 00:00:00-04:00,30.399999618530277,31.299999237060547,30.270000457763672,30.46999931335449,30.202999114990234,32700,0.0,0.0,False -2024-07-11 00:00:00-04:00,30.600000381469727,31.920000076293945,30.600000381469727,31.86000061035156,31.580820083618164,26800,0.0,0.0,False +2024-07-05 00:00:00-04:00,32.25,32.36000061035156,31.299999237060547,31.399999618530273,31.12485122680664,40700,0.0,0.0,False +2024-07-08 00:00:00-04:00,31.479999542236328,31.950000762939453,30.760000228881836,31.950000762939453,31.670032501220703,24700,0.0,0.0,False +2024-07-09 00:00:00-04:00,31.700000762939453,31.700000762939453,30.6200008392334,30.829999923706055,30.559844970703125,26400,0.0,0.0,False +2024-07-10 00:00:00-04:00,30.399999618530273,31.299999237060547,30.270000457763672,30.469999313354492,30.202999114990234,32700,0.0,0.0,False +2024-07-11 00:00:00-04:00,30.600000381469727,31.920000076293945,30.600000381469727,31.860000610351562,31.580820083618164,26800,0.0,0.0,False 2024-07-12 00:00:00-04:00,31.68000030517578,32.43000030517578,31.68000030517578,32.029998779296875,31.74932861328125,34900,0.0,0.0,False -2024-07-15 00:00:00-04:00,31.96999931335449,32.279998779296875,31.96999931335449,32.119998931884766,31.83854103088379,94700,0.0,0.0,False +2024-07-15 00:00:00-04:00,31.969999313354492,32.279998779296875,31.969999313354492,32.119998931884766,31.83854103088379,94700,0.0,0.0,False 2024-07-16 00:00:00-04:00,32.25,32.25,31.770000457763672,31.950000762939453,31.670032501220703,46500,0.0,0.0,False 2024-07-17 00:00:00-04:00,32.060001373291016,32.16999816894531,31.350000381469727,32.150001525878906,31.8682804107666,18300,0.0,0.0,False -2024-07-18 00:00:00-04:00,32.25,32.380001068115234,31.81999969482422,32.15999984741211,31.87819099426269,14300,0.0,0.0,False +2024-07-18 00:00:00-04:00,32.25,32.380001068115234,31.81999969482422,32.15999984741211,31.878190994262695,14300,0.0,0.0,False 2024-07-19 00:00:00-04:00,32.369998931884766,32.4900016784668,32.0,32.150001525878906,31.8682804107666,21400,0.0,0.0,False 2024-07-22 00:00:00-04:00,32.06999969482422,33.029998779296875,31.950000762939453,32.75,32.46302032470703,15800,0.0,0.0,False 2024-07-23 00:00:00-04:00,31.8700008392334,32.279998779296875,31.8700008392334,32.2599983215332,31.977313995361328,23600,0.0,0.0,False -2024-07-24 00:00:00-04:00,31.770000457763672,32.119998931884766,31.170000076293945,31.25,30.97616577148437,31500,0.0,0.0,False -2024-07-25 00:00:00-04:00,31.200000762939453,31.489999771118164,30.1200008392334,31.15999984741211,30.88695335388184,27600,0.0,0.0,False -2024-07-26 00:00:00-04:00,31.15999984741211,31.25,30.6200008392334,31.21999931335449,30.94642639160156,9100,0.0,0.0,False -2024-07-29 00:00:00-04:00,31.200000762939453,31.25,30.770000457763672,31.209999084472656,30.93651390075684,6100,0.0,0.0,False +2024-07-24 00:00:00-04:00,31.770000457763672,32.119998931884766,31.170000076293945,31.25,30.976165771484375,31500,0.0,0.0,False +2024-07-25 00:00:00-04:00,31.200000762939453,31.489999771118164,30.1200008392334,31.15999984741211,30.886953353881836,27600,0.0,0.0,False +2024-07-26 00:00:00-04:00,31.15999984741211,31.25,30.6200008392334,31.219999313354492,30.946426391601562,9100,0.0,0.0,False +2024-07-29 00:00:00-04:00,31.200000762939453,31.25,30.770000457763672,31.209999084472656,30.936513900756836,6100,0.0,0.0,False 2024-07-30 00:00:00-04:00,30.520000457763672,31.489999771118164,30.520000457763672,30.68000030517578,30.41115951538086,10600,0.0,0.0,False -2024-07-31 00:00:00-04:00,31.38999938964844,32.400001525878906,31.38999938964844,32.400001525878906,32.1160888671875,27700,0.0,0.0,False +2024-07-31 00:00:00-04:00,31.389999389648438,32.400001525878906,31.389999389648438,32.400001525878906,32.1160888671875,27700,0.0,0.0,False 2024-08-01 00:00:00-04:00,32.209999084472656,32.209999084472656,30.6299991607666,31.06999969482422,30.79774284362793,38100,0.0,0.0,False -2024-08-02 00:00:00-04:00,30.61000061035156,30.61000061035156,28.559999465942383,28.8799991607666,28.62693214416504,60000,0.0,0.0,False +2024-08-02 00:00:00-04:00,30.610000610351562,30.610000610351562,28.559999465942383,28.8799991607666,28.62693214416504,60000,0.0,0.0,False 2024-08-06 00:00:00-04:00,28.8799991607666,29.239999771118164,28.0,29.239999771118164,28.98377799987793,51400,0.0,0.0,False -2024-08-07 00:00:00-04:00,30.34000015258789,30.350000381469727,28.32999992370605,28.96999931335449,28.716142654418945,21500,0.0,0.0,False -2024-08-08 00:00:00-04:00,29.32999992370605,29.979999542236328,29.059999465942383,29.65999984741211,29.400096893310547,20400,0.0,0.0,False -2024-08-09 00:00:00-04:00,31.299999237060547,31.299999237060547,29.299999237060547,29.76000022888184,29.49922180175781,13700,0.0,0.0,False +2024-08-07 00:00:00-04:00,30.34000015258789,30.350000381469727,28.329999923706055,28.969999313354492,28.716142654418945,21500,0.0,0.0,False +2024-08-08 00:00:00-04:00,29.329999923706055,29.979999542236328,29.059999465942383,29.65999984741211,29.400096893310547,20400,0.0,0.0,False +2024-08-09 00:00:00-04:00,31.299999237060547,31.299999237060547,29.299999237060547,29.760000228881836,29.499221801757812,13700,0.0,0.0,False 2024-08-12 00:00:00-04:00,29.799999237060547,30.81999969482422,29.799999237060547,30.670000076293945,30.401247024536133,19400,0.0,0.0,False -2024-08-13 00:00:00-04:00,30.270000457763672,30.86000061035156,28.959999084472656,30.799999237060547,30.530107498168945,28200,0.0,0.0,False -2024-08-14 00:00:00-04:00,31.5,32.5,31.07999992370605,32.20000076293945,31.9178409576416,72600,0.0,0.0,False +2024-08-13 00:00:00-04:00,30.270000457763672,30.860000610351562,28.959999084472656,30.799999237060547,30.530107498168945,28200,0.0,0.0,False +2024-08-14 00:00:00-04:00,31.5,32.5,31.079999923706055,32.20000076293945,31.9178409576416,72600,0.0,0.0,False 2024-08-15 00:00:00-04:00,32.79999923706055,33.56999969482422,32.0,32.5,32.2152099609375,44800,0.0,0.0,False -2024-08-16 00:00:00-04:00,32.08000183105469,32.58000183105469,31.520000457763672,32.02000045776367,31.73941802978516,21900,0.0,0.0,False +2024-08-16 00:00:00-04:00,32.08000183105469,32.58000183105469,31.520000457763672,32.02000045776367,31.739418029785156,21900,0.0,0.0,False 2024-08-19 00:00:00-04:00,32.119998931884766,32.66999816894531,31.5,31.940000534057617,31.660120010375977,39600,0.0,0.0,False -2024-08-20 00:00:00-04:00,31.68000030517578,31.770000457763672,30.76000022888184,31.149999618530277,30.87704086303711,58000,0.0,0.0,False -2024-08-21 00:00:00-04:00,31.040000915527344,31.420000076293945,30.790000915527344,31.38999938964844,31.11493682861328,37100,0.0,0.0,False -2024-08-22 00:00:00-04:00,31.40999984741211,31.559999465942383,30.600000381469727,30.649999618530277,30.38142204284668,23000,0.0,0.0,False -2024-08-23 00:00:00-04:00,31.06999969482422,31.399999618530277,30.979999542236328,31.21999931335449,30.94642639160156,22400,0.0,0.0,False -2024-08-26 00:00:00-04:00,31.26000022888184,32.65999984741211,31.26000022888184,32.619998931884766,32.33415985107422,41400,0.0,0.0,False -2024-08-27 00:00:00-04:00,32.130001068115234,32.15999984741211,31.56999969482422,31.76000022888184,31.48169708251953,16400,0.0,0.0,False -2024-08-28 00:00:00-04:00,31.71999931335449,31.71999931335449,30.940000534057617,31.280000686645508,31.005903244018555,11300,0.0,0.0,False -2024-08-29 00:00:00-04:00,31.420000076293945,31.57999992370605,31.040000915527344,31.1299991607666,30.857215881347656,12900,0.0,0.0,False -2024-08-30 00:00:00-04:00,30.86000061035156,31.049999237060547,30.57999992370605,31.0,30.728355407714844,31700,0.0,0.0,False -2024-09-03 00:00:00-04:00,30.51000022888184,30.76000022888184,29.100000381469727,29.559999465942383,29.300973892211918,68800,0.0,0.0,False -2024-09-04 00:00:00-04:00,29.01000022888184,29.6299991607666,28.6200008392334,29.309999465942383,29.053163528442383,44300,0.0,0.0,False -2024-09-05 00:00:00-04:00,28.979999542236328,30.0,28.84000015258789,28.84000015258789,28.58728408813477,34800,0.0,0.0,False -2024-09-06 00:00:00-04:00,29.059999465942383,29.15999984741211,27.709999084472656,27.899999618530277,27.655519485473636,68800,0.0,0.0,False +2024-08-20 00:00:00-04:00,31.68000030517578,31.770000457763672,30.760000228881836,31.149999618530273,30.87704086303711,58000,0.0,0.0,False +2024-08-21 00:00:00-04:00,31.040000915527344,31.420000076293945,30.790000915527344,31.389999389648438,31.11493682861328,37100,0.0,0.0,False +2024-08-22 00:00:00-04:00,31.40999984741211,31.559999465942383,30.600000381469727,30.649999618530273,30.38142204284668,23000,0.0,0.0,False +2024-08-23 00:00:00-04:00,31.06999969482422,31.399999618530273,30.979999542236328,31.219999313354492,30.946426391601562,22400,0.0,0.0,False +2024-08-26 00:00:00-04:00,31.260000228881836,32.65999984741211,31.260000228881836,32.619998931884766,32.33415985107422,41400,0.0,0.0,False +2024-08-27 00:00:00-04:00,32.130001068115234,32.15999984741211,31.56999969482422,31.760000228881836,31.48169708251953,16400,0.0,0.0,False +2024-08-28 00:00:00-04:00,31.719999313354492,31.719999313354492,30.940000534057617,31.280000686645508,31.005903244018555,11300,0.0,0.0,False +2024-08-29 00:00:00-04:00,31.420000076293945,31.579999923706055,31.040000915527344,31.1299991607666,30.857215881347656,12900,0.0,0.0,False +2024-08-30 00:00:00-04:00,30.860000610351562,31.049999237060547,30.579999923706055,31.0,30.728355407714844,31700,0.0,0.0,False +2024-09-03 00:00:00-04:00,30.510000228881836,30.760000228881836,29.100000381469727,29.559999465942383,29.300973892211914,68800,0.0,0.0,False +2024-09-04 00:00:00-04:00,29.010000228881836,29.6299991607666,28.6200008392334,29.309999465942383,29.053163528442383,44300,0.0,0.0,False +2024-09-05 00:00:00-04:00,28.979999542236328,30.0,28.84000015258789,28.84000015258789,28.587284088134766,34800,0.0,0.0,False +2024-09-06 00:00:00-04:00,29.059999465942383,29.15999984741211,27.709999084472656,27.899999618530273,27.655519485473633,68800,0.0,0.0,False 2024-09-09 00:00:00-04:00,27.920000076293945,28.809999465942383,27.920000076293945,28.020000457763672,27.77446937561035,22400,0.0,0.0,False -2024-09-10 00:00:00-04:00,28.020000457763672,28.020000457763672,26.5,27.899999618530277,27.655519485473636,46400,0.0,0.0,False +2024-09-10 00:00:00-04:00,28.020000457763672,28.020000457763672,26.5,27.899999618530273,27.655519485473633,46400,0.0,0.0,False 2024-09-11 00:00:00-04:00,28.479999542236328,28.8700008392334,27.6200008392334,28.790000915527344,28.537721633911133,56300,0.0,0.0,False -2024-09-12 00:00:00-04:00,28.0,29.559999465942383,27.61000061035156,27.790000915527344,27.546485900878903,86900,0.0,0.0,False +2024-09-12 00:00:00-04:00,28.0,29.559999465942383,27.610000610351562,27.790000915527344,27.546485900878906,86900,0.0,0.0,False 2024-09-13 00:00:00-04:00,27.950000762939453,29.450000762939453,27.950000762939453,28.530000686645508,28.280000686645508,42900,0.0,0.0,False 2024-09-16 00:00:00-04:00,28.290000915527344,28.309999465942383,27.530000686645508,27.790000915527344,27.790000915527344,33300,0.25,0.0,False -2024-09-17 00:00:00-04:00,28.13999938964844,28.200000762939453,27.6299991607666,28.190000534057617,28.190000534057617,25100,0.0,0.0,False -2024-09-18 00:00:00-04:00,28.09000015258789,28.09000015258789,27.13999938964844,27.32999992370605,27.32999992370605,41400,0.0,0.0,False -2024-09-19 00:00:00-04:00,28.239999771118164,28.270000457763672,27.5,27.899999618530277,27.899999618530277,56100,0.0,0.0,False +2024-09-17 00:00:00-04:00,28.139999389648438,28.200000762939453,27.6299991607666,28.190000534057617,28.190000534057617,25100,0.0,0.0,False +2024-09-18 00:00:00-04:00,28.09000015258789,28.09000015258789,27.139999389648438,27.329999923706055,27.329999923706055,41400,0.0,0.0,False +2024-09-19 00:00:00-04:00,28.239999771118164,28.270000457763672,27.5,27.899999618530273,27.899999618530273,56100,0.0,0.0,False 2024-09-20 00:00:00-04:00,27.6200008392334,27.6200008392334,27.030000686645508,27.06999969482422,27.06999969482422,23600,0.0,0.0,False -2024-09-23 00:00:00-04:00,27.11000061035156,27.540000915527344,26.25,26.32999992370605,26.32999992370605,41000,0.0,0.0,False +2024-09-23 00:00:00-04:00,27.110000610351562,27.540000915527344,26.25,26.329999923706055,26.329999923706055,41000,0.0,0.0,False 2024-09-24 00:00:00-04:00,26.56999969482422,28.06999969482422,26.56999969482422,27.989999771118164,27.989999771118164,35600,0.0,0.0,False 2024-09-25 00:00:00-04:00,27.8700008392334,27.8700008392334,27.0,27.489999771118164,27.489999771118164,30200,0.0,0.0,False -2024-09-26 00:00:00-04:00,27.299999237060547,27.479999542236328,26.559999465942383,26.61000061035156,26.61000061035156,51800,0.0,0.0,False -2024-09-27 00:00:00-04:00,26.989999771118164,26.989999771118164,26.25,26.57999992370605,26.57999992370605,20600,0.0,0.0,False -2024-09-30 00:00:00-04:00,26.61000061035156,27.0,26.5,26.950000762939453,26.950000762939453,25200,0.0,0.0,False -2024-10-01 00:00:00-04:00,26.96999931335449,27.690000534057617,26.93000030517578,27.3799991607666,27.3799991607666,42600,0.0,0.0,False -2024-10-02 00:00:00-04:00,27.790000915527344,27.799999237060547,26.290000915527344,26.61000061035156,26.61000061035156,78000,0.0,0.0,False +2024-09-26 00:00:00-04:00,27.299999237060547,27.479999542236328,26.559999465942383,26.610000610351562,26.610000610351562,51800,0.0,0.0,False +2024-09-27 00:00:00-04:00,26.989999771118164,26.989999771118164,26.25,26.579999923706055,26.579999923706055,20600,0.0,0.0,False +2024-09-30 00:00:00-04:00,26.610000610351562,27.0,26.5,26.950000762939453,26.950000762939453,25200,0.0,0.0,False +2024-10-01 00:00:00-04:00,26.969999313354492,27.690000534057617,26.93000030517578,27.3799991607666,27.3799991607666,42600,0.0,0.0,False +2024-10-02 00:00:00-04:00,27.790000915527344,27.799999237060547,26.290000915527344,26.610000610351562,26.610000610351562,78000,0.0,0.0,False 2024-10-03 00:00:00-04:00,26.84000015258789,28.489999771118164,26.84000015258789,28.15999984741211,28.15999984741211,84200,0.0,0.0,False 2024-10-04 00:00:00-04:00,28.190000534057617,28.549999237060547,27.790000915527344,28.049999237060547,28.049999237060547,65200,0.0,0.0,False -2024-10-07 00:00:00-04:00,28.07999992370605,29.15999984741211,27.76000022888184,28.01000022888184,28.01000022888184,44900,0.0,0.0,False -2024-10-08 00:00:00-04:00,27.989999771118164,28.11000061035156,26.850000381469727,27.709999084472656,27.709999084472656,26300,0.0,0.0,False -2024-10-09 00:00:00-04:00,27.030000686645508,28.36000061035156,27.030000686645508,28.36000061035156,28.36000061035156,23000,0.0,0.0,False -2024-10-10 00:00:00-04:00,28.020000457763672,28.799999237060547,27.96999931335449,28.36000061035156,28.36000061035156,24300,0.0,0.0,False +2024-10-07 00:00:00-04:00,28.079999923706055,29.15999984741211,27.760000228881836,28.010000228881836,28.010000228881836,44900,0.0,0.0,False +2024-10-08 00:00:00-04:00,27.989999771118164,28.110000610351562,26.850000381469727,27.709999084472656,27.709999084472656,26300,0.0,0.0,False +2024-10-09 00:00:00-04:00,27.030000686645508,28.360000610351562,27.030000686645508,28.360000610351562,28.360000610351562,23000,0.0,0.0,False +2024-10-10 00:00:00-04:00,28.020000457763672,28.799999237060547,27.969999313354492,28.360000610351562,28.360000610351562,24300,0.0,0.0,False 2024-10-11 00:00:00-04:00,28.780000686645508,28.780000686645508,28.06999969482422,28.520000457763672,28.520000457763672,12100,0.0,0.0,False 2024-10-15 00:00:00-04:00,28.350000381469727,28.350000381469727,26.540000915527344,26.690000534057617,26.690000534057617,77300,0.0,0.0,False -2024-10-16 00:00:00-04:00,26.81999969482422,27.11000061035156,26.700000762939453,26.8700008392334,26.8700008392334,12500,0.0,0.0,False -2024-10-17 00:00:00-04:00,26.81999969482422,27.18000030517578,26.770000457763672,27.149999618530277,27.149999618530277,21700,0.0,0.0,False +2024-10-16 00:00:00-04:00,26.81999969482422,27.110000610351562,26.700000762939453,26.8700008392334,26.8700008392334,12500,0.0,0.0,False +2024-10-17 00:00:00-04:00,26.81999969482422,27.18000030517578,26.770000457763672,27.149999618530273,27.149999618530273,21700,0.0,0.0,False 2024-10-18 00:00:00-04:00,27.0,27.09000015258789,26.799999237060547,27.040000915527344,27.040000915527344,24400,0.0,0.0,False 2024-10-21 00:00:00-04:00,27.059999465942383,27.739999771118164,27.0,27.739999771118164,27.739999771118164,32400,0.0,0.0,False -2024-10-22 00:00:00-04:00,27.8799991607666,28.350000381469727,27.63999938964844,28.290000915527344,28.290000915527344,23900,0.0,0.0,False +2024-10-22 00:00:00-04:00,27.8799991607666,28.350000381469727,27.639999389648438,28.290000915527344,28.290000915527344,23900,0.0,0.0,False 2024-10-23 00:00:00-04:00,28.1200008392334,28.1200008392334,27.450000762939453,27.81999969482422,27.81999969482422,7200,0.0,0.0,False -2024-10-24 00:00:00-04:00,27.71999931335449,27.979999542236328,27.46999931335449,27.979999542236328,27.979999542236328,9100,0.0,0.0,False -2024-10-25 00:00:00-04:00,27.479999542236328,29.13999938964844,27.479999542236328,28.8799991607666,28.8799991607666,26900,0.0,0.0,False +2024-10-24 00:00:00-04:00,27.719999313354492,27.979999542236328,27.469999313354492,27.979999542236328,27.979999542236328,9100,0.0,0.0,False +2024-10-25 00:00:00-04:00,27.479999542236328,29.139999389648438,27.479999542236328,28.8799991607666,28.8799991607666,26900,0.0,0.0,False 2024-10-28 00:00:00-04:00,27.950000762939453,28.06999969482422,27.299999237060547,27.739999771118164,27.739999771118164,75500,0.0,0.0,False -2024-10-29 00:00:00-04:00,27.479999542236328,27.899999618530277,27.3799991607666,27.6299991607666,27.6299991607666,23100,0.0,0.0,False +2024-10-29 00:00:00-04:00,27.479999542236328,27.899999618530273,27.3799991607666,27.6299991607666,27.6299991607666,23100,0.0,0.0,False 2024-10-30 00:00:00-04:00,27.290000915527344,28.06999969482422,27.290000915527344,28.06999969482422,28.06999969482422,11500,0.0,0.0,False 2024-10-31 00:00:00-04:00,27.75,27.809999465942383,27.190000534057617,27.520000457763672,27.520000457763672,14500,0.0,0.0,False -2024-11-01 00:00:00-04:00,27.75,28.229999542236328,27.07999992370605,27.21999931335449,27.21999931335449,20300,0.0,0.0,False -2024-11-04 00:00:00-05:00,27.81999969482422,28.51000022888184,27.59000015258789,28.21999931335449,28.21999931335449,21300,0.0,0.0,False +2024-11-01 00:00:00-04:00,27.75,28.229999542236328,27.079999923706055,27.219999313354492,27.219999313354492,20300,0.0,0.0,False +2024-11-04 00:00:00-05:00,27.81999969482422,28.510000228881836,27.59000015258789,28.219999313354492,28.219999313354492,21300,0.0,0.0,False 2024-11-05 00:00:00-05:00,28.440000534057617,28.440000534057617,28.09000015258789,28.290000915527344,28.290000915527344,7100,0.0,0.0,False -2024-11-06 00:00:00-05:00,27.32999992370605,28.479999542236328,27.32999992370605,28.15999984741211,28.15999984741211,35200,0.0,0.0,False +2024-11-06 00:00:00-05:00,27.329999923706055,28.479999542236328,27.329999923706055,28.15999984741211,28.15999984741211,35200,0.0,0.0,False 2024-11-07 00:00:00-05:00,27.65999984741211,29.34000015258789,27.65999984741211,29.25,29.25,25200,0.0,0.0,False 2024-11-08 00:00:00-05:00,29.43000030517578,29.43000030517578,28.0,28.06999969482422,28.06999969482422,27000,0.0,0.0,False -2024-11-11 00:00:00-05:00,27.940000534057617,29.190000534057617,27.940000534057617,28.96999931335449,28.96999931335449,20600,0.0,0.0,False -2024-11-12 00:00:00-05:00,29.13999938964844,29.32999992370605,28.15999984741211,28.68000030517578,28.68000030517578,31900,0.0,0.0,False -2024-11-13 00:00:00-05:00,28.489999771118164,28.71999931335449,28.030000686645508,28.690000534057617,28.690000534057617,54300,0.0,0.0,False +2024-11-11 00:00:00-05:00,27.940000534057617,29.190000534057617,27.940000534057617,28.969999313354492,28.969999313354492,20600,0.0,0.0,False +2024-11-12 00:00:00-05:00,29.139999389648438,29.329999923706055,28.15999984741211,28.68000030517578,28.68000030517578,31900,0.0,0.0,False +2024-11-13 00:00:00-05:00,28.489999771118164,28.719999313354492,28.030000686645508,28.690000534057617,28.690000534057617,54300,0.0,0.0,False 2024-11-14 00:00:00-05:00,31.489999771118164,32.540000915527344,30.0,32.5,32.5,150800,0.0,0.0,False 2024-11-15 00:00:00-05:00,32.16999816894531,33.119998931884766,32.0,32.209999084472656,32.209999084472656,51300,0.0,0.0,False diff --git a/tests/test_cache.py b/tests/test_cache.py deleted file mode 100644 index 67dc75e23..000000000 --- a/tests/test_cache.py +++ /dev/null @@ -1,93 +0,0 @@ -""" -Tests for cache - -To run all tests in suite from commandline: - python -m unittest tests.cache - -Specific test class: - python -m unittest tests.cache.TestCache - -""" -from unittest import TestSuite - -from tests.context import yfinance as yf - -import unittest -import tempfile -import os - - -class TestCache(unittest.TestCase): - @classmethod - def setUpClass(cls): - cls.tempCacheDir = tempfile.TemporaryDirectory() - yf.set_tz_cache_location(cls.tempCacheDir.name) - - @classmethod - def tearDownClass(cls): - yf.cache._TzDBManager.close_db() - cls.tempCacheDir.cleanup() - - def test_storeTzNoRaise(self): - # storing TZ to cache should never raise exception - tkr = 'AMZN' - tz1 = "America/New_York" - tz2 = "London/Europe" - cache = yf.cache.get_tz_cache() - cache.store(tkr, tz1) - cache.store(tkr, tz2) - - def test_setTzCacheLocation(self): - self.assertEqual(yf.cache._TzDBManager.get_location(), self.tempCacheDir.name) - - tkr = 'AMZN' - tz1 = "America/New_York" - cache = yf.cache.get_tz_cache() - cache.store(tkr, tz1) - - self.assertTrue(os.path.exists(os.path.join(self.tempCacheDir.name, "tkr-tz.db"))) - - -class TestCacheNoPermission(unittest.TestCase): - @classmethod - def setUpClass(cls): - if os.name == "nt": # Windows - cls.cache_path = "C:\\Windows\\System32\\yf-cache" - else: # Unix/Linux/MacOS - # Use a writable directory - cls.cache_path = "/yf-cache" - yf.set_tz_cache_location(cls.cache_path) - - def test_tzCacheRootStore(self): - # Test that if cache path in read-only filesystem, no exception. - tkr = 'AMZN' - tz1 = "America/New_York" - - # During attempt to store, will discover cannot write - yf.cache.get_tz_cache().store(tkr, tz1) - - # Handling the store failure replaces cache with a dummy - cache = yf.cache.get_tz_cache() - self.assertTrue(cache.dummy) - cache.store(tkr, tz1) - - def test_tzCacheRootLookup(self): - # Test that if cache path in read-only filesystem, no exception. - tkr = 'AMZN' - # During attempt to lookup, will discover cannot write - yf.cache.get_tz_cache().lookup(tkr) - - # Handling the lookup failure replaces cache with a dummy - cache = yf.cache.get_tz_cache() - self.assertTrue(cache.dummy) - cache.lookup(tkr) - -def suite(): - ts: TestSuite = unittest.TestSuite() - ts.addTest(TestCache('Test cache')) - ts.addTest(TestCacheNoPermission('Test cache no permission')) - return ts - - -if __name__ == '__main__': - unittest.main() diff --git a/tests/test_price_repair.py b/tests/test_price_repair.py index e8c9be890..c15e220e0 100644 --- a/tests/test_price_repair.py +++ b/tests/test_price_repair.py @@ -367,9 +367,9 @@ def test_repair_zeroes_daily(self): "Close": [103.03, 102.05, 102.08], "Adj Close": [102.03, 102.05, 102.08], "Volume": [560, 137, 117]}, - index=_pd.to_datetime([_dt.datetime(2024, 11, 1), - _dt.datetime(2024, 10, 31), - _dt.datetime(2024, 10, 30)])) + index=_pd.to_datetime([_dt.datetime(2022, 11, 1), + _dt.datetime(2022, 10, 31), + _dt.datetime(2022, 10, 30)])) df_bad = df_bad.sort_index() df_bad.index.name = "Date" df_bad.index = df_bad.index.tz_localize(tz_exchange) @@ -377,9 +377,9 @@ def test_repair_zeroes_daily(self): repaired_df = hist._fix_zeroes(df_bad, "1d", tz_exchange, prepost=False) correct_df = df_bad.copy() - correct_df.loc["2024-11-01", "Open"] = 102.572729 - correct_df.loc["2024-11-01", "Low"] = 102.309091 - correct_df.loc["2024-11-01", "High"] = 102.572729 + correct_df.loc["2022-11-01", "Open"] = 102.080002 + correct_df.loc["2022-11-01", "Low"] = 102.032501 + correct_df.loc["2022-11-01", "High"] = 102.080002 for c in ["Open", "Low", "High", "Close"]: self.assertTrue(_np.isclose(repaired_df[c], correct_df[c], rtol=1e-8).all()) @@ -462,7 +462,7 @@ def test_repair_bad_stock_splits(self): # Stocks that split in 2022 but no problems in Yahoo data, # so repair should change nothing good_tkrs = ['AMZN', 'DXCM', 'FTNT', 'GOOG', 'GME', 'PANW', 'SHOP', 'TSLA'] - good_tkrs += ['AEI', 'GHI', 'IRON', 'LXU', 'RSLS', 'TISI'] + good_tkrs += ['AEI', 'GHI', 'IRON', 'LXU', 'NUZE', 'RSLS', 'TISI'] good_tkrs += ['BOL.ST', 'TUI1.DE'] intervals = ['1d', '1wk', '1mo', '3mo'] for tkr in good_tkrs: @@ -580,6 +580,7 @@ def test_repair_bad_div_adjusts(self): # Div 100x bad_tkrs += ['ABDP.L'] bad_tkrs += ['ELCO.L'] + bad_tkrs += ['KWS.L'] bad_tkrs += ['PSH.L'] # Div 100x and adjust too big diff --git a/tests/test_prices.py b/tests/test_prices.py index fac6bb135..ee21ff3fd 100644 --- a/tests/test_prices.py +++ b/tests/test_prices.py @@ -118,7 +118,7 @@ def test_duplicatingWeekly(self): continue test_run = True - df = dat.history(start=dt.date() - _dt.timedelta(days=13), interval="1wk") + df = dat.history(start=dt.date() - _dt.timedelta(days=7), interval="1wk") dt0 = df.index[-2] dt1 = df.index[-1] try: @@ -401,7 +401,7 @@ def test_prune_post_intraday_us(self): # Setup tkr = "AMZN" - special_day = _dt.date(2024, 11, 29) + special_day = _dt.date(2023, 11, 24) time_early_close = _dt.time(13) dat = yf.Ticker(tkr, session=self.session) @@ -427,8 +427,8 @@ def test_prune_post_intraday_asx(self): dat = yf.Ticker(tkr, session=self.session) # Test no other afternoons (or mornings) were pruned - start_d = _dt.date(2024, 1, 1) - end_d = _dt.date(2024+1, 1, 1) + start_d = _dt.date(2023, 1, 1) + end_d = _dt.date(2023+1, 1, 1) df = dat.history(start=start_d, end=end_d, interval="1h", prepost=False, keepna=True) last_dts = _pd.Series(df.index).groupby(df.index.date).last() dfd = dat.history(start=start_d, end=end_d, interval='1d', prepost=False, keepna=True) diff --git a/tests/test_screener.py b/tests/test_screener.py index 894124333..0ec6c201e 100644 --- a/tests/test_screener.py +++ b/tests/test_screener.py @@ -1,38 +1,153 @@ import unittest from unittest.mock import patch, MagicMock -from yfinance.screener.screener import screen -from yfinance.screener.query import EquityQuery +from yfinance.const import PREDEFINED_SCREENER_BODY_MAP +from yfinance.screener.screener import Screener +from yfinance.screener.screener_query import EquityQuery class TestScreener(unittest.TestCase): @classmethod def setUpClass(self): + self.screener = Screener() self.query = EquityQuery('gt',['eodprice',3]) - self.predefined = 'aggressive_small_caps' + + def test_set_default_body(self): + result = self.screener.set_default_body(self.query) + + self.assertEqual(self.screener.body['offset'], 0) + self.assertEqual(self.screener.body['size'], 100) + self.assertEqual(self.screener.body['sortField'], 'ticker') + self.assertEqual(self.screener.body['sortType'], 'desc') + self.assertEqual(self.screener.body['quoteType'], 'equity') + self.assertEqual(self.screener.body['query'], self.query.to_dict()) + self.assertEqual(self.screener.body['userId'], '') + self.assertEqual(self.screener.body['userIdType'], 'guid') + self.assertEqual(self.screener, result) + + def test_set_predefined_body(self): + k = 'most_actives' + result = self.screener.set_predefined_body(k) + self.assertEqual(self.screener.body, PREDEFINED_SCREENER_BODY_MAP[k]) + self.assertEqual(self.screener, result) + + def test_set_predefined_body_invalid_key(self): + with self.assertRaises(ValueError): + self.screener.set_predefined_body('invalid_key') + + def test_set_body(self): + body = { + "offset": 0, + "size": 100, + "sortField": "ticker", + "sortType": "desc", + "quoteType": "equity", + "query": self.query.to_dict(), + "userId": "", + "userIdType": "guid" + } + result = self.screener.set_body(body) + + self.assertEqual(self.screener.body, body) + self.assertEqual(self.screener, result) + + def test_set_body_missing_keys(self): + body = { + "offset": 0, + "size": 100, + "sortField": "ticker", + "sortType": "desc", + "quoteType": "equity" + } + with self.assertRaises(ValueError): + self.screener.set_body(body) + + def test_set_body_extra_keys(self): + body = { + "offset": 0, + "size": 100, + "sortField": "ticker", + "sortType": "desc", + "quoteType": "equity", + "query": self.query.to_dict(), + "userId": "", + "userIdType": "guid", + "extraKey": "extraValue" + } + with self.assertRaises(ValueError): + self.screener.set_body(body) + + def test_patch_body(self): + initial_body = { + "offset": 0, + "size": 100, + "sortField": "ticker", + "sortType": "desc", + "quoteType": "equity", + "query": self.query.to_dict(), + "userId": "", + "userIdType": "guid" + } + self.screener.set_body(initial_body) + patch_values = {"size": 50} + result = self.screener.patch_body(patch_values) + + self.assertEqual(self.screener.body['size'], 50) + self.assertEqual(self.screener.body['query'], self.query.to_dict()) + self.assertEqual(self.screener, result) + + def test_patch_body_extra_keys(self): + initial_body = { + "offset": 0, + "size": 100, + "sortField": "ticker", + "sortType": "desc", + "quoteType": "equity", + "query": self.query.to_dict(), + "userId": "", + "userIdType": "guid" + } + self.screener.set_body(initial_body) + patch_values = {"extraKey": "extraValue"} + with self.assertRaises(ValueError): + self.screener.patch_body(patch_values) @patch('yfinance.screener.screener.YfData.post') def test_set_large_size_in_body(self, mock_post): + body = { + "offset": 0, + "size": 251, # yahoo limits at 250 + "sortField": "ticker", + "sortType": "desc", + "quoteType": "equity", + "query": self.query.to_dict(), + "userId": "", + "userIdType": "guid" + } + with self.assertRaises(ValueError): - screen(self.query, size=251) + self.screener.set_body(body).response - @patch('yfinance.data.YfData.post') - def test_fetch_query(self, mock_post): + @patch('yfinance.screener.screener.YfData.post') + def test_fetch(self, mock_post): mock_response = MagicMock() - mock_response.json.return_value = {'finance': {'result': [{'key': 'value'}]}} + mock_response.json.return_value = {'finance': {'result': [{}]}} mock_post.return_value = mock_response - response = screen(self.query) - self.assertEqual(response, {'key': 'value'}) + self.screener.set_default_body(self.query) + response = self.screener._fetch() + + self.assertEqual(response, {'finance': {'result': [{}]}}) - @patch('yfinance.data.YfData.get') - def test_fetch_predefined(self, mock_get): + @patch('yfinance.screener.screener.YfData.post') + def test_fetch_and_parse(self, mock_post): mock_response = MagicMock() mock_response.json.return_value = {'finance': {'result': [{'key': 'value'}]}} - mock_get.return_value = mock_response + mock_post.return_value = mock_response - response = screen(self.predefined) - self.assertEqual(response, {'key': 'value'}) + self.screener.set_default_body(self.query) + self.screener._fetch_and_parse() + self.assertEqual(self.screener.response, {'key': 'value'}) if __name__ == '__main__': unittest.main() \ No newline at end of file diff --git a/tests/test_ticker.py b/tests/test_ticker.py index 7a383bd36..c3af7c66d 100644 --- a/tests/test_ticker.py +++ b/tests/test_ticker.py @@ -180,7 +180,7 @@ def test_valid_custom_periods(self): expected_start = expected_start.replace(hour=0, minute=0, second=0, microsecond=0) # leeway added because of weekends - self.assertGreaterEqual(actual_start, expected_start - timedelta(days=10), + self.assertGreaterEqual(actual_start, expected_start - timedelta(days=7), f"Start date {actual_start} out of range for period={period}") self.assertLessEqual(df.index[-1].to_pydatetime().replace(tzinfo=None), now, f"End date {df.index[-1]} out of range for period={period}") @@ -308,13 +308,14 @@ def test_no_expensive_calls_introduced(self): actual_urls_called[i] = u actual_urls_called = tuple(actual_urls_called) - expected_urls = [ - f"https://query2.finance.yahoo.com/v8/finance/chart/{symbol}?interval=1d&range=1d", # ticker's tz - f"https://query2.finance.yahoo.com/v8/finance/chart/{symbol}?events=div%2Csplits%2CcapitalGains&includePrePost=False&interval=1d&range={period}" - ] - for url in actual_urls_called: - self.assertTrue(url in expected_urls, f"Unexpected URL called: {url}") - + expected_urls = ( + f"https://query2.finance.yahoo.com/v8/finance/chart/{symbol}?events=div%2Csplits%2CcapitalGains&includePrePost=False&interval=1d&range={period}", + ) + self.assertEqual( + expected_urls, + actual_urls_called, + "Different than expected url used to fetch history." + ) def test_dividends(self): data = self.ticker.dividends self.assertIsInstance(data, pd.Series, "data has wrong type") @@ -357,7 +358,7 @@ def test_earnings_dates(self): def test_earnings_dates_with_limit(self): # use ticker with lots of historic earnings ticker = yf.Ticker("IBM") - limit = 100 + limit = 110 data = ticker.get_earnings_dates(limit=limit) self.assertIsInstance(data, pd.DataFrame, "data has wrong type") self.assertFalse(data.empty, "data is empty") @@ -818,6 +819,9 @@ def test_analyst_price_targets(self): data = self.ticker.analyst_price_targets self.assertIsInstance(data, dict, "data has wrong type") + keys = {'current', 'low', 'high', 'mean', 'median'} + self.assertCountEqual(data.keys(), keys, "data has wrong keys") + data_cached = self.ticker.analyst_price_targets self.assertIs(data, data_cached, "data not cached") @@ -826,6 +830,12 @@ def test_earnings_estimate(self): self.assertIsInstance(data, pd.DataFrame, "data has wrong type") self.assertFalse(data.empty, "data is empty") + columns = ['numberOfAnalysts', 'avg', 'low', 'high', 'yearAgoEps', 'growth'] + self.assertCountEqual(data.columns.values.tolist(), columns, "data has wrong column names") + + index = ['0q', '+1q', '0y', '+1y'] + self.assertCountEqual(data.index.values.tolist(), index, "data has wrong row names") + data_cached = self.ticker.earnings_estimate self.assertIs(data, data_cached, "data not cached") @@ -834,6 +844,12 @@ def test_revenue_estimate(self): self.assertIsInstance(data, pd.DataFrame, "data has wrong type") self.assertFalse(data.empty, "data is empty") + columns = ['numberOfAnalysts', 'avg', 'low', 'high', 'yearAgoRevenue', 'growth'] + self.assertCountEqual(data.columns.values.tolist(), columns, "data has wrong column names") + + index = ['0q', '+1q', '0y', '+1y'] + self.assertCountEqual(data.index.values.tolist(), index, "data has wrong row names") + data_cached = self.ticker.revenue_estimate self.assertIs(data, data_cached, "data not cached") @@ -842,6 +858,8 @@ def test_earnings_history(self): self.assertIsInstance(data, pd.DataFrame, "data has wrong type") self.assertFalse(data.empty, "data is empty") + columns = ['epsEstimate', 'epsActual', 'epsDifference', 'surprisePercent'] + self.assertCountEqual(data.columns.values.tolist(), columns, "data has wrong column names") self.assertIsInstance(data.index, pd.DatetimeIndex, "data has wrong index type") data_cached = self.ticker.earnings_history @@ -852,6 +870,12 @@ def test_eps_trend(self): self.assertIsInstance(data, pd.DataFrame, "data has wrong type") self.assertFalse(data.empty, "data is empty") + columns = ['current', '7daysAgo', '30daysAgo', '60daysAgo', '90daysAgo'] + self.assertCountEqual(data.columns.values.tolist(), columns, "data has wrong column names") + + index = ['0q', '+1q', '0y', '+1y'] + self.assertCountEqual(data.index.values.tolist(), index, "data has wrong row names") + data_cached = self.ticker.eps_trend self.assertIs(data, data_cached, "data not cached") @@ -860,6 +884,12 @@ def test_growth_estimates(self): self.assertIsInstance(data, pd.DataFrame, "data has wrong type") self.assertFalse(data.empty, "data is empty") + columns = ['stockTrend', 'indexTrend'] + self.assertCountEqual(data.columns.values.tolist(), columns, "data has wrong column names") + + index = ['0q', '+1q', '0y', '+1y', '+5y'] + self.assertCountEqual(data.index.values.tolist(), index, "data has wrong row names") + data_cached = self.ticker.growth_estimates self.assertIs(data, data_cached, "data not cached") diff --git a/tests/test_utils.py b/tests/test_utils.py index 309daebab..bcaac8de2 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -12,12 +12,78 @@ from unittest import TestSuite import pandas as pd +# import numpy as np + +from tests.context import yfinance as yf import unittest +# import requests_cache +import tempfile +import os from yfinance.utils import is_valid_period_format +class TestCache(unittest.TestCase): + @classmethod + def setUpClass(cls): + cls.tempCacheDir = tempfile.TemporaryDirectory() + yf.set_tz_cache_location(cls.tempCacheDir.name) + + @classmethod + def tearDownClass(cls): + cls.tempCacheDir.cleanup() + + def test_storeTzNoRaise(self): + # storing TZ to cache should never raise exception + tkr = 'AMZN' + tz1 = "America/New_York" + tz2 = "London/Europe" + cache = yf.cache.get_tz_cache() + cache.store(tkr, tz1) + cache.store(tkr, tz2) + + def test_setTzCacheLocation(self): + self.assertEqual(yf.cache._TzDBManager.get_location(), self.tempCacheDir.name) + + tkr = 'AMZN' + tz1 = "America/New_York" + cache = yf.cache.get_tz_cache() + cache.store(tkr, tz1) + + self.assertTrue(os.path.exists(os.path.join(self.tempCacheDir.name, "tkr-tz.db"))) + + +class TestCacheNoPermission(unittest.TestCase): + @classmethod + def setUpClass(cls): + yf.set_tz_cache_location("/root/yf-cache") + + def test_tzCacheRootStore(self): + # Test that if cache path in read-only filesystem, no exception. + tkr = 'AMZN' + tz1 = "America/New_York" + + # During attempt to store, will discover cannot write + yf.cache.get_tz_cache().store(tkr, tz1) + + # Handling the store failure replaces cache with a dummy + cache = yf.cache.get_tz_cache() + self.assertTrue(cache.dummy) + cache.store(tkr, tz1) + + def test_tzCacheRootLookup(self): + # Test that if cache path in read-only filesystem, no exception. + tkr = 'AMZN' + # During attempt to lookup, will discover cannot write + yf.cache.get_tz_cache().lookup(tkr) + + # Handling the lookup failure replaces cache with a dummy + cache = yf.cache.get_tz_cache() + self.assertTrue(cache.dummy) + cache.lookup(tkr) + + class TestPandas(unittest.TestCase): date_strings = ["2024-08-07 09:05:00+02:00", "2024-08-07 09:05:00-04:00"] @@ -63,6 +129,8 @@ def test_is_valid_period_format_edge_cases(self): def suite(): ts: TestSuite = unittest.TestSuite() + ts.addTest(TestCache('Test cache')) + ts.addTest(TestCacheNoPermission('Test cache no permission')) ts.addTest(TestPandas("Test pandas")) ts.addTest(TestUtils("Test utils")) return ts diff --git a/yfinance/__init__.py b/yfinance/__init__.py index 2f78eb46e..e2cefd551 100644 --- a/yfinance/__init__.py +++ b/yfinance/__init__.py @@ -28,17 +28,15 @@ from .cache import set_tz_cache_location from .domain.sector import Sector from .domain.industry import Industry +from .screener.screener import Screener +from .screener.screener_query import EquityQuery from .domain.market import Market -from .screener.query import EquityQuery, FundQuery -from .screener.screener import screen, PREDEFINED_SCREENER_QUERIES - __version__ = version.version __author__ = "Ran Aroussi" import warnings warnings.filterwarnings('default', category=DeprecationWarning, module='^yfinance') -__all__ = ['download', 'Market', 'Search', 'Ticker', 'Tickers', 'enable_debug_mode', 'set_tz_cache_location', 'Sector', 'Industry'] -# screener stuff: -__all__ += ['EquityQuery', 'FundQuery', 'screen', 'PREDEFINED_SCREENER_QUERIES'] \ No newline at end of file +__all__ = ['download', 'Market', 'Search', 'Ticker', 'Tickers', 'enable_debug_mode', 'set_tz_cache_location', 'Sector', + 'Industry', 'EquityQuery', 'Screener'] diff --git a/yfinance/base.py b/yfinance/base.py index ec03364a7..dc773ff9b 100644 --- a/yfinance/base.py +++ b/yfinance/base.py @@ -21,14 +21,15 @@ from __future__ import print_function +from io import StringIO import json as _json import warnings from typing import Optional, Union from urllib.parse import quote as urlencode -import numpy as np import pandas as pd import requests +from datetime import date from . import utils, cache from .data import YfData @@ -40,7 +41,7 @@ from .scrapers.history import PriceHistory from .scrapers.funds import FundsData -from .const import _BASE_URL_, _ROOT_URL_, _QUERY1_URL_ +from .const import _BASE_URL_, _ROOT_URL_ class TickerBase: @@ -592,62 +593,94 @@ def get_earnings_dates(self, limit=12, proxy=None) -> Optional[pd.DataFrame]: Returns: pd.DataFrame """ + if self._earnings_dates and limit in self._earnings_dates: + return self._earnings_dates[limit] + logger = utils.get_yf_logger() - clamped_limit = min(limit, 100) # YF caps at 100, don't go higher - - if self._earnings_dates and clamped_limit in self._earnings_dates: - return self._earnings_dates[clamped_limit] - - # Fetch data - url = f"{_QUERY1_URL_}/v1/finance/visualization" - params = {"lang": "en-US", "region": "US"} - body = { - "size": clamped_limit, - "query": { - "operator": "and", - "operands": [ - {"operator": "eq", "operands": ["ticker", self.ticker]}, - {"operator": "eq", "operands": ["eventtype", "2"]} - ] - }, - "sortField": "startdatetime", - "sortType": "DESC", - "entityIdType": "earnings", - "includeFields": ["startdatetime", "timeZoneShortName", "epsestimate", "epsactual", "epssurprisepct"] - } - response = self._data.post(url, params=params, body=body, proxy=proxy) - json_data = response.json() - # Extract data - columns = [row['label'] for row in json_data['finance']['result'][0]['documents'][0]['columns']] - rows = json_data['finance']['result'][0]['documents'][0]['rows'] - df = pd.DataFrame(rows, columns=columns) + page_size = min(limit, 100) # YF caps at 100, don't go higher + page_offset = 0 + dates = None + while True: + url = f"{_ROOT_URL_}/calendar/earnings?day={date.today()}&symbol={self.ticker}&offset={page_offset}&size={page_size}" + data = self._data.cache_get(url=url, proxy=proxy).text + + if "Will be right back" in data: + raise RuntimeError("*** YAHOO! FINANCE IS CURRENTLY DOWN! ***\n" + "Our engineers are working quickly to resolve " + "the issue. Thank you for your patience.") + + try: + data = pd.read_html(StringIO(data))[0] + except ValueError: + if page_offset == 0: + # Should not fail on first page + if "Showing Earnings for:" in data: + # Actually YF was successful, problem is company doesn't have earnings history + dates = utils.empty_earnings_dates_df() + break + if dates is None: + dates = data + else: + dates = pd.concat([dates, data], axis=0) + + page_offset += page_size + # got less data then we asked for or already fetched all we requested, no need to fetch more pages + if len(data) < page_size or len(dates) >= limit: + dates = dates.iloc[:limit] + break + else: + # do not fetch more than needed next time + page_size = min(limit - len(dates), page_size) - if df.empty: + if dates is None or dates.shape[0] == 0: _exception = YFEarningsDateMissing(self.ticker) err_msg = str(_exception) logger.error(f'{self.ticker}: {err_msg}') return None + dates = dates.reset_index(drop=True) - # Calculate earnings date - df['Earnings Date'] = pd.to_datetime(df['Event Start Date']).dt.normalize() - tz = self._get_ticker_tz(proxy=proxy, timeout=30) - if df['Earnings Date'].dt.tz is None: - df['Earnings Date'] = df['Earnings Date'].dt.tz_localize(tz) - else: - df['Earnings Date'] = df['Earnings Date'].dt.tz_convert(tz) + # Drop redundant columns + dates = dates.drop(["Symbol", "Company"], axis=1) + + # Compatibility + dates = dates.rename(columns={'Surprise (%)': 'Surprise(%)'}) + + # Drop empty rows + for i in range(len(dates)-1, -1, -1): + if dates.iloc[i].isna().all(): + dates = dates.drop(i) # Convert types - columns_to_update = ['Surprise (%)', 'EPS Estimate', 'Reported EPS'] - df[columns_to_update] = df[columns_to_update].astype('float64').replace(0.0, np.nan) + for cn in ["EPS Estimate", "Reported EPS", "Surprise(%)"]: + dates.loc[dates[cn] == '-', cn] = float("nan") + dates[cn] = dates[cn].astype(float) + + # Parse earnings date string + cn = "Earnings Date" + try: + dates_backup = dates.copy() + # - extract timezone because Yahoo stopped returning in UTC + tzy = dates[cn].str.split(' ').str.get(-1) + tzy[tzy.isin(['EDT', 'EST'])] = 'US/Eastern' + # - tidy date string + dates[cn] = dates[cn].str.split(' ').str[:-1].str.join(' ') + dates[cn] = dates[cn].replace(' at', ',', regex=True) + # - parse + dates[cn] = pd.to_datetime(dates[cn], format="%B %d, %Y, %I %p") + # - convert to exchange timezone + self._quote.proxy = proxy or self.proxy + tz = self._get_ticker_tz(proxy=proxy, timeout=30) + dates[cn] = [dates[cn].iloc[i].tz_localize(tzy.iloc[i], ambiguous=True).tz_convert(tz) for i in range(len(dates))] + + dates = dates.set_index("Earnings Date") + except Exception as e: + utils.get_yf_logger().info(f"{self.ticker}: Problem parsing earnings_dates: {str(e)}") + dates = dates_backup - # Format the dataframe - df.drop(['Event Start Date', 'Timezone short name'], axis=1, inplace=True) - df.set_index('Earnings Date', inplace=True) - df.rename(columns={'Surprise (%)': 'Surprise(%)'}, inplace=True) # Compatibility + self._earnings_dates[limit] = dates - self._earnings_dates[clamped_limit] = df - return df + return dates def get_history_metadata(self, proxy=None) -> dict: return self._lazy_load_price_history().get_history_metadata(proxy) diff --git a/yfinance/const.py b/yfinance/const.py index 1489d25e8..2735f2544 100644 --- a/yfinance/const.py +++ b/yfinance/const.py @@ -305,92 +305,21 @@ 'utilities-independent-power-producers', 'utilities-regulated-water'} } - -def merge_two_level_dicts(dict1, dict2): - result = dict1.copy() - for key, value in dict2.items(): - if key in result: - # If both are sets, merge them - if isinstance(value, set) and isinstance(result[key], set): - result[key] = result[key] | value - # If both are dicts, merge their contents - elif isinstance(value, dict) and isinstance(result[key], dict): - result[key] = { - k: (result[key].get(k, set()) | v if isinstance(v, set) - else v) if k in result[key] - else v - for k, v in value.items() - } - else: - result[key] = value - return result - EQUITY_SCREENER_EQ_MAP = { - "exchange": { - 'ar': {'BUE'}, - 'at': {'VIE'}, - 'au': {'ASX'}, - 'be': {'BRU'}, - 'br': {'SAO'}, - 'ca': {'CNQ', 'NEO', 'TOR', 'VAN'}, - 'ch': {'EBS'}, - 'cl': {'SGO'}, - 'cn': {'SHH', 'SHZ'}, - 'co': {'BVC'}, - 'cz': {'PRA'}, - 'de': {'BER', 'DUS', 'FRA', 'HAM', 'GER', 'MUN', 'STU'}, - 'dk': {'CPH'}, - 'ee': {'TAL'}, - 'eg': {'CAI'}, - 'es': {'MCE'}, - 'fi': {'HEL'}, - 'fr': {'PAR'}, - 'gb': {'AQS', 'IOB', 'LSE'}, - 'gr': {'ATH'}, - 'hk': {'HKG'}, - 'hu': {'BUD'}, - 'id': {'JKT'}, - 'ie': {'ISE'}, - 'il': {'TLV'}, - 'in': {'BSE', 'NSI'}, - 'is': {'ICE'}, - 'it': {'MIL'}, - 'jp': {'FKA', 'JPX', 'SAP'}, - 'kr': {'KOE', 'KSC'}, - 'kw': {'KUW'}, - 'lk': {}, - 'lt': {'LIT'}, - 'lv': {'RIS'}, - 'mx': {'MEX'}, - 'my': {'KLS'}, - 'nl': {'AMS'}, - 'no': {'OSL'}, - 'nz': {'NZE'}, - 'pe': {}, - 'ph': {'PHP', 'PHS'}, - 'pk': {}, - 'pl': {'WSE'}, - 'pt': {'LIS'}, - 'qa': {'DOH'}, - 'ro': {'BVB'}, - 'ru': {}, - 'sa': {'SAU'}, - 'se': {'STO'}, - 'sg': {'SES'}, - 'sr': {}, - 'th': {'SET'}, - 'tr': {'IST'}, - 'tw': {'TAI', 'TWO'}, - 'us': {'ASE', 'BTS', 'CXI', 'NCM', 'NGM', 'NMS', 'NYQ', 'OEM', 'OQB', 'OQX', 'PCX', 'PNK', 'YHD'}, - 've': {'CCS'}, - 'vn': {}, - 'za': {'JNB'} + "region": { + "za", "ve", "vn", "us", "tw", "th", "tr", "sr", "sg", "sa", "se", "ru", "ro", "qa", "pt", "pk", "pl", + "ph", "nz", "nl", "mx", "pe", "no", "my", "lv", "lt", "kw", "jp", "is", "il", "lk", "kr", "it", "in", + "ie", "hu", "id", "hk", "gb", "fi", "eg", "dk", "gr", "fr", "es", "ee", "de", "cz", "cl", "ca", "be", + "at", "cn", "br", "au", "ar", "ch" }, "sector": { "Basic Materials", "Industrials", "Communication Services", "Healthcare", "Real Estate", "Technology", "Energy", "Utilities", "Financial Services", "Consumer Defensive", "Consumer Cyclical" }, + "exchanges": { + "NMS", "NAS", "YHD", "NYQ", "NGM", "NCM", "BSE" + }, "peer_group": { "US Fund Equity Energy", "US CE Convertibles", @@ -497,42 +426,20 @@ def merge_two_level_dicts(dict1, dict2): "Banks" } } -EQUITY_SCREENER_EQ_MAP['region'] = EQUITY_SCREENER_EQ_MAP['exchange'].keys() -ordered_keys = ['region'] + [k for k in EQUITY_SCREENER_EQ_MAP.keys() if k != 'region'] -EQUITY_SCREENER_EQ_MAP = {k:EQUITY_SCREENER_EQ_MAP[k] for k in ordered_keys} -FUND_SCREENER_EQ_MAP = { - "exchange": { - 'us': {'NAS'} - } -} -COMMON_SCREENER_FIELDS = { - "price":{ - "eodprice", - "intradaypricechange", - "intradayprice" - }, - "eq_fields": { - "exchange"}, -} -FUND_SCREENER_FIELDS = { - "eq_fields": { - "categoryname", - "performanceratingoverall", - "initialinvestment", - "annualreturnnavy1categoryrank", - "riskratingoverall"} -} -FUND_SCREENER_FIELDS = merge_two_level_dicts(FUND_SCREENER_FIELDS, COMMON_SCREENER_FIELDS) EQUITY_SCREENER_FIELDS = { "eq_fields": { "region", "sector", - "peer_group"}, + "peer_group", + "exchanges"}, "price":{ + "eodprice", + "intradaypricechange", "lastclosemarketcap.lasttwelvemonths", "percentchange", "lastclose52weekhigh.lasttwelvemonths", "fiftytwowkpercentchange", + "intradayprice", "lastclose52weeklow.lasttwelvemonths", "intradaymarketcap"}, "trading":{ @@ -623,22 +530,21 @@ def merge_two_level_dicts(dict1, dict2): "social_score", "highest_controversy"} } -EQUITY_SCREENER_FIELDS = merge_two_level_dicts(EQUITY_SCREENER_FIELDS, COMMON_SCREENER_FIELDS) - -USER_AGENTS = [ - # Chrome - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36", - "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36", - - # Firefox - "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101 Firefox/135.0", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 14.7; rv:135.0) Gecko/20100101 Firefox/135.0", - "Mozilla/5.0 (X11; Linux i686; rv:135.0) Gecko/20100101 Firefox/135.0", - - # Safari - "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_7_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.3 Safari/605.1.15", - # Edge - "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/131.0.2903.86" -] +PREDEFINED_SCREENER_BODY_MAP = { + 'aggressive_small_caps': {"offset":0,"size":25,"sortField":"eodvolume","sortType":"desc","quoteType":"equity","query":{"operator":"and","operands":[{"operator":"or","operands":[{"operator":"eq","operands":["exchange","NMS"]},{"operator":"eq","operands":["exchange","NYQ"]}]},{"operator":"or","operands":[{"operator":"LT","operands":["epsgrowth.lasttwelvemonths",15]}]}]},"userId":"","userIdType":"guid"}, + 'day_gainers': {"offset":0,"size":25,"sortField":"percentchange","sortType":"DESC","quoteType":"EQUITY","query":{"operator":"AND","operands":[{"operator":"gt","operands":["percentchange",3]},{"operator":"eq","operands":["region","us"]},{"operator":"or","operands":[{"operator":"BTWN","operands":["intradaymarketcap",2000000000,10000000000]},{"operator":"BTWN","operands":["intradaymarketcap",10000000000,100000000000]},{"operator":"GT","operands":["intradaymarketcap",100000000000]}]},{"operator":"gte","operands":["intradayprice",5]},{"operator":"gt","operands":["dayvolume",15000]}]},"userId":"","userIdType":"guid"}, + 'day_losers': {"offset":0,"size":25,"sortField":"percentchange","sortType":"ASC","quoteType":"EQUITY","query":{"operator":"AND","operands":[{"operator":"lt","operands":["percentchange",-2.5]},{"operator":"eq","operands":["region","us"]},{"operator":"or","operands":[{"operator":"BTWN","operands":["intradaymarketcap",2000000000,10000000000]},{"operator":"BTWN","operands":["intradaymarketcap",10000000000,100000000000]},{"operator":"GT","operands":["intradaymarketcap",100000000000]}]},{"operator":"gte","operands":["intradayprice",5]},{"operator":"gt","operands":["dayvolume",20000]}]},"userId":"","userIdType":"guid"}, + 'growth_technology_stocks': {"offset":0,"size":25,"sortField":"eodvolume","sortType":"desc","quoteType":"equity","query":{"operator":"and","operands":[{"operator":"or","operands":[{"operator":"BTWN","operands":["quarterlyrevenuegrowth.quarterly",50,100]},{"operator":"GT","operands":["quarterlyrevenuegrowth.quarterly",100]},{"operator":"BTWN","operands":["quarterlyrevenuegrowth.quarterly",25,50]}]},{"operator":"or","operands":[{"operator":"BTWN","operands":["epsgrowth.lasttwelvemonths",25,50]},{"operator":"BTWN","operands":["epsgrowth.lasttwelvemonths",50,100]},{"operator":"GT","operands":["epsgrowth.lasttwelvemonths",100]}]},{"operator":"eq","operands":["sector","Technology"]},{"operator":"or","operands":[{"operator":"eq","operands":["exchange","NMS"]},{"operator":"eq","operands":["exchange","NYQ"]}]}]},"userId":"","userIdType":"guid"}, + 'most_actives': {"offset":0,"size":25,"sortField":"dayvolume","sortType":"DESC","quoteType":"EQUITY","query":{"operator":"AND","operands":[{"operator":"eq","operands":["region","us"]},{"operator":"or","operands":[{"operator":"BTWN","operands":["intradaymarketcap",10000000000,100000000000]},{"operator":"GT","operands":["intradaymarketcap",100000000000]},{"operator":"BTWN","operands":["intradaymarketcap",2000000000,10000000000]}]},{"operator":"gt","operands":["dayvolume",5000000]}]},"userId":"","userIdType":"guid"}, + 'most_shorted_stocks': {"size":25,"offset":0,"sortField":"short_percentage_of_shares_outstanding.value","sortType":"DESC","quoteType":"EQUITY","topOperator":"AND","query":{"operator":"AND","operands":[{"operator":"or","operands":[{"operator":"EQ","operands":["region","us"]}]},{"operator":"gt","operands":["intradayprice",1]},{"operator":"gt","operands":["avgdailyvol3m",200000]}]},"userId":"","userIdType":"guid"}, + 'small_cap_gainers': {"offset":0,"size":25,"sortField":"eodvolume","sortType":"desc","quoteType":"equity","query":{"operator":"and","operands":[{"operator":"lt","operands":["intradaymarketcap",2000000000]},{"operator":"or","operands":[{"operator":"eq","operands":["exchange","NMS"]},{"operator":"eq","operands":["exchange","NYQ"]}]}]},"userId":"","userIdType":"guid"}, + 'undervalued_growth_stocks': {"offset":0,"size":25,"sortType":"DESC","sortField":"eodvolume","quoteType":"EQUITY","query":{"operator":"and","operands":[{"operator":"or","operands":[{"operator":"BTWN","operands":["peratio.lasttwelvemonths",0,20]}]},{"operator":"or","operands":[{"operator":"LT","operands":["pegratio_5y",1]}]},{"operator":"or","operands":[{"operator":"BTWN","operands":["epsgrowth.lasttwelvemonths",25,50]},{"operator":"BTWN","operands":["epsgrowth.lasttwelvemonths",50,100]},{"operator":"GT","operands":["epsgrowth.lasttwelvemonths",100]}]},{"operator":"or","operands":[{"operator":"eq","operands":["exchange","NMS"]},{"operator":"eq","operands":["exchange","NYQ"]}]}]},"userId":"","userIdType":"guid"}, + 'undervalued_large_caps': {"offset":0,"size":25,"sortField":"eodvolume","sortType":"desc","quoteType":"equity","query":{"operator":"and","operands":[{"operator":"or","operands":[{"operator":"BTWN","operands":["peratio.lasttwelvemonths",0,20]}]},{"operator":"lt","operands":["pegratio_5y",1]},{"operator":"btwn","operands":["intradaymarketcap",10000000000,100000000000]},{"operator":"or","operands":[{"operator":"eq","operands":["exchange","NMS"]},{"operator":"eq","operands":["exchange","NYQ"]}]}]},"userId":"","userIdType":"guid"}, + 'conservative_foreign_funds': {"offset":0,"size":25,"sortType":"DESC","sortField":"fundnetassets","quoteType":"MUTUALFUND","query":{"operator":"and","operands":[{"operator":"or","operands":[{"operator":"EQ","operands":["categoryname","Foreign Large Value"]},{"operator":"EQ","operands":["categoryname","Foreign Large Blend"]},{"operator":"EQ","operands":["categoryname","Foreign Large Growth"]},{"operator":"EQ","operands":["categoryname","Foreign Small/Mid Growth"]},{"operator":"EQ","operands":["categoryname","Foreign Large Blend"]},{"operator":"EQ","operands":["categoryname","Foreign Small/Mid Blend"]},{"operator":"EQ","operands":["categoryname","Foreign Small/Mid Value"]},{"operator":"EQ","operands":["categoryname","Foreign Small/Mid Blend"]},{"operator":"EQ","operands":["categoryname","Foreign Small/Mid Value"]},{"operator":"EQ","operands":["categoryname","Foreign Small/Mid Blend"]},{"operator":"EQ","operands":["categoryname","Foreign Small/Mid Value"]},{"operator":"EQ","operands":["categoryname","Foreign Small/Mid Blend"]},{"operator":"EQ","operands":["categoryname","Foreign Small/Mid Value"]}]},{"operator":"or","operands":[{"operator":"EQ","operands":["performanceratingoverall",4]},{"operator":"EQ","operands":["performanceratingoverall",5]}]},{"operator":"lt","operands":["initialinvestment",100001]},{"operator":"lt","operands":["annualreturnnavy1categoryrank",50]},{"operator":"or","operands":[{"operator":"EQ","operands":["riskratingoverall",1]},{"operator":"EQ","operands":["riskratingoverall",3]},{"operator":"EQ","operands":["riskratingoverall",2]}]},{"operator":"or","operands":[{"operator":"eq","operands":["exchange","NAS"]}]}]},"userId":"","userIdType":"guid"}, + 'high_yield_bond': {"offset":0,"size":25,"sortType":"DESC","sortField":"fundnetassets","quoteType":"MUTUALFUND","query":{"operator":"and","operands":[{"operator":"or","operands":[{"operator":"EQ","operands":["performanceratingoverall",4]},{"operator":"EQ","operands":["performanceratingoverall",5]}]},{"operator":"lt","operands":["initialinvestment",100001]},{"operator":"lt","operands":["annualreturnnavy1categoryrank",50]},{"operator":"or","operands":[{"operator":"EQ","operands":["riskratingoverall",1]},{"operator":"EQ","operands":["riskratingoverall",3]},{"operator":"EQ","operands":["riskratingoverall",2]}]},{"operator":"or","operands":[{"operator":"EQ","operands":["categoryname","High Yield Bond"]}]},{"operator":"or","operands":[{"operator":"eq","operands":["exchange","NAS"]}]}]},"userId":"","userIdType":"guid"}, + 'portfolio_anchors': {"offset":0,"size":25,"sortType":"DESC","sortField":"fundnetassets","quoteType":"MUTUALFUND","query":{"operator":"and","operands":[{"operator":"or","operands":[{"operator":"EQ","operands":["categoryname","Large Blend"]}]},{"operator":"or","operands":[{"operator":"EQ","operands":["performanceratingoverall",4]},{"operator":"EQ","operands":["performanceratingoverall",5]}]},{"operator":"lt","operands":["initialinvestment",100001]},{"operator":"lt","operands":["annualreturnnavy1categoryrank",50]},{"operator":"or","operands":[{"operator":"eq","operands":["exchange","NAS"]}]}]},"userId":"","userIdType":"guid"}, + 'solid_large_growth_funds': {"offset":0,"size":25,"sortType":"DESC","sortField":"fundnetassets","quoteType":"MUTUALFUND","query":{"operator":"and","operands":[{"operator":"or","operands":[{"operator":"EQ","operands":["categoryname","Large Growth"]}]},{"operator":"or","operands":[{"operator":"EQ","operands":["performanceratingoverall",5]},{"operator":"EQ","operands":["performanceratingoverall",4]}]},{"operator":"lt","operands":["initialinvestment",100001]},{"operator":"lt","operands":["annualreturnnavy1categoryrank",50]},{"operator":"or","operands":[{"operator":"eq","operands":["exchange","NAS"]}]}]},"userId":"","userIdType":"guid"}, + 'solid_midcap_growth_funds': {"offset":0,"size":25,"sortType":"DESC","sortField":"fundnetassets","quoteType":"MUTUALFUND","query":{"operator":"and","operands":[{"operator":"or","operands":[{"operator":"EQ","operands":["categoryname","Mid-Cap Growth"]}]},{"operator":"or","operands":[{"operator":"EQ","operands":["performanceratingoverall",5]},{"operator":"EQ","operands":["performanceratingoverall",4]}]},{"operator":"lt","operands":["initialinvestment",100001]},{"operator":"lt","operands":["annualreturnnavy1categoryrank",50]},{"operator":"or","operands":[{"operator":"eq","operands":["exchange","NAS"]}]}]},"userId":"","userIdType":"guid"}, + 'top_mutual_funds': {"offset":0,"size":25,"sortType":"DESC","sortField":"percentchange","quoteType":"MUTUALFUND","query":{"operator":"and","operands":[{"operator":"gt","operands":["intradayprice",15]},{"operator":"or","operands":[{"operator":"EQ","operands":["performanceratingoverall",5]},{"operator":"EQ","operands":["performanceratingoverall",4]}]},{"operator":"gt","operands":["initialinvestment",1000]},{"operator":"or","operands":[{"operator":"eq","operands":["exchange","NAS"]}]}]},"userId":"","userIdType":"guid"} +} \ No newline at end of file diff --git a/yfinance/data.py b/yfinance/data.py index 884c937aa..48af3cefa 100644 --- a/yfinance/data.py +++ b/yfinance/data.py @@ -1,5 +1,4 @@ import functools -import random from functools import lru_cache import requests as requests @@ -11,7 +10,6 @@ from . import utils, cache import threading -from .const import USER_AGENTS from .exceptions import YFRateLimitError cache_maxsize = 64 @@ -61,8 +59,7 @@ class YfData(metaclass=SingletonMeta): Singleton means one session one cookie shared by all threads. """ user_agent_headers = { - 'User-Agent': random.choice(USER_AGENTS) - } + 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.95 Safari/537.36'} def __init__(self, session=None): self._crumb = None @@ -234,16 +231,11 @@ def _get_cookie_csrf(self, proxy, timeout): 'timeout': timeout} get_args = {**base_args, 'url': 'https://guce.yahoo.com/consent'} - try: - if self._session_is_caching: - get_args['expire_after'] = self._expire_after - response = self._session.get(**get_args) - else: - response = self._session.get(**get_args) - except requests.exceptions.ChunkedEncodingError: - # No idea why happens, but handle nicely so can switch to other cookie method. - utils.get_yf_logger().debug('_get_cookie_csrf() encountering requests.exceptions.ChunkedEncodingError, aborting') - return False + if self._session_is_caching: + get_args['expire_after'] = self._expire_after + response = self._session.get(**get_args) + else: + response = self._session.get(**get_args) soup = BeautifulSoup(response.content, 'html.parser') csrfTokenInput = soup.find('input', attrs={'name': 'csrfToken'}) @@ -272,18 +264,14 @@ def _get_cookie_csrf(self, proxy, timeout): get_args = {**base_args, 'url': f'https://guce.yahoo.com/copyConsent?sessionId={sessionId}', 'data': data} - try: - if self._session_is_caching: - post_args['expire_after'] = self._expire_after - get_args['expire_after'] = self._expire_after - self._session.post(**post_args) - self._session.get(**get_args) - else: - self._session.post(**post_args) - self._session.get(**get_args) - except requests.exceptions.ChunkedEncodingError: - # No idea why happens, but handle nicely so can switch to other cookie method. - utils.get_yf_logger().debug('_get_cookie_csrf() encountering requests.exceptions.ChunkedEncodingError, aborting') + if self._session_is_caching: + post_args['expire_after'] = self._expire_after + get_args['expire_after'] = self._expire_after + self._session.post(**post_args) + self._session.get(**get_args) + else: + self._session.post(**post_args) + self._session.get(**get_args) self._cookie = True self._save_session_cookies() return True diff --git a/yfinance/domain/market.py b/yfinance/domain/market.py index d01868702..e4c7d8b25 100644 --- a/yfinance/domain/market.py +++ b/yfinance/domain/market.py @@ -5,7 +5,7 @@ from ..const import _QUERY1_URL_ import json as _json -class Market: +class Market(): def __init__(self, market:'str', session=None, proxy=None, timeout=30): self.market = market self.session = session @@ -52,7 +52,7 @@ def _parse_data(self): status_params = { "formatted": True, "key": "finance", - "lang": "en-US", + "lang": "en-GB", "market": self.market } @@ -73,11 +73,11 @@ def _parse_data(self): self._status['timezone'] = self._status['timezone'][0] del self._status['time'] # redundant try: - self._status.update({ - "open": dt.datetime.fromisoformat(self._status["open"]), - "close": dt.datetime.fromisoformat(self._status["close"]), - "tz": dt.timezone(dt.timedelta(hours=int(self._status["timezone"]["gmtoffset"]))/1000, self._status["timezone"]["short"]) - }) + self._status.update( + open = dt.datetime.fromisoformat(self._status["open"]), + close = dt.datetime.fromisoformat(self._status["close"]), + tz = dt.timezone(self._status["timezone"]["gmtoffset"], self._status["timezone"]["short"]) + ) except Exception as e: self._logger.error(f"{self.market}: Failed to update market status") self._logger.debug(f"{type(e)}: {e}") diff --git a/yfinance/multi.py b/yfinance/multi.py index 0d567e04a..490189f1c 100644 --- a/yfinance/multi.py +++ b/yfinance/multi.py @@ -36,7 +36,7 @@ @utils.log_indent_decorator def download(tickers, start=None, end=None, actions=False, threads=True, - ignore_tz=None, group_by='column', auto_adjust=None, back_adjust=False, + ignore_tz=None, group_by='column', auto_adjust=True, back_adjust=False, repair=False, keepna=False, progress=True, period="max", interval="1d", prepost=False, proxy=None, rounding=False, timeout=10, session=None, multi_level_index=True) -> Union[_pd.DataFrame, None]: @@ -93,11 +93,6 @@ def download(tickers, start=None, end=None, actions=False, threads=True, """ logger = utils.get_yf_logger() - if auto_adjust is None: - # Warn users that default has changed to True - utils.print_once("YF.download() has changed argument auto_adjust default to True") - auto_adjust = True - if logger.isEnabledFor(logging.DEBUG): if threads: # With DEBUG, each thread generates a lot of log messages. @@ -111,7 +106,7 @@ def download(tickers, start=None, end=None, actions=False, threads=True, if ignore_tz is None: # Set default value depending on interval - if interval[-1] in ['m', 'h']: + if interval[1:] in ['m', 'h']: # Intraday ignore_tz = False else: @@ -185,7 +180,7 @@ def download(tickers, start=None, end=None, actions=False, threads=True, errors = {} for ticker in shared._ERRORS: err = shared._ERRORS[ticker] - err = err.replace(f'${ticker}: ', '') + err = err.replace(f'{ticker}', '%ticker%') if err not in errors: errors[err] = [ticker] else: @@ -197,7 +192,7 @@ def download(tickers, start=None, end=None, actions=False, threads=True, tbs = {} for ticker in shared._TRACEBACKS: tb = shared._TRACEBACKS[ticker] - tb = tb.replace(f'${ticker}: ', '') + tb = tb.replace(f'{ticker}', '%ticker%') if tb not in tbs: tbs[tb] = [ticker] else: diff --git a/yfinance/scrapers/history.py b/yfinance/scrapers/history.py index 51ec87349..7692208e3 100644 --- a/yfinance/scrapers/history.py +++ b/yfinance/scrapers/history.py @@ -1304,7 +1304,7 @@ def _fix_bad_div_adjust(self, df, interval, currency): if df is None or df.empty: return df - if interval in ['1wk', '1mo', '3mo', '1y']: + if interval != '1d': return df logger = utils.get_yf_logger() @@ -1614,9 +1614,9 @@ def cluster_dividends(df, column='div', threshold=7): checks += ['adj_missing', 'adj_exceeds_div', 'div_exceeds_adj'] div_status_df['phantom'] = False - phantom_proximity_threshold = _datetime.timedelta(days=17) + phantom_proximity_threshold = _datetime.timedelta(days=7) f = div_status_df[['div_too_big', 'div_exceeds_adj']].any(axis=1) - if f.any() and len(div_status_df) > 1: + if f.any(): # One/some of these may be phantom dividends. Clue is if another correct dividend is very close indices = np.where(f)[0] dts_to_check = div_status_df.index[f] @@ -1625,24 +1625,37 @@ def cluster_dividends(df, column='div', threshold=7): div_dt = div.name phantom_dt = None if i > 0: - other_div = div_status_df.iloc[i-1] - else: - other_div = div_status_df.iloc[i+1] - ratio1 = (div['div']/currency_divide) / other_div['div'] - ratio2 = div['div'] / other_div['div'] - divergence = min(abs(ratio1-1.0), abs(ratio2-1.0)) - if abs(div_dt-other_div.name) <= phantom_proximity_threshold and not other_div['phantom'] and divergence < 0.01: - if other_div.name in dts_to_check: - # Both this and previous are anomalous, so mark smallest drop as phantom - drop = div['drop'] - drop_next = other_div['drop'] - if drop > 1.5*drop_next: - phantom_dt = other_div.name + prev_div = div_status_df.iloc[i-1] + ratio1 = (div['div']/currency_divide) / prev_div['div'] + ratio2 = div['div'] / prev_div['div'] + divergence = min(abs(ratio1-1.0), abs(ratio2-1.0)) + if abs(div_dt-prev_div.name) <= phantom_proximity_threshold and not prev_div['phantom'] and divergence < 0.01: + if prev_div.name in dts_to_check: + # Both this and previous are anomalous, so mark smallest drop as phantom + drop = div['drop'] + drop_prev = prev_div['drop'] + if drop > 1.5*drop_prev: + phantom_dt = prev_div.name + else: + phantom_dt = div_dt + else: + phantom_dt = div_dt + elif i < len(div_status_df)-1: + next_div = div_status_df.iloc[i+1] + ratio1 = (div['div']/currency_divide) / next_div['div'] + ratio2 = div['div'] / next_div['div'] + divergence = min(abs(ratio1-1.0), abs(ratio2-1.0)) + if abs(div_dt-next_div.name) <= phantom_proximity_threshold and divergence < 0.01: + if next_div.name in dts_to_check: + # Both this and previous are anomalous, so mark smallest drop as phantom + drop = div['drop'] + drop_next = next_div['drop'] + if drop > 1.5*drop_next: + phantom_dt = next_div.name + else: + phantom_dt = div_dt else: phantom_dt = div_dt - else: - phantom_dt = div_dt - if phantom_dt: div_status_df.loc[phantom_dt, 'phantom'] = True for c in checks: @@ -1741,7 +1754,7 @@ def cluster_dividends(df, column='div', threshold=7): lookahead_idx = bisect.bisect_left(df2.index, lookahead_date) lookahead_idx = min(lookahead_idx, len(df2)-1) # In rare cases, the price dropped 1 day before dividend (DVD.OL @ 2024-05-15) - lookback_idx = max(0, div_idx-14) + lookback_idx = div_idx-2 if div_idx > 1 else div_idx-1 # Check for bad stock splits in the lookahead period - # if present, reduce lookahead to before. future_changes = df2['Close'].iloc[div_idx:lookahead_idx+1].pct_change() @@ -1763,6 +1776,8 @@ def cluster_dividends(df, column='div', threshold=7): adjDeltas = x['Adj Low'].iloc[1:].to_numpy() - x['Adj Close'].iloc[:-1].to_numpy() adjDeltas = np.append([0.0], adjDeltas) x['adjDelta'] = adjDeltas + for i in np.where(x['Dividends']>0)[0]: + x.loc[x.index[i], 'adjDelta'] += x['Dividends'].iloc[i]*x['Adj'].iloc[i] deltas = x[['delta', 'adjDelta']] if div_pct > 0.05 and div_pct < 1.0: adjDiv = div * x['Adj'].iloc[0] @@ -1897,7 +1912,7 @@ def cluster_dividends(df, column='div', threshold=7): pct_fail = n_fail / n if c == 'div_too_big': true_threshold = 1.0 - fals_threshold = 0.25 + fals_threshold = 0.2 if 'div_date_wrong' in cluster.columns and (cluster[c] == cluster['div_date_wrong']).all(): continue @@ -1976,7 +1991,7 @@ def cluster_dividends(df, column='div', threshold=7): if c == 'div_date_wrong': # Fine, these should be rare continue - if c in ['div_pre_split', 'div_too_big_and_pre_split']: + if c == 'div_pre_split': # Fine, these should be rare continue @@ -2212,26 +2227,6 @@ def cluster_dividends(df, column='div', threshold=7): df2_nan.loc[:enddt, 'Repaired?'] = True cluster.loc[dt, 'Fixed?'] = True - elif n_failed_checks == 3: - if div_too_big and div_exceeds_adj and div_pre_split: - k = 'too-big div & pre-split' - correction = (1.0/currency_divide) * (1.0/df2['Stock Splits'].loc[dt]) - correct_div = row['div'] * correction - df2.loc[dt, 'Dividends'] = correct_div - - target_div_pct = row['%'] * correction - target_adj = 1.0 - target_div_pct - present_adj = row['present adj'] - # Also correct adjustment to match corrected dividend - k += ' & div-adjust' - adj_correction = target_adj / present_adj - df2.loc[ :enddt, 'Adj Close'] *= adj_correction - df2.loc[ :enddt, 'Repaired?'] = True - df2_nan.loc[:enddt, 'Adj Close'] *= adj_correction - df2_nan.loc[:enddt, 'Repaired?'] = True - cluster.loc[dt, 'Fixed?'] = True - div_repairs.setdefault(k, []).append(dt) - if cluster.empty: continue @@ -2487,14 +2482,14 @@ def _fix_prices_sudden_change(self, df, interval, tz_exchange, change, correct_v r = _1d_change_x / split_rcp f_down = _1d_change_x < 1.0 / threshold - # if f_down.any(): - # # Discard where triggered by negative Adj Close after dividend - # f_neg = _1d_change_x < 0.0 - # f_div = (df2['Dividends']>0).to_numpy() - # f_div_before = np.roll(f_div, 1) - # if f_down.ndim == 2: - # f_div_before = f_div_before[:, np.newaxis].repeat(f_down.shape[1], axis=1) - # f_down = f_down & ~(f_neg + f_div_before) + if f_down.any(): + # Discard where triggered by negative Adj Close after dividend + f_neg = _1d_change_x < 0.0 + f_div = (df2['Dividends']>0).to_numpy() + f_div_before = np.roll(f_div, 1) + if f_down.ndim == 2: + f_div_before = f_div_before[:, np.newaxis].repeat(f_down.shape[1], axis=1) + f_down = f_down & ~(f_neg + f_div_before) f_up = _1d_change_x > threshold f_up_ndims = len(f_up.shape) f_up_shifts = f_up if f_up_ndims==1 else f_up.any(axis=1) @@ -2517,7 +2512,7 @@ def _fix_prices_sudden_change(self, df, interval, tz_exchange, change, correct_v # assume false positive continue avg_vol_after = df2['Volume'].iloc[lookback:i-1].mean() - if not np.isnan(avg_vol_after) and avg_vol_after > 0 and v/avg_vol_after < 2.0: + if not np.isnan(avg_vol_after) and v/avg_vol_after < 2.0: # volume spike is actually a step-change, so # probably missing stock split continue diff --git a/yfinance/scrapers/holders.py b/yfinance/scrapers/holders.py index e23aafc5e..f5d7457c2 100644 --- a/yfinance/scrapers/holders.py +++ b/yfinance/scrapers/holders.py @@ -1,3 +1,5 @@ +# from io import StringIO + import pandas as pd import requests @@ -6,7 +8,7 @@ from yfinance.const import _BASE_URL_ from yfinance.exceptions import YFDataException -_QUOTE_SUMMARY_URL_ = f"{_BASE_URL_}/v10/finance/quoteSummary" +_QUOTE_SUMMARY_URL_ = f"{_BASE_URL_}/v10/finance/quoteSummary/" class Holders: @@ -29,36 +31,42 @@ def __init__(self, data: YfData, symbol: str, proxy=None): @property def major(self) -> pd.DataFrame: if self._major is None: + # self._scrape(self.proxy) self._fetch_and_parse() return self._major @property def institutional(self) -> pd.DataFrame: if self._institutional is None: + # self._scrape(self.proxy) self._fetch_and_parse() return self._institutional @property def mutualfund(self) -> pd.DataFrame: if self._mutualfund is None: + # self._scrape(self.proxy) self._fetch_and_parse() return self._mutualfund @property def insider_transactions(self) -> pd.DataFrame: if self._insider_transactions is None: + # self._scrape_insider_transactions(self.proxy) self._fetch_and_parse() return self._insider_transactions @property def insider_purchases(self) -> pd.DataFrame: if self._insider_purchases is None: + # self._scrape_insider_transactions(self.proxy) self._fetch_and_parse() return self._insider_purchases @property def insider_roster(self) -> pd.DataFrame: if self._insider_roster is None: + # self._scrape_insider_ros(self.proxy) self._fetch_and_parse() return self._insider_roster @@ -179,10 +187,8 @@ def _parse_insider_holders(self, data): del owner["maxAge"] df = pd.DataFrame(holders) if not df.empty: - if "positionDirectDate" in df: - df["positionDirectDate"] = pd.to_datetime(df["positionDirectDate"], unit="s") - if "latestTransDate" in df: - df["latestTransDate"] = pd.to_datetime(df["latestTransDate"], unit="s") + df["positionDirectDate"] = pd.to_datetime(df["positionDirectDate"], unit="s") + df["latestTransDate"] = pd.to_datetime(df["latestTransDate"], unit="s") df.rename(columns={ "name": "Name", diff --git a/yfinance/scrapers/quote.py b/yfinance/scrapers/quote.py index 800ff48fd..a155c6209 100644 --- a/yfinance/scrapers/quote.py +++ b/yfinance/scrapers/quote.py @@ -7,7 +7,7 @@ from yfinance import utils from yfinance.data import YfData -from yfinance.const import quote_summary_valid_modules, _BASE_URL_, _QUERY1_URL_ +from yfinance.const import quote_summary_valid_modules, _BASE_URL_ from yfinance.exceptions import YFDataException, YFException info_retired_keys_price = {"currentPrice", "dayHigh", "dayLow", "open", "previousClose", "volume", "volume24Hr"} @@ -590,56 +590,33 @@ def _fetch(self, proxy, modules: list): return None return result - def _fetch_additional_info(self, proxy): - params_dict = {"symbols": self._symbol, "formatted": "false"} - try: - result = self._data.get_raw_json(f"{_QUERY1_URL_}/v7/finance/quote?", - user_agent_headers=self._data.user_agent_headers, - params=params_dict, proxy=proxy) - except requests.exceptions.HTTPError as e: - utils.get_yf_logger().error(str(e)) - return None - return result - def _fetch_info(self, proxy): if self._already_fetched: return self._already_fetched = True modules = ['financialData', 'quoteType', 'defaultKeyStatistics', 'assetProfile', 'summaryDetail'] result = self._fetch(proxy, modules=modules) - result.update(self._fetch_additional_info(proxy)) if result is None: self._info = {} return - query1_info = {} - for quote in ["quoteSummary", "quoteResponse"]: - if quote in result: - result[quote]["result"][0]["symbol"] = self._symbol - query_info = next( - (info for info in result.get(quote, {}).get("result", []) - if info["symbol"] == self._symbol), - None, - ) - if query_info: - query1_info.update(query_info) - - # Normalize and flatten nested dictionaries while converting maxAge from days (1) to seconds (86400). - # This handles Yahoo Finance API inconsistency where maxAge is sometimes expressed in days instead of seconds. - processed_info = {} - for k, v in query1_info.items(): - - # Handle nested dictionary - if isinstance(v, dict): - for k1, v1 in v.items(): - if v1 is not None: - processed_info[k1] = 86400 if k1 == "maxAge" and v1 == 1 else v1 - - elif v is not None: - processed_info[k] = v - - query1_info = processed_info - + result["quoteSummary"]["result"][0]["symbol"] = self._symbol + query1_info = next( + (info for info in result.get("quoteSummary", {}).get("result", []) if info["symbol"] == self._symbol), + None, + ) + # Most keys that appear in multiple dicts have same value. Except 'maxAge' because + # Yahoo not consistent with days vs seconds. Fix it here: + for k in query1_info: + if "maxAge" in query1_info[k] and query1_info[k]["maxAge"] == 1: + query1_info[k]["maxAge"] = 86400 + query1_info = { + k1: v1 + for k, v in query1_info.items() + if isinstance(v, dict) + for k1, v1 in v.items() + if v1 + } # recursively format but only because of 'companyOfficers' def _format(k, v): @@ -654,8 +631,9 @@ def _format(k, v): else: v2 = v return v2 - - self._info = {k: _format(k, v) for k, v in query1_info.items()} + for k, v in query1_info.items(): + query1_info[k] = _format(k, v) + self._info = query1_info def _fetch_complementary(self, proxy): if self._already_fetched_complementary: diff --git a/yfinance/screener/__init__.py b/yfinance/screener/__init__.py index b3e312242..3254bdcc9 100644 --- a/yfinance/screener/__init__.py +++ b/yfinance/screener/__init__.py @@ -1,4 +1,4 @@ -from .query import EquityQuery -from .screener import screen, PREDEFINED_SCREENER_QUERIES +from .screener import Screener +from .screener_query import EquityQuery -__all__ = ['EquityQuery', 'FundQuery', 'screen', 'PREDEFINED_SCREENER_QUERIES'] +__all__ = ['EquityQuery', 'Screener'] \ No newline at end of file diff --git a/yfinance/screener/query.py b/yfinance/screener/query.py deleted file mode 100644 index 81214a7d1..000000000 --- a/yfinance/screener/query.py +++ /dev/null @@ -1,218 +0,0 @@ -from abc import ABC, abstractmethod -import numbers -from typing import List, Union, Dict, TypeVar, Tuple - -from yfinance.const import EQUITY_SCREENER_EQ_MAP, EQUITY_SCREENER_FIELDS -from yfinance.const import FUND_SCREENER_EQ_MAP, FUND_SCREENER_FIELDS -from yfinance.exceptions import YFNotImplementedError -from ..utils import dynamic_docstring, generate_list_table_from_dict_universal - -T = TypeVar('T', bound=Union[str, numbers.Real]) - -class QueryBase(ABC): - def __init__(self, operator: str, operand: Union[ List['QueryBase'], Tuple[str, Tuple[Union[str, numbers.Real], ...]] ]): - operator = operator.upper() - - if not isinstance(operand, list): - raise TypeError('Invalid operand type') - if len(operand) <= 0: - raise ValueError('Invalid field for EquityQuery') - - if operator == 'IS-IN': - self._validate_isin_operand(operand) - elif operator in {'OR','AND'}: - self._validate_or_and_operand(operand) - elif operator == 'EQ': - self._validate_eq_operand(operand) - elif operator == 'BTWN': - self._validate_btwn_operand(operand) - elif operator in {'GT','LT','GTE','LTE'}: - self._validate_gt_lt(operand) - else: - raise ValueError('Invalid Operator Value') - - self.operator = operator - self.operands = operand - - @property - @abstractmethod - def valid_fields(self) -> List: - raise YFNotImplementedError('valid_fields() needs to be implemented by child') - - @property - @abstractmethod - def valid_values(self) -> Dict: - raise YFNotImplementedError('valid_values() needs to be implemented by child') - - def _validate_or_and_operand(self, operand: List['QueryBase']) -> None: - if len(operand) <= 1: - raise ValueError('Operand must be length longer than 1') - if all(isinstance(e, QueryBase) for e in operand) is False: - raise TypeError(f'Operand must be type {type(self)} for OR/AND') - - def _validate_eq_operand(self, operand: List[Union[str, numbers.Real]]) -> None: - if len(operand) != 2: - raise ValueError('Operand must be length 2 for EQ') - - if not any(operand[0] in fields_by_type for fields_by_type in self.valid_fields.values()): - raise ValueError(f'Invalid field for {type(self)} "{operand[0]}"') - if operand[0] in self.valid_values: - vv = self.valid_values[operand[0]] - if isinstance(vv, dict): - # this data structure is slightly different to generate better docs, - # need to unpack here. - vv = set().union(*[e for e in vv.values()]) - if operand[1] not in vv: - raise ValueError(f'Invalid EQ value "{operand[1]}"') - - def _validate_btwn_operand(self, operand: List[Union[str, numbers.Real]]) -> None: - if len(operand) != 3: - raise ValueError('Operand must be length 3 for BTWN') - if not any(operand[0] in fields_by_type for fields_by_type in self.valid_fields.values()): - raise ValueError(f'Invalid field for {type(self)}') - if isinstance(operand[1], numbers.Real) is False: - raise TypeError('Invalid comparison type for BTWN') - if isinstance(operand[2], numbers.Real) is False: - raise TypeError('Invalid comparison type for BTWN') - - def _validate_gt_lt(self, operand: List[Union[str, numbers.Real]]) -> None: - if len(operand) != 2: - raise ValueError('Operand must be length 2 for GT/LT') - if not any(operand[0] in fields_by_type for fields_by_type in self.valid_fields.values()): - raise ValueError(f'Invalid field for {type(self)} "{operand[0]}"') - if isinstance(operand[1], numbers.Real) is False: - raise TypeError('Invalid comparison type for GT/LT') - - def _validate_isin_operand(self, operand: List['QueryBase']) -> None: - if len(operand) < 2: - raise ValueError('Operand must be length 2+ for IS-IN') - - if not any(operand[0] in fields_by_type for fields_by_type in self.valid_fields.values()): - raise ValueError(f'Invalid field for {type(self)} "{operand[0]}"') - if operand[0] in self.valid_values: - vv = self.valid_values[operand[0]] - if isinstance(vv, dict): - # this data structure is slightly different to generate better docs, - # need to unpack here. - vv = set().union(*[e for e in vv.values()]) - for i in range(1, len(operand)): - if operand[i] not in vv: - raise ValueError(f'Invalid EQ value "{operand[i]}"') - - def to_dict(self) -> Dict: - op = self.operator - ops = self.operands - if self.operator == 'IS-IN': - # Expand to OR of EQ queries - op = 'OR' - ops = [type(self)('EQ', [self.operands[0], v]) for v in self.operands[1:]] - return { - "operator": op, - "operands": [o.to_dict() if isinstance(o, QueryBase) else o for o in ops] - } - - def __repr__(self, indent=0) -> str: - indent_str = " " * indent - class_name = self.__class__.__name__ - - if isinstance(self.operands, list): - # For list operands, check if they contain any QueryBase objects - if any(isinstance(op, QueryBase) for op in self.operands): - # If there are nested queries, format them with newlines - operands_str = ",\n".join( - f"{indent_str} {op.__repr__(indent + 1) if isinstance(op, QueryBase) else repr(op)}" - for op in self.operands - ) - return f"{class_name}({self.operator}, [\n{operands_str}\n{indent_str}])" - else: - # For lists of simple types, keep them on one line - return f"{class_name}({self.operator}, {repr(self.operands)})" - else: - # Handle single operand - return f"{class_name}({self.operator}, {repr(self.operands)})" - - def __str__(self) -> str: - return self.__repr__() - - -class EquityQuery(QueryBase): - """ - The `EquityQuery` class constructs filters for stocks based on specific criteria such as region, sector, exchange, and peer group. - - Start with value operations: `EQ` (equals), `IS-IN` (is in), `BTWN` (between), `GT` (greater than), `LT` (less than), `GTE` (greater or equal), `LTE` (less or equal). - - Combine them with logical operations: `AND`, `OR`. - - Example: - Predefined Yahoo query `aggressive_small_caps`: - - .. code-block:: python - - from yfinance import EquityQuery - - EquityQuery('and', [ - EquityQuery('is-in', ['exchange', 'NMS', 'NYQ']), - EquityQuery('lt', ["epsgrowth.lasttwelvemonths", 15]) - ]) - """ - - @dynamic_docstring({"valid_operand_fields_table": generate_list_table_from_dict_universal(EQUITY_SCREENER_FIELDS)}) - @property - def valid_fields(self) -> Dict: - """ - Valid operands, grouped by category. - {valid_operand_fields_table} - """ - return EQUITY_SCREENER_FIELDS - - @dynamic_docstring({"valid_values_table": generate_list_table_from_dict_universal(EQUITY_SCREENER_EQ_MAP, concat_keys=['exchange'])}) - @property - def valid_values(self) -> Dict: - """ - Most operands take number values, but some have a restricted set of valid values. - {valid_values_table} - """ - return EQUITY_SCREENER_EQ_MAP - - -class FundQuery(QueryBase): - """ - The `FundQuery` class constructs filters for mutual funds based on specific criteria such as region, sector, exchange, and peer group. - - Start with value operations: `EQ` (equals), `IS-IN` (is in), `BTWN` (between), `GT` (greater than), `LT` (less than), `GTE` (greater or equal), `LTE` (less or equal). - - Combine them with logical operations: `AND`, `OR`. - - Example: - Predefined Yahoo query `solid_large_growth_funds`: - - .. code-block:: python - - from yfinance import FundQuery - - FundQuery('and', [ - FundQuery('eq', ['categoryname', 'Large Growth']), - FundQuery('is-in', ['performanceratingoverall', 4, 5]), - FundQuery('lt', ['initialinvestment', 100001]), - FundQuery('lt', ['annualreturnnavy1categoryrank', 50]), - FundQuery('eq', ['exchange', 'NAS']) - ]) - """ - @dynamic_docstring({"valid_operand_fields_table": generate_list_table_from_dict_universal(FUND_SCREENER_FIELDS)}) - @property - def valid_fields(self) -> Dict: - """ - Valid operands, grouped by category. - {valid_operand_fields_table} - """ - return FUND_SCREENER_FIELDS - - @dynamic_docstring({"valid_values_table": generate_list_table_from_dict_universal(FUND_SCREENER_EQ_MAP)}) - @property - def valid_values(self) -> Dict: - """ - Most operands take number values, but some have a restricted set of valid values. - {valid_values_table} - """ - return FUND_SCREENER_EQ_MAP - diff --git a/yfinance/screener/screener.py b/yfinance/screener/screener.py index 60d84c318..01ff667b1 100644 --- a/yfinance/screener/screener.py +++ b/yfinance/screener/screener.py @@ -1,180 +1,225 @@ -from .query import EquityQuery as EqyQy -from .query import FundQuery as FndQy -from .query import QueryBase, EquityQuery, FundQuery +from typing import Dict -from yfinance.const import _BASE_URL_ +from yfinance import utils from yfinance.data import YfData - -from ..utils import dynamic_docstring, generate_list_table_from_dict_universal - -from typing import Union -import requests +from yfinance.const import _BASE_URL_, PREDEFINED_SCREENER_BODY_MAP +from .screener_query import Query +from ..utils import dynamic_docstring, generate_list_table_from_dict_of_dict _SCREENER_URL_ = f"{_BASE_URL_}/v1/finance/screener" -_PREDEFINED_URL_ = f"{_SCREENER_URL_}/predefined/saved" - -PREDEFINED_SCREENER_BODY_DEFAULTS = { - "offset":0, "size":25, "userId":"","userIdType":"guid" -} - -PREDEFINED_SCREENER_QUERIES = { - 'aggressive_small_caps': {"sortField":"eodvolume", "sortType":"desc", - "query": EqyQy('and', [EqyQy('is-in', ['exchange', 'NMS', 'NYQ']), EqyQy('lt', ["epsgrowth.lasttwelvemonths", 15])])}, - 'day_gainers': {"sortField":"percentchange", "sortType":"DESC", - "query": EqyQy('and', [EqyQy('gt', ['percentchange', 3]), EqyQy('eq', ['region', 'us']), EqyQy('gte', ['intradaymarketcap', 2000000000]), EqyQy('gte', ['intradayprice', 5]), EqyQy('gt', ['dayvolume', 15000])])}, - 'day_losers': {"sortField":"percentchange", "sortType":"ASC", - "query": EqyQy('and', [EqyQy('lt', ['percentchange', -2.5]), EqyQy('eq', ['region', 'us']), EqyQy('gte', ['intradaymarketcap', 2000000000]), EqyQy('gte', ['intradayprice', 5]), EqyQy('gt', ['dayvolume', 20000])])}, - 'growth_technology_stocks': {"sortField":"eodvolume", "sortType":"desc", - "query": EqyQy('and', [EqyQy('gte', ['quarterlyrevenuegrowth.quarterly', 25]), EqyQy('gte', ['epsgrowth.lasttwelvemonths', 25]), EqyQy('eq', ['sector', 'Technology']), EqyQy('is-in', ['exchange', 'NMS', 'NYQ'])])}, - 'most_actives': {"sortField":"dayvolume", "sortType":"DESC", - "query": EqyQy('and', [EqyQy('eq', ['region', 'us']), EqyQy('gte', ['intradaymarketcap', 2000000000]), EqyQy('gt', ['dayvolume', 5000000])])}, - 'most_shorted_stocks': {"size":25, "offset":0, "sortField":"short_percentage_of_shares_outstanding.value", "sortType":"DESC", - "query": EqyQy('and', [EqyQy('eq', ['region', 'us']), EqyQy('gt', ['intradayprice', 1]), EqyQy('gt', ['avgdailyvol3m', 200000])])}, - 'small_cap_gainers': {"sortField":"eodvolume", "sortType":"desc", - "query": EqyQy("and", [EqyQy("lt", ["intradaymarketcap",2000000000]), EqyQy("is-in", ["exchange", "NMS", "NYQ"])])}, - 'undervalued_growth_stocks': {"sortType":"DESC", "sortField":"eodvolume", - "query": EqyQy('and', [EqyQy('btwn', ['peratio.lasttwelvemonths', 0, 20]), EqyQy('lt', ['pegratio_5y', 1]), EqyQy('gte', ['epsgrowth.lasttwelvemonths', 25]), EqyQy('is-in', ['exchange', 'NMS', 'NYQ'])])}, - 'undervalued_large_caps': {"sortField":"eodvolume", "sortType":"desc", - "query": EqyQy('and', [EqyQy('btwn', ['peratio.lasttwelvemonths', 0, 20]), EqyQy('lt', ['pegratio_5y', 1]), EqyQy('btwn', ['intradaymarketcap', 10000000000, 100000000000]), EqyQy('is-in', ['exchange', 'NMS', 'NYQ'])])}, - 'conservative_foreign_funds': {"sortType":"DESC", "sortField":"fundnetassets", - "query": FndQy('and', [FndQy('is-in', ['categoryname', 'Foreign Large Value', 'Foreign Large Blend', 'Foreign Large Growth', 'Foreign Small/Mid Growth', 'Foreign Small/Mid Blend', 'Foreign Small/Mid Value']), FndQy('is-in', ['performanceratingoverall', 4, 5]), FndQy('lt', ['initialinvestment', 100001]), FndQy('lt', ['annualreturnnavy1categoryrank', 50]), FndQy('is-in', ['riskratingoverall', 1, 2, 3]), FndQy('eq', ['exchange', 'NAS'])])}, - 'high_yield_bond': {"sortType":"DESC", "sortField":"fundnetassets", - "query": FndQy('and', [FndQy('is-in', ['performanceratingoverall', 4, 5]), FndQy('lt', ['initialinvestment', 100001]), FndQy('lt', ['annualreturnnavy1categoryrank', 50]), FndQy('is-in', ['riskratingoverall', 1, 2, 3]), FndQy('eq', ['categoryname', 'High Yield Bond']), FndQy('eq', ['exchange', 'NAS'])])}, - 'portfolio_anchors': {"sortType":"DESC", "sortField":"fundnetassets", - "query": FndQy('and', [FndQy('eq', ['categoryname', 'Large Blend']), FndQy('is-in', ['performanceratingoverall', 4, 5]), FndQy('lt', ['initialinvestment', 100001]), FndQy('lt', ['annualreturnnavy1categoryrank', 50]), FndQy('eq', ['exchange', 'NAS'])])}, - 'solid_large_growth_funds': {"sortType":"DESC", "sortField":"fundnetassets", - "query": FndQy('and', [FndQy('eq', ['categoryname', 'Large Growth']), FndQy('is-in', ['performanceratingoverall', 4, 5]), FndQy('lt', ['initialinvestment', 100001]), FndQy('lt', ['annualreturnnavy1categoryrank', 50]), FndQy('eq', ['exchange', 'NAS'])])}, - 'solid_midcap_growth_funds': {"sortType":"DESC", "sortField":"fundnetassets", - "query": FndQy('and', [FndQy('eq', ['categoryname', 'Mid-Cap Growth']), FndQy('is-in', ['performanceratingoverall', 4, 5]), FndQy('lt', ['initialinvestment', 100001]), FndQy('lt', ['annualreturnnavy1categoryrank', 50]), FndQy('eq', ['exchange', 'NAS'])])}, - 'top_mutual_funds': {"sortType":"DESC", "sortField":"percentchange", - "query": FndQy('and', [FndQy('gt', ['intradayprice', 15]), FndQy('is-in', ['performanceratingoverall', 4, 5]), FndQy('gt', ['initialinvestment', 1000]), FndQy('eq', ['exchange', 'NAS'])])} -} - -@dynamic_docstring({"predefined_screeners": generate_list_table_from_dict_universal(PREDEFINED_SCREENER_QUERIES, bullets=True, title='Predefined queries (Dec-2024)')}) -def screen(query: Union[str, EquityQuery, FundQuery], - offset: int = None, - size: int = None, - sortField: str = None, - sortAsc: bool = None, - userId: str = None, - userIdType: str = None, - session = None, proxy = None): - """ - Run a screen: predefined query, or custom query. - - :Parameters: - * Defaults only apply if query = EquityQuery or FundQuery - query : str | Query: - The query to execute, either name of predefined or custom query. - For predefined list run yf.PREDEFINED_SCREENER_QUERIES.keys() - offset : int - The offset for the results. Default 0. - size : int - number of results to return. Default 100, maximum 250 (Yahoo) - sortField : str - field to sort by. Default "ticker" - sortAsc : bool - Sort ascending? Default False - userId : str - The user ID. Default empty. - userIdType : str - Type of user ID (e.g., "guid"). Default "guid". - - Example: predefined query - .. code-block:: python - - import yfinance as yf - response = yf.screen("aggressive_small_caps") - - Example: custom query - .. code-block:: python - - import yfinance as yf - from yfinance import EquityQuery - q = EquityQuery('and', [ - EquityQuery('gt', ['percentchange', 3]), - EquityQuery('eq', ['region', 'us']) - ]) - response = yf.screen(q, sortField = 'percentchange', sortAsc = True) - - To access predefineds query code - .. code-block:: python - - import yfinance as yf - query = yf.PREDEFINED_SCREENER_QUERIES['aggressive_small_caps'] - - {predefined_screeners} + +class Screener: """ + The `Screener` class is used to execute the queries and return the filtered results. - # Only use defaults when user NOT give a predefined, because - # Yahoo's predefined endpoint auto-applies defaults. Also, - # that endpoint might be ignoring these fields. - defaults = { - 'offset': 0, - 'size': 25, - 'sortField': 'ticker', - 'sortAsc': False, - 'userId': "", - 'userIdType': "guid" - } - - if size is not None and size > 250: - raise ValueError("Yahoo limits query size to 250, reduce size.") - - fields = dict(locals()) - for k in ['query', 'session', 'proxy']: - if k in fields: - del fields[k] - - params_dict = {"corsDomain": "finance.yahoo.com", "formatted": "false", "lang": "en-US", "region": "US"} - - post_query = None - if isinstance(query, str): - # post_query = PREDEFINED_SCREENER_QUERIES[query] - # Switch to Yahoo's predefined endpoint - _data = YfData(session=session) - params_dict['scrIds'] = query - for k,v in fields.items(): - if v is not None: - params_dict[k] = v - resp = _data.get(url=_PREDEFINED_URL_, params=params_dict, proxy=proxy) + The Screener class provides methods to set and manipulate the body of a screener request, + fetch and parse the screener results, and access predefined screener bodies. + """ + def __init__(self, session=None, proxy=None): + """ + Args: + session (requests.Session, optional): A requests session object to be used for making HTTP requests. Defaults to None. + proxy (str, optional): A proxy URL to be used for making HTTP requests. Defaults to None. + + .. seealso:: + + :attr:`Screener.predefined_bodies ` + supported predefined screens + """ + self.proxy = proxy + self.session = session + + self._data: YfData = YfData(session=session) + self._body: Dict = {} + self._response: Dict = {} + self._body_updated = False + self._accepted_body_keys = {"offset","size","sortField","sortType","quoteType","query","userId","userIdType"} + self._predefined_bodies = PREDEFINED_SCREENER_BODY_MAP.keys() + + @property + def body(self) -> Dict: + return self._body + + @property + def response(self) -> Dict: + """ + Fetch screen result + + Example: + + .. code-block:: python + + result = screener.response + symbols = [quote['symbol'] for quote in result['quotes']] + """ + if self._body_updated or self._response is None: + self._fetch_and_parse() + + self._body_updated = False + return self._response + + @dynamic_docstring({"predefined_screeners": generate_list_table_from_dict_of_dict(PREDEFINED_SCREENER_BODY_MAP,bullets=False)}) + @property + def predefined_bodies(self) -> Dict: + """ + Predefined Screeners + {predefined_screeners} + """ + return self._predefined_bodies + + def set_default_body(self, query: Query, offset: int = 0, size: int = 100, sortField: str = "ticker", sortType: str = "desc", quoteType: str = "equity", userId: str = "", userIdType: str = "guid") -> 'Screener': + """ + Set the default body using a custom query. + + Args: + query (Query): The Query object to set as the body. + offset (Optional[int]): The offset for the results. Defaults to 0. + size (Optional[int]): The number of results to return. Defaults to 100. Maximum is 250 as set by Yahoo. + sortField (Optional[str]): The field to sort the results by. Defaults to "ticker". + sortType (Optional[str]): The type of sorting (e.g., "asc" or "desc"). Defaults to "desc". + quoteType (Optional[str]): The type of quote (e.g., "equity"). Defaults to "equity". + userId (Optional[str]): The user ID. Defaults to an empty string. + userIdType (Optional[str]): The type of user ID (e.g., "guid"). Defaults to "guid". + + Returns: + Screener: self + + Example: + + .. code-block:: python + + screener.set_default_body(qf) + """ + self._body_updated = True + + self._body = { + "offset": offset, + "size": size, + "sortField": sortField, + "sortType": sortType, + "quoteType": quoteType, + "query": query.to_dict(), + "userId": userId, + "userIdType": userIdType + } + return self + + def set_predefined_body(self, predefined_key: str) -> 'Screener': + """ + Set a predefined body + + Args: + predefined_key (str): key to one of predefined screens + + Returns: + Screener: self + + Example: + + .. code-block:: python + + screener.set_predefined_body('day_gainers') + + + .. seealso:: + + :attr:`Screener.predefined_bodies ` + supported predefined screens + """ + body = PREDEFINED_SCREENER_BODY_MAP.get(predefined_key, None) + if not body: + raise ValueError(f'Invalid key {predefined_key} provided for predefined screener') + + self._body_updated = True + self._body = body + return self + + def set_body(self, body: Dict) -> 'Screener': + """ + Set the fully custom body using dictionary input + + Args: + body (Dict): full query body + + Returns: + Screener: self + + Example: + + .. code-block:: python + + screener.set_body({ + "offset": 0, + "size": 100, + "sortField": "ticker", + "sortType": "desc", + "quoteType": "equity", + "query": qf.to_dict(), + "userId": "", + "userIdType": "guid" + }) + """ + missing_keys = [key for key in self._accepted_body_keys if key not in body] + if missing_keys: + raise ValueError(f"Missing required keys in body: {missing_keys}") + + extra_keys = [key for key in body if key not in self._accepted_body_keys] + if extra_keys: + raise ValueError(f"Body contains extra keys: {extra_keys}") + + self._body_updated = True + self._body = body + return self + + def patch_body(self, values: Dict) -> 'Screener': + """ + Patch parts of the body using dictionary input + + Args: + body (Dict): partial query body + + Returns: + Screener: self + + Example: + + .. code-block:: python + + screener.patch_body({"offset": 100}) + """ + extra_keys = [key for key in values if key not in self._accepted_body_keys] + if extra_keys: + raise ValueError(f"Body contains extra keys: {extra_keys}") + + self._body_updated = True + for k in values: + self._body[k] = values[k] + return self + + def _validate_body(self) -> None: + if not all(k in self._body for k in self._accepted_body_keys): + raise ValueError("Missing required keys in body") + + if self._body["size"] > 250: + raise ValueError("Yahoo limits query size to 250. Please decrease the size of the query.") + + def _fetch(self) -> Dict: + params_dict = {"corsDomain": "finance.yahoo.com", "formatted": "false", "lang": "en-US", "region": "US"} + response = self._data.post(_SCREENER_URL_, body=self.body, user_agent_headers=self._data.user_agent_headers, params=params_dict, proxy=self.proxy) + response.raise_for_status() + return response.json() + + def _fetch_and_parse(self) -> None: + response = None + self._validate_body() + try: - resp.raise_for_status() - except requests.exceptions.HTTPError: - if query not in PREDEFINED_SCREENER_QUERIES: - print(f"yfinance.screen: '{query}' is probably not a predefined query.") - raise - return resp.json()["finance"]["result"][0] - - elif isinstance(query, QueryBase): - # Prepare other fields - for k in defaults: - if k not in fields or fields[k] is None: - fields[k] = defaults[k] - fields['sortType'] = 'ASC' if fields['sortAsc'] else 'DESC' - del fields['sortAsc'] - - post_query = fields - post_query['query'] = query - - else: - raise ValueError(f'Query must be type str or QueryBase, not "{type(query)}"') - - if query is None: - raise ValueError('No query provided') - - if isinstance(post_query['query'], EqyQy): - post_query['quoteType'] = 'EQUITY' - elif isinstance(post_query['query'], FndQy): - post_query['quoteType'] = 'MUTUALFUND' - post_query['query'] = post_query['query'].to_dict() - - # Fetch - _data = YfData(session=session) - response = _data.post(_SCREENER_URL_, - body=post_query, - user_agent_headers=_data.user_agent_headers, - params=params_dict, - proxy=proxy) - response.raise_for_status() - return response.json()['finance']['result'][0] + response = self._fetch() + self._response = response['finance']['result'][0] + except Exception as e: + logger = utils.get_yf_logger() + logger.error(f"Failed to get screener data for '{self._body.get('query', 'query not set')}' reason: {e}") + logger.debug("Got response: ") + logger.debug("-------------") + logger.debug(f" {response}") + logger.debug("-------------") diff --git a/yfinance/screener/screener_query.py b/yfinance/screener/screener_query.py new file mode 100644 index 000000000..65c937591 --- /dev/null +++ b/yfinance/screener/screener_query.py @@ -0,0 +1,145 @@ +from abc import ABC, abstractmethod +import numbers +from typing import List, Union, Dict + +from yfinance.const import EQUITY_SCREENER_EQ_MAP, EQUITY_SCREENER_FIELDS +from yfinance.exceptions import YFNotImplementedError +from ..utils import dynamic_docstring, generate_list_table_from_dict + +class Query(ABC): + def __init__(self, operator: str, operand: Union[numbers.Real, str, List['Query']]): + self.operator = operator + self.operands = operand + + @abstractmethod + def to_dict(self) -> Dict: + raise YFNotImplementedError('to_dict() needs to be implemented by children classes') + +class EquityQuery(Query): + """ + The `EquityQuery` class constructs filters for stocks based on specific criteria such as region, sector, exchange, and peer group. + + The queries support operators: `GT` (greater than), `LT` (less than), `BTWN` (between), `EQ` (equals), and logical operators `AND` and `OR` for combining multiple conditions. + + Example: + Screen for stocks where the end-of-day price is greater than 3. + + .. code-block:: python + + gt = yf.EquityQuery('gt', ['eodprice', 3]) + + Screen for stocks where the average daily volume over the last 3 months is less than a very large number. + + .. code-block:: python + + lt = yf.EquityQuery('lt', ['avgdailyvol3m', 99999999999]) + + Screen for stocks where the intraday market cap is between 0 and 100 million. + + .. code-block:: python + + btwn = yf.EquityQuery('btwn', ['intradaymarketcap', 0, 100000000]) + + Screen for stocks in the Technology sector. + + .. code-block:: python + + eq = yf.EquityQuery('eq', ['sector', 'Technology']) + + Combine queries using AND/OR. + + .. code-block:: python + + qt = yf.EquityQuery('and', [gt, lt]) + qf = yf.EquityQuery('or', [qt, btwn, eq]) + """ + def __init__(self, operator: str, operand: Union[numbers.Real, str, List['EquityQuery']]): + """ + .. seealso:: + + :attr:`EquityQuery.valid_operand_fields ` + supported operand values for query + :attr:`EquityQuery.valid_eq_operand_map ` + supported `EQ query operand parameters` + """ + operator = operator.upper() + + if not isinstance(operand, list): + raise TypeError('Invalid operand type') + if len(operand) <= 0: + raise ValueError('Invalid field for Screener') + + if operator in {'OR','AND'}: + self._validate_or_and_operand(operand) + elif operator == 'EQ': + self._validate_eq_operand(operand) + elif operator == 'BTWN': + self._validate_btwn_operand(operand) + elif operator in {'GT','LT'}: + self._validate_gt_lt(operand) + else: + raise ValueError('Invalid Operator Value') + + self.operator = operator + self.operands = operand + self._valid_eq_operand_map = EQUITY_SCREENER_EQ_MAP + self._valid_operand_fields = EQUITY_SCREENER_FIELDS + + @dynamic_docstring({"valid_eq_operand_map_table": generate_list_table_from_dict(EQUITY_SCREENER_EQ_MAP)}) + @property + def valid_eq_operand_map(self) -> Dict: + """ + Valid Operand Map for Operator "EQ" + {valid_eq_operand_map_table} + """ + return self._valid_eq_operand_map + + @dynamic_docstring({"valid_operand_fields_table": generate_list_table_from_dict(EQUITY_SCREENER_FIELDS)}) + @property + def valid_operand_fields(self) -> Dict: + """ + Valid Operand Fields + {valid_operand_fields_table} + """ + return self._valid_operand_fields + + def _validate_or_and_operand(self, operand: List['EquityQuery']) -> None: + if len(operand) <= 1: + raise ValueError('Operand must be length longer than 1') + if all(isinstance(e, EquityQuery) for e in operand) is False: + raise TypeError('Operand must be type EquityQuery for OR/AND') + + def _validate_eq_operand(self, operand: List[Union[str, numbers.Real]]) -> None: + if len(operand) != 2: + raise ValueError('Operand must be length 2 for EQ') + + if not any(operand[0] in fields_by_type for fields_by_type in EQUITY_SCREENER_FIELDS.values()): + raise ValueError('Invalid field for Screener') + if operand[0] not in EQUITY_SCREENER_EQ_MAP: + raise ValueError('Invalid EQ key') + if operand[1] not in EQUITY_SCREENER_EQ_MAP[operand[0]]: + raise ValueError('Invalid EQ value') + + def _validate_btwn_operand(self, operand: List[Union[str, numbers.Real]]) -> None: + if len(operand) != 3: + raise ValueError('Operand must be length 3 for BTWN') + if not any(operand[0] in fields_by_type for fields_by_type in EQUITY_SCREENER_FIELDS.values()): + raise ValueError('Invalid field for Screener') + if isinstance(operand[1], numbers.Real) is False: + raise TypeError('Invalid comparison type for BTWN') + if isinstance(operand[2], numbers.Real) is False: + raise TypeError('Invalid comparison type for BTWN') + + def _validate_gt_lt(self, operand: List[Union[str, numbers.Real]]) -> None: + if len(operand) != 2: + raise ValueError('Operand must be length 2 for GT/LT') + if not any(operand[0] in fields_by_type for fields_by_type in EQUITY_SCREENER_FIELDS.values()): + raise ValueError('Invalid field for Screener') + if isinstance(operand[1], numbers.Real) is False: + raise TypeError('Invalid comparison type for GT/LT') + + def to_dict(self) -> Dict: + return { + "operator": self.operator, + "operands": [operand.to_dict() if isinstance(operand, EquityQuery) else operand for operand in self.operands] + } \ No newline at end of file diff --git a/yfinance/utils.py b/yfinance/utils.py index 201e98789..a3493fc67 100644 --- a/yfinance/utils.py +++ b/yfinance/utils.py @@ -954,12 +954,10 @@ def decorator(func): return func return decorator -def _generate_table_configurations(title = None) -> str: +def _generate_table_configurations() -> str: import textwrap - if title is None: - title = "Permitted Keys/Values" - table = textwrap.dedent(f""" - .. list-table:: {title} + table = textwrap.dedent(""" + .. list-table:: Permitted Keys/Values :widths: 25 75 :header-rows: 1 @@ -969,134 +967,34 @@ def _generate_table_configurations(title = None) -> str: return table -def generate_list_table_from_dict(data: dict, bullets: bool=True, title: str=None) -> str: +def generate_list_table_from_dict(data: dict, bullets: bool=True) -> str: """ Generate a list-table for the docstring showing permitted keys/values. """ - table = _generate_table_configurations(title) - for k in sorted(data.keys()): - values = data[k] - table += ' '*3 + f"* - {k}\n" - lengths = [len(str(v)) for v in values] - if bullets and max(lengths) > 5: - table += ' '*5 + "-\n" + table = _generate_table_configurations() + for key, values in data.items(): + value_str = ', '.join(sorted(values)) + table += f" * - {key}\n" + if bullets: + table += " -\n" for value in sorted(values): - table += ' '*7 + f"- {value}\n" + table += f" - {value}\n" else: - value_str = ', '.join(sorted(values)) - table += ' '*5 + f"- {value_str}\n" + table += f" - {value_str}\n" return table -# def generate_list_table_from_dict_of_dict(data: dict, bullets: bool=True, title: str=None) -> str: -# """ -# Generate a list-table for the docstring showing permitted keys/values. -# """ -# table = _generate_table_configurations(title) -# for k in sorted(data.keys()): -# values = data[k] -# table += ' '*3 + f"* - {k}\n" -# if bullets: -# table += ' '*5 + "-\n" -# for value in sorted(values): -# table += ' '*7 + f"- {value}\n" -# else: -# table += ' '*5 + f"- {values}\n" -# return table - - -def generate_list_table_from_dict_universal(data: dict, bullets: bool=True, title: str=None, concat_keys=[]) -> str: +def generate_list_table_from_dict_of_dict(data: dict, bullets: bool=True) -> str: """ Generate a list-table for the docstring showing permitted keys/values. """ - table = _generate_table_configurations(title) - for k in data.keys(): - values = data[k] - - table += ' '*3 + f"* - {k}\n" - if isinstance(values, dict): - table_add = '' - - concat_short_lines = k in concat_keys - - if bullets: - k_keys = sorted(list(values.keys())) - current_line = '' - block_format = 'query' in k_keys - for i in range(len(k_keys)): - k2 = k_keys[i] - k2_values = values[k2] - k2_values_str = None - if isinstance(k2_values, set): - k2_values = list(k2_values) - elif isinstance(k2_values, dict) and len(k2_values) == 0: - k2_values = [] - if isinstance(k2_values, list): - k2_values = sorted(k2_values) - all_scalar = all(isinstance(k2v, (int, float, str)) for k2v in k2_values) - if all_scalar: - k2_values_str = _re.sub(r"[{}\[\]']", "", str(k2_values)) - - if k2_values_str is None: - k2_values_str = str(k2_values) - - if len(current_line) > 0 and (len(current_line) + len(k2_values_str) > 40): - # new line - table_add += current_line + '\n' - current_line = '' - - if concat_short_lines: - if current_line == '': - current_line += ' '*5 - if i == 0: - # Only add dash to first - current_line += "- " - else: - current_line += " " - # Don't draw bullet points: - current_line += '| ' - else: - current_line += '. ' - current_line += f"{k2}: " + k2_values_str - else: - table_add += ' '*5 - if i == 0: - # Only add dash to first - table_add += "- " - else: - table_add += " " - - if '\n' in k2_values_str: - # Block format multiple lines - table_add += '| ' + f"{k2}: " + "\n" - k2_values_str_lines = k2_values_str.split('\n') - for j in range(len(k2_values_str_lines)): - line = k2_values_str_lines[j] - table_add += ' '*7 + '|' + ' '*5 + line - if j < len(k2_values_str_lines)-1: - table_add += "\n" - else: - if block_format: - table_add += '| ' - else: - table_add += '* ' - table_add += f"{k2}: " + k2_values_str - - table_add += "\n" - if current_line != '': - table_add += current_line + '\n' - else: - table_add += ' '*5 + f"- {values}\n" - - table += table_add - + table = _generate_table_configurations() + for key, values in data.items(): + value_str = values + table += f" * - {key}\n" + if bullets: + table += " -\n" + for value in sorted(values): + table += f" - {value}\n" else: - lengths = [len(str(v)) for v in values] - if bullets and max(lengths) > 5: - table += ' '*5 + "-\n" - for value in sorted(values): - table += ' '*7 + f"- {value}\n" - else: - value_str = ', '.join(sorted(values)) - table += ' '*5 + f"- {value_str}\n" - - return table + table += f" - {value_str}\n" + return table \ No newline at end of file diff --git a/yfinance/version.py b/yfinance/version.py index fb18d1d94..8142a0d90 100644 --- a/yfinance/version.py +++ b/yfinance/version.py @@ -1 +1 @@ -version = "0.2.54" +version = "0.2.51" From 2e494e5cbca44170a60ca66bbbc0228585e81025 Mon Sep 17 00:00:00 2001 From: R5dan Date: Tue, 25 Feb 2025 12:41:23 +0000 Subject: [PATCH 15/15] Update Remove SearchCache --- yfinance/search.py | 118 +++++++++++++++++---------------------------- 1 file changed, 45 insertions(+), 73 deletions(-) diff --git a/yfinance/search.py b/yfinance/search.py index 5ae1c607a..d6d0e5fd8 100644 --- a/yfinance/search.py +++ b/yfinance/search.py @@ -24,73 +24,8 @@ from . import utils from .const import _BASE_URL_ from .data import YfData -from typing import TypedDict -import typing as t - -SEARCH_CACHE = TypedDict('SEARCH_CACHE', { - "query": str, - "fields": list[str], - "results": dict -}) - -class SearchCache: - data = YfData() - logger = utils.get_yf_logger() - def __init__(self): - self.cache = {} - - def get(self, query:'tuple[str, list[str]]') -> 't.Union[dict, None]': - if query in self.cache: - return self.cache[query] - return None - - def set(self, query:'tuple[str, list[str]]', data:'dict') -> 'None': - self.cache[query] = data - - def fetch(self, query:'str', fields:'list[str]', session=None, proxy=None, timeout=30, **kwargs:'dict') -> 'dict': - if res := self.get((query, fields)): - return res - - params = { - "q": query, - "enableFuzzyQuery": "enable_fuzzy_query" in fields, - "quotesQueryId": "tss_match_phrase_query", - "newsQueryId": "news_cie_vespa", - "enableCb": "cb" in fields, - "enableNavLinks": "nav_links" in fields, - "enableResearchReports": "research" in fields, - "enableCulturalAssets": "cultural_assets" in fields, - } - - - if "quotes" in fields: - params["quotesCount"] = kwargs.get("max_results", 8) - params["recommendedCount"] = kwargs.get("recommended", 8) - if "news" in fields: - params["newsCount"] = kwargs.get("news_count", 8) - if "lists" in fields: - params["listsCount"] = kwargs.get("lists_count", 8) - - url = f"{_BASE_URL_}/v1/finance/search" - data = self.data.cache_get(url=url, params=params, proxy=proxy, timeout=timeout, session=session) - if data is None or "Will be right back" in data.text: - raise RuntimeError("*** YAHOO! FINANCE IS CURRENTLY DOWN! ***\n" - "Our engineers are working quickly to resolve " - "the issue. Thank you for your patience.") - try: - data = data.json() - self.set((query, fields), data) - except _json.JSONDecodeError: - self.logger.error(f"{query}: Failed to retrieve search results and received faulty response instead.") - data = {} - return data - - - - class Search: - cache = SearchCache() def __init__(self, query, max_results=8, news_count=8, lists_count=8, include_cb=True, include_nav_links=False, include_research=False, include_cultural_assets=False, enable_fuzzy_query=False, recommended=8, session=None, proxy=None, timeout=30, raise_errors=True): @@ -130,8 +65,6 @@ def __init__(self, query, max_results=8, news_count=8, lists_count=8, include_cb self.enable_cultural_assets = include_cultural_assets self.recommended = recommended - self._logger = utils.get_yf_logger() - self._response = {} self._all = {} self._quotes = [] @@ -140,13 +73,52 @@ def __init__(self, query, max_results=8, news_count=8, lists_count=8, include_cb self._research = [] self._nav = [] + self._data = YfData() + self._logger = utils.get_yf_logger() + + self.search() + def fetch(self, query:'str', fields:'list[str]', session=None, proxy=None, timeout=30, **kwargs:'dict') -> 'dict': + params = { + "q": query, + "enableFuzzyQuery": "enable_fuzzy_query" in fields, + "quotesQueryId": "tss_match_phrase_query", + "newsQueryId": "news_cie_vespa", + "enableCb": "cb" in fields, + "enableNavLinks": "nav_links" in fields, + "enableResearchReports": "research" in fields, + "enableCulturalAssets": "cultural_assets" in fields, + } + + + if "quotes" in fields: + params["quotesCount"] = kwargs.get("max_results", 8) + params["recommendedCount"] = kwargs.get("recommended", 8) + if "news" in fields: + params["newsCount"] = kwargs.get("news_count", 8) + if "lists" in fields: + params["listsCount"] = kwargs.get("lists_count", 8) + + url = f"{_BASE_URL_}/v1/finance/search" + data = self._data.cache_get(url=url, params=params, proxy=proxy, timeout=timeout, session=session) + if data is None or "Will be right back" in data.text: + raise RuntimeError("*** YAHOO! FINANCE IS CURRENTLY DOWN! ***\n" + "Our engineers are working quickly to resolve " + "the issue. Thank you for your patience.") + try: + data = data.json() + except _json.JSONDecodeError: + self._logger.error(f"{query}: Failed to retrieve search results and received faulty response instead.") + data = {} + return data + + def search(self) -> 'Search': """Search using the query parameters defined in the constructor.""" self._logger.debug(f'{self.query}: Fields: {self.fields}') - data = self.cache.fetch(self.query, self.fields, session=self.session, proxy=self.proxy, timeout=self.timeout) + data = self.fetch(self.query, self.fields, session=self.session, proxy=self.proxy, timeout=self.timeout) self._response = data # Filter quotes to only include symbols @@ -171,7 +143,7 @@ def search(self) -> 'Search': def search_quotes(self) -> 'list': """Search using the query parameters defined in the constructor, but only return the quotes.""" self._logger.debug(f'{self.query}: Fields: [quotes]') - data = self.cache.fetch(self.query, ["quotes"], session=self.session, proxy=self.proxy, timeout=self.timeout) + data = self.fetch(self.query, ["quotes"], session=self.session, proxy=self.proxy, timeout=self.timeout) self._quotes = data.get("quotes", []) self._response = data @@ -181,7 +153,7 @@ def search_quotes(self) -> 'list': def search_news(self) -> 'list': """Search using the query parameters defined in the constructor, but only return the news.""" self._logger.debug(f'{self.query}: Fields: [news]') - data = self.cache.fetch(self.query, ["news"], session=self.session, proxy=self.proxy, timeout=self.timeout) + data = self.fetch(self.query, ["news"], session=self.session, proxy=self.proxy, timeout=self.timeout) self._news = data.get("news", []) self._response = data @@ -191,7 +163,7 @@ def search_news(self) -> 'list': def search_lists(self) -> 'list': """Search using the query parameters defined in the constructor, but only return the lists.""" self._logger.debug(f'{self.query}: Fields: [lists]') - data = self.cache.fetch(self.query, ["lists"], session=self.session, proxy=self.proxy, timeout=self.timeout) + data = self.fetch(self.query, ["lists"], session=self.session, proxy=self.proxy, timeout=self.timeout) self._lists = data.get("lists", []) self._response = data @@ -201,7 +173,7 @@ def search_lists(self) -> 'list': def search_research(self) -> 'list': """Search using the query parameters defined in the constructor, but only return the research reports.""" self._logger.debug(f'{self.query}: Fields: [research]') - data = self.cache.fetch(self.query, ["research"], session=self.session, proxy=self.proxy, timeout=self.timeout) + data = self.fetch(self.query, ["research"], session=self.session, proxy=self.proxy, timeout=self.timeout) self._research = data.get("researchReports", []) self._response = data @@ -211,7 +183,7 @@ def search_research(self) -> 'list': def search_nav(self) -> 'list': """Search using the query parameters defined in the constructor, but only return the navigation links.""" self._logger.debug(f'{self.query}: Fields: [nav]') - data = self.cache.fetch(self.query, ["nav"], session=self.session, proxy=self.proxy, timeout=self.timeout) + data = self.fetch(self.query, ["nav"], session=self.session, proxy=self.proxy, timeout=self.timeout) self._nav = data.get("nav", []) self._response = data