Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Error getting portfolio positions

I am trying to sell all my positions, however, I am having some trouble. Here is my code:

def makeTrades(context, data):  
    #close all current positions  
    for position in context.portfolio.positions:  
        #line 97  \/  
        order(position, position.amount * -1, style=MarketOrder())  
    perTrade = context.account.net_liquidation / len(context.toTradeReturn)  
    for security in context.toTradeReturn:  
        order(security, perTrade, style=MarketOrder())  

and here is my error

AttributeError: 'zipline.assets._assets.Equity' object has no attribute 'amount'  
...
USER ALGORITHM:97, in makeTrades  
order(position, position.amount * -1, style=MarketOrder())  

Please help.
Thanks.

1 response

Using a for loop to iterate over a dictionary (ie 'context.portfolio.positions') will loop over the keys and NOT the values. What this means is that 'position' is an equity object (ie the key) and not a position object (ie the value). So, the error you are getting basically says that an equity object doesn't have an attribute of amount (which it doesn't).

You really don't want to iterate through the dictionary, you really want to iterate through the items in the dictionary. The syntax is a little different and looks like this

for equity, position in context.portfolio.positions.items():  
    if data.can_trade(position):  
        order(position, position.amount * -1, style=MarketOrder()) 

A couple of things to note. First, equity will be the key and position will be the associated value (the position in this case). The '.items()' method presents the items or values in the dictionary to the for loop iterator. Second, it's generally a good idea to always check if a security can trade before actually trying to trade. Put in a check for that.

However, another approach is to go back to your original loop through the equities. Since you simply want to close out each position, you could simply order a target position of zero. This way you don't need to access the '.amount' attribute.

for position in context.portfolio.positions:  
    if data.can_trade(position):  
        order_target(position,  0, style=MarketOrder())

Hope that helps.