311 lines
7.1 KiB
Plaintext
311 lines
7.1 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "ffd5a549",
|
|
"metadata": {},
|
|
"source": [
|
|
"<div style=\"background-color:#000;\"><img src=\"pqn.png\"></img></div>"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "8ebd9176",
|
|
"metadata": {},
|
|
"source": [
|
|
"This code constructs and optimizes a financial portfolio using historical stock data. It uses the Riskfolio library to estimate asset returns and covariance. The code further optimizes the portfolio for risk parity and visualizes the resulting asset allocation and risk contributions. Additionally, it demonstrates the impact of adding a constraint on expected returns. This is useful for portfolio management and risk assessment in finance."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "fe7c58a8",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import yfinance as yf\n",
|
|
"import riskfolio as rp\n",
|
|
"import warnings\n",
|
|
"warnings.filterwarnings(\"ignore\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "f926ae4e",
|
|
"metadata": {},
|
|
"source": [
|
|
"Define a list of stock tickers to include in the portfolio"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "7042f7bf",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"assets = [\"JCI\", \"TGT\", \"CMCSA\", \"CPB\", \"MO\", \"APA\", \"MMC\", \"JPM\",\n",
|
|
" \"ZION\", \"PSA\", \"BAX\", \"BMY\", \"LUV\", \"PCAR\", \"TXT\", \"TMO\",\n",
|
|
" \"DE\", \"MSFT\", \"HPQ\", \"SEE\", \"VZ\", \"CNP\", \"NI\", \"T\", \"BA\"]"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "79e0a66f",
|
|
"metadata": {},
|
|
"source": [
|
|
"Sort the list of tickers alphabetically"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "68e33540",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"assets.sort()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "0e39a06b",
|
|
"metadata": {},
|
|
"source": [
|
|
"Download historical stock data for the specified tickers from Yahoo Finance"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "1020999e",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"data = yf.download(assets, start=\"2016-01-01\", end=\"2019-12-30\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "965ab385",
|
|
"metadata": {},
|
|
"source": [
|
|
"Calculate daily returns based on adjusted closing prices"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "6c6cf1fd",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"returns = data['Adj Close'].pct_change().dropna()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "0b4b580c",
|
|
"metadata": {},
|
|
"source": [
|
|
"Create a Portfolio object using the calculated returns"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "1f3a849b",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"port = rp.Portfolio(returns=returns)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "aefeba8e",
|
|
"metadata": {},
|
|
"source": [
|
|
"Estimate expected returns and covariance matrix using historical data"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "6d5508fd",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"port.assets_stats(method_mu='hist', method_cov='hist', d=0.94)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "d01b6618",
|
|
"metadata": {},
|
|
"source": [
|
|
"Optimize the portfolio for risk parity using mean-variance optimization"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "e81ffa05",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"w_rp = port.rp_optimization(\n",
|
|
" model=\"Classic\", # use historical\n",
|
|
" rm=\"MV\", # use mean-variance optimization\n",
|
|
" hist=True, # use historical scenarios\n",
|
|
" rf=0, # set risk free rate to 0\n",
|
|
" b=None # don't use constraints\n",
|
|
")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "c1831b35",
|
|
"metadata": {},
|
|
"source": [
|
|
"Plot the asset allocation of the optimized portfolio"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "65904137",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"ax = rp.plot_pie(w=w_rp)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "e25e251f",
|
|
"metadata": {},
|
|
"source": [
|
|
"Plot the risk contribution of each asset in the optimized portfolio"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "79c79c02",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"ax = rp.plot_risk_con(\n",
|
|
" w_rp,\n",
|
|
" cov=port.cov,\n",
|
|
" returns=port.returns,\n",
|
|
" rm=\"MV\",\n",
|
|
" rf=0,\n",
|
|
")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "2a97ece3",
|
|
"metadata": {},
|
|
"source": [
|
|
"Set a constraint for the minimum level of expected returns for the portfolio"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "be3c355a",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"port.lowerret = 0.0008"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "6400a196",
|
|
"metadata": {},
|
|
"source": [
|
|
"Optimize the portfolio for risk parity with the added constraint on expected returns"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "856a87ed",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"w_rp_c = port.rp_optimization(\n",
|
|
" model=\"Classic\", # use historical\n",
|
|
" rm=\"MV\", # use mean-variance optimization\n",
|
|
" hist=True, # use historical scenarios\n",
|
|
" rf=0, # set risk free rate to 0\n",
|
|
" b=None # don't use constraints\n",
|
|
")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "0aa64fb9",
|
|
"metadata": {},
|
|
"source": [
|
|
"Plot the asset allocation of the constrained optimized portfolio"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "3f34eb3a",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"ax = rp.plot_pie(w=w_rp_c)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "42e39406",
|
|
"metadata": {},
|
|
"source": [
|
|
"Plot the risk contribution of each asset in the constrained optimized portfolio"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "9dc06f47",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"ax = rp.plot_risk_con(\n",
|
|
" w_rp_c,\n",
|
|
" cov=port.cov,\n",
|
|
" returns=port.returns,\n",
|
|
" rm=\"MV\",\n",
|
|
" rf=0,\n",
|
|
")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "bcf00531",
|
|
"metadata": {},
|
|
"source": [
|
|
"<a href=\"https://pyquantnews.com/\">PyQuant News</a> is where finance practitioners level up with Python for quant finance, algorithmic trading, and market data analysis. Looking to get started? Check out the fastest growing, top-selling course to <a href=\"https://gettingstartedwithpythonforquantfinance.com/\">get started with Python for quant finance</a>. For educational purposes. Not investment advise. Use at your own risk."
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"jupytext": {
|
|
"cell_metadata_filter": "-all",
|
|
"main_language": "python",
|
|
"notebook_metadata_filter": "-all"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|