@@ -1052,6 +1052,74 @@ def test_empty_info(self):
10521052 self .assertCountEqual (['quoteType' , 'symbol' , 'underlyingSymbol' , 'uuid' , 'maxAge' , 'trailingPegRatio' ], data .keys ())
10531053 self .assertIn ("trailingPegRatio" , data .keys (), "Did not find expected key 'trailingPegRatio' in info dict" )
10541054
1055+ def test_price_to_book_mixed_currencies (self ):
1056+ # Test for Issue #2593: priceToBook should be None when currency and financialCurrency differ.
1057+
1058+ from unittest .mock import Mock , patch
1059+ from yfinance .scrapers .quote import Quote
1060+
1061+ # Test Case 1: Mixed currencies (INR price, USD book value) - the main issue
1062+ quote = Quote (Mock (), "TEST.NS" )
1063+ quote ._info = {
1064+ "symbol" : "TEST.NS" ,
1065+ "currentPrice" : 1531.4 , # INR
1066+ "bookValue" : 2.67 , # USD
1067+ "priceToBook" : 573.6 , # Invalid: 1531.4 / 2.67 but mismatched currencies
1068+ "currency" : "INR" ,
1069+ "financialCurrency" : "USD"
1070+ }
1071+ quote ._sanitize_price_to_book ()
1072+ self .assertIsNone (quote ._info ["priceToBook" ],
1073+ "priceToBook should be None when currencies don't match" )
1074+ self .assertEqual (quote ._info ["currency" ], "INR" )
1075+ self .assertEqual (quote ._info ["financialCurrency" ], "USD" )
1076+
1077+ # Test Case 2: Matching currencies - priceToBook should be preserved
1078+ quote2 = Quote (Mock (), "TEST.US" )
1079+ quote2 ._info = {
1080+ "symbol" : "TEST.US" ,
1081+ "currentPrice" : 150.0 ,
1082+ "bookValue" : 50.0 ,
1083+ "priceToBook" : 3.0 ,
1084+ "currency" : "USD" ,
1085+ "financialCurrency" : "USD"
1086+ }
1087+ quote2 ._sanitize_price_to_book ()
1088+ self .assertEqual (quote2 ._info ["priceToBook" ], 3.0 ,
1089+ "priceToBook should be preserved when currencies match" )
1090+
1091+ # Test Case 3: Missing priceToBook - should not raise error
1092+ quote3 = Quote (Mock (), "TEST.IN" )
1093+ quote3 ._info = {
1094+ "symbol" : "TEST.IN" ,
1095+ "currency" : "INR" ,
1096+ "financialCurrency" : "USD"
1097+ }
1098+ quote3 ._sanitize_price_to_book () # Should not raise error
1099+ self .assertNotIn ("priceToBook" , quote3 ._info )
1100+
1101+ # Test Case 4: Missing financialCurrency - should not clear priceToBook
1102+ quote4 = Quote (Mock (), "TEST.XX" )
1103+ quote4 ._info = {
1104+ "symbol" : "TEST.XX" ,
1105+ "priceToBook" : 2.5 ,
1106+ "currency" : "EUR"
1107+ }
1108+ quote4 ._sanitize_price_to_book ()
1109+ self .assertEqual (quote4 ._info ["priceToBook" ], 2.5 ,
1110+ "priceToBook should be preserved when financialCurrency is missing" )
1111+
1112+ # Test Case 5: Missing currency - should not clear priceToBook
1113+ quote5 = Quote (Mock (), "TEST.YY" )
1114+ quote5 ._info = {
1115+ "symbol" : "TEST.YY" ,
1116+ "priceToBook" : 2.5 ,
1117+ "financialCurrency" : "EUR"
1118+ }
1119+ quote5 ._sanitize_price_to_book ()
1120+ self .assertEqual (quote5 ._info ["priceToBook" ], 2.5 ,
1121+ "priceToBook should be preserved when currency is missing" )
1122+
10551123 # def test_fast_info_matches_info(self):
10561124 # fast_info_keys = set()
10571125 # for ticker in self.tickers:
0 commit comments