Merge pull request #1449 from quantopian/getitem-is-not-getattr

MAINT: remove __getitem__ as alias of __getattr__
This commit is contained in:
Joe Jevnik
2016-09-06 13:48:17 -04:00
committed by GitHub
6 changed files with 163 additions and 80 deletions
+4 -3
View File
@@ -1448,9 +1448,10 @@ class TestBeforeTradingStart(WithDataPortal,
assert (context.hd_portfolio.__dict__[k]
== bts_portfolio.__dict__[k])
record(pos_value=bts_portfolio.positions_value)
record(pos_amount=bts_portfolio.positions[sid(3)]['amount'])
record(last_sale_price=bts_portfolio.positions[sid(3)]
['last_sale_price'])
record(pos_amount=bts_portfolio.positions[sid(3)].amount)
record(
last_sale_price=bts_portfolio.positions[sid(3)].last_sale_price
)
def handle_data(context, data):
if not context.ordered:
order(sid(3), 1)
+30 -30
View File
@@ -111,26 +111,26 @@ def check_account(account,
# so net and gross leverage are equal.
np.testing.assert_allclose(settled_cash,
account['settled_cash'], rtol=1e-3)
account.settled_cash, rtol=1e-3)
np.testing.assert_allclose(equity_with_loan,
account['equity_with_loan'], rtol=1e-3)
account.equity_with_loan, rtol=1e-3)
np.testing.assert_allclose(total_positions_value,
account['total_positions_value'], rtol=1e-3)
account.total_positions_value, rtol=1e-3)
np.testing.assert_allclose(total_positions_exposure,
account['total_positions_exposure'], rtol=1e-3)
account.total_positions_exposure, rtol=1e-3)
np.testing.assert_allclose(regt_equity,
account['regt_equity'], rtol=1e-3)
account.regt_equity, rtol=1e-3)
np.testing.assert_allclose(available_funds,
account['available_funds'], rtol=1e-3)
account.available_funds, rtol=1e-3)
np.testing.assert_allclose(excess_liquidity,
account['excess_liquidity'], rtol=1e-3)
account.excess_liquidity, rtol=1e-3)
np.testing.assert_allclose(cushion,
account['cushion'], rtol=1e-3)
np.testing.assert_allclose(leverage, account['leverage'], rtol=1e-3)
account.cushion, rtol=1e-3)
np.testing.assert_allclose(leverage, account.leverage, rtol=1e-3)
np.testing.assert_allclose(net_leverage,
account['net_leverage'], rtol=1e-3)
account.net_leverage, rtol=1e-3)
np.testing.assert_allclose(net_liquidation,
account['net_liquidation'], rtol=1e-3)
account.net_liquidation, rtol=1e-3)
def create_txn(asset, dt, price, amount):
@@ -368,28 +368,28 @@ class TestSplitPerformance(WithSimParams, WithTmpDir, ZiplineTestCase):
# Validate that the account attributes were updated.
account = results[1]['account']
self.assertEqual(float('inf'), account['day_trades_remaining'])
self.assertEqual(float('inf'), account.day_trades_remaining)
# this is a long only portfolio that is only partially invested
# so net and gross leverage are equal.
np.testing.assert_allclose(0.198, account['leverage'], rtol=1e-3)
np.testing.assert_allclose(0.198, account['net_leverage'], rtol=1e-3)
np.testing.assert_allclose(8020, account['regt_equity'], rtol=1e-3)
self.assertEqual(float('inf'), account['regt_margin'])
np.testing.assert_allclose(8020, account['available_funds'], rtol=1e-3)
self.assertEqual(0, account['maintenance_margin_requirement'])
np.testing.assert_allclose(0.198, account.leverage, rtol=1e-3)
np.testing.assert_allclose(0.198, account.net_leverage, rtol=1e-3)
np.testing.assert_allclose(8020, account.regt_equity, rtol=1e-3)
self.assertEqual(float('inf'), account.regt_margin)
np.testing.assert_allclose(8020, account.available_funds, rtol=1e-3)
self.assertEqual(0, account.maintenance_margin_requirement)
np.testing.assert_allclose(10000,
account['equity_with_loan'], rtol=1e-3)
self.assertEqual(float('inf'), account['buying_power'])
self.assertEqual(0, account['initial_margin_requirement'])
np.testing.assert_allclose(8020, account['excess_liquidity'],
account.equity_with_loan, rtol=1e-3)
self.assertEqual(float('inf'), account.buying_power)
self.assertEqual(0, account.initial_margin_requirement)
np.testing.assert_allclose(8020, account.excess_liquidity,
rtol=1e-3)
np.testing.assert_allclose(8020, account['settled_cash'], rtol=1e-3)
np.testing.assert_allclose(10000, account['net_liquidation'],
np.testing.assert_allclose(8020, account.settled_cash, rtol=1e-3)
np.testing.assert_allclose(10000, account.net_liquidation,
rtol=1e-3)
np.testing.assert_allclose(0.802, account['cushion'], rtol=1e-3)
np.testing.assert_allclose(1980, account['total_positions_value'],
np.testing.assert_allclose(0.802, account.cushion, rtol=1e-3)
np.testing.assert_allclose(1980, account.total_positions_value,
rtol=1e-3)
self.assertEqual(0, account['accrued_interest'])
self.assertEqual(0, account.accrued_interest)
for i, result in enumerate(results):
for perf_kind in ('daily_perf', 'cumulative_perf'):
@@ -1346,10 +1346,10 @@ class TestPositionPerformance(WithInstanceTmpDir, WithTradingCalendars,
self.assertEqual(
pp.positions[1].last_sale_price,
trades[-1]['price'],
trades[-1].price,
"last sale should be same as last trade. \
expected {exp} actual {act}".format(
exp=trades[-1]['price'],
exp=trades[-1].price,
act=pp.positions[1].last_sale_price)
)
@@ -1456,7 +1456,7 @@ single short-sale transaction"""
self.assertEqual(
pp.positions[1].last_sale_price,
trades_1[-1]['price'],
trades_1[-1].price,
"last sale should be price of last trade"
)
+1 -1
View File
@@ -394,5 +394,5 @@ class MaxLeverage(AccountControl):
"""
Fail if the leverage is greater than the allowed leverage.
"""
if _account['leverage'] > self.max_leverage:
if _account.leverage > self.max_leverage:
self.fail()
+104 -22
View File
@@ -1,5 +1,5 @@
#
# Copyright 2013 Quantopian, Inc.
# Copyright 2016 Quantopian, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -12,10 +12,11 @@
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
from warnings import warn
import pandas as pd
from .utils.enum import enum
from zipline._protocol import BarData # noqa
@@ -61,16 +62,7 @@ class Event(object):
def __init__(self, initial_values=None):
if initial_values:
self.__dict__ = initial_values
def __getitem__(self, name):
return getattr(self, name)
def __setitem__(self, name, value):
setattr(self, name, value)
def __delitem__(self, name):
delattr(self, name)
self.__dict__.update(initial_values)
def keys(self):
return self.__dict__.keys()
@@ -88,8 +80,52 @@ class Event(object):
return pd.Series(self.__dict__, index=index)
def _deprecated_getitem_method(name, attrs):
"""Create a deprecated ``__getitem__`` method that tells users to use
getattr instead.
Parameters
----------
name : str
The name of the object in the warning message.
attrs : iterable[str]
The set of allowed attributes.
Returns
-------
__getitem__ : callable[any, str]
The ``__getitem__`` method to put in the class dict.
"""
attrs = frozenset(attrs)
msg = "'{0}[attr]' is deprecated, please use '{0}.attr' instead".format(
name,
)
def __getitem__(self, key):
"""``__getitem__`` is deprecated, please use attribute access instead.
"""
warn(msg, DeprecationWarning, stacklevel=1)
if key in attrs:
return self.__dict__[key]
raise KeyError(key)
return __getitem__
class Order(Event):
pass
# 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(
'order', {
'dt',
'sid',
'amount',
'stop',
'limit',
'id',
},
)
class Portfolio(object):
@@ -105,12 +141,26 @@ class Portfolio(object):
self.start_date = None
self.positions_value = 0.0
def __getitem__(self, key):
return self.__dict__[key]
def __repr__(self):
return "Portfolio({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(
'portfolio', {
'capital_used',
'starting_cash',
'portfolio_value',
'pnl',
'returns',
'cash',
'positions',
'start_date',
'positions_value',
},
)
class Account(object):
'''
@@ -139,12 +189,34 @@ class Account(object):
self.net_leverage = 0.0
self.net_liquidation = 0.0
def __getitem__(self, key):
return self.__dict__[key]
def __repr__(self):
return "Account({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(
'account', {
'settled_cash',
'accrued_interest',
'buying_power',
'equity_with_loan',
'total_positions_value',
'total_positions_exposure',
'regt_equity',
'regt_margin',
'initial_margin_requirement',
'maintenance_margin_requirement',
'available_funds',
'excess_liquidity',
'cushion',
'day_trades_remaining',
'leverage',
'net_leverage',
'net_liquidation',
},
)
class Position(object):
@@ -155,12 +227,22 @@ class Position(object):
self.last_sale_price = 0.0
self.last_sale_date = None
def __getitem__(self, key):
return self.__dict__[key]
def __repr__(self):
return "Position({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):
+19 -19
View File
@@ -62,7 +62,7 @@ The algorithm must expose methods:
algorithm can then check position information with the
Portfolio object::
self.Portfolio[sid(133)]['cost_basis']
self.Portfolio[sid(133)].cost_basis
- set_transact_setter: method that accepts a callable. Will
be set as the value of the set_transact_setter method of
@@ -261,9 +261,9 @@ class TestOrderAlgorithm(TradingAlgorithm):
if self.incr == 0:
assert 0 not in self.portfolio.positions
else:
assert self.portfolio.positions[0]['amount'] == \
assert self.portfolio.positions[0].amount == \
self.incr, "Orders not filled immediately."
assert self.portfolio.positions[0]['last_sale_price'] == \
assert self.portfolio.positions[0].last_sale_price == \
data.current(sid(0), "price"), \
"Orders not filled at current price."
self.incr += 1
@@ -279,9 +279,9 @@ class TestOrderInstantAlgorithm(TradingAlgorithm):
if self.incr == 0:
assert 0 not in self.portfolio.positions
else:
assert self.portfolio.positions[0]['amount'] == \
assert self.portfolio.positions[0].amount == \
self.incr, "Orders not filled immediately."
assert self.portfolio.positions[0]['last_sale_price'] == \
assert self.portfolio.positions[0].last_sale_price == \
self.last_price, "Orders was not filled at last price."
self.incr += 1
self.order_value(self.sid(0), data.current(sid(0), "price"))
@@ -330,9 +330,9 @@ class TestOrderValueAlgorithm(TradingAlgorithm):
if self.incr == 0:
assert 0 not in self.portfolio.positions
else:
assert self.portfolio.positions[0]['amount'] == \
assert self.portfolio.positions[0].amount == \
self.incr, "Orders not filled immediately."
assert self.portfolio.positions[0]['last_sale_price'] == \
assert self.portfolio.positions[0].last_sale_price == \
data.current(sid(0), "price"), \
"Orders not filled at current price."
self.incr += 2
@@ -357,9 +357,9 @@ class TestTargetAlgorithm(TradingAlgorithm):
if self.target_shares == 0:
assert 0 not in self.portfolio.positions
else:
assert self.portfolio.positions[0]['amount'] == \
assert self.portfolio.positions[0].amount == \
self.target_shares, "Orders not filled immediately."
assert self.portfolio.positions[0]['last_sale_price'] == \
assert self.portfolio.positions[0].last_sale_price == \
data.current(sid(0), "price"), \
"Orders not filled at current price."
self.target_shares = 10
@@ -380,9 +380,9 @@ class TestOrderPercentAlgorithm(TradingAlgorithm):
return
else:
assert self.portfolio.positions[0]['amount'] == \
assert self.portfolio.positions[0].amount == \
self.target_shares, "Orders not filled immediately."
assert self.portfolio.positions[0]['last_sale_price'] == \
assert self.portfolio.positions[0].last_sale_price == \
data.current(sid(0), "price"), \
"Orders not filled at current price."
@@ -418,13 +418,13 @@ class TestTargetPercentAlgorithm(TradingAlgorithm):
# no more than a share's value away from our current
# holdings.
target_value = self.portfolio.portfolio_value * 0.002
position_value = self.portfolio.positions[0]['amount'] * \
position_value = self.portfolio.positions[0].amount * \
self.sale_price
assert abs(target_value - position_value) <= self.sale_price, \
"Orders not filled correctly"
assert self.portfolio.positions[0]['last_sale_price'] == \
assert self.portfolio.positions[0].last_sale_price == \
data.current(sid(0), "price"), \
"Orders not filled at current price."
@@ -446,9 +446,9 @@ class TestTargetValueAlgorithm(TradingAlgorithm):
self.target_shares = 10
return
else:
assert self.portfolio.positions[0]['amount'] == \
assert self.portfolio.positions[0].amount == \
self.target_shares, "Orders not filled immediately."
assert self.portfolio.positions[0]['last_sale_price'] == \
assert self.portfolio.positions[0].last_sale_price == \
data.current(sid(0), "price"), \
"Orders not filled at current price."
@@ -763,9 +763,9 @@ def handle_data_api(context, data):
if context.incr == 0:
assert 0 not in context.portfolio.positions
else:
assert context.portfolio.positions[0]['amount'] == \
assert context.portfolio.positions[0].amount == \
context.incr, "Orders not filled immediately."
assert context.portfolio.positions[0]['last_sale_price'] == \
assert context.portfolio.positions[0].last_sale_price == \
data.current(sid(0), "price"), \
"Orders not filled at current price."
context.incr += 1
@@ -805,9 +805,9 @@ def handle_data(context, data):
if context.incr == 0:
assert 0 not in context.portfolio.positions
else:
assert context.portfolio.positions[0]['amount'] == \
assert context.portfolio.positions[0].amount == \
context.incr, "Orders not filled immediately."
assert context.portfolio.positions[0]['last_sale_price'] == \
assert context.portfolio.positions[0].last_sale_price == \
data.current(sid(0), "price"), \
"Orders not filled at current price."
context.incr += 1
+5 -5
View File
@@ -591,11 +591,11 @@ def trades_by_sid_to_dfs(trades_by_sid, index):
closes = []
volumes = []
for trade in trades:
opens.append(trade["open_price"])
highs.append(trade["high"])
lows.append(trade["low"])
closes.append(trade["close_price"])
volumes.append(trade["volume"])
opens.append(trade.open_price)
highs.append(trade.high)
lows.append(trade.low)
closes.append(trade.close_price)
volumes.append(trade.volume)
yield sidint, pd.DataFrame(
{