@@ -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