From d84bdefef8538827b172d1af68a2350710cc879e Mon Sep 17 00:00:00 2001 From: jfkirk Date: Wed, 16 Sep 2015 09:51:10 -0400 Subject: [PATCH] MAINT: Removes lookup_symbol_resolve_multiple method lookup_symbol_resolve_multiple was identical to lookup_symbol, except that lookup_symbol performed upper-casing of the input string and lookup_symbol would return Nones. Now, lookup_symbol has a kwarg 'default_None=True' and all symbols are upper-cased on insertion and request. --- tests/test_algorithm.py | 2 +- tests/test_assets.py | 33 +++++++++++---------------- zipline/algorithm.py | 5 +++-- zipline/assets/asset_writer.py | 8 +++++++ zipline/assets/assets.py | 41 +++++++++++++--------------------- 5 files changed, 41 insertions(+), 48 deletions(-) diff --git a/tests/test_algorithm.py b/tests/test_algorithm.py index 94cf4d18..9dfcb592 100644 --- a/tests/test_algorithm.py +++ b/tests/test_algorithm.py @@ -503,7 +503,7 @@ class TestMiscellaneousAPI(TestCase): self.assertEqual(result.symbol, 'DUP') # By first calling set_symbol_lookup_date, the relevant asset - # should be returned by lookup_symbol_resolve_multiple + # should be returned by lookup_symbol for i, date in enumerate(dates): algo.set_symbol_lookup_date(date) result = algo.symbol('DUP') diff --git a/tests/test_assets.py b/tests/test_assets.py index 01638e4a..6127ca43 100644 --- a/tests/test_assets.py +++ b/tests/test_assets.py @@ -312,24 +312,15 @@ class AssetFinderTestCase(TestCase): # Shouldn't find this with no fuzzy_str passed. self.assertIsNone(finder.lookup_symbol('test', as_of)) self.assertIsNone(finder.lookup_symbol('test1', as_of)) - self.assertEqual( - asset_1, - finder.lookup_symbol('test.1', as_of) - ) + self.assertEqual(asset_1, finder.lookup_symbol('test.1', as_of)) # Adding an unnecessary fuzzy shouldn't matter. - self.assertEqual( - asset_1, - finder.lookup_symbol('test/1', as_of) - ) + self.assertEqual(asset_1, finder.lookup_symbol('test/1', as_of)) # Should find exact match. - self.assertEqual( - asset_1, - finder.lookup_symbol('test-1', as_of), - ) + self.assertEqual(asset_1, finder.lookup_symbol('test-1', as_of)) - def test_lookup_symbol_resolve_multiple(self): + def test_lookup_symbol(self): # Incrementing by two so that start and end dates for each # generated Asset don't overlap (each Asset's end_date is the @@ -351,19 +342,21 @@ class AssetFinderTestCase(TestCase): finder = AssetFinder(self.env.engine) for _ in range(2): # Run checks twice to test for caching bugs. with self.assertRaises(SymbolNotFound): - finder.lookup_symbol_resolve_multiple('non_existing', dates[0]) + finder.lookup_symbol('non_existing', dates[0], + default_None=False) with self.assertRaises(MultipleSymbolsFound): - finder.lookup_symbol_resolve_multiple('existing', None) + finder.lookup_symbol('existing', None) for i, date in enumerate(dates): # Verify that we correctly resolve multiple symbols using # the supplied date - result = finder.lookup_symbol_resolve_multiple( + result = finder.lookup_symbol( 'existing', date, + default_None=False, ) - self.assertEqual(result.symbol, 'existing') + self.assertEqual(result.symbol, 'EXISTING') self.assertEqual(result.sid, i) @parameterized.expand( @@ -422,11 +415,11 @@ class AssetFinderTestCase(TestCase): ) self.assertEqual(len(results), 3) - self.assertEqual(results[0].symbol, 'real') + self.assertEqual(results[0].symbol, 'REAL') self.assertEqual(results[0].sid, 0) - self.assertEqual(results[1].symbol, 'also_real') + self.assertEqual(results[1].symbol, 'ALSO_REAL') self.assertEqual(results[1].sid, 1) - self.assertEqual(results[2].symbol, 'real_but_old') + self.assertEqual(results[2].symbol, 'REAL_BUT_OLD') self.assertEqual(results[2].sid, 2) self.assertEqual(len(missing), 2) diff --git a/zipline/algorithm.py b/zipline/algorithm.py index 4fce2d7b..76caa6fe 100644 --- a/zipline/algorithm.py +++ b/zipline/algorithm.py @@ -749,9 +749,10 @@ class TradingAlgorithm(object): _lookup_date = self._symbol_lookup_date if self._symbol_lookup_date is not None \ else self.sim_params.period_end - return self.asset_finder.lookup_symbol_resolve_multiple( + return self.asset_finder.lookup_symbol( symbol_str, - as_of_date=_lookup_date + as_of_date=_lookup_date, + default_None=False, ) @api_method diff --git a/zipline/assets/asset_writer.py b/zipline/assets/asset_writer.py index d21503e0..71c6a35f 100644 --- a/zipline/assets/asset_writer.py +++ b/zipline/assets/asset_writer.py @@ -412,6 +412,14 @@ class AssetDBWriter(with_metaclass(ABCMeta)): ) equities_output = equities_output.join(split_symbols) + # Upper-case all symbol data + equities_output['symbol'] = \ + equities_output.symbol.str.upper() + equities_output['company_symbol'] = \ + equities_output.company_symbol.str.upper() + equities_output['share_class_symbol'] = \ + equities_output.share_class_symbol.str.upper() + # Convert date columns to UNIX Epoch integers (nanoseconds) equities_output['start_date'] = \ equities_output['start_date'].apply(self.convert_datetime) diff --git a/zipline/assets/assets.py b/zipline/assets/assets.py index 3b44b1b2..b44d56b1 100644 --- a/zipline/assets/assets.py +++ b/zipline/assets/assets.py @@ -262,15 +262,19 @@ class AssetFinder(object): self._future_cache[sid] = future return future - def lookup_symbol_resolve_multiple(self, symbol, as_of_date=None): + def lookup_symbol(self, symbol, as_of_date, default_None=True): """ Return matching Asset of name symbol in database. If multiple Assets are found and as_of_date is not set, raises MultipleSymbolsFound. - If no Asset was active at as_of_date raises SymbolNotFound. + If no Asset was active at as_of_date raises SymbolNotFound, or None + if default_None is true. """ + + # Format inputs + symbol = symbol.upper() if as_of_date is not None: as_of_date = pd.Timestamp(normalize_date(as_of_date)) @@ -317,7 +321,10 @@ class AssetFinder(object): if sid is not None: return self._retrieve_equity(sid) - raise SymbolNotFound(symbol=symbol) + if default_None: + return None + else: + raise SymbolNotFound(symbol=symbol) else: sids = sa.select((equities_cols.sid,)).where( @@ -327,7 +334,10 @@ class AssetFinder(object): if len(sids) == 1: return self._retrieve_equity(sids[0]['sid']) elif not sids: - raise SymbolNotFound(symbol=symbol) + if default_None: + return None + else: + raise SymbolNotFound(symbol=symbol) else: raise MultipleSymbolsFound( symbol=symbol, @@ -337,23 +347,6 @@ class AssetFinder(object): )) ) - def lookup_symbol(self, symbol, as_of_date): - """ - If a fuzzy string is provided, then we try various symbols based on - the provided symbol. This is to facilitate mapping from a broker's - symbol to ours in cases where mapping to the broker's symbol loses - information. For example, if we have CMCS_A, but a broker has CMCSA, - when the broker provides CMCSA, it can also provide fuzzy='_', - so we can find a match by inserting an underscore. - """ - - symbol = symbol.upper() - - try: - return self.lookup_symbol_resolve_multiple(symbol, as_of_date) - except SymbolNotFound: - return None - def lookup_future_chain(self, root_symbol, as_of_date, knowledge_date): """ Return the futures chain for a given root symbol. @@ -459,10 +452,8 @@ class AssetFinder(object): elif isinstance(asset_convertible, string_types): try: matches.append( - self.lookup_symbol_resolve_multiple( - asset_convertible, - as_of_date, - ) + self.lookup_symbol(asset_convertible, as_of_date, + default_None=False) ) except SymbolNotFound: missing.append(asset_convertible)