Back to Community
Using both fundamental and technical analysis

I'd love to be able to mix indicators that are both technical and fundamental, but it seems like it's hard to do so with Quantopian backtesting.

For example, I can use the fundamentals query tool to screen some stocks and add them to my universe inside the before_trading_start function. But, this is limited in two ways:

1) The universe limit is 200 stocks and I don't have access to price history in this function, so I can't mix technical selection criteria with fundamental criteria that I got from the stock screener.
2) Even after I've selected my 200 stocks and I'm in the handle_data function (or a function called by schedule_function), it's my understanding that the history has not been backfilled for these stocks. I have to wait N number of days to be able to look back N days and compute technical metrics that pertain to the original 200 stocks I screened for.

Does anybody have a good way to work around these issues or advice on how to combine technical and fundamental signals in Quantopian backtesting?

7 responses
  • +1 : I am facing exactly the same issues you mention :-(

For any security added to data you will have data back to the (theoretical) start date around 2002. Provided the security was trading then. A combination of data[stock].start_date and the 2002 cutoff will tell you if you've got data.

This means that if you start a strat on 1/1/2010 and ask for 251 periods in history your first period, for a stock that qualifies as noted above, will be 1/1/2009. Any new securities added through the update_universe, will automatically make available their own history.

I'm tired of having to run a formal back test to produce code examples so you'll have to work with this github repo, but the linked code demonstrates the above theory REF: Plugable code block strategy framework.

I ran that code and will demonstrate the data availability in the log:

2008-02-14 PRINT SPY Begin date:1993-01-29 00:00:00+00:00 first data avail:2007-05-02 00:00:00+00:00  
2008-02-14 PRINT MGA Begin date:1993-01-04 00:00:00+00:00 first data avail:2007-05-02 00:00:00+00:00  
2008-02-15 PRINT SPY Begin date:1993-01-29 00:00:00+00:00 first data avail:2007-05-03 00:00:00+00:00  
2008-02-15 PRINT IRE Begin date:1996-09-17 00:00:00+00:00 first data avail:2007-05-03 00:00:00+00:00  
2008-02-15 PRINT MGA Begin date:1993-01-04 00:00:00+00:00 first data avail:2007-05-03 00:00:00+00:00  

This came from the following code:

    testDataDeck = history(200, "1d", "close_price")  
    for stock in data:  
        print("{0} Begin date:{1} first data avail:{2}".format(stock.symbol, stock.start_date, testDataDeck[stock].index[0]))

You'll notice that an additional security was added (through update_universe) on 2/15/2008. And that this security's data was immediately available.

The above linked strategy's code models both fundamental filter logic as well as some rudimentary technical analytics. If this is what you're referring to when you speak of combining both fundy and TA then this strategy might help. If not, perhaps more clarification is needed.

MT

thanks for the reply. unfortunately the history function is only available for price data but not for fundamentals (at least so it says so in the documentation). so for instance if I want to select stocks which have an increasing gross profit, there is no other way to keep track of the gross profit field myself (in a dictionary in the context object), correct?

Thanks for the reply MT. I thought I had read in the help docs that when a stock is added to the universe, it doesn't have price history. I guess I should've actually checked this myself. Thanks again

Ueli H., We've been finding that although you can only assign, through update_universe, a maximum of 200 securities at one time, you can continue to do so way beyond the 200 limit thought to have been the data length limit. As it turns out you can add 200 securities on period 1, and then add an additional (and different) 200 on period 2 and you will then have 400 in data.

We don't know how var you can go but this behavior has been confirmed. This may be a bug at this time, but, well, there it is.

Whether this addresses your situation may be beside the point. However, you could load up 1000 securities in data (5 consecutive days), and then keep track of their gross profit. Simple testing would confirm this.

Thanks a lot MT !!! Yes this helps (together with finally realizing that the get_fundamentals function is not restricted to 200 securities).

Dear Market Tech,
How can I load 1000 securities in data(5 consecutive days) and at the same time to make sure these 1000 securities are different.
If I simply use

def before_trading_start(context,data):  
    fundamental_df = get_fundamentals(  
        query(fundamentals.valuation.market_cap,  
              fundamentals.valuation_ratios.ev_to_ebitda,  
              fundamentals.income_statement.ebit,  
              fundamentals.valuation.enterprise_value,  
              fundamentals.asset_classification.morningstar_sector_code,  
              fundamentals.operation_ratios.roa,  
              fundamentals.valuation_ratios.pe_ratio,  
              )  
        .filter(fundamentals.valuation.market_cap > 5e7)  
        .filter(fundamentals.operation_ratios.roa > 0.25)  
        .filter(fundamentals.asset_classification.morningstar_sector_code != 103)  
        .filter(fundamentals.asset_classification.morningstar_sector_code != 207)  
        .filter(fundamentals.valuation.shares_outstanding != None)  
        .limit(200)  
        ).T  

I think a lot of securities in the 1000 will be the same. How can I add 200 different ones?
Thanks a lot