Skip to content

Commit e329f26

Browse files
committed
Fix price-repair-currency, logic was inverted
1 parent bd1a597 commit e329f26

File tree

1 file changed

+56
-42
lines changed

1 file changed

+56
-42
lines changed

yfinance/scrapers/history.py

Lines changed: 56 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -368,48 +368,7 @@ def history(self, period="1mo", interval="1d",
368368
# Must fix bad 'Adj Close' & dividends before 100x/split errors.
369369
# First make currency consistent. On some exchanges, dividends often in different currency
370370
# to prices, e.g. £ vs pence.
371-
if currency in ["GBp", "ZAc", "ILA"]:
372-
if currency == 'GBp':
373-
# UK £/pence
374-
currency = 'GBP'
375-
m = 0.01
376-
elif currency == 'ZAc':
377-
# South Africa Rand/cents
378-
currency = 'ZAR'
379-
m = 0.01
380-
elif currency == 'ILA':
381-
# Israel Shekels/Agora
382-
currency = 'ILS'
383-
m = 0.01
384-
385-
prices_in_subunits = True # usually is true
386-
if df.index[-1] > (pd.Timestamp.utcnow() - _datetime.timedelta(days=30)):
387-
try:
388-
ratio = self._history_metadata['regularMarketPrice'] / self._history_metadata['chartPreviousClose']
389-
if abs((ratio*m)-1) < 0.1:
390-
# within 10% of 100x
391-
prices_in_subunits = True
392-
except Exception:
393-
pass
394-
if prices_in_subunits:
395-
for c in _PRICE_COLNAMES_:
396-
df[c] *= m
397-
self._history_metadata["currency"] = currency
398-
399-
f_div = df['Dividends']!=0.0
400-
if f_div.any():
401-
# But sometimes the dividend was in pence.
402-
# Heuristic is: if dividend yield is ridiculous high vs converted prices, then
403-
# assume dividend was also in pence and convert to GBP.
404-
# Threshold for "ridiculous" based on largest yield I've seen anywhere - 63.4%
405-
# If this simple heuritsic generates a false positive, then _fix_bad_div_adjust()
406-
# will detect and repair.
407-
divs = df[['Close','Dividends']].copy()
408-
divs['Close'] = divs['Close'].ffill().shift(1, fill_value=divs['Close'].iloc[0])
409-
divs = divs[f_div]
410-
div_pcts = (divs['Dividends'] / divs['Close']).to_numpy()
411-
if len(div_pcts) > 0 and np.average(div_pcts) > 1:
412-
df['Dividends'] *= m
371+
df, currency = self._standardise_currency(df, currency)
413372

414373
df = self._fix_bad_div_adjust(df, interval, currency)
415374

@@ -933,6 +892,61 @@ def _reconstruct_intervals_batch(self, df, interval, prepost, tag=-1):
933892

934893
return df_v2
935894

895+
def _standardise_currency(self, df, currency):
896+
if currency not in ["GBp", "ZAc", "ILA"]:
897+
return df, currency
898+
currency2 = currency
899+
if currency == 'GBp':
900+
# UK £/pence
901+
currency2 = 'GBP'
902+
m = 0.01
903+
elif currency == 'ZAc':
904+
# South Africa Rand/cents
905+
currency2 = 'ZAR'
906+
m = 0.01
907+
elif currency == 'ILA':
908+
# Israel Shekels/Agora
909+
currency2 = 'ILS'
910+
m = 0.01
911+
912+
# Use latest row with actual volume, because volume=0 rows can be 0.01x the other rows.
913+
# _fix_unit_switch() will ensure all rows are on same scale.
914+
f_volume = df['Volume']>0
915+
if not f_volume.any():
916+
return df, currency
917+
last_row = df.iloc[np.where(f_volume)[0][-1]]
918+
prices_in_subunits = True # usually is true
919+
if last_row.name > (pd.Timestamp.utcnow() - _datetime.timedelta(days=30)):
920+
try:
921+
ratio = self._history_metadata['regularMarketPrice'] / last_row['Close']
922+
if abs((ratio*m)-1) < 0.1:
923+
# within 10% of 100x
924+
prices_in_subunits = False
925+
except Exception:
926+
# Should never happen but just-in-case
927+
pass
928+
if prices_in_subunits:
929+
for c in _PRICE_COLNAMES_:
930+
df[c] *= m
931+
self._history_metadata["currency"] = currency
932+
933+
f_div = df['Dividends']!=0.0
934+
if f_div.any():
935+
# But sometimes the dividend was in pence.
936+
# Heuristic is: if dividend yield is ridiculous high vs converted prices, then
937+
# assume dividend was also in pence and convert to GBP.
938+
# Threshold for "ridiculous" based on largest yield I've seen anywhere - 63.4%
939+
# If this simple heuristic generates a false positive, then _fix_bad_div_adjust()
940+
# will detect and repair.
941+
divs = df[['Close','Dividends']].copy()
942+
divs['Close'] = divs['Close'].ffill().shift(1, fill_value=divs['Close'].iloc[0])
943+
divs = divs[f_div]
944+
div_pcts = (divs['Dividends'] / divs['Close']).to_numpy()
945+
if len(div_pcts) > 0 and np.average(div_pcts) > 1:
946+
df['Dividends'] *= m
947+
948+
return df, currency2
949+
936950
@utils.log_indent_decorator
937951
def _fix_unit_mixups(self, df, interval, tz_exchange, prepost):
938952
if df.empty:

0 commit comments

Comments
 (0)