What Quantopian use as approximation of risk-free return to calculate Sharpe Ratio ?

What Quantopian use as approximation of risk-free return to calculate Sharpe Ratio ?

13 responses

The risk free rate used is gotten from the US treasuries data repository, the code is in zipline, you can check it out at https://github.com/quantopian/zipline/blob/master/zipline/data/treasuries.py.

The raw data is at http://data.treasury.gov/feed.svc/DailyTreasuryYieldCurveRateData.

@David Edwards
Which one ?
1 mo 3 mo 6 mo 1 yr 2 yr 3 yr 5 yr 7 yr 10 yr 20 yr 30 yr

Hi Vladimir,
The answer to this is actually dependent on the range of the backtest. Unfortunately the engineer who built it is out today, but it looks like the curve used is the smallest duration that spans the entire period. The function below selects the duration used, the source code can be found in Zipline's risk module.

def select_treasury_duration(start_date, end_date):
td = end_date - start_date
if td.days <= 31:
treasury_duration = '1month'
elif td.days <= 93:
treasury_duration = '3month'
elif td.days <= 186:
treasury_duration = '6month'
elif td.days <= 366:
treasury_duration = '1year'
elif td.days <= 365 * 2 + 1:
treasury_duration = '2year'
elif td.days <= 365 * 3 + 1:
treasury_duration = '3year'
elif td.days <= 365 * 5 + 2:
treasury_duration = '5year'
elif td.days <= 365 * 7 + 2:
treasury_duration = '7year'
elif td.days <= 365 * 10 + 2:
treasury_duration = '10year'
else:
treasury_duration = '30year'

return treasury_duration



Hmm that doesn't seem right. The 'risk-free' rate usually means the return of a continuously-compounded bank account, which these days is assumed to be the return of daily-compounded overnight index swap rates. Generally, it's the 'cost of money', financing rate, funding rate, etc, which in the context of quantopian, could either be the opportunity cost of uninvested funds (ie. the brokerage overnight rate, or money market sweep rate), or the real cost of margin fund (ie. the brokerage margin loan rate).

I am not sure how one would argue that long-term bond rates are the correct choice, given they are neither risk free nor a plausible opportunity cost. I would probably argue for using the 3-month LIBOR rates on a rolling basis is probably the most appropriate proxy, given that OIS rates were not that liquid until recently.

EDIT: I don't mean this to be a statement of fact, just my opinion. I wouldn't have expected long-term bonds to be used as a risk-free rate in an ongoing daily-marked possibly-self-financing algorithmic trading strategy's Sharpe ratio.

It doesn't seem right to me ether.

Let's calculate what Quantopian use as approximation to risk free interest rate.
(I will take data from Jeffery contest metric,who initiated this investigation). https://www.quantopian.com/leaderboard/5552d8b7c4b238fb42000579?month=6&year=2015
but the results are the same on any context data.

As of now it is
Annual Returns 5.158%
Annual Volatility 2.111%
Sharpe 1.297
If
Sharpe Ratio = (Annual Returns-Risk Free Return)/Annual Volatility
then
Risk Free Return = Annual Returns - Sharpe Ratio*Annual Volatility
Risk Free Return = 5.158-1.297*0.8752 = 2.4200
Witch corresponding to 10 year US Treasury Yield
By Zipline's risk module code

def select_treasury_duration(start_date, end_date):
td = end_date - start_date
if td.days <= 31:
treasury_duration = '1month'


It should choose 1 month US T-Bill Yield =-0.010
http://www.investing.com/rates-bonds/usa-government-bonds?maturity_from=10&maturity_to=290
Conclusion:
1.Zipline's risk module choosing wrong US Treasury (not as written in the code) -Please Fix the bug.
2.US Treasury Yields higher than 3 month TBill may not be accepted as approximation to risk free interest rate.
Please remove them from Zipline's risk module code

@Simon, I agree with your opinion as well, a risk free rate is a short term (overnight) rate, other rates should be inferred from that rate in my opinion. The 3 month LIBOR is a pretty commonly used risk free rate, but there's several schools of thought on the subject. I will bring this up and would love to hear from others on the subject.

This is a really important component of strategy evaluation in my opinion, do you think making the short rate configurable is a worthwhile project? If so I'd like to hear some thoughts on how that might look from an api standpoint.

@Vladimir, I have not dug into your example yet, but conclusion 1. sounds like a bug and we will look into it, if you already know what's causing it feel free submit a PR or point us in the right direction. Conclusion 2. is your opinion (one I agree with) on a subjective matter, so we cannot just remove the longer term rates. These kinds of subjective issues are a big part of why zipline is an open sourced project. Rather than delete code, a better solution would be a configurable api capable of supporting multiple subjective opinions. Let me know what that might look like to you and we can work towards a more robust solution.

@ David Edwards

Thank You for timely response.
1.I figured out the bug using absolutely not Pythonian skills so you probably better than me can
locate exact point of the problem.
Let me know when it will be solved.

2.If there is no way to remove US Treasury Yields higher than 3 month T-Bill than
Yours recommendation about configurable api capable of supporting multiple subjective opinions
is the solution to the problem with only one condition:
Quantopian will never use in default configuration instruments which may not be considered as
approximation to risk free interest rate.

A bit puzzled by the discussion here. I thought when you are looking at HFT, the risk free rate is dropped. Irene Aldridge book High-Frequency Trading: A Practical Guide to Algorithmic Strategies and Trading Systems in page 108 stated "most instruments HFT with no positions carried overnight, the position carrying costs are zero. Therefore, the high-frequency Sharpe ratio is computed as SR = annualized average return / annualized standard deviation. I would think that most of the algo here at least at the minutely level can be classified as high-frequency.

Sure, if you are all cash by the end of the day, then arguably your cost of capital is zero, since you still earn the overnight interest on that cash.

David, I took a look through the zipline code, it's a bit confusing to be honest, it looks like it's searching through possibly daily updates of the entire treasury yield curve, searching for the "closest" long-term rate to whatever the target period is ? If so, that might explain why the Sharpe ratio appears to jump around so much in backtests, since it keeps using different yard sticks for the risk-free rate? (total hypothesizing).

That would certainly be incorrect, in my view. IF one were to use say, the 10 year treasury rate, for a 10 year backtest (already dubious), then one would fetch the 10 year treasury rate as of the first day of the backtest, and calculate the Sharpe ratio for the entire backtest using the annualized compounded rate that you fetched just once. This is because you are assuming that you took out a 10-year loan to fund this strategy, and so you want to know what it's performance is like, over top of the hurdle of the cost of your capital. You certainly wouldn't look up the new 10-year rate tomorrow, I wouldn't think - that will add a lot of unnecessary volatility to the Sharpe ratio, and it's probably just wrong.

Far more reasonable would be to assume that the account is funded like a margin loan, and use the overnight rate or some proxy plus a fixed adjustable spread. Perhaps IB would just give you a CSV of their historical margin loan rates for the last 15 years?

Re: the bug above,

choose_treasury = functools.partial(choose_treasury, lambda *args: '10year',
compound=False)


I did notice that in cumulative.py which seems a bit suspect...

I cringed when I saw that partial function as well Simon. If '10year' is replaced with '3month' in that line it does look like the 3 month rate becomes the default risk free rate for the backtest. Also it looks like the variable rates are only used when creating the risk report which applies to the tabs on the left side of the full backtest screen. I'm pretty sure a different rate gets used for each of those columns which feels wrong to me.

I'm not sure how much backwards compatibility would break if we just switch to a 3 month default, but it would fix the bug Vladimir is referring to, I'm guessing everyones backtests will look a little better too. I think being able to set the risk free rate in initialize would be ideal, but it doesn't look like it will be a quick win to get done.

This is the OIS rate for USD swaps and I think should be used if Quantopian doesn't have another funding rate.

When that type of error is found in a timely fashion,
there's no reason to stick with the bad calculations.
Dan Dunn

I can not see any changes .
Zipline's risk module still choosing wrong US Treasury (not as written in the code)
It is not a risk free rate 2.4%
Standard deviation taken not from excessive return but from return.
This is not Sharpe Ratio at all but somebody's else ratio.
It is very similar to ratio of forgotten father of MPT Roy Arthur
safety-first criterion.

If you want to keep it that way just change name.

I see two problems with the calculation:

1. First is as said above. It does not respect the spirit of what the Sharpe ratio is trying to calculate - namely the leverage independent quality of a strategy. For that, the risk free rate needs to be a cost of leverage, which is always a short term interest rate.
2. The other and maybe more subtle issue is that it creates a look ahead issue in the analysis of performance. By using a rate that matches the length of the backtest, Quantopian is assuming that at the start of the strategy, the investor knows exactly how long the strategy will be managed.

In total this is very disappointing to me. It means that Quantopian, though they make a wonderful service and have done a fabulous thing by opening up the backtester, may not really be populated by enough people with a solid understanding of the finance principles involved. This leads into a different discussion about the contest criteria and the flaws of the selection process. I will save that for a different post.