Repository: ranaroussi/yfinance

Issue:
Found code that will always fail in silence
See:
[Complementary key-statistics code](https://github.com/ranaroussi/yfinance/blob/dev/yfinance/base.py#L860-L864)

This code references variable named `ticker` (should probably be `self.ticker`) that is not defined and will trigger exception:
But as the code is surrounded by a try/except that silences all exceptions it is probably never noticed more than the functionality not working as expected.

Note: Code exists in both main and dev branches but at different location.

```
        # Complementary key-statistics (currently fetching the important trailingPegRatio which is the value shown in the website)
        res = {}
        try:
            my_headers = {'user-agent': 'curl/7.55.1', 'accept': 'application/json', 'content-type': 'application/json',
                          'referer': 'https://finance.yahoo.com/', 'cache-control': 'no-cache', 'connection': 'close'}
            p = _re.compile(r'root\.App\.main = (.*);')
            r = _requests.session().get('https://finance.yahoo.com/quote/{}/key-statistics?p={}'.format(self.ticker,
                                                                                                        self.ticker), headers=my_headers)
            q_results = {}
            my_qs_keys = ['pegRatio']  # QuoteSummaryStore
            # , 'quarterlyPegRatio']  # QuoteTimeSeriesStore
            my_ts_keys = ['trailingPegRatio']

            # Complementary key-statistics
            data = _json.loads(p.findall(r.text)[0])
            key_stats = data['context']['dispatcher']['stores']['QuoteTimeSeriesStore']
            q_results.setdefault(self.ticker, [])
            for i in my_ts_keys:
                # j=0
                try:
                    # res = {i: key_stats['timeSeries'][i][1]['reportedValue']['raw']}
                    # We need to loop over multiple items, if they exist: 0,1,2,..
                    zzz = key_stats['timeSeries'][i]
                    for j in range(len(zzz)):
                        if key_stats['timeSeries'][i][j]:
                            res = {i: key_stats['timeSeries']
                                   [i][j]['reportedValue']['raw']}
                            q_results[self.ticker].append(res)

                # print(res)
                # q_results[ticker].append(res)
                except:
                    q_results[ticker].append({i: np.nan})

            res = {'Company': ticker}
            q_results[ticker].append(res)
        except Exception:
            pass
```


Discussion:
Found another issue with the code, `np` is never imported so this will be need to be fixed as well.
```
q_results[ticker].append({i: np.nan})
```
@ValueRaider the silenced exception is intentional 
@asafravid Sorry I deleted my last message, wanted to rephrase. The PR was #911

Why is the logic to retrieve 'trailingPegRatio' so complicated? Why not just lookup with `key_stats["timeSeries"]["trailingPegRatio"][0]["reportedValue"]["raw"]`
@ValueRaider There was a whole investigation about the “why”
See the linked issue which this PR resolved which you can read in #903 
@ValueRaider if the raw contains the same as the extended code then agree - but didn’t check this. The actual code fix was contributed by @eabase
Thanks @asafravid.

@fredrik-corneliusson You're right about the silent error, but this triggered after the useful work was done (retrieving 'trailingPegRatio in loop') so no one noticed.

Resolving patch:
diff --git a/yfinance/base.py b/yfinance/base.py
--- a/yfinance/base.py
+++ b/yfinance/base.py
@@ -712,6 +712,50 @@ def _get_info(self, proxy=None):
         except Exception:
             pass
 
+        # Complementary key-statistics. For now just want 'trailing PEG ratio'
+        session = self.session or _requests
+        keys = {"trailingPegRatio"}
+        if len(keys)>0:
+            # Simplified the original scrape code for key-statistics. Very expensive for fetching
+            # just one value, best if scraping most/all:
+            #
+            # p = _re.compile(r'root\.App\.main = (.*);')
+            # url = 'https://finance.yahoo.com/quote/{}/key-statistics?p={}'.format(self.ticker, self.ticker)
+            # try:
+            #     r = session.get(url, headers=utils.user_agent_headers)
+            #     data = _json.loads(p.findall(r.text)[0])
+            #     key_stats = data['context']['dispatcher']['stores']['QuoteTimeSeriesStore']["timeSeries"]
+            #     for k in keys:
+            #         if k not in key_stats or len(key_stats[k])==0:
+            #             # Yahoo website prints N/A, indicates Yahoo lacks necessary data to calculate
+            #             v = None
+            #         else:
+            #             # Select most recent (last) raw value in list:
+            #             v = key_stats[k][-1]["reportedValue"]["raw"]
+            #         self._info[k] = v
+            # except Exception:
+            #     raise
+            #     pass
+            #
+            # For just one/few variable is faster to query directly:
+            url = "https://query1.finance.yahoo.com/ws/fundamentals-timeseries/v1/finance/timeseries/{}?symbol={}".format(self.ticker, self.ticker)
+            for k in keys:
+                url += "&type="+k
+            # Request 6 months of data
+            url += "&period1={}".format(int((_datetime.datetime.now()-_datetime.timedelta(days=365//2)).timestamp()))
+            url += "&period2={}".format(int((_datetime.datetime.now()+_datetime.timedelta(days=1)).timestamp()))
+            json_str = session.get(url=url, proxies=proxy, headers=utils.user_agent_headers).text
+            json_data = _json.loads(json_str)
+            key_stats = json_data["timeseries"]["result"][0]
+            if k not in key_stats:
+                # Yahoo website prints N/A, indicates Yahoo lacks necessary data to calculate
+                v = None
+            else:
+                # Select most recent (last) raw value in list:
+                v = key_stats[k][-1]["reportedValue"]["raw"]
+            self._info[k] = v
+
+
     def _get_fundamentals(self, proxy=None):
         def cleanup(data):
             '''
@@ -860,48 +904,6 @@ def cleanup(data):
             except Exception:
                 pass
 
-        # Complementary key-statistics (currently fetching the important trailingPegRatio which is the value shown in the website)
-        res = {}
-        try:
-            my_headers = {'user-agent': 'curl/7.55.1', 'accept': 'application/json', 'content-type': 'application/json',
-                          'referer': 'https://finance.yahoo.com/', 'cache-control': 'no-cache', 'connection': 'close'}
-            p = _re.compile(r'root\.App\.main = (.*);')
-            r = _requests.session().get('https://finance.yahoo.com/quote/{}/key-statistics?p={}'.format(self.ticker,
-                                                                                                        self.ticker), headers=my_headers)
-            q_results = {}
-            my_qs_keys = ['pegRatio']  # QuoteSummaryStore
-            # , 'quarterlyPegRatio']  # QuoteTimeSeriesStore
-            my_ts_keys = ['trailingPegRatio']
-
-            # Complementary key-statistics
-            data = _json.loads(p.findall(r.text)[0])
-            key_stats = data['context']['dispatcher']['stores']['QuoteTimeSeriesStore']
-            q_results.setdefault(self.ticker, [])
-            for i in my_ts_keys:
-                # j=0
-                try:
-                    # res = {i: key_stats['timeSeries'][i][1]['reportedValue']['raw']}
-                    # We need to loop over multiple items, if they exist: 0,1,2,..
-                    zzz = key_stats['timeSeries'][i]
-                    for j in range(len(zzz)):
-                        if key_stats['timeSeries'][i][j]:
-                            res = {i: key_stats['timeSeries']
-                                   [i][j]['reportedValue']['raw']}
-                            q_results[self.ticker].append(res)
-
-                # print(res)
-                # q_results[ticker].append(res)
-                except:
-                    q_results[ticker].append({i: np.nan})
-
-            res = {'Company': ticker}
-            q_results[ticker].append(res)
-        except Exception:
-            pass
-
-        if 'trailingPegRatio' in res:
-            self._info['trailingPegRatio'] = res['trailingPegRatio']
-
         # Analysis Data/Analyst Forecasts
         try:
             analysis_data = utils.get_json_data_stores(ticker_url+'/analysis',proxy,self.session)


Test patch: