Back to Community
Problem with restrictions. Any help?

Hello community,
I am starting with quantopian and I would really appreciate some help. I am working on improving this algorithm that buys the best 4 Sector ETFs each month, but when the SPY<MA200_SPY (bear market) it buys a bond instead and no ETFs. In this sense, I can't seem to find out why if one month I have a bond, and next I need 4 ETFs (and therefore I need to sell the bond), it doesn't actually sell it (that's why I have 5 positions, and double leverage). Any one could help me find out what's the problem with the restrictions below?
Furthemore, I have tried to tell the algorithm not to sell an ETF I already have, if next month it keeps being in the top 4 (I don't want to sell the same thing I need to immediately buy).

for stock in context.portfolio.positions:

    #If the SP>SP_MA200  
    if spy_ma1>spy_ma200:  
        #If I have the bond in my portfolio, sell the bond  
        if sid(23921) in context.portfolio.positions:  
            order_target_percent(sid(23921), 0)  

        #If I don't have the bond (because I have ETFs)  
        else:  
            #If the ETFs on my portfolio are not on the Top 4 this month, sell the ETFs I have  
            if stock not in context.longs:  
                order_target_percent(stock, 0)  

    #If SP<SP_MA200  
    else:  
        #If we don't have the bond in the portfolio, sell the ETFs  
        if context.shy not in context.portfolio.positions:  
            order_target_percent(stock, 0)  
Clone Algorithm
111
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
# Backtest ID: 596f3e5faf493a527a31843b
There was a runtime error.
6 responses

The problem is that the above logic is within a for loop

for stock in context.portfolio.positions:

The code above is being executed as many times as there are open positions. Therefore, if you have 4 ETFs in your portfolio, you will sell sid(23921) 4 times. You really just want to sell it once. The fix is to move that statement outside of the for loop. There are a few other problems with the code too. You don't need to call close each month for example. You also do not need to check if a security is currently held to close the position

if sid(23921) in context.portfolio.positions:  
    order_target_percent(sid(23921), 0)

Just do this

order_target_percent(sid(23921), 0)  

Anyway, attached is an algorithm which I think does what what you want...

Good luck.

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
# Backtest ID: 596f5cad74e8d15265c85f17
There was a runtime error.

Hey Dan,
First of all, thanks for your time and effort! However, in the second part (bull market), I think you are buying but not selling the ETFs that you already have. For example:
Month 1 I have the following ETFs: A, B, C, D
Month 2 (I need to have the new top 4): A, B, C, E >> You just need to sell D, and replace it for E. In the algo you kindly attached, it doesn't sell.

else:  
    # Sell Treasury Bond 1-3 years if held and buy sector ETFs #that's fine for selling the bond  
    if data.can_trade(context.shy):  
        order_target_percent(context.shy, 0.0)  

    for stock in context.longs:  
        if data.can_trade(stock):  
            order_target_percent(stock, 1.0 / len(context.longs))  
            log.info("Buy" + str(stock))  

    log.info("ETF Month")  

In bear markets the problem is this:
Month 1 (bear): I buy the bond
Month 2 (bear): I don't need to sell the bond (which in your algorithm it does), I just need to keep it and don't buy or sell.

Thank you very much for helping! Best regards

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
# Backtest ID: 596f6cc8f154994e21b8d807
There was a runtime error.

Oops. Correct. Forgot to sell anything that isn't currently in 'context.longs'.

This should be what you want. See attached algo.

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
# Backtest ID: 596f7725bf57a9520c8753f6
There was a runtime error.

Hey Dan! Thanks again for your time and patience, I truly appreciate it.
The bond keeps being bought and sold each month. Maybe I should add something like:
if spy_ma1 < spy_ma200:
if context.shy not in context.portfolio.positions:
order_target_percent(stock, 0)

A condition that says:
If it's a bear market and I have the bond in my portfolio, pass
and if it's a bear market and I don't have the bond, buy the bond and sell the stocks

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
# Backtest ID: 596f78f5e69654520576f6ad
There was a runtime error.

Third times a charm? Maybe do your ordering a bit differently. Separate the algo logic from the actual trading logic. That might keep things cleaner. So, put in your algo logic

    if spy_ma1 < spy_ma200:  
        # Go long 100% of Treasury Bond  
        longs = [context.shy]  
        log.info("Safety Month")  

    else:  
        # Go long the ETFs returned in the pipeline  
        longs = context.output.index.tolist()  
        log.info("ETF Month")  

Then do your trading logic which simply buys everything in 'longs' and sells everything else...

    # Now do actual trading  
    # Buy everything in longs  
    for stock in longs:  
        if data.can_trade(stock):  
            order_target_percent(stock, 1.0 / len(longs))  
            log.info("Buy" + str(stock))


    # Sell everything in current positions but not in longs  
    for stock in context.portfolio.positions:  
        if not stock in longs:  
            if data.can_trade(stock):  
                order_target_percent(stock, 0.0)  
                log.info("Sell" + str(stock))  

See attached 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
# Backtest ID: 596f80d3b173484e17f75cf3
There was a runtime error.

Hey Dan! That look's pretty good. Thanks so much for the help! Separating the algo logic from the actual orders was the key. Thanks again