Optimal Growth Portfolio Derivations

Overview

The solution to the optimal growth portfolio is a straightforward application of Lagrange multipliers. The following derivations are states using Linear Algebra to simplify the calculations.

Optimal Portfolio with Target Volatility

We solve the problem of finding the portfolio with the highest growth rate, given a chosen portfolio standard deviation.

Maximize
{% \vec{w}^T \vec{\mu} - \vec{w}^T \Sigma \vec{w} %}
subject to
{% \vec{w}^T \vec{1} = 1 %}
{% \vec{w}^T \Sigma \vec{w} = \sigma^2 %}

Solution



Introduce Lagrange multipliers {% \lambda %} and {% \gamma %} the Lagrangian is given by
{% L = \vec{w}^T\vec{\mu} - \vec{w}^T \Sigma \vec{w} - \lambda(\vec{w}^T \vec{1} - 1) - \gamma(\vec{w}^T \Sigma \vec{w} - \sigma^2) %}
then we have first order conditions
{% \vec{\mu} - \Sigma \vec{w} - \lambda \vec{1} - 2 \gamma \Sigma \vec{w} = 0 %}
{% \vec{w} = \frac{1}{1+2\gamma} \Sigma ^{-1} (\vec{\mu} - \lambda \vec{1}) %}
The two Lagrange coefficients are set so that the original constraints are satisfied. (see Luenberger pg 431)

Optimal Portfolio

If {% \gamma %} is set to zero, then the second constraint is ignored and the resulting portfolio is the growth optimal portfolio.
{% \vec{w} = \Sigma ^{-1} (\vec{\mu} - \lambda \vec{1}) %}
To solve, solve for {% \lambda %} using the constraint on weights, and then plug back in
{% [S^{-1}\vec{\mu} - \lambda S^{-1} \vec{1}]^T \vec{1} = 1 %}
{% [\vec{\mu}^T S^{-T} - \lambda \vec{1}^T S^{-T}] \vec{1} = 1 %}
{% \lambda \vec{1}^T S^{-1} \vec{1} = \vec{\mu}^T S^{-T} \vec{1} - 1 %}
{% \lambda = \frac{1}{\vec{1}^T S^{-T}\vec{1}} (\vec{\mu}^T S^{-T}\vec{1}-1) %}

Implementation

def growth_lambda(r, covariance, inv): rows = covariance.shape[0] one = np.array([ [1.0] for x in range(rows) ]) factor1 = r.T @ inv.T @ one factor2 = one.T @inv.T @ one result = (1/factor2[0][0]) * (factor1[0][0]-1) return result def optimal_growth(r, covariance): rows = covariance.shape[0] sigmaInverse = np.linalg.inv(covariance) r2 = np.array([ [p] for p in r.tolist() ]) lambda1 = growth_lambda(r2, covariance, sigmaInverse) lambda2 = np.array([ [-1.0 * lambda1] for x in range(rows) ]) factor = r2+lambda2 result = sigmaInverse @ factor return result
import numpy as np import lib.trading.portfolio as pt sigma = np.array([[0.2,0.05,0.05],[0.05, 0.12, 0.05],[0.05,0.05, 0.15]]) f = np.array([0.10,0.12, 0.13]) w = pt.optimal_growth(f,sigma)