Merge pull request #1768 from quantopian/shim-portfolio-access-by-int

BUG: Add backwards compatibility for position lookup by int.
This commit is contained in:
Jean Bredeche
2017-04-26 10:13:16 -04:00
committed by GitHub
2 changed files with 84 additions and 3 deletions
+46
View File
@@ -113,6 +113,22 @@ def handle_data(context, data):
assert iter_list == items_list
"""
reference_missing_position_by_int_algo = """
def initialize(context):
pass
def handle_data(context, data):
context.portfolio.positions[24]
"""
reference_missing_position_by_unexpected_type_algo = """
def initialize(context):
pass
def handle_data(context, data):
context.portfolio.positions["foobar"]
"""
class TestAPIShim(WithCreateBarData,
WithDataPortal,
@@ -513,3 +529,33 @@ class TestAPIShim(WithCreateBarData,
self.assertEqual("Iterating over the assets in `data` is "
"deprecated.",
str(warning.message))
def test_reference_empty_position_by_int(self):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("default", ZiplineDeprecationWarning)
algo = self.create_algo(reference_missing_position_by_int_algo)
algo.run(self.data_portal)
self.assertEqual(1, len(w))
self.assertEqual(
w[0].message.message,
"Referencing positions by integer is deprecated. Use an asset "
"instead."
)
def test_reference_empty_position_by_unexpected_type(self):
with warnings.catch_warnings(record=True) as w:
warnings.simplefilter("default", ZiplineDeprecationWarning)
algo = self.create_algo(
reference_missing_position_by_unexpected_type_algo
)
algo.run(self.data_portal)
self.assertEqual(1, len(w))
self.assertEqual(
w[0].message.message,
"Position lookup expected a value of type Asset but got str"
" instead."
)
+38 -3
View File
@@ -257,8 +257,43 @@ class Position(object):
)
class Positions(dict):
# Copied from Position and renamed. This is used to handle cases where a user
# does something like `context.portfolio.positions[100]` instead of
# `context.portfolio.positions[sid(100)]`.
class _DeprecatedSidLookupPosition(object):
def __init__(self, sid):
self.sid = sid
self.amount = 0
self.cost_basis = 0.0 # per share
self.last_sale_price = 0.0
self.last_sale_date = None
def __repr__(self):
return "_DeprecatedSidLookupPosition({0})".format(self.__dict__)
# If you are adding new attributes, don't update this set. This method
# is deprecated to normal attribute access so we don't want to encourage
# new usages.
__getitem__ = _deprecated_getitem_method(
'position', {
'sid',
'amount',
'cost_basis',
'last_sale_price',
'last_sale_date',
},
)
class Positions(dict):
def __missing__(self, key):
pos = Position(key)
return pos
if isinstance(key, Asset):
return Position(key)
elif isinstance(key, int):
warn("Referencing positions by integer is deprecated."
" Use an asset instead.")
else:
warn("Position lookup expected a value of type Asset but got {0}"
" instead.".format(type(key).__name__))
return _DeprecatedSidLookupPosition(key)