I'm trying to replicate the annualized Sharpe ratio of an buy-and-hold strategy for the Dow Jones Industrial Average index for a period consisting of multiple years. I got the daily DJIA (closing) price index (variable: "price") and the risk-free rate (given in a year percentage, variable: "rf").

The procedure I follow:

  • Compute daily log returns, by: log_returns = log(1+(price(t)/price(t-1)-1))
  • Compute daily log risk-free rates, by: log_rf = log(1+(rf/100))/252
  • Compute daily excess returns, by: excess_returns = log_returns-log_rf
  • Compute daily Sharpe ratio, by: daily_sharpe = mean(excess_returns)/std(excess_returns)
  • Compute annualized Sharpe ratio, by: annualized_sharpe = sqrt(252)*daily_sharpe

However the annualized Sharpe ratio doesn't correspond to the reported numbers. Am I missing a step/doing something wrong (with the logs?)?


The calculation used by the paper (Bajgrowicz & Scaillet, December 2012): Sharpe ratio calculation

  • $\begingroup$ Try: calculate the CAGR of the index, then subtract the average risk-free rate (not logged or de-annualized), and divide by the daily arithmetic (not log) standard deviation times the square root of 250 or 252. $\endgroup$
    – John
    Oct 14, 2015 at 13:46
  • $\begingroup$ Unfortunately this approach didn't gave me the desired numbers either. $\endgroup$
    – Wildman
    Oct 14, 2015 at 14:10
  • $\begingroup$ What sharpe ratio is the "correct" answer (and what is the exact period they cover)? $\endgroup$ Oct 22, 2015 at 15:27
  • $\begingroup$ For example from 2-1-1997 up to 29-7-2011 they find a annualized Sharpe ratio of 0.12 and for 2-1-1987 up to 31-12-1996 a Sharpe ratio of 0.66 for the buy-and-hold strategy of the DJIA index (with daily Federal Funds Rates used as risk free rate, hence use the formula Log(1+rf/100)/252). The Excel file with the DJIA data they used (uploaded on Dropbox): DJIA Database $\endgroup$
    – Wildman
    Oct 23, 2015 at 8:37

2 Answers 2


This is how people usually approach calculating SR with logreturns:

getSymbols('DJIA', src='yahoo', from = '2009-01-01')
price <- Cl(DJIA)
log_ret <- log(price/lag(price,1))
mean_log_ret <- mean(log_ret, na.rm=T)
sd_log_ret <- sd(log_ret, na.rm=T)
rf <- 0.0025 # benchmark
SR <- (252 * mean_log_ret - log(1+rf))/(sd_log_ret*sqrt(252))

[1] 0.5565204

UPDATE. SR with geometrically compounding returns:

g_ret <- (price/lag(price,1) - 1)[-1]
n_periods <- length(g_ret)
avg_g_ret <- prod(1 + coredata(g_ret)) ^ (1/n_periods)
annual_g_return <- avg_g_ret^252 - 1
annual_sd_g_return <- sd(g_ret) * sqrt(252)
SR <- (annual_g_return - rf)/annual_sd_g_return

[1] 0.5844989
  • $\begingroup$ That is the same procedure as I'm describing above (only written in a different manner), so I'm doing everything correct (in theory)? $\endgroup$
    – Wildman
    Oct 14, 2015 at 9:57
  • $\begingroup$ Supposedly yes, everything is correct in your code, assuming the desired SR is also calculated on logreturns. What is the "reported" number? $\endgroup$ Oct 14, 2015 at 13:42
  • 3
    $\begingroup$ I suspect there are circa 64 ways to calculate SR depending on how you define returns and volatilities and annualize them. The most fundamental fact about SR: numerator -- excess return over period, denominator -- volatility of excess return over the same period (i.e. return on a unit of risk, or risk adjusted return). From here, you may proceed in several common ways. (1) log returns, see above. (2) arithmetic returns, questionable for long term. (3) geometrically compounded returns. Practically speaking, the last is preferable. Anyways, procedure should be agreed upon prior to calculations $\endgroup$ Oct 14, 2015 at 14:27
  • $\begingroup$ BTW, what is the purpose of this exercise, to get the reported figure? $\endgroup$ Oct 14, 2015 at 14:28
  • $\begingroup$ "Arithmetic" return may mean different things for different people, so you should try all the possible scenarios if you want to backengineer their results exaclty. Anyways, the difference I suspect will be in pct points... $\endgroup$ Oct 14, 2015 at 14:48

Another way to skin cat:

    # risk-free = 0
require( PerformanceAnalytics)
getSymbols('DJIA', src='yahoo', from = '2009-01-01', to ='2014-12-31')
price       <- Cl(DJIA)
simple.ret  <- price/lag(price)-1
# [1] 0.7267

log.ret <- na.omit(ROC(price))
SD <- sd(log.ret)*sqrt(252)
R <- exp(mean(log.ret)*252)-1
SR <- R/SD
# [1] 0.7263711

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.