diff --git a/tests/test_assets.py b/tests/test_assets.py index bb6142cb..a4cdfa3c 100644 --- a/tests/test_assets.py +++ b/tests/test_assets.py @@ -757,6 +757,56 @@ class AssetFinderTestCase(WithTradingCalendars, ZiplineTestCase): result = finder.lookup_symbol('FOO/B', date + timedelta(1), fuzzy=True) self.assertEqual(result.sid, 1) + def test_endless_multiple_resolves(self): + """ + Situation: + 1. Asset 1 w/ symbol FOOB changes to FOO_B, and then is delisted. + 2. Asset 2 is listed with symbol FOO_B. + + If someone asks for FOO_B with fuzzy matching after 2 has been listed, + they should be able to correctly get 2. + """ + + date = pd.Timestamp('2013-01-01', tz='UTC') + + df = pd.DataFrame.from_records( + [ + { + 'sid': 1, + 'symbol': 'FOOB', + 'start_date': date.value, + 'end_date': date.max.value, + 'exchange': 'NYSE', + }, + { + 'sid': 1, + 'symbol': 'FOO_B', + 'start_date': (date + timedelta(days=31)).value, + 'end_date': (date + timedelta(days=60)).value, + 'exchange': 'NYSE', + }, + { + 'sid': 2, + 'symbol': 'FOO_B', + 'start_date': (date + timedelta(days=61)).value, + 'end_date': date.max.value, + 'exchange': 'NYSE', + }, + + ] + ) + self.write_assets(equities=df) + finder = self.asset_finder + + # If we are able to resolve this with any result, means that we did not + # raise a MultipleSymbolError. + result = finder.lookup_symbol( + 'FOO/B', + date + timedelta(days=90), + fuzzy=True + ) + self.assertEqual(result.sid, 2) + def test_lookup_generic_handle_missing(self): data = pd.DataFrame.from_records( [ diff --git a/zipline/assets/assets.py b/zipline/assets/assets.py index e797ff26..000a0fc7 100644 --- a/zipline/assets/assets.py +++ b/zipline/assets/assets.py @@ -657,8 +657,11 @@ class AssetFinder(object): return self.retrieve_asset(sid_keys[0]) for sid, sym in options.items(): - if sym == symbol: - # look for an exact match on the asof date + # Possible to have a scenario where multiple fuzzy matches have the + # same date. Want to find the one where symbol and share class + # match. + if (company_symbol, share_class_symbol) == \ + split_delimited_symbol(sym): return self.retrieve_asset(sid) # multiple equities held tickers matching the fuzzy ticker but