Trading strategies: No need for the holy grail

We demonstrate that weak trading signals, which do not offer high risk-adjusted returns on their own, can be combined into a powerful portfolio. In other words, no need for holy grails when researching signals.

We start our experiment with some key assumptions. We have 20 signals with annualized log returns of 8% and annualized Sharpe Ratios of 0.6 – not exactly stellar signals. The signals make daily bets. The strategies in this experiment run for 10 years (on a daily basis), but we will later show how the statistics change when the number of observations decline. The experiment is repeated 500 times to get a sense of the distributions of relevant statistics, such as Sharpe Ratios and annualized returns.

An important input variable in trading is the correlation between signals and our experiment is carried out across a sequence of cross-signal correlations from zero to 0.9. Disregarding trading costs (because we are simply interested in relative performances) and using daily rebalancing the distributions of annualized portfolio returns across correlations looks more or less identical. Clearly, having more than one strategy does not improve the annualized return – regardless of the correlations between the strategies.


Blending multiple signals with lower correlation does not enhance returns, but the chart above does hint at the benefit to having more strategies – and especially if those strategies are relatively uncorrelated. The left-most distributions are much narrower and none of the 500 trials have returns below zero (up to and including strategies with correlations of 0.4).

The result becomes clearer when we move to risk-adjusted returns measured by the Sharpe Ratio. Here 20 strategies with zero correlation and low individual annualized Sharpe Ratios of 0.6 turn into a portfolio with an annualized Sharpe Ratio of 3 compared to 0.64 for a portfolio with average correlations of 0.9 between the trading strategies – this translates into a 370% improvement.

What is also fascinating about the chart above is how fast the improvement in Sharpe Ratio declines as the signals become more correlated. Increasing the correlations to 0.2 from 0 results in a decline of 56% in the Sharpe Ratio.

Despite a high Sharpe Ratio and around 50,000 bets across the signals (i.e. trading strategies) the variance of the Sharpe Ratios for the zero cross-signal correlation portfolios is still staggering. One investor might get lucky and produce a Sharpe Ratio of 3.5 (probably turning the person into a multi-billionaire) while another investor with the same types of strategies may be less fortunate, resulting in a Sharpe Ratio of 2.5. Luck does play a role in trading even for high Sharpe Ratio portfolios.

Obviously, an edge becomes clearer with more observations. What happens if our investor only has one year of observations rather than ten years? The chart below shows the explosion in the variances of the Sharpe Ratios across correlations. Despite 5,000 trades most portfolios cannot be separated from random luck. It is clear why data-driven hedge funds prefer higher frequencies (intraday trading). It validates the signals faster.

If we simulate 10,000 time-series with the above properties what is the percentage of them with a p-value lower than 5%? The answer is close to 48%, which could lead most researchers to discard such daily strategies (with an annualized Sharpe Ratio of 0.6). However, blending such weak signals can result in magic – if the correlations are low enough – whereby a portfolio’s combined return stream becomes highly significant. Among the zero correlation portfolios all of them have a p-value of less than 5%.


A daily strategy with an annualized Sharpe Ratio of 0.6 would likely be discarded on its own by a researcher as insufficient to produce anything attractive in trading. But with the right (i.e. low) correlations to existing signals, it could well add value to the portfolio.

This post does not break new ground as the effects of diversification are well-known in the investment community, but it does serve as a reminder that instead of discarding that 0.6 Sharpe Ratio strategy of yours perhaps you can add it to your existing portfolio of strategies, thereby lowering your portfolio volatility and hence allowing for more leverage to be used enhancing the total return.

Note: This post will be the final post (for a while) on random returns and fundamental concepts. Upcoming blog posts will instead focus on specific trading strategies in various asset classes.

# define variables
N <- 252 * 10 # number of observations
M <- 500 # number of trials
cors <- seq(0, .9, .1) # sequence of cross-signal correlations
strats <- 20 # number of strategies
er <- 8 / 252 # expected daily log return in percent
esr <- 0.6 / sqrt(252) # expected daily sharpe ratio

# pre-allocate arrays to store portfolio returns and p-values
port.rets <- array(NA, dim = c(N, M, length(cors)))
port.pv <- array(NA, dim = c(M, length(cors)))

for (i in 1:length(cors)) {

# correlation structure
R <- matrix(1, strats, strats)
R[lower.tri(R)] <- cors[i]
R[upper.tri(R)] <- cors[i]

# transpose Choleski decomposition
W <- t(chol(R))

for (m in 1:M) {

# generate 5 random stratey return streams with zero mean and expected weekly log returns
rets <- matrix(rnorm(N*strats, 0, er / esr / 100), ncol = strats)

# multiply the Cholesky decomposition matrix with our random returns and add drift
rets <- t(W %*% t(rets)) + er / 100

# calculate equal-weighted portfolio return
port.rets[, m, i] <- log(apply(exp(rets) - 1, 1, mean) + 1)

# insert p-values for portfolios
port.pv[m, i] <- t.test(port.rets[, m, i])$p.value


cat(paste("Calculations done for correlation", cors[i]), "\n")


# calculate annualized Sharpe ratio and returns <- apply(port.rets, c(2, 3), mean) / apply(port.rets, c(2, 3), sd) * sqrt(252)
ann.ret <- apply(port.rets, c(2, 3), mean) * 252

# calculate percent of portfolios with p-value below 5% across correlations
pv <- apply(port.pv < 0.05, 2, mean)

# calculate theoretical percentage of time-series with p-value below 5% for the specified strategy properties
# daily strategy with annualized Sharpe Ratio of 0.6
t.pv <- sum(replicate(10000, ifelse(t.test(rnorm(252 * 10, 8 / 252 / 100, (8/252/100) / (0.6/sqrt(252))))[["p.value"]] < 0.05, 1, 0))) / 10000

# create data.frame for ggplot2 charts of p-values
pv.df <- data.frame(P.value = c(t.pv, sort(pv)) * 100,
Name = c("Single signal p-value", paste("Correlation (", sort(cors, decreasing = TRUE), ")", sep = "")))

# create data.frame for ggplot2 charts of annualized return and Sharpe Ratio
stat.df <- data.frame(Sharpe = c(,
Ann.Returns = c(ann.ret),
Correlation = rep(cors,each = M))