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

Is there a preferred method for setting up an initial portfolio at the start of a backtest?

I'm trying to start out my test with an initial purchase and then, based on performance, balance those positions over time. The handle_data function operates on each frame so currently I check to see if the portfolio is empty and setup my portfolio if it is. However, this seems inefficient to do on every frame.

Perhaps even more confusing to me is that I've noticed, after building several times, and changing the backtest date range, that my previous settings for the portfolio are still in memory. After placing several orders I went back into my code and commented out everything except a log statement which showed that the portfolio object still had the previous orders. However the context.portfolio.cash and context.portfolio.positions_value are reset.

I feel like I must be missing something very basic, so my apologies if I haven't picked up on it.

5 responses

Hello Pumplerod,

I've attached an example that should address your first concern. The code is:

import time

def initialize(context):  
    context.stocks = [sid(24),sid(8554)]  
    context.orders_submitted = False  
    context.initialized = False  
    set_slippage(slippage.VolumeShareSlippage(volume_limit=0.25, price_impact=0.1))  
def handle_data(context, data):  
    t = time.time()  
    # submit initial orders  
    if not context.orders_submitted:  
        for stock in context.stocks:  
            order(stock, 100000000)  
        print 'Initial orders submitted'  
        context.orders_submitted = True  
    # check if initial orders filled  
    if not context.initialized:  
        open_orders = []  
        for stock in context.stocks:  
            open_orders.append(bool(get_open_orders(stock)))  
        if True in open_orders:  
            print 'Open initial orders:'  
            print open_orders  
            return  
        context.initialized = True  
    elapsed = (time.time() - t)/1e-3  
    print elapsed  

Basically, you need to submit your initial orders, and then confirm that they've been filled, prior to executing your re-balancing routine. There is no efficiency hit, because once you get beyond the initialization, you are just checking the initialization flags (context.orders_submitted and context.initialized).

To test the approach when there is slippage, I order a relatively high number of shares, order(stock, 100000000). Particularly under minute-level trading, you may encounter thinly traded securities. I think that the example code I provided will handle that case, as well--you could do a google search to see if you can find some, and try it.

Your second observation sounds like a potential bug. Do you have an example algorithm you could post?

Grant

Thanks Grant. I did wind up employing this very approach, however it never dawned on me to insure that the open order be filled first so that's a really helpful tip.

As to the other "potential bug", just like taking your car to the mechanic, when I tried to create a test case I can no longer recreate the problem. I'm still reasonably certain it happened but alas. I'll keep my eyes open for it.

I've felt on a number of occasions that there has been some unwelcome 'persistance' between consecutive 'Build Algorithm's even after code changes. There is a fairly obvious issue of log entries persisting between runs so this is not a fantastical idea.

P.

Every backtest run is kicked off independently - fresh use of Zipline, etc.- so it would be a highly improbable bug where the position was carried from one run to another. (I never say never when it comes to software bugs. . . )

We did have a persistent problem where the logs from "Build A" were mixing with the logs from "Build B"; that bug took a couple rounds to knock out. To my knowledge that was fixed in early September. If it's still happening, I would appreciate hearing about it.

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.

Hello Dan,

I omitted to say that I felt 'Run Full Backtest' started with 'a clean slate'. I think the log persistance within 'Build Algorithm' is still happening so I will try to capture an example.

P.