Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Quick Basic Questions not Covered in "Getting Started" or API Ref

I have some beginner knowledge of Python and am struggling with some basic tasks that are not explained in any help docs in quantopian. It is frustrating to struggle with these basics since I have my program already planned out.

1) How do I extract a particular value from "context.portfolio.positions", such as 'amount', and then store it in a variable? I'm not sure how to work with the portfolio, data, and order objects because they don't seem to work like normal python dictionaries and I am getting lost.
2) How do I extract a particular value from the Order Object, such as order status, and then store it in a variable?
3) How do I extract an order ID of a purchase I just made (in the previous line of code) and store it in a variable? I want to be able to make a purchase, then check its status to see if it was filled, and if it is filled then I can run my sell function.
4) Where can I find examples of these basic tasks? I feel like there are a lot of things missing from the help docs. For instance, how can I have the sell part of my algorithm run only when I know my buy order is filled? Without this I can sell what I do not own, causing massive leverage problems.

The help doc will refer to things like the "Order Object" and its "properties" but I'd like to know what it actually is: is it a dictionary, dataframe, or something else? If I know what I am working with then I can google my problems.

Thanks,
Need4Greed

4 responses

The context.portfolio.positions object is indeed a dictionary. The keys of the dictionary are 'Asset' objects (which are also sometimes referred to as security and equity objects) and the values are 'Position' objects. It may not seem like a 'normal' Python dictionary maybe because both the keys and the values are objects and NOT the actual data itself. As an example, 'amount' is a property of each 'Position' object in the context.portfolio.positions dictionary. So, to get the amount of a particular position one could do something like this (assuming you know that you hold SPY)

spy_asset = symbol('SPY')  
my_spy_amount = context.portfolio.positions[spy_asset].amount

# or another way  
my_spy_amount = context.portfolio.positions.get(spy_asset).amount

'context.portfolio.positions[spy_asset] returns the value indexed by 'spy_asset'. This 'value' is a position object. So, to get to the properties of that object a simple way is to use the '.' (dot) notation.

Typically, one doesn't know what's currently held in the portfolio. It's common to loop over all positions to do something. In this case, close all positions with less than $1000 in value.

for security, position in context.portfolio.positions.items():  
    value = abs(position.amount) * position.last_sale_price  
    if value < 1000 and data.can_trade(security):  
        order_target(security, 0)

The order object is just a plain object with properties like 'amount' and 'status'. (See https://www.quantopian.com/help#api-orderobj for more properties.) The way to get a reference to an order object is with the get_order method. Give it the order ID and it returns a reference to the object. Order IDs are returned by every order method (they are really functions). Most of the time one doesn't care about the order id so it's often not programmed like this but, if you do want to store the id, do something like this.

my_order_id = order_target_percent(my_stock, my_percent)

Here's perhaps a more realistic example

    for order_id in context.todays_orders[:]:  
        original_order = get_order(order_id)  
        if original_order and original_order.status == 2 :  
            # The order was somehow cancelled so retry  
            retry_id = order(  
                original_order.sid,  
                original_order.amount,  
                style=LimitOrder(original_order.limit)  
                )  
            log.info('order for %i shares of %s cancelled - retrying' % (original_order.amount, original_order.sid))  
            # Remove the original order (typically can't do but note the [:]) and store the new order  
            context.todays_orders.remove(original_order)  
            context.todays_orders.append(retry_id)

This will check each order previously stored in a user defined list 'context.todays_orders'. If it has a status of 'cancelled' (ie 2) then place another order using the properties in the original order. It then takes the new order id and put's it into the order list. Generally it's good practice to store order ids and NOT the actual references to the order.

There is another ordering example where the order id is used here https://www.quantopian.com/help#ide-ordering .

Hope this helps?

Hi Dan,
Thank you so much for your thoughtful and detailed reply!

That is extremely helpful, though I am still struggling a bit. My program has four functions:

1) GoldOpen (every day at 9:31 stores JNUG's open price in a global variable, then sets the GoldBuy, GoldStop, and GoldProfit global variables based on it)
2) InitialStop (Every day, every minute up until 3:55, checks if the price of gold is at or below the initial stop loss level. If it is, it sells the original number of shares bought)
3) SellGold (Every day, every minute, if the current price of JNUG is at or above my profit level (context.GoldProfit), it sells the original number of shares bought).
4) EndDaySell (Every day, if I haven't sold JNUG by 3:55, it sells it).

To help me figure out if I am using these order and context.portfolio.positions objects correctly, would you mind letting me know what you think of my code? I am getting an error with my limit orders.

Thanks,
Need4Greed

A couple of things...

The error is simply because your syntax is wrong for setting the limit order. You have

            order_target(context.jnug, my_JNUG_amount, LimitOrder(context.jnugCurrent))

but should be

            order_target(context.jnug, my_JNUG_amount, style=LimitOrder(context.jnugCurrent))

Notice the 'style='.

You should maybe also set 'half_days=False' in all the schedule methods since your trade timing won't be correct on short trading days. Another way is to base everything off market_close and then schedule backwards.

Also, maybe put the 'GlobalReset' code into the 'before_trading_start' built in method and it will run every day before any trading. It's actually being run at the same time as the other functions at minute 1. Probably doesn't impact the code but you can't guarantee which method gets run first.

I see that now, really appreciate it! However, I still cannot understand why none of my sell functions are running correctly. The log shows buying and selling a different number of shares. Also, the leverage is getting out of control even though I clearly tried to limit leverage by using logic to prevent my program from overbuying or overselling. Do you know why this is?