Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
RISK ON /RISK OFF Algo

First off, I would like to thank Delaney Granizo-Mackenzie for his help coding this Algo. I have great trading ideas, but still leaning python.

This algo attempts to be invested in the right asset class on a monthly basis. to accomplish this, we first calculate the ratio of the two assets, and calculate the MA of that ratio. Buy Equity if Ratio > MA ( risk on) , Buy Bonds if Ratio < MA ( Risk off). In this backtest , I use EFA ( no reason) and TLT. Return and Draw down are quite acceptable for such a simple algo.

I'm working on a better version of this , and will share the results soon enough.

Cheers

Lionel

11 responses

I just realized that I used "SPY" as a benchmark. Should of used "EFA , for a better comparison.

I like the concept, I only wonder if a bond portfolio is a good hedge vs the market going forward. Look at the '08 crash, we had room to reduce interest rates while the market was tanking, this provided returns in the bond portfolio. However in my view, it is likely during the next large drawdown in the market there will be little room to drop rates - and if the fed is still trying to raise rates at that time then your bond value is only declining. I like the approach, but I wonder if there is a better asset class than bonds to hedge the market going forward?
.. Just my opinion, I'm sure many will think the complete opposite

Happy to help! Glad you got this one working.

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.

I wonder why the algoriithm backtest in daily mode will have the big difference performance?
the algorithm handle_entry through schedule_function, and through history() to calculate MA, it shouldn't have the big difference performance?
could help clarify what caused this issue?

Hey Novice, the issue here is that in daily mode, you only see prices from the market close, and orders are executed on the next market close. The delay in order execution can cause problems for some algorithms, I would just run in minute mode and use schedule_function to have the most accurate backtests. Our own Alisa explains it better than I in this thread.

@Leonel.. is this leverage?

Nope , no leverage. i added custom data to show you cash and leverage levels.

Yup, leverage of 1.99 actually.

Lionel, I don't want you to feel bad about this, we have ALL been cruising along thinking context.account.leverage was gold, not true in the custom chart because it only records the last value (of 390 possible) of the day when in minute mode. You are helping reveal this for the first time. It's going to help a lot of people down the line. It's a great example because it is very clear. You provided a great service in this algo (and it might be repairable now).

Problem

That result would not be achieved without requiring ~2x the starting capital.
In the first 1 single solitary minute that TLT went unfilled, MDY took cash to negative -$9,888.
Then back again 4 minutes later when TLT sold.
Margin account required, with borrowing costs.

It is an illustration of intraday over-leverage unseen by context.account.leverage

The value of context.account.leverage is relied upon and trusted in many algorithms on Quantopian currently and missing leverage intraday spikes in record(). (Would be seen in logging).

1970-01-01 initialize:32 INFO 2005-01-03 to 2005-03-30  10000  minute  
2005-01-31 track_orders:113 INFO  15   Buy 109 TLT at 91.38       cash 10000  
2005-01-31 track_orders:85  INFO  16      Bot 109 TLT at 91.41    cash 30  
2005-02-28 track_orders:113 INFO  15   Sell -109 TLT at 91.05     cash 67  
2005-02-28 track_orders:113 INFO  15   Buy 81 MDY at 122.95       cash 67  
2005-02-28 track_orders:89  INFO  16         TLT -109 unfilled        <==== Due to this  
2005-02-28 track_orders:85  INFO  16      Bot 81 MDY at 122.87    cash -9888  <==== Negative  
2005-02-28 track_orders:89  INFO  17         TLT -109 unfilled  
2005-02-28 track_orders:89  INFO  18         TLT -109 unfilled  
2005-02-28 track_orders:89  INFO  19         TLT -109 unfilled  
2005-02-28 track_orders:85  INFO  20      Sold -109 TLT at 90.97  cash 20  
End of logs.  

It would produce very different results at Interactive Brokers vs. the backtest (except for margin accounts).

Solution

A request that Quantopian provide context.account.leverage_max to make those spikes visible more easily may need to come from you, the members.

This can be dropped into any algo for a quick sanity check in the interim:

def handle_data(context, data):  
    if 'mx_lvrg' not in context:  
        context.mx_lvrg = 0                  # init this instead in initialize() for better efficiency  
    if context.account.leverage > context.mx_lvrg:  
        context.mx_lvrg = context.account.leverage  
        record(mx_lvrg = context.mx_lvrg)    # Record maximum leverage encountered  

This would be easier:

    record(max_lvg = context.account.leverage_max)  

Yes, I too was being fooled by context.account.leverage although I felt like something was off, it wasn't clear until working thru this code and adding track_orders() along with the modification to add each minute and portfolio cash.

There's quite a bit of code added here as I was trying to wrap my head around what was happening, don't let it intimidate you, if anyone would like this to be commented more, I'd be happy to.

Please mouse-over the custom chart and look at the values.

I too Garyha.. figure... something was off... although Im not a familiar... with python code... and how algo works.. but it doesn't seem.... to add up...
That's why... Im asking if this was leverage... since his algo perform.. well... in short amount of time... I suspect its leverage.... but could not confirm...
since there's no leverage written in his algo... by the way... I dont know how... to diagnose... or print the inner workings of algo like Garyha... whether... the algo perform... correctly as shown.. in the illustration.. as evidence... thanks Garyha... for addressing my concern... about the leverage issue... and not completely... ignoring it as an anomaly....

@garyha

Thank you for exposing this. It's a huge eye opener for me and might delay the live deployment of another Algo I have. I',m sending you a private message to see if you could take a second look at my code.

thanks again,

Lionel

@ lionel.. pls post your corrected algo without the leverage on... thanks... ;)