Skip to content

Commit 393aa06

Browse files
authored
Merge pull request #1462 from quantopian/symbol-lookup-raises
Symbol lookup raises
2 parents c09f7ab + 658b536 commit 393aa06

File tree

2 files changed

+50
-10
lines changed

2 files changed

+50
-10
lines changed

tests/test_assets.py

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -720,6 +720,43 @@ def test_lookup_generic(self):
720720
self.assertEqual(results, expected)
721721
self.assertEqual(missing, [])
722722

723+
def test_lookup_none_raises(self):
724+
"""
725+
If lookup_symbol is vectorized across multiple symbols, and one of them
726+
is None, want to raise a TypeError.
727+
"""
728+
729+
with self.assertRaises(TypeError):
730+
self.asset_finder.lookup_symbol(None, pd.Timestamp('2013-01-01'))
731+
732+
def test_lookup_mult_are_one(self):
733+
"""
734+
Ensure that multiple symbols that return the same sid are collapsed to
735+
a single returned asset.
736+
"""
737+
738+
date = pd.Timestamp('2013-01-01', tz='UTC')
739+
740+
df = pd.DataFrame.from_records(
741+
[
742+
{
743+
'sid': 1,
744+
'symbol': symbol,
745+
'start_date': date.value,
746+
'end_date': (date + timedelta(days=30)).value,
747+
'exchange': 'NYSE',
748+
}
749+
for symbol in ('FOOB', 'FOO_B')
750+
]
751+
)
752+
self.write_assets(equities=df)
753+
finder = self.asset_finder
754+
755+
# If we are able to resolve this with any result, means that we did not
756+
# raise a MultipleSymbolError.
757+
result = finder.lookup_symbol('FOO/B', date + timedelta(1), fuzzy=True)
758+
self.assertEqual(result.sid, 1)
759+
723760
def test_lookup_generic_handle_missing(self):
724761
data = pd.DataFrame.from_records(
725762
[

zipline/assets/assets.py

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -640,21 +640,23 @@ def _lookup_symbol_fuzzy(self, symbol, as_of_date):
640640
options=set(options),
641641
)
642642

643-
options = []
643+
options = {}
644644
for start, end, sid, sym in owners:
645645
if start <= as_of_date < end:
646646
# see which fuzzy symbols were owned on the asof date.
647-
options.append((sid, sym))
647+
options[sid] = sym
648648

649649
if not options:
650650
# no equity owned the fuzzy symbol on the date requested
651-
SymbolNotFound(symbol=symbol)
651+
raise SymbolNotFound(symbol=symbol)
652652

653+
sid_keys = list(options.keys())
654+
# If there was only one owner, or there is a fuzzy and non-fuzzy which
655+
# map to the same sid, return it.
653656
if len(options) == 1:
654-
# there was only one owner, return it
655-
return self.retrieve_asset(options[0][0])
657+
return self.retrieve_asset(sid_keys[0])
656658

657-
for sid, sym in options:
659+
for sid, sym in options.items():
658660
if sym == symbol:
659661
# look for an exact match on the asof date
660662
return self.retrieve_asset(sid)
@@ -663,10 +665,7 @@ def _lookup_symbol_fuzzy(self, symbol, as_of_date):
663665
# there are no exact matches
664666
raise MultipleSymbolsFound(
665667
symbol=symbol,
666-
options=set(map(
667-
compose(self.retrieve_asset, itemgetter(0)),
668-
options,
669-
)),
668+
options=[self.retrieve_asset(s) for s in sid_keys],
670669
)
671670

672671
def lookup_symbol(self, symbol, as_of_date, fuzzy=False):
@@ -703,6 +702,10 @@ def lookup_symbol(self, symbol, as_of_date, fuzzy=False):
703702
there are multiple candidates for the given ``symbol`` on the
704703
``as_of_date``.
705704
"""
705+
if symbol is None:
706+
raise TypeError("Cannot lookup asset for symbol of None for "
707+
"as of date %s." % as_of_date)
708+
706709
if fuzzy:
707710
return self._lookup_symbol_fuzzy(symbol, as_of_date)
708711
return self._lookup_symbol_strict(symbol, as_of_date)

0 commit comments

Comments
 (0)