Files
ArtStudies/M1/Portfolio Management/TP-Project.ipynb
Arthur DANJOU d5a6bfd339 Refactor code for improved readability and consistency across multiple Jupyter notebooks
- Added missing commas in various print statements and function calls for better syntax.
- Reformatted code to enhance clarity, including breaking long lines and aligning parameters.
- Updated function signatures to use float type for sigma parameters instead of int for better precision.
- Cleaned up comments and documentation strings for clarity and consistency.
- Ensured consistent formatting in plotting functions and data handling.
2025-12-13 23:38:17 +01:00

525 lines
16 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"id": "81049114d821d00e",
"metadata": {},
"source": [
"# Project - Portfolio Management\n",
"\n",
"## Group: Danjou Arthur & Forest Thais\n",
"\n",
"### Time period studied from 2017-01-01 to 2018-01-01\n",
"\n",
"### Risk-free rate: 2%"
]
},
{
"cell_type": "code",
"execution_count": 51,
"id": "initial_id",
"metadata": {
"ExecuteTime": {
"end_time": "2024-11-25T13:43:46.298758Z",
"start_time": "2024-11-25T13:43:46.293696Z"
},
"collapsed": true
},
"outputs": [],
"source": [
"import yfinance as yf\n",
"\n",
"import numpy as np\n",
"import pandas as pd"
]
},
{
"cell_type": "code",
"execution_count": 52,
"id": "9f9fc36832c97e0",
"metadata": {
"ExecuteTime": {
"end_time": "2024-11-25T13:43:47.318911Z",
"start_time": "2024-11-25T13:43:47.198820Z"
}
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"[*********************100%***********************] 1 of 1 completed\n",
"[*********************100%***********************] 1 of 1 completed\n",
"[*********************100%***********************] 1 of 1 completed\n",
"[*********************100%***********************] 1 of 1 completed\n",
"/var/folders/tp/_ld5_pzs6nx6mv1pbjhq1l740000gn/T/ipykernel_92506/348989065.py:9: FutureWarning: DataFrame.interpolate with method=pad is deprecated and will raise in a future version. Use obj.ffill() or obj.bfill() instead.\n",
" S = S.interpolate(method=\"pad\")\n"
]
},
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>^RUT</th>\n",
" <th>^IXIC</th>\n",
" <th>^GSPC</th>\n",
" <th>XWD.TO</th>\n",
" </tr>\n",
" <tr>\n",
" <th>Date</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>2017-01-03 00:00:00+00:00</th>\n",
" <td>1365.489990</td>\n",
" <td>5429.080078</td>\n",
" <td>2257.830078</td>\n",
" <td>38.499630</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-01-04 00:00:00+00:00</th>\n",
" <td>1387.949951</td>\n",
" <td>5477.000000</td>\n",
" <td>2270.750000</td>\n",
" <td>38.553375</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-01-05 00:00:00+00:00</th>\n",
" <td>1371.939941</td>\n",
" <td>5487.939941</td>\n",
" <td>2269.000000</td>\n",
" <td>38.481716</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-01-06 00:00:00+00:00</th>\n",
" <td>1367.280029</td>\n",
" <td>5521.060059</td>\n",
" <td>2276.979980</td>\n",
" <td>38.517544</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-01-09 00:00:00+00:00</th>\n",
" <td>1357.489990</td>\n",
" <td>5531.819824</td>\n",
" <td>2268.899902</td>\n",
" <td>38.383186</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" ^RUT ^IXIC ^GSPC XWD.TO\n",
"Date \n",
"2017-01-03 00:00:00+00:00 1365.489990 5429.080078 2257.830078 38.499630\n",
"2017-01-04 00:00:00+00:00 1387.949951 5477.000000 2270.750000 38.553375\n",
"2017-01-05 00:00:00+00:00 1371.939941 5487.939941 2269.000000 38.481716\n",
"2017-01-06 00:00:00+00:00 1367.280029 5521.060059 2276.979980 38.517544\n",
"2017-01-09 00:00:00+00:00 1357.489990 5531.819824 2268.899902 38.383186"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<div>\n",
"<style scoped>\n",
" .dataframe tbody tr th:only-of-type {\n",
" vertical-align: middle;\n",
" }\n",
"\n",
" .dataframe tbody tr th {\n",
" vertical-align: top;\n",
" }\n",
"\n",
" .dataframe thead th {\n",
" text-align: right;\n",
" }\n",
"</style>\n",
"<table border=\"1\" class=\"dataframe\">\n",
" <thead>\n",
" <tr style=\"text-align: right;\">\n",
" <th></th>\n",
" <th>^RUT</th>\n",
" <th>^IXIC</th>\n",
" <th>^GSPC</th>\n",
" <th>XWD.TO</th>\n",
" </tr>\n",
" <tr>\n",
" <th>Date</th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" <th></th>\n",
" </tr>\n",
" </thead>\n",
" <tbody>\n",
" <tr>\n",
" <th>2017-12-22 00:00:00+00:00</th>\n",
" <td>1542.930054</td>\n",
" <td>6959.959961</td>\n",
" <td>2683.340088</td>\n",
" <td>44.323349</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-12-26 00:00:00+00:00</th>\n",
" <td>1544.229980</td>\n",
" <td>6936.250000</td>\n",
" <td>2680.500000</td>\n",
" <td>44.323349</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-12-27 00:00:00+00:00</th>\n",
" <td>1543.939941</td>\n",
" <td>6939.339844</td>\n",
" <td>2682.620117</td>\n",
" <td>44.052303</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-12-28 00:00:00+00:00</th>\n",
" <td>1548.930054</td>\n",
" <td>6950.160156</td>\n",
" <td>2687.540039</td>\n",
" <td>43.857414</td>\n",
" </tr>\n",
" <tr>\n",
" <th>2017-12-29 00:00:00+00:00</th>\n",
" <td>1535.510010</td>\n",
" <td>6903.390137</td>\n",
" <td>2673.610107</td>\n",
" <td>43.784576</td>\n",
" </tr>\n",
" </tbody>\n",
"</table>\n",
"</div>"
],
"text/plain": [
" ^RUT ^IXIC ^GSPC XWD.TO\n",
"Date \n",
"2017-12-22 00:00:00+00:00 1542.930054 6959.959961 2683.340088 44.323349\n",
"2017-12-26 00:00:00+00:00 1544.229980 6936.250000 2680.500000 44.323349\n",
"2017-12-27 00:00:00+00:00 1543.939941 6939.339844 2682.620117 44.052303\n",
"2017-12-28 00:00:00+00:00 1548.930054 6950.160156 2687.540039 43.857414\n",
"2017-12-29 00:00:00+00:00 1535.510010 6903.390137 2673.610107 43.784576"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"(251, 4)\n"
]
}
],
"source": [
"# Data Extraction\n",
"Tickers = [\"^RUT\", \"^IXIC\", \"^GSPC\", \"XWD.TO\"]\n",
"start_input = \"2017-01-01\"\n",
"end_input = \"2018-01-01\"\n",
"S = pd.DataFrame()\n",
"for t in Tickers:\n",
" S[t] = yf.Tickers(t).history(start=start_input, end=end_input)[\"Close\"]\n",
"\n",
"S = S.interpolate(method=\"pad\")\n",
"\n",
"# Show the first five and last five values extracted\n",
"display(S.head())\n",
"display(S.tail())\n",
"print(S.shape)"
]
},
{
"cell_type": "code",
"execution_count": 53,
"id": "53483cf3a925a4db",
"metadata": {
"ExecuteTime": {
"end_time": "2024-11-25T13:43:50.080380Z",
"start_time": "2024-11-25T13:43:50.073119Z"
}
},
"outputs": [],
"source": [
"R = S / S.shift() - 1\n",
"R = R[1:]\n",
"mean_d = R.mean()\n",
"covar_d = R.cov()\n",
"corr = R.corr()"
]
},
{
"cell_type": "code",
"execution_count": 54,
"id": "c327ed5967b1f442",
"metadata": {
"ExecuteTime": {
"end_time": "2024-11-25T13:43:50.965092Z",
"start_time": "2024-11-25T13:43:50.961969Z"
}
},
"outputs": [],
"source": [
"mean = mean_d * 252\n",
"covar = covar_d * 252\n",
"std = np.sqrt(np.diag(covar))"
]
},
{
"cell_type": "code",
"execution_count": 55,
"id": "6bc6a850bf06cc9d",
"metadata": {
"ExecuteTime": {
"end_time": "2024-11-25T13:43:51.701725Z",
"start_time": "2024-11-25T13:43:51.695020Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Mean:\n",
"\n",
"^RUT 0.125501\n",
"^IXIC 0.246863\n",
"^GSPC 0.172641\n",
"XWD.TO 0.133175\n",
"dtype: float64\n",
"\n",
"Covariance:\n",
"\n",
" ^RUT ^IXIC ^GSPC XWD.TO\n",
"^RUT 0.014417 0.008400 0.006485 0.004797\n",
"^IXIC 0.008400 0.009182 0.005583 0.004337\n",
"^GSPC 0.006485 0.005583 0.004426 0.003309\n",
"XWD.TO 0.004797 0.004337 0.003309 0.006996\n",
"\n",
"Standard Deviation:\n",
"\n",
"[0.12007222 0.09582499 0.06653127 0.08364295]\n",
"\n",
"Correlation:\n",
"\n",
" ^RUT ^IXIC ^GSPC XWD.TO\n",
"^RUT 1.000000 0.730047 0.811734 0.477668\n",
"^IXIC 0.730047 1.000000 0.875687 0.541087\n",
"^GSPC 0.811734 0.875687 1.000000 0.594658\n",
"XWD.TO 0.477668 0.541087 0.594658 1.000000\n"
]
}
],
"source": [
"print(\"Mean:\\n\")\n",
"print(mean)\n",
"print(\"\\nCovariance:\\n\")\n",
"print(covar)\n",
"print(\"\\nStandard Deviation:\\n\")\n",
"print(std)\n",
"print(\"\\nCorrelation:\\n\")\n",
"print(corr)"
]
},
{
"cell_type": "markdown",
"id": "fc4bec874f710f7c",
"metadata": {},
"source": "# Question 1"
},
{
"cell_type": "code",
"execution_count": 56,
"id": "780c9cca6e0ed2d3",
"metadata": {
"ExecuteTime": {
"end_time": "2024-11-25T13:43:53.113423Z",
"start_time": "2024-11-25T13:43:53.109514Z"
}
},
"outputs": [],
"source": [
"r = 0.02\n",
"d = len(Tickers)\n",
"vec1 = np.linspace(1, 1, d)\n",
"sigma = covar\n",
"inv_sigma = np.linalg.inv(sigma)\n",
"\n",
"a = vec1.T.dot(inv_sigma).dot(vec1)\n",
"b = mean.T.dot(inv_sigma).dot(vec1)"
]
},
{
"cell_type": "code",
"execution_count": 57,
"id": "81c956f147c68070",
"metadata": {
"ExecuteTime": {
"end_time": "2024-11-25T13:43:54.545400Z",
"start_time": "2024-11-25T13:43:54.541579Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Expected return m_T: 0.2364033641931515\n",
"Standard deviation sd_T: 0.07276528490265963\n",
"Allocation pi_T: [-0.60853811 0.45748917 1.17944152 -0.02839259]\n",
"We can verify that the allocation is possible as the sum of the allocations for the different indices is 0.9999999999999993, that is very close to 1\n"
]
}
],
"source": [
"# Tangent portfolio\n",
"pi_T = inv_sigma.dot(mean - r * vec1) / (b - r * a)\n",
"sd_T = np.sqrt(pi_T.T.dot(sigma).dot(pi_T)) # Variance\n",
"m_T = pi_T.T.dot(mean) # expected return\n",
"\n",
"print(f\"Expected return m_T: {m_T}\")\n",
"print(f\"Standard deviation sd_T: {sd_T}\")\n",
"print(f\"Allocation pi_T: {pi_T}\")\n",
"print(\n",
" f\"We can verify that the allocation is possible as the sum of the allocations for the different indices is {sum(pi_T)}, that is very close to 1\",\n",
")"
]
},
{
"cell_type": "markdown",
"id": "2e121c2dfb946f3c",
"metadata": {},
"source": "# Question 2"
},
{
"cell_type": "code",
"execution_count": 58,
"id": "c169808384ca1112",
"metadata": {
"ExecuteTime": {
"end_time": "2024-11-25T13:43:59.797115Z",
"start_time": "2024-11-25T13:43:59.792462Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The annualized volatilities of the index ^RUT is 0.12007221535411407\n",
"The annualized expected returns of the index ^RUT is 0.12550141384538263\n",
"\n",
"The annualized volatilities of the index ^IXIC is 0.09582499431305072\n",
"The annualized expected returns of the index ^IXIC is 0.24686267015709437\n",
"\n",
"The annualized volatilities of the index ^GSPC is 0.06653126757186174\n",
"The annualized expected returns of the index ^GSPC is 0.17264098207081371\n",
"\n",
"The annualized volatilities of the index XWD.TO is 0.08364295296865466\n",
"The annualized expected returns of the index XWD.TO is 0.1331750489518068\n",
"\n",
"The annualized volatility of the Tangent Portfolio is 1.155113087587201\n",
"The annualized expected return of the Tangent Portfolio is 59.57364777667418\n"
]
}
],
"source": [
"for i in range(len(std)):\n",
" print(f\"The annualized volatilities of the index {Tickers[i]} is {std[i]}\")\n",
" print(\n",
" f\"The annualized expected returns of the index {Tickers[i]} is {mean[Tickers[i]]}\",\n",
" )\n",
" print()\n",
"\n",
"print(f\"The annualized volatility of the Tangent Portfolio is {sd_T * np.sqrt(252)}\")\n",
"print(f\"The annualized expected return of the Tangent Portfolio is {m_T * 252}\")"
]
},
{
"cell_type": "markdown",
"id": "af8d29ecdbf2ae1",
"metadata": {},
"source": "# Question 3"
},
{
"cell_type": "code",
"execution_count": 59,
"id": "2e0215ab7904906a",
"metadata": {
"ExecuteTime": {
"end_time": "2024-11-25T13:44:01.393591Z",
"start_time": "2024-11-25T13:44:01.388830Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"sharpe ratio of the Tangent portfolio : 2.9739918490340687\n",
"the sharpe ratio of the index ^RUT is 0.8786496820620858\n",
"the sharpe ratio of the index ^IXIC is 2.3674686524473625\n",
"the sharpe ratio of the index ^GSPC is 2.294274371158541\n",
"the sharpe ratio of the index XWD.TO is 1.353073330567601\n"
]
}
],
"source": [
"print(\"sharpe ratio of the Tangent portfolio :\", (m_T - r) / sd_T)\n",
"\n",
"for i in range(4):\n",
" print(\n",
" f\"the sharpe ratio of the index {Tickers[i]} is {(mean[Tickers[i]] - r) / std[i]}\",\n",
" )"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.6"
}
},
"nbformat": 4,
"nbformat_minor": 5
}