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

Is this the correct way of creating a new variable that relies on fundamental data from "before_trading_start"? I keep getting an error when running the code on the payout_ratio line... I have tried breaking the line and using the debugger but don't get any return on: "payout_ratio". When I remove the break I get the runtime error: "KeyError: , {}), orders={}, new_orders=[], current_dt=2011-01-04 00:00:00+00:00), recorded_vars={'cash': 1000000.0, 'asset': 1000000.0})>
There was a runtime error on line 59."

def before_trading_start(context):
"""
Called before the start of each trading day.
It updates our universe with the
securities and values found from fetch_fundamentals.
"""
#Number of stocks to be stored in our universe
#num_stocks = 30
#simplify by using f for fundamentals

fundamental_df = get_fundamentals(  
    query(  
        # put your query in here by typing "fundamentals."  
        fundamentals.operation_ratios.revenue_growth,  
        fundamentals.asset_classification.morningstar_sector_code,  
        fundamentals.balance_sheet.ordinary_shares_number,  
        fundamentals.valuation_ratios.book_value_per_share,  
        fundamentals.valuation_ratios.earning_yield,  
        fundamentals.balance_sheet.total_assets,  
        fundamentals.balance_sheet.total_liabilities,  
        fundamentals.earnings_report.dividend_per_share,  
        fundamentals.earnings_report.basic_eps,  
        fundamentals.asset_classification.profitability_grade,

    )  
    .filter(fundamentals.valuation.market_cap > 0)  
    .filter(fundamentals.earnings_report.dividend_per_share > 0)  
    .filter(fundamentals.earnings_report.basic_eps > 0)  
    .filter(fundamentals.valuation_ratios.book_value_per_share > 0)  
    .filter(fundamentals.valuation_ratios.earning_yield > 0)  
    .filter(fundamentals.valuation.shares_outstanding != None)  
    .order_by(fundamentals.asset_classification.profitability_grade.asc())  
    .limit(30),  
)  

# Filter out only stocks that fits in criteria  
context.stocks = [stock for stock in fundamental_df]  

# Update context.fundamental_df with the securities that we need  
context.fundamental_df = fundamental_df[context.stocks]  

update_universe(context.fundamental_df.columns.values)  

record (cash = context.portfolio.cash, asset = context.portfolio.portfolio_value)  

def handle_data(context,data):

payout_ratio = (context.fundamental_df['dividend_per_share'])/(context.fundamental_df['basic_eps'])  
book_value = context.fundamental_df['book_value_per_share']  
ROE = context.fundamental_df['earning_yield']  
5 responses

@Stephen

So after you get your fundamental dataframe and set it to your context.fundamental_df you don't need to reindex it by going context.fundamental_df = fundamental_df[context.stocks] instead just set it equal like this context.fundamental_df = fundamental_df After you do this things will go much smoother. BTW the fundamental_df has the fundamentals as the row indices and the the securities as the column values. Since that is the case to get the data for a certain fundamental you need to use the Pandas .loc method as that will get the entire row. The code below works, give it a shot and let me know if it's what you are looking for!

James Christopher

def before_trading_start(context):  
    """  
    Called before the start of each trading day.  
    It updates our universe with the  
    securities and values found from fetch_fundamentals.  
    """  
    #Number of stocks to be stored in our universe  
    #num_stocks = 30  
    #simplify by using f for fundamentals

    fundamental_df = get_fundamentals(  
        query(  
            # put your query in here by typing "fundamentals."  
            fundamentals.operation_ratios.revenue_growth,  
            fundamentals.asset_classification.morningstar_sector_code,  
            fundamentals.balance_sheet.ordinary_shares_number,  
            fundamentals.valuation_ratios.book_value_per_share,  
            fundamentals.valuation_ratios.earning_yield,  
            fundamentals.balance_sheet.total_assets,  
            fundamentals.balance_sheet.total_liabilities,  
            fundamentals.earnings_report.dividend_per_share,  
            fundamentals.earnings_report.basic_eps,  
            fundamentals.asset_classification.profitability_grade,

        )  
        .filter(fundamentals.valuation.market_cap > 0)  
        .filter(fundamentals.earnings_report.dividend_per_share > 0)  
        .filter(fundamentals.earnings_report.basic_eps > 0)  
        .filter(fundamentals.valuation_ratios.book_value_per_share > 0)  
        .filter(fundamentals.valuation_ratios.earning_yield > 0)  
        .filter(fundamentals.valuation.shares_outstanding != None)  
        .order_by(fundamentals.asset_classification.profitability_grade.asc())  
        .limit(30),  
    )  

    # Filter out only stocks that fits in criteria  
    context.stocks = [stock for stock in fundamental_df]  

    # Update context.fundamental_df with the securities that we need  
    context.fundamental_df = fundamental_df#[context.stocks]  

    update_universe(context.fundamental_df.columns.values)  

    #record (cash = context.portfolio.cash, asset = context.portfolio.portfolio_value)  
def initialize(context):  
    pass

def handle_data(context, data):  
    print(context.fundamental_df)  
    payout_ratio = (context.fundamental_df.loc['dividend_per_share'])/(context.fundamental_df.loc['basic_eps'])  
    book_value = context.fundamental_df.loc['book_value_per_share']  
    ROE = context.fundamental_df.loc['earning_yield']  
    print(payout_ratio)  
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.

Thanks James, that did the trick! Just a quick question, further down in my algo I am trying to define two variables for every stock that I have and these variables are dependent upon the earnings yield of each and every stock, so in essence I guess you could say I am trying to add two rows - or alternatively store two variables - for every listed stock. The way that I have approached this issue so far is by using the following.


ROE = context.fundamental_df.loc['earning_yield']*10000  
#Multiplied ROE by 10000 to get figures as integers not floats.  
for stock in data:  
    #Multiplied all payouts by 100 to get these as integers divide these later in the process.  
    #Multiplied all retained earnings by 1000 to get these as integers divide these later in the process.  
    if  ROE.any()<= 500:  
        Weight_100_payout=50  
        Weight_retained_earnings=218  
    elif ROE.any()<=4750 :  
        Weight_100_payout=75  
        Weight_retained_earnings=531  
    elif ROE.any()>4750:  
        Weight_100_payout=500  
        Weight_retained_earnings=18119  

I have used the debugger and found that the value returned for Weight_100_payout is equal to 50, there is no series data. To try and simplify the problem I tried to replace all of the ROE's in the if statements with their original definition "context.fundamental_df.loc['earning_yield']*10000" and ultimately came to the same result.

Thanks for your help so far!

@stephen

Can you show a little bit more of your code? I'm trying to understand what you're trying to do and need some more context.

JC

So towards the end of the algo I use an if statement to try and define two weight variables for every stock under analysis. I then plan to use these two variables to find a fair price value of the stock and send an order to buy if the fair price value is less than the current price of the stock. Here's some more of the algo.

import pandas as pd
import numpy as np

def initialize(context):
pass

def before_trading_start(context):
"""
Called before the start of each trading day.
It updates our universe with the
securities and values found from fetch_fundamentals.
"""
#num_stocks = 30

fundamental_df = get_fundamentals(  
    query(  
        # put your query in here by typing "fundamentals."  
        fundamentals.operation_ratios.revenue_growth,  
        fundamentals.asset_classification.morningstar_sector_code,  
        fundamentals.balance_sheet.ordinary_shares_number,  
        fundamentals.valuation_ratios.book_value_per_share,  
        fundamentals.valuation_ratios.earning_yield,  
        fundamentals.balance_sheet.total_assets,  
        fundamentals.balance_sheet.total_liabilities,  
        fundamentals.earnings_report.dividend_per_share,  
        fundamentals.earnings_report.basic_eps,  
        fundamentals.asset_classification.profitability_grade,


    )  
    .filter(fundamentals.valuation.market_cap > 0)  
    .filter(fundamentals.earnings_report.dividend_per_share > 0)  
    .filter(fundamentals.earnings_report.basic_eps > 0)  
    .filter(fundamentals.valuation_ratios.book_value_per_share > 0)  
    .filter(fundamentals.valuation_ratios.earning_yield > 0)  
    .filter(fundamentals.valuation.shares_outstanding != None)  
    .order_by(fundamentals.asset_classification.profitability_grade.asc())  
    .limit(30),  
)  

# Filter out only stocks that fit in criteria  
context.stocks = [stock for stock in fundamental_df]  

# Update context.fundamental_df with the securities that we need  
context.fundamental_df = fundamental_df  
update_universe(context.fundamental_df.columns.values)  

record (cash = context.portfolio.cash, asset = context.portfolio.portfolio_value)  

def handle_data(context,data):
#print context.fundamental_df
book_value = context.fundamental_df.loc['book_value_per_share']

ROE = context.fundamental_df.loc['earning_yield']*10000  

for stock in data:  
    #Multiplied ROE by 10000 to get figures as integers not floats.  
    #Multiplied all payouts by 100 to get these as integers.  
    #Multiplied all retained earnings by 1000 to get these as integers.  
if  ROE.any()<= 500:  
    Weight_100_payout=50  
    Weight_retained_earnings=218  
elif ROE.any()<=4750 :  
    Weight_100_payout=75  
    Weight_retained_earnings=531  
elif ROE.any()>4750:  
    Weight_100_payout=500  
    Weight_retained_earnings=18119  

for stock in data:  
    price=data[stock].price  
    fair_price = (1/(Weight_100_payout/Weight_retained_earnings))*book_value  
    ratio=fair_price/price  

if ratio>1.2:
order_target_percent(stock, 0.05,MarketOrder())

okay now I can help!

So in your first for loop you are iterating through every security in your universe. And accoring to some logic you are setting some variables to a predefined value. When programming you need to recognize the 'scope' of a variable. If you define a variable inside of a loop then it will only be available in the loop. So what is happening in your code is that you are setting a bunch of variables that are never used. They don't automatically get binded to the current security you are at in you iteration. In addition, if you are trying to do some logic on the ROE for each security you need to access that security in the loop, which you are currently not doing.

One last point I'd like to make that would make your code much simpler: combine your for loops. Since it looks like you are trying to place an order for every security you can just move your fair_price and buy logic into the for loop with you variable assignments. that would solve the issue of scope and be faster.