Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Why is data.can_trade throwing error - "KeyError: 0"?

Attached is Backtest and Source code that throws the following error:

KeyError: 0  
      There was a runtime error on line 53.  

This error is coming from this method:

def find_positions_to_sell(context, data):  
    print 'find_positions_to_sell:'  
    show_portfolio_details(context)  

    print 'context.positions_held:'  
    print context.positions_held  
    if not data.can_trade(context.positions_held.SID).all():  
        return #Optionally pd.DataFrame({'Empty' : []})  
    print 'Can Trade All: {}'.format(data.can_trade(context.positions_held.SID).all())

    return context.positions_held.head(1).SID  

I am trying to understand why "data.can_trade" is throwing error.

Is there a way to capture or prevent such an error?

The dates used for this test were between 10/26/16 - 10/27/16
Unable to attach the code, so putting it here:

import pandas as pd

def initialize(context):  
    trading_minutes = 300  
    run_interval = 60  
    schedule_function(  
        func=start_of_day,  
        date_rule=date_rules.every_day(),  
        time_rule=time_rules.market_open(minutes=15),  
        half_days=False  
    )

    #Only needed for testing  
    for i in range(run_interval + 15, trading_minutes, run_interval):  
        #print 'Trading Minutes: {}'.format(i)  
        # Every #run_interval minutes run schedule  
        schedule_function(  
            func=my_handle_data,  
            date_rule=date_rules.every_day(),  
            time_rule=time_rules.market_open(minutes=i),  
            half_days=False  
        )

def before_trading_start(context, data):  
    context.test_count = 0  
    context.positions_held = pd.DataFrame(columns=('SID', 'Count'))  

def start_of_day(context, data):  
    if data.can_trade(sid(7761)):  
        order_value(sid(7761), 250)  
        context.positions_held = context.positions_held.append( \  
                                        { 'SID' : sid(7761)}  
                                       , ignore_index=True)  
    if data.can_trade(sid(50013)):  
        order_value(sid(50013), 250)  
    context.positions_held = context.positions_held.append( \  
                                        { 'SID' : sid(50013)}  
                                       , ignore_index=True)  
def my_handle_data(context, data):  
    print 'my_handle_data:'

    if context.positions_held is None or context.positions_held.empty:  
        print 'No Positions Held'  
        return

    positions_to_sell = find_positions_to_sell(context, data)

    if positions_to_sell is None or positions_to_sell.empty:  
        return

    print 'positions_to_sell: {}'.format(positions_to_sell)  
    print 'Before:'  
    print context.positions_held  
    #Remove the position that will be sold  
    context.positions_held = context.positions_held[~context.positions_held.SID.isin(positions_to_sell)]

    print 'After:'  
    print context.positions_held 

    for position in positions_to_sell:  
        sell_position(context, position)  

def find_positions_to_sell(context, data):  
    print 'find_positions_to_sell:'  
    show_portfolio_details(context)  

    print 'context.positions_held:'  
    print context.positions_held  
    if not data.can_trade(context.positions_held.SID).all():  
        return #Optionally pd.DataFrame({'Empty' : []})  
    print 'Can Trade All: {}'.format(data.can_trade(context.positions_held.SID).all())

    return context.positions_held.head(1).SID  

def sell_position(context, position):  
    print 'Sell Position: {}'.format(position)  
    #TODO:  Want to know when this is complete  
    order_target(position, 0)  
def show_portfolio_details(context):  
    print 'show_portfolio_details:'  
    print 'Position Count: {}'.format(len(context.portfolio.positions))  
    for key in context.portfolio.positions:  
        position = context.portfolio.positions[key]  
        print 'SID: {0}, Count: {1}'.format(position.sid, position.amount)  
1 response

Received a response from Quantopian help:

The key error you see is due to the way you are removing SIDs from context.positions_held and the use of .all() with data.can_trade.

If you look at the logs generated before the runtime error is reached, you will see that for the second day, after you have removed one asset from context.positions_held, the remaining SID's index is 1. This causes .all() to raise an error, since it expects the first row to have an index of 0.

This has a simple solution. In line 62, after removing the positions to sell, you will need to reset the index of context.positions_held using .reset_index(). You can find the documentation for this DataFrame method here (http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.reset_index.html).

I hope this information helps. Let me know if you have further questions.

Best regards,

Ernesto Ezequiel Perez
Quantopian