Back to Community
Help with fetcher and filling NAN values

EDIT: So.... in trying to sort out the issue posted below I ended up confusing myself more and posted a number of things below this first post that I have since resolved. The issue mentioned in this first post, i.e. the fill of NAN values seeming to be forward filled instead of 0, is something I'm still trying to fix.

Hi All-

I have a log of trades that I want to execute through Quantopian's backtester - https://dl.dropboxusercontent.com/s/xff9qws4ciidsuo/20130821_TradeLog_v2.csv

So the trade log provides the ticker symbol, the date of the trade and the number of shares. It would appear, based on the backtest below, that the algo buys (for example) the 272 shares specific on 04/05/2002 but then it continues to buy 272 share blocks! I want it to do nothing until the next trade is supposed to be executed (note that the trades in this trade log are not sorted by date but I can do that if that would help).

Any ideas?

Clone Algorithm
10
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
#Use SPY 15 day MA to determine when to go to cash
#When not in cash buy and hold the most undervalued sectors

import datetime
import math
import numpy
import pandas

def clean_col(df):
    df = df.fillna(0)
    df = df[['Nshares', 'sid']]
    log.info(' \n %s % df.head()')
    return df

def initialize(context):
    #
    #
    #Variables for later
    context.day=None
    context.pauseUntil=63
    context.timestep=0
    context.margin_req=0 
    context.totalShorts=0
    context.totalLongs=0
    context.cash=0
    context.oldRanks=None
    context.timer=0
    context.holdNmanyDays=63
    context.liquid=1
          
    #
    #
    #Set constraints on borrowing
    context.pct_invested_threshold=1 #Set limit on percent invested (as a decimal)
    context.init_margin=.01 #Set initial margin requirement    
    context.maint_margin=.01 #Set the maintenance margin requirement   


    #
    #
    #Read universe
    context.SPY=sid(8554)
    context.Sectors=[sid(19662), sid(19659), sid(19656), sid(19661), sid(19655), sid(19658), sid(19660), sid(19654), sid(19657)]  
    
    #Read the rankings
    fetch_csv('https://dl.dropboxusercontent.com/s/xff9qws4ciidsuo/20130821_TradeLog_v2.csv',
              date_column='Date',
              post_func=clean_col)

    
    

def handle_data(context, data):
    
    for i in context.Sectors:
        if 'Nshares' in data[i] and data[i]['Nshares']!=0:
            log.debug("Ordering "+str(data[i]['Nshares'])+" of ticker "+str(i))
            order(i,data[i]['Nshares'])
        #else:
            #log.debug("Nshares not found for "+str(i))

            
            
            
            
            
            
            
            
This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.
10 responses

EDIT: This problem is that the default testing period for the back test does not correspond to the period I had been previously using. So the only issue I have now is the fillna(0) seeming to forward fill.

I tried to simplify the code by stripping out the majority of the trades and all but one of the securities and now it doesn't seem to be reading the .csv at all! Anyone have any ideas?

EDIT: This problem is that the default testing period for the back test does not correspond to the period I had been previously using. So the only issue I have now is the fillna(0) seeming to forward fill.

Heres the simpler backtest.

Clone Algorithm
0
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
import datetime
import math
import numpy
import pandas

def clean_col(df):
    df = df.fillna(0)
    df = df[['Nshares', 'sid']]
    #log.info(' \n %s % df.head()')
    return df

def initialize(context):
    #
    #Read universe
    context.SPY=sid(8554)
    context.Sectors=[sid(19662)]#, sid(19659), sid(19656), sid(19661), sid(19655), sid(19658), sid(19660), sid(19654), sid(19657)]  
    
    #Read the rankings
    fetch_csv('https://dl.dropboxusercontent.com/s/0y894yo5yg1y9pm/Trades.csv',
              date_column='Date',
              post_func=clean_col)

    
    

def handle_data(context, data):
    
    for i in context.Sectors:
        if 'Nshares' in data[i] and data[i]['Nshares']!=0:
            log.debug("Ordering "+str(data[i]['Nshares'])+" of ticker "+str(i))
#            order(i,data[i]['Nshares'])
        else:
            log.debug("Nshares not found for "+str(i))

            
            
            
            
            
            
            
            
This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.

EDIT: The issue below was already handled here: https://quantopian.com/posts/fetcher-problems

Hmm.... So it looked like fetcher was working fine on the algo below
but now I'm seeing the following in the logs:

  • 2002-04-04handle_data:113DEBUGWARNING: rank not found for ticker Security(19657 [XLI]) 2002-07-02handle_data:113DEBUGWARNING: rank not
    found for ticker Security(19657 [XLI])
    2002-10-01handle_data:113DEBUGWARNING: rank not found for ticker
    Security(19657 [XLI]) 2002-12-31handle_data:113DEBUGWARNING: rank not
    found for ticker Security(19657 [XLI])
    2003-04-02handle_data:113DEBUGWARNING: rank not found for ticker
    Security(19657 [XLI]) 2003-07-02handle_data:113DEBUGWARNING: rank not
    found for ticker Security(19657 [XLI]) This backtest didn't generate
    any logs.

So 1) for ticker XLI it appears that the fetcher did not gather data,
but it gathered data for the other symbols?? and 2) I get the "This
backtest didn't generate any logs." error.

Am I doing something wrong with these algos above or is it possible
fetcher is a little buggy?

Clone Algorithm
6
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
#Use SPY 15 day MA to determine when to go to cash
#When not in cash buy and hold the most undervalued sectors

import datetime
import math
import numpy
import pandas

def clean_col(df):
    df = df.fillna(method='ffill')
    df = df[['rank', 'sid']]
    log.info(' \n %s % df.head()')
    return df

def initialize(context):
    #
    #
    #Variables for later
    context.day=None
    context.pauseUntil=63
    context.timestep=0
    context.margin_req=0 
    context.totalShorts=0
    context.totalLongs=0
    context.cash=0
    context.oldRanks=None
    context.timer=0
    context.holdNmanyDays=63
    context.liquid=1
          
    #
    #
    #Set constraints on borrowing
    context.pct_invested_threshold=1 #Set limit on percent invested (as a decimal)
    context.init_margin=.01 #Set initial margin requirement    
    context.maint_margin=.01 #Set the maintenance margin requirement   


    #
    #
    #Read universe
    context.SPY=sid(8554)
    context.Sectors=[sid(19662), sid(19659), sid(19656), sid(19661), sid(19655), sid(19658), sid(19660), sid(19654), sid(19657)]  
    
    #Read the rankings
    fetch_csv('https://dl.dropboxusercontent.com/s/7shk9xm1xi311at/Ranks_QuantopianTest.csv',
              date_column='Date',
              post_func=clean_col)

    
    

def handle_data(context, data):

    update_newFrame(context, data)

    #Set Liquidate to false
    Liquidate = 0
    
    #If its before the pause time
    if context.timestep == 1:
        nshares=context.cash / data[sid(8554)].price
        order(sid(8554), nshares)
        context.liquid=0
        return
    
    elif context.timestep == (context.pauseUntil-1):
        Liquidate = 1

    if context.timestep < (context.pauseUntil-1): #context.PauseUntil:
        context.timer=0
        return
    
    if context.timer >= context.holdNmanyDays: #reset the timer to 0 after the specified holding period
        #log.debug ("Liquidating and rotating sectors now because "+str(context.timer)+" indicates we have reached "+str(context.holdNmanyDays))
        Liquidate = 1
        context.timer=0
         

    #
    #
    #Its time to trade!
        
    if context.liquid == 1: #if we are in cash    
              
        ts1=None
        tr1=-100
        ts2=None
        tr2=-100
        ts3=None
        tr3=-100

        for stock in context.Sectors:
            if 'rank' in data[stock]:
                if data[stock]['rank']>tr1:
                    ts3=ts2
                    tr3=tr2
                    ts2=ts1
                    tr2=tr1
                    tr1=data[stock]['rank']
                    ts1=stock
 
                elif data[stock]['rank']>tr2:
                    ts3=ts2
                    tr3=tr2
                    tr2=data[stock]['rank']
                    ts2=stock
                
    #            elif data[stock]['rank']>tr3:
    #                tr3=data[stock]['rank']
    #                ts3=stock
        else:
            log.debug ("WARNING: rank not found for ticker "+str(stock))

                            
        if ts1!=None:
            nshares=context.cash*0.49/data[ts1].price
            log.debug ("Buying most undervalued stock "+str(ts1)+" with score of "+str(tr1))
            generate_order(ts1, nshares, context, data) 
            context.liquid=0 #we are not in cash

        if ts2!=None:
            nshares=context.cash*0.49/data[ts2].price
            log.debug ("Buying second most undervalued stock "+str(ts2)+" with score of "+str(tr2))
            generate_order(ts2, nshares, context, data) 
            context.liquid=0 #we are not in cash
        
#        if ts3!=None:
#            nshares=context.cash*0.3333/data[ts3].price
#            generate_order(ts3, nshares, context, data) 
#            context.liquid=0 #we are not in cash
#            log.debug ("Changed context.liquid to "+str(context.liquid))
            
    if Liquidate == 1:
        for i in context.Sectors:
            liquidate_position(i, context)
        liquidate_position(context.SPY, context)
        context.liquid=1
    

    
#
#
#    Supporting Functions
#
#

    

def update_newFrame(context, data):
    #
    context.cash = context.portfolio.cash
    context.portvalue = context.portfolio.positions_value
    context.totalShorts=0
    for sym in data.keys():
        if context.portfolio.positions[sym].amount < 0:
            context.totalShorts += (context.portfolio.positions[sym].amount * data[sym].price)
        else:
            context.totalLongs += (context.portfolio.positions[sym].amount * data[sym].price)

    update_portvals(context)
    
    #Handle assigning the timestep number (1 day is 1 timestep)
    if get_datetime().day <> context.day: #look for a new day
        context.day=get_datetime().day
        context.timestep += 1
        context.timer += 1
        #log.info ( "Cash: "+str(context.cash)+"; Margin Req: "+str(context.margin_req)+" Avail Cash:"+str(context.cash - context.margin_req) )
        if context.timestep>context.pauseUntil:
            if context.cash < context.margin_req: #check for margin calls daily
                generate_marginCall(context, data)
            
    
def update_portvals(context):
    #Update account information when this function is called
    context.total_equity = context.cash + context.portvalue
    context.pct_invested = (context.totalLongs-context.totalShorts) / context.total_equity
    context.pct_cash = context.cash / context.total_equity
    context.margin_req = abs(context.totalShorts * context.maint_margin)
    
        
def generate_order(sym, size, context, data):    
    #log.info("Call to generate_order")
    if size>0: #Opening a long position    

        #log.info("Buy long "+str(size)+" shares "+str(sym) )
        #log.info("Cash = "+str(context.cash)+"; Current Margin Req.="+str(context.margin_req) )                 

        #Is there enough available cash to buy the position
        if (context.cash-context.margin_req) < size * data[sym].price:
            #log.info("Trade canceled : Insufficient funds.")
            return

        #Deduct price from cash and add to portfolio value
        context.cash -= size * data[sym].price
        context.portvalue += size * data[sym].price
        context.totalLongs += size * data[sym].price
        update_portvals(context)

        #Abort the transaction if the percent invested is greater than the threshold
        #before slippage and commissions
        if context.pct_invested > context.pct_invested_threshold:
            context.cash += size * data[sym].price
            context.portvalue -= size * data[sym].price
            context.totalLongs -= size * data[sym].price
            update_portvals(context)

#            if size>100:
#                log.info("Re-generating order for "+str(size*context.pct_invested_threshold)+" instead of "+str(size))
#                generate_order(sym,size*context.pct_invested_threshold, context,data)
#            return
        
        #Abort the transaction if the investment would generate a margin call
        if context.cash < context.margin_req:
#            log.info("Invest would generate a margin call")
            context.cash += size * data[sym].price
            context.portvalue -= size * data[sym].price
            context.totalLongs -= size * data[sym].price
            update_portvals(context)
            return
    
        order(sym,size)

    else: #Opening a short position
        
        #log.info("Generating a short order for "+str(size)+" shares of "+str(sym)+" and context.cash="+str(context.cash)+" and context.margin_req="+str(context.margin_req) )
        #Is there at least enough available cash to cover the initial maintenance margin
        if (context.cash-context.margin_req) < abs(size * data[sym].price * context.init_margin):
            #log.info("Trade canceled")
            return
        
        #Deduct price from cash and add to portfolio value (note that size is negative)
        context.cash -= size * data[sym].price
        context.portvalue += size * data[sym].price
        context.totalShorts += size * data[sym].price
        update_portvals(context)
        
        #Abort the transaction if the percent invested is greater than the threshold
        #before slippage and commission
        if context.pct_invested > context.pct_invested_threshold:
            context.cash += size * data[sym].price
            context.portvalue -= size * data[sym].price
            context.totalShorts -= size * data[sym].price
            update_portvals(context)
            #log.info("Trade canceled")
            return
            
        #Abort the transaction if the investment would generate a margin call
        if context.cash < context.margin_req:
            context.cash += size * data[sym].price
            context.portvalue -= size * data[sym].price
            context.totalShorts -= size * data[sym].price
            update_portvals(context)
            #log.info("Trade canceled")
            return
        
        order(sym,size)
            
        
def generate_marginCall(context,data):
    #This function should be coded to address margin calls
    #log.info("Margin call")
    return(0)

def liquidate_position(sym,context):
    if context.portfolio.positions[sym].amount is not 0:
        log.debug("Liquidating "+str(context.portfolio.positions[sym].amount)+" shares of position "+str(sym))
        order(sym, -context.portfolio.positions[sym].amount)
        
This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.

So the first three posts were one issue I was having with fetch_csv and the last two posts were another issue that I thought was related. The issue in the last two posts was a dumb mistake on my part, realized by John Fawcett (https://quantopian.com/posts/fetcher-problems). The first issue is outstanding and I'm not sure what is going on there.

Hi Daniel,

tl;dr -- What you are seeing is intended behavior for fetcher, which wasn't intended to ingest raw orders. The core issue is your source data has indexing collisions. However, you can adapt your source data to produce the behavior you want.

Some background - the idea for fetcher is to pull in prices, signals, and other values. The data pulled in is translated to a series of events, such that each row in a csv will be a distinct event. The data parameter sent to handle_data always has the most recent values received -- effectively forward filling.

The confusing bit is that the data you are fetching is used to create the index on the dataframe fed into the simulation. Because the rows have sparse dates, the dataframe itself will have the same sparse dates as its index, and there will be no NaNs for "missing" days.

My initial thought to fix the problem was to massage the dataframe to have a complete index of trading days, letting pandas fill in missing values with NaNs.

This requires some advanced pandas programming. To create the "missing" days, you need the dataframe produced by fetcher to have all the trading days, not just the days where you generated orders. My strategy was to re-index the dataframe with the datetimeindex produced from the zipline trading calendar.

This is complicated firstly because the index in the dataframe is not unique. Since you have orders for multiple securities on each day, there are multiple entries in the index for each day. Look for 7/8/2002 in your source data, for example, there are four orders. The format of the data in the csv is known as "record" or "stacked". Pandas includes a method called pivot, which can reshape the data (more info here: http://pandas.pydata.org/pandas-docs/stable/reshaping.html). This code should make a column for each symbol, create a unique index for the date, and make NShares the value of each cell:

pivot = df.pivot(columns="symbol", index="Date", values="Nshares")  

However, this call fails with your source csv, because there are some days that have multiple orders for the same symbol (e.g. XLK has a buy and sell on 7/8/2002), and pandas needs to be able to create a unique index of date,symbol to do the pivot. If you plan to place multiple orders per day, your date field needs more resolution, to avoid index collisions.

Given the issues with reshaping the data, it occurred to me that feeding orders to your algorithm this way conflicts with "expected" use cases for Fetcher, and the best resolution might be to just reformat your input data. My advice is to change your source csv to have "target_position_size" in number of shares for a target position, instead of order amounts. That way you can compare your current position in the sid to the target position from the csv, and place orders accordingly.

thanks,
fawce

Disclaimer

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by Quantopian. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. No information contained herein should be regarded as a suggestion to engage in or refrain from any investment-related course of action as none of Quantopian nor any of its affiliates is undertaking to provide investment advice, act as an adviser to any plan or entity subject to the Employee Retirement Income Security Act of 1974, as amended, individual retirement account or individual retirement annuity, or give advice in a fiduciary capacity with respect to the materials presented herein. If you are an individual retirement or other investor, contact your financial advisor or other fiduciary unrelated to Quantopian about whether any given investment idea, strategy, product or service described herein may be appropriate for your circumstances. All investments involve risk, including loss of principal. Quantopian makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances.

Hi John -

A little background on what I'm attempting here.... I been developing a backtester, similar to Quantopian, since November of last year. Of course, being just one person, there are a number of features and things that I have yet to include - not the least of which is the potential to interface with a trading platform. So I was excited to shift from working on creating the infrastructure of a backtester to using Quantopian and actually working on algorithmic models. However, I've been observing discrepancies between the two backtesters and been trying to resolve them. Some issues have involved the benchmark (https://quantopian.com/posts/question-regarding-the-benchmark), some involve price differences in the daily closing prices (https://quantopian.com/posts/problems-with-data-feeds-prices), and some are just specific to assumptions made within the backtester ( https://www.quantopian.com/posts/sector-rotation-strategy-dot-dot-dot ).

So far I have not found anything "wrong" in either backtester and, as I resolve the differences between the two, the answers seem to converge. The final step is to essentially have one backtester read the other backtester's log of trades and vice versa, to verify the results are nearly exact.

As far as the issue with the fetcher, I think I understand... My assumption was that "fetched" data was somehow appended to the data block with all the security information and that if dates were missing then they would become NAN. I guess that assumption was wrong....

As a hypothetical, if I called a string of data that had "signal" information, let's say it is not specific to a single security, and all dates within the backtest were present except for a few, would the missing few be automatically forward filled? Is there any way to NOT forward fill those missing dates when backtesting?

As far as the "unique" combination of date and symbol I can adjust my in-house backtester log to handle this. No problem. Thanks for looking into this.

Done. Thanks John.

Clone Algorithm
4
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
import datetime
import math
import numpy
import pandas

def clean_col(df):
    df = df.fillna(0)
    df = df[['Nshares', 'sid']]
    log.info(' \n %s % df.head()')
    return df

def initialize(context):
    #
    #Read universe
    context.SPY=sid(8554)
    context.Sectors=[sid(19662), sid(19659), sid(19656), sid(19661), sid(19655), sid(19658), sid(19660), sid(19654), sid(19657)]  
    
    #Read the rankings
    fetch_csv('https://dl.dropboxusercontent.com/s/5r7bgm5nj9eaj06/Verbose_TradeLog.csv',
              date_column='Date',
              post_func=clean_col)

    
    

def handle_data(context, data):
    
    for i in context.Sectors:
        if 'Nshares' in data[i] and data[i]['Nshares']!=0:
            log.debug("Ordering "+str(data[i]['Nshares'])+" of ticker "+str(i))
            order(i,data[i]['Nshares'])
        #else:
            #log.debug("Nshares not found for "+str(i))

            
This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.

Hello fawce,

I'm trying to use df.pivot() as described above on a CSV imported via fetcher. The pivot is:

MDLZ    15/02/2008  23.50064225  
SNY     15/02/2008  1.1108326  

to

                 MDLZ                   SNY  
15/02/2008       23.50064225            1.1108326  

and I can get as far as a DataFrame that seems to be correct. What I can't do is do anything with it. I'm creating the DataFrame using 'fetcher' pre-func but if I try to return it I get:
KeyError: no item named date

This is the code so far:

from datetime import datetime

def get_data(df):  
    myPivot = df  
    # Convert mm/dd/yyy to yyyy-mm-dd  
    for i in range (0, len(df['date'])):  
       myPivot['date'].ix[i] = str(datetime.strptime(str(df['date'].ix[i]), '%m/%d/%Y').date())  
    myPivot = myPivot.pivot(index="date", columns="symbol", values="change")  
    print myPivot  
    return myPivot

def initialize(context):  
    context.sid = sid(2)  
    fetch_csv('https://raw.github.com/pcawthron/StockData/master/berkshire_new_indexed.csv',  
               symbol='sec',  
               date_column='date',  
               date_format='%m/%d/%Y',  
               pre_func=get_data)

def handle_data(context, data):  
    return  

Any ideas, please?

P.

It wanted a 'date' column so I gave it a 'date' column. I now get the pivot rows in handle_data but how do I access the prices? This is the log output:

2002-02-15 PRINT SIDData({'COP': nan, 'STRZA': nan, 'WLP': nan, 'NEE': 46.78793461, 'DVA': nan, ...  

P.

Clone Algorithm
7
Loading...
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
from datetime import datetime

def pivot_data(df):
    myPivot = df
    # Convert mm/dd/yyyy to yyyy-mm-dd
    for i in range (0, len(df['date'])):
       myPivot['date'].ix[i] = str(datetime.strptime(str(df['date'].ix[i]), '%m/%d/%Y').date())
    myPivot = myPivot.pivot(index="date", columns="symbol", values="change")
    myPivot['date'] = myPivot.index[:]
    return myPivot


def initialize(context):
    fetch_csv('https://raw.github.com/pcawthron/StockData/master/berkshire_new_indexed.csv',
               symbol='sec',
               date_column='date',
               date_format='%Y-%m-%d',
               pre_func=pivot_data)
    context.stocks = { 'GPS'  : sid(3321),
                       'HON'  : sid(25090),
                       'LIZ'  : sid(23309),
                       'NKE'  : sid(33472),
                       'ODP'  : sid(5583),
                       'OSI'  : sid(5712),
                       'USB'  : sid(25010),
                       'NEE'  : sid(2968),
                       'TT'   : sid(7622),
                       'PTR'  : sid(21439),
                       'LVLT' : sid(18587),
                       'svm'  : sid(7227),
                       'PG'   : sid(5938),
                       'WMT'  : sid(8229),
                       'WU'   : sid(32603),
                       'UNP'  : sid(7800),
                       'FDC'  : sid(2755),
                       'OMC'  : sid(5651),
                       'PNC'  : sid(6068)}            

def handle_data(context, data):
    print data['sec']
    
This backtest was created using an older version of the backtester. Please re-run this backtest to see results using the latest backtester. Learn more about the recent changes.
There was a runtime error.