Let me try to explain the experiment which I’ve done here. Inspired by some code samples from pyfolio, I’m trying to fit a bayesian model to infer the sharpe ratio (and its credible interval) for a given series comprised of daily returns.
I’ve generated some synthetic data to represent a skewed and fat tailed distribution. So, in this experiment, I haven’t used any real data, but the return stream should be somewhat representative of a strategy or an asset with extreme skew and kurtosis. The median for the generated values is positive, but there’s strong negative skew and kurtosis.
Using a StudentT distribution to represent the returns, similar to how it is done in pyfolio, it seems that the posterior values for the sharpe ratio distribution are capped at around zero. So if I try to estimate the probability that the sharpe ratio is negative using this posterior, it actually gives me 0 probability, which is not intuitive at all. Since there’s extreme negative skew, I would expect a non negligible probability for the sharpe ratio being lesser than 0. The problem seems related to how the mean_returns
have only positive values in the posterior, when the StudentT distribution is used.
Here is code that I’ve used to do the experiment:
with pm.Model() as model:
mu = pm.Normal('mean_returns', mu=0, sd=0.1)
sigma = pm.HalfCauchy('volatility', beta=1)
nu = pm.Exponential('nu_minus_two', 1 / 10)
returns = pm.StudentT(
'returns',
nu=nu + 2,
mu=mu,
sd=sigma,
observed=_rets
)
pm.Deterministic(
'annual_volatility',
returns.distribution.variance**0.5 *
np.sqrt(252)
)
pm.Deterministic(
'sharpe',
returns.distribution.mean /
returns.distribution.variance**0.5 *
np.sqrt(252)
)
trace = pm.sample(5000, tune=2000, target_accept=0.95)
and here’s the trace plot:
Doing the same experiment, but using a Normal prior for the daily return distribution, the results are much more intuitive. However, I’m confused about the fact that the StudentT distribution accounts for fait tails and so intuitively it should give more reliable results for these kind of fait tailed return streams. Any advice on what I am missing here?
Code for the experiment with the Normal prior:
with pm.Model() as model:
mu = pm.Normal('mean returns', mu=0, sd=0.1)
sigma = pm.HalfCauchy('volatility', beta=1)
rets = pm.Normal('returns', mu=mu, sd=sigma, observed=_rets)
pm.Deterministic(
'annual volatility',
rets.distribution.variance**0.5 *
np.sqrt(252)
)
pm.Deterministic(
'sharpe',
rets.distribution.mean /
rets.distribution.variance**0.5 *
np.sqrt(252)
)
trace = pm.sample(5000, tune=2000, target_accept=0.95)