mirror of
https://github.com/wassname/catalyst.git
synced 2026-07-01 22:21:12 +08:00
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:
@@ -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
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user