<jupyter_start><jupyter_text>Minimum Variance Portfolio Problem with Unknown $\mu$ and $\Sigma$---In practice, we do not know the true $\mu$ or $\Sigma$. So we need to estimate them with data.Let $r_{nt}$ denote realized return on asset $n$ at period $t$  $(t=1,\dots,T)$. The sample mean $\bar r_n$ and the sample covariance $s_{nm}$ (or the sample variance $s_n^2$ when $n=m$) are defined as\begin{align*} \bar r_n &= \frac1T\sum_{t=1}^T r_{it},\\ s_{nm} &= \frac1T\sum_{t=1}^T(r_{nt}-\bar r_n)(r_{mt}-\bar r_m),\\ & (n,m = 1,\dots,N).\end{align*}A straightforward way is to replace $\mu$ and $\Sigma$ with\begin{equation*} \bar r = \begin{bmatrix} \bar r_1 \\ \vdots \\ \bar r_N \end{bmatrix}, \quad S = \begin{bmatrix}  s_1^2 &\cdots & s_{1N} \\  \vdots & \ddots & \vdots \\  s_{N1} &\cdots & s_N^2 \end{bmatrix}.\end{equation*}A more elegant way is to rewrite the sample variance $w^{\intercal}Sw$ as\begin{align*} w^{\intercal}Sw &= \sum_{n=1}^N\sum_{m=1}^N w_n w_m s_{nm} \\ &= \sum_{n=1}^N\sum_{m=1}^N w_n w_m \left\{\frac1T\sum_{t=1}^T(r_{nt}-\bar r_n)(r_{mt}-\bar r_m)\right\}  \\ &= \frac1T\sum_{t=1}^T\sum_{n=1}^N w_n(r_{nt}-\bar r_n)\sum_{m=1}^N w_n(r_{nt}-\bar r_n) \\ &= \frac1T\sum_{t=1}^T\left\{\sum_{n=1}^N w_n(r_{nt}-\bar r_n)\right\}^2  = \frac1T\sum_{t=1}^T\left(r_{Pt}-\bar r_P\right)^2,\end{align*}where\begin{equation*} r_{Pt} = \sum_{n=1}^N w_n r_{nt}, \quad \bar r_P = \sum_{n=1}^N w_n \bar r_n = \frac1T\sum_{t=1}^T r_{Pt}.\end{equation*}Then the minimum variance portfolio problem is rearranged as \begin{align*} \min_{w,v} & \quad \widehat{\mathrm{Var}}[R_P] = \frac1Tv^{\intercal}v, \\ \mathrm{s.t.} & \quad Dw = v,  			   \quad w^{\intercal}\bar r = \mu_P, \quad w^{\intercal}\iota = 1, \\             & \quad w_1\geqq 0,\ \cdots,\ w_N\geqq 0,\end{align*}where\begin{equation*} v = \begin{bmatrix} v_1 \\ \vdots \\ v_T \end{bmatrix},\quad D = \begin{bmatrix} r_{11}-\bar r_1 & \cdots & r_{N1}-\bar r_N \\ \vdots & \ddots & \vdots \\ r_{1T}-\bar r_1 & \cdots & r_{NT}-\bar r_N \end{bmatrix}.\end{equation*}<jupyter_code>import numpy as np
import matplotlib.pyplot as plt
import cvxpy as cp
import pandas as pd
from IPython.display import display<jupyter_output><empty_output><jupyter_text>`read_csv` loads data from a CSV file into a Pandas dataframe. The option `index_col=0` means that the first column (the index starts at zero in Python) of the CSV file is used as the index of the dataframe.See more details on `read_csv` at https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html<jupyter_code>marketcap = pd.read_csv('stock_market_cap.csv', index_col=0)
display(marketcap)<jupyter_output><empty_output><jupyter_text>`date_range` creates a series of dates.+ `periods` - the number of periods+ `freq` - frequency of datesSee more details on `data_range` at https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.date_range.html<jupyter_code>R = (marketcap.diff()/marketcap.shift(1))[1:] * 100
R.index = pd.date_range('2014-2-1', periods=R.shape[0], freq='M')
display(R)
T, N = R.shape
Mu = R.mean().values
Sigma = R.cov().values * ((T - 1.0) / T)
Return_Dev = (R - Mu).values
Weight = cp.Variable(N)
Deviation = cp.Variable(T)
Target_Return = cp.Parameter()
Risk_Variance = cp.sum_squares(Deviation) / T
Opt_Portfolio = cp.Problem(cp.Minimize(Risk_Variance),
                           [Return_Dev @ Weight == Deviation,
                            Weight.T @ Mu == Target_Return,
                            cp.sum(Weight) == 1.0,
                            Weight >= 0.0])<jupyter_output><empty_output><jupyter_text>Minimum Variance Portfolio Frontier<jupyter_code>V_Target = np.linspace(Mu.min(), Mu.max(), num=100)
V_Risk = np.zeros(V_Target.shape)
for idx, Target_Return.value in enumerate(V_Target):
    Opt_Portfolio.solve(solver=cp.OSQP)
    V_Risk[idx] = np.sqrt(Risk_Variance.value)
fig1 = plt.figure(num=1, facecolor='w')
plt.plot(V_Risk, V_Target, 'b-')
plt.plot(np.sqrt(np.diagonal(Sigma)), Mu, 'rx')
plt.legend(['Frontier', 'Asset'], loc='best', frameon=False)
plt.xlabel('Standard deviation (%)')
plt.ylabel('Expected return (%)')
plt.show()<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.18864292589027912, 'fraction_numerical': 0.0170837343599615, 'mean_word_length': 3.996394230769231, 'pattern_counts': {'":': 0, '<': 17, '<?xml version=': 0, '>': 18, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '4', 'dir': 'jupyter-structured-clean-dedup', 'id': '603659', 'license': 'MIT', 'n_tokens_mistral': 1666, 'n_tokens_neox': 1589, 'n_words': 356, 'path': 'notebook/ges_mvf_sample.ipynb', 'repo_name': 'nakatsuma/GES-PEARL', 'size': '4156'}