Pymc3 migration - Sharpe Ratio Example

Hey folks,

I am absolutely new into pymc and bayesian statistics, so please bare with me for my potentially stupid question beforehand :smiley:

I am currently working over an example from a book modelling the sharpe ratio (mean/std) of an asset with the pymc3 package, which is not compatible anymore with the new version of pymc.

The author models the sharpe the following:

mean_prior = data.stock.mean()
std_prior = data.stock.std()
std_low = std_prior / 1000
std_high = std_prior * 1000

with pm.Model() as sharpe_model:
    mean = pm.Normal('mean', mu=mean_prior, sigma=std_prior)
    std = pm.Uniform('std', lower=std_low, upper=std_high)

    nu = pm.Exponential('nu_minus_two', 1 / 29, testval=4) + 2.
    returns = pm.StudentT('returns', nu=nu, mu=mean, sigma=std, observed=data.stock)

    sharpe = returns.distribution.mean / returns.distribution.variance ** .5 * np.sqrt(252)
    pm.Deterministic('sharpe', sharpe)

However, this yields the error: AttributeError:

'TensorVariable' object has no attribute 'distribution'

I already tried to solve this by changing the sharpe definition to:

sharpe = returns.mean() / returns.std() * np.sqrt(252)

Which does not lead to an error anymore, however the sharpe is then not a distribution anymore:

How can this be properly fixed with the new pymc version? Feel also free to correct potentially wrong wordings of mine :slight_smile:



I think you just need to import the tensor functionality:

import pytensor.tensor as pt

and then use the mean() and std() functions:

sharpe = pt.mean(returns) / pt.std(returns) * np.sqrt(252)

Don’t you already have the moments from the parameters of the model for returns? The mean return is just mean, and the variance is std ** 2 * nu / (nu - 2)

Ha. I didn’t even look at the model (dumb). Good call @jessegrabowski .

Thanks a lot for your helpful answers guys!

Indeed, @jessegrabowski 's hint did the trick.

I just replaced the sharpe definition with the already existent mean & std variables.

sharpe = mean / std * np.sqrt(252)

I think if you just use std you will inflate your Sharpes, because it doesn’t take into account the tail mass from the nu term.

Thanks a lot for the hint.

So should I use your term above?
like sharpe = mean / (std**2*nu/(nu-2))?

That’s the variance, but sharpe wants the std. You can use std * pt.sqrt(nu / (nu - 2))

PS: This is why it’s not ideal to give the parameters moment names. In the normal case you have sigma = std, but here we don’t.

1 Like