Optimization
Given a portfolio \( \vec{p} = ( p_1, p_2, \ldots )^\intercal \) and a return \( \vec{r} = ( r_1, r_2, \ldots )^\intercal \), we want to optimize growth rate (expected log return), \( g = \mathbb{E}\left[\log\left(p^\intercal r\right)\right] \).
Generating returns
Ignoring correlations and volatility clustering
We don’t know the exact expected return and volatility of each asset. So to be more robust, we treat these as random variables. We model the expected return with a normal distribution. As the volatility can not be negative, we model that with a lognormal distribution.
An important step after that is to convert the geometric return of an asset to its instant return, by subtracting half the variance from the expected return (cf. the expectation of a lognormal distribution).
Then we can generate our return as a normal distribution with the instant return and the volatility. However, it is actually more accurate to represent returns as a Laplace distribution empirically. This makes sense because it is the amount of shocks that increases with volatility. A normal distribution with exponentially distributed variance is Laplace. Note that by convention, the standard deviation of a Laplace distribution has a factor \( \sqrt{2} \) compared to a normal distribution.
In conclusion: \[ \begin{align} \mu_\text{g} &= \text{Normal}(\ldots) \\ \sigma &= \text{LogNormal}(\ldots) \\ \mu_\text{i} &= \mu_\text{g} - \sigma^2 / 2 \\ r &= \text{Laplace}\left(\mu_\text{i}, \sigma / \sqrt{2}\right) \end{align} \]
Single factor model
Using a single factor model with only equity market beta \( \beta \), first we generate the return of equities (normalized): \( F = \text{Laplace}(0, 1 / \sqrt{2}) \). Then \( \beta \cdot F + \sqrt{1 - \beta^2} \cdot \text{Laplace}(0, 1/\sqrt{2}) \) is the normalized return of each asset, which we can shift and scale to the actual mean return and volatility.
Optimization algorithm
Any standard optimization algorithm like SGD, SignSGD, Adam, or L-BFSG with or without momentum works.
Note that we need a special asset, that balances the portfolio to always sum to one. It is not a trainable parameter. By convention we choose cash to fill this role.
Constraints
One thing that we notice when running the optimization is that the results can take a lot of leverage. However, in practice it may not be possible to run a portfolio with that much leverage.
This means we should constrain our optimization so our margin stays within the limits, using e.g. projecting onto the feasible set or using SLSQP with constraints.
Outliers
When we run our code we notice that we have issues with returns of negative 100% or less, which breaks our logarithmic utility. This is not a coding error that can be fixed with clipping but a mathematical fact. Just clipping results in very unstable returns especially as leverage increases.
If we are optimizing with the returns as given then we are implicitly rebalancing annually. That is plenty of time to go bankrupt, so a first improvement is to move to daily by dividing the returns by 250 trading days. Practically this is enough.
But even a single day, or a single second, is enough to bankrupt us if we are unlucky enough. What we really need to do is rebalance continually, taking the limit as the time span goes to zero. This takes us into the realm of stochastic calculus.
According to stochastic calculus, on a small enough timescale everything is normally distributed. Like how in differential calculus everything is a line on a small enough scale. So one thing we could do is take the Taylor approximation of \( \log(1 + x ) = x - x^2 / 2 + x^3 / 3 - x^4 / 4 + \ldots \) and use only the first two terms. This is similar to the conversion of geometric to annual that we did above.