From ebe8311f8ba68073ddaf3e90dd470ac21bafb540 Mon Sep 17 00:00:00 2001 From: kglowinski Date: Thu, 1 Sep 2016 13:54:24 -0400 Subject: [PATCH 1/3] BUG: Fixing SymbolNotFound to be raised. --- zipline/assets/assets.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/zipline/assets/assets.py b/zipline/assets/assets.py index 91f114f6..08c481e3 100644 --- a/zipline/assets/assets.py +++ b/zipline/assets/assets.py @@ -648,7 +648,7 @@ class AssetFinder(object): if not options: # no equity owned the fuzzy symbol on the date requested - SymbolNotFound(symbol=symbol) + raise SymbolNotFound(symbol=symbol) if len(options) == 1: # there was only one owner, return it @@ -703,6 +703,10 @@ class AssetFinder(object): there are multiple candidates for the given ``symbol`` on the ``as_of_date``. """ + if symbol is None: + raise TypeError("Cannot lookup symbol of type NoneType for " + "as of date %s" % as_of_date) + if fuzzy: return self._lookup_symbol_fuzzy(symbol, as_of_date) return self._lookup_symbol_strict(symbol, as_of_date) From d7b3c5486057f92722275167e35d6221996eb663 Mon Sep 17 00:00:00 2001 From: kglowinski Date: Thu, 1 Sep 2016 18:03:53 -0400 Subject: [PATCH 2/3] BUG: Handle case with mult symbol options for same sid. --- tests/test_assets.py | 37 +++++++++++++++++++++++++++++++++++++ zipline/assets/assets.py | 21 ++++++++++----------- 2 files changed, 47 insertions(+), 11 deletions(-) diff --git a/tests/test_assets.py b/tests/test_assets.py index cf52be8d..bb6142cb 100644 --- a/tests/test_assets.py +++ b/tests/test_assets.py @@ -720,6 +720,43 @@ class AssetFinderTestCase(WithTradingCalendars, ZiplineTestCase): self.assertEqual(results, expected) self.assertEqual(missing, []) + def test_lookup_none_raises(self): + """ + If lookup_symbol is vectorized across multiple symbols, and one of them + is None, want to raise a TypeError. + """ + + with self.assertRaises(TypeError): + self.asset_finder.lookup_symbol(None, pd.Timestamp('2013-01-01')) + + def test_lookup_mult_are_one(self): + """ + Ensure that multiple symbols that return the same sid are collapsed to + a single returned asset. + """ + + date = pd.Timestamp('2013-01-01', tz='UTC') + + df = pd.DataFrame.from_records( + [ + { + 'sid': 1, + 'symbol': symbol, + 'start_date': date.value, + 'end_date': (date + timedelta(days=30)).value, + 'exchange': 'NYSE', + } + for symbol in ('FOOB', 'FOO_B') + ] + ) + 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(1), fuzzy=True) + self.assertEqual(result.sid, 1) + 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 08c481e3..1e25181b 100644 --- a/zipline/assets/assets.py +++ b/zipline/assets/assets.py @@ -640,21 +640,23 @@ class AssetFinder(object): options=set(options), ) - options = [] + options = {} for start, end, sid, sym in owners: if start <= as_of_date < end: # see which fuzzy symbols were owned on the asof date. - options.append((sid, sym)) + options[sid] = sym if not options: # no equity owned the fuzzy symbol on the date requested raise SymbolNotFound(symbol=symbol) + sid_keys = options.keys() + # If there was only one owner, or there is a fuzzy and non-fuzzy which + # map to the same sid, return it. if len(options) == 1: - # there was only one owner, return it - return self.retrieve_asset(options[0][0]) + return self.retrieve_asset(sid_keys[0]) - for sid, sym in options: + for sid, sym in options.items(): if sym == symbol: # look for an exact match on the asof date return self.retrieve_asset(sid) @@ -663,10 +665,7 @@ class AssetFinder(object): # there are no exact matches raise MultipleSymbolsFound( symbol=symbol, - options=set(map( - compose(self.retrieve_asset, itemgetter(0)), - options, - )), + options=[self.retrieve_asset(s) for s in sid_keys], ) def lookup_symbol(self, symbol, as_of_date, fuzzy=False): @@ -704,8 +703,8 @@ class AssetFinder(object): ``as_of_date``. """ if symbol is None: - raise TypeError("Cannot lookup symbol of type NoneType for " - "as of date %s" % as_of_date) + raise TypeError("Cannot lookup asset for symbol of None for " + "as of date %s." % as_of_date) if fuzzy: return self._lookup_symbol_fuzzy(symbol, as_of_date) From 658b5364d82132e62f821b4ab3aa22bfd9f19f74 Mon Sep 17 00:00:00 2001 From: kglowinski Date: Tue, 6 Sep 2016 10:11:44 -0400 Subject: [PATCH 3/3] BUG: Fixing 2/3 compat. --- zipline/assets/assets.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zipline/assets/assets.py b/zipline/assets/assets.py index 1e25181b..e797ff26 100644 --- a/zipline/assets/assets.py +++ b/zipline/assets/assets.py @@ -650,7 +650,7 @@ class AssetFinder(object): # no equity owned the fuzzy symbol on the date requested raise SymbolNotFound(symbol=symbol) - sid_keys = options.keys() + sid_keys = list(options.keys()) # If there was only one owner, or there is a fuzzy and non-fuzzy which # map to the same sid, return it. if len(options) == 1: