Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Python Newbie Question

I have been working on the batch transforms example and I just can't seem to figure out how data is stored and accessed in series / dataframes. So in the example given in the docs:

# This is the standard Quantopian function that initializes your data and  
# variables. In it, we define how large of a 'bet' we're making (in dollars) and what  
# stock we're working with.  
def initialize(context):  
    # we will be trading in AMZN and WMT shares  
    context.stocks = [sid(8554),sid(19662)]  
    context.bet_amount = 100000  
    context.long = 0

# This is the standard Quantopian event handling function. This function is  
# run once for each bar of data.  In this example, it the min and max  
# prices for the trailing window.  If the price exceeds the recent high, it  
# goes short; if the price dips below the recent low, it goes long. The algo  
# is a contrarian/mean reversion bet.  
def handle_data(context, data):  
    # Until our batch transform's datapanel is full, it will return None.  Once  
    # the datapanel is full, then we have a max and min to work with.  
    rval = get_values(data)  
    if rval is None:  
        return  
    maximums, minimums = rval  
    for stock in context.stocks:  
        cur_max = maximums[stock]  
        cur_min = minimums[stock]  
        cur_price = data[stock].price  
        cur_position = context.portfolio.positions[stock]  
        order_direction = calculate_direction(stock, cur_min, cur_max, cur_price, cur_position)  
        order_amount = calculate_order_amount(context, stock, order_direction, cur_price)  
        # Optional: uncomment the log line below if you're looking for more detail about what's  
        # going on.  It will log all the information that is a 'moving part' of this  
        # algorithm. Note: if you're doing a full backtest it's a lot of log lines!  
        #logmsg = '\n{s}: max {m} min {i} price {p} position amount {l}\nordering {n} shares'  
        #log.info(logmsg.format(  
        #    s=stock,  
        #    m=cur_max,  
        #    i=cur_min,  
        #    p=cur_price,  
        #    l=cur_position.amount,  
        #    n=order_amount  
        #))  
        order(stock, order_amount)  
# Here we do our test to see if we should buy or sell or do nothing.  This is  
# the main part of the algorithm. Once we establish a position (long or short)  
# we use the context.long variable to remember which we took.  
def calculate_direction(stock, cur_min, cur_max, cur_price, cur_position):  
    if cur_max is not None and cur_position.amount <= 0 and cur_price >= cur_max:  
        return -1  
    elif cur_min is not None and cur_position.amount >= 0 and cur_price <= cur_min:  
        return 1  
    return 0  
# This method is purely for order management. It calculates and returns an  
# order amount to place binary bets.  
# If signal_val is -1, get to a short position of -1 * context.bet_size  
# If signal_val is 1, get to a long position of context.bet_size  
def calculate_order_amount(context, stock, signal_val, cur_price):  
    current_amount = context.portfolio.positions[stock].amount  
    abs_order_amount = int(context.bet_amount / cur_price)  
    if signal_val == -1:  
        return (-1 * abs_order_amount) - current_amount  
    elif signal_val == 1:  
        return abs_order_amount - current_amount  
    else:  
        return 0  
# This is our batch transform decorator/declaration. We set the  
# refresh_period and length of the window.  In this case, once per day we're loading  
# the last 10 trading days and evaluating them.  
@batch_transform(refresh_period=1, window_length=10)  
def get_values(datapanel):  
    # We are looking for the min and the max price to return. Just because it's interesting  
    # we also are logging the current price.  
    prices_df = datapanel['price']  
    min_price = prices_df.min()  
    max_price = prices_df.max()  
    print("Prices:")  
    print(prices_df)  
    print("")  
    print("min_price:")  
    print(str(min_price))  
    print("AND LASTLY")  
    print(str(min_price('8554')))

    if min_price is not None and max_price is not None:  
        return (max_price, min_price)  
    else:  
        return None

I only modified the last function, which I renamed get_values (from minmax). So the data panel is passed to the function and the "prices" row of data is read into prices_df. When I print prices_df I see two columns, one for each SID, with the prices for the time period specified. So far so good. Then I print out min_price and again I get 4 entries, two on the first row specifying the SID and two on the second row specifying the minimum price.

Now here is where I get jammed up. Let's say I just want to evaluate the min_price of the first SID. I tried printing min_price[0] and min_price[0,0] as well as min_price('8554') but so far no progress. Anyone know how I can access just that one ticker's min price?

4 responses

p.s. - I have been reading thru the pandas docs but my progress has been very slow and I was hoping someone could help me out.

I think what you want is

print(min_price[sid(8554)])  

Hey thanks! That worked. How about if I want to access just the last price in the array for each column. For example, if I have 10 tickers and I'm looking at 5 days worth of data, lets say I want to return a series with the last day's price for each ticker divided by its average price over the 5 day period.

This might be similar to what you're looking for; it simply loops through the stocks and adds your five-day average to an array called 'numbers'

numbers = []  
for stock in context.stock:  
   current_price = data[stock].price  
   average = data[stock].mavg(5)  
   last_average = current_price/average  
   numbers.append(last_average)  

Printing 'numbers' will give you all ten tickers with the last day's price for each ticker divided by its average price over the last 5 day period
print numbers Let me know if that works for you

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.