Commit d52e93db authored by iLampard's avatar iLampard

Add Quick Start 3

parent 2161714e
{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"collapsed": true
},
"source": [
"alpha-mind的portfolio文件夹提供了构建组合的工具函数。\n",
"- 不同的构建方式实质上对应了不同的优化问题。\n",
"- 该文件夹报告的构建方式包括线性构建、均值方差构建等。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 线性构建: *linear_builder*\n",
"- 目标: 在线性约束下最大化组合的预期收益率。\n",
"- 线性约束包括\n",
" - 标的权重的上下限 *lbound, ubound*\n",
" - 组合风险暴露的上下限 *risk_target* : 函数内部会以因子矩阵乘以权重得到组合的风险暴露。 \n",
" - 仓位调整的换手率上限(换手率以目标权重和当前权重向量的一范数表示,即差的绝对值之和) *turn_over_target*"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Optimization status - optimal\n",
"Optimal expect return - -0.3075339260279713\n",
"Optimial portfolio weights - [3.33333333e-01 3.13308565e-13 2.16666667e-01 3.33333333e-01\n",
" 1.16666667e-01]\n",
"Initial portfolio weights - [0.33333333 0. 0.16666667 0.33333333 0.16666667]\n",
"Turn over amount - 0.10000000000113718\n"
]
}
],
"source": [
"import numpy as np\n",
"from alphamind.portfolio.linearbuilder import linear_builder\n",
"\n",
"\"\"\"\n",
"问题初始化\n",
"\"\"\"\n",
"\n",
"# 假设有5个标的\n",
"n = 5\n",
"\n",
"# 假设当前标的的权重\n",
"current_pos = np.random.randint(0, n, size=n)\n",
"current_pos = current_pos / current_pos.sum() \n",
"\n",
"# 假设标的预期收益向量\n",
"expect_return = np.random.randn(n)\n",
"\n",
"# 假设标的风险因子矩阵, 仅有一个风险因子\n",
"risk_factors = np.ones((n, 1))\n",
"\n",
"# 约束条件\n",
"# 约束条件1 - 标的权重的上下限\n",
"weight_lb = np.zeros(n)\n",
"weight_ub = 0.5 * np.ones(n)\n",
"\n",
"# 限制条件2 - 组合风险暴露的上下限\n",
"risk_lbound = np.ones(1)\n",
"risk_ubound = np.ones(1)\n",
"\n",
"# 限制条件3 - 仓位调整的换手率上限(下限为0,故无需设置)\n",
"turn_over_target = 0.1\n",
"\n",
"\"\"\"\n",
"问题求解\n",
"\"\"\"\n",
"status, fvalue, x_values = linear_builder(expect_return,\n",
" weight_lb,\n",
" weight_ub,\n",
" risk_factors,\n",
" (risk_lbound, risk_ubound),\n",
" turn_over_target,\n",
" current_pos,\n",
" method='ecos')\n",
"\n",
"\n",
"print('Optimization status - {}'.format(status))\n",
"print('Optimal expect return - {}'.format(fvalue))\n",
"print('Optimial portfolio weights - {}'.format(x_values))\n",
"print('Initial portfolio weights - {}'.format(current_pos))\n",
"print('Turn over amount - {}'.format(np.abs(x_values - current_pos).sum()))"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### 均值方差构建: *mean_variance_builder*\n",
"- 根据经典的均值方差组合优化问题构建模型。\n",
"- 目标函数为\n",
"\n",
"\n",
"\\begin{align*}\n",
"&\\mathop{\\arg\\max}_{\\omega} \\ \\ \\omega_a R - \\frac{1}{2} \\lambda \\sigma \\\\\n",
"&s.t.\\quad\n",
"\\begin{cases}\n",
"\\omega_L \\le \\omega_a \\le \\omega_U \\\\\n",
"\\sigma_L \\le \\sigma \\le \\sigma_U\n",
"\\end{cases}\n",
"\\end{align*}\n",
"\n",
"\n",
"\n",
"\n",
"其中\n",
"- $\\omega_a$是组合的主动权重向量,如果用$\\omega$和$\\omega_b$表示组合标的绝对权重向量和基准指数的标的权重向量,那么$\\omega_a =\\omega -\\omega_b$。\n",
"- $R$是组合标的预期收益率向量。\n",
"- $\\lambda$是风险厌恶系数, $\\sigma$是整个组合收益率的方差。\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"##### 函数的参数说明和使用"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"*mean_variance_builder* 接受的参数有\n",
"- 组合标的的预期收益率向量 *er* \n",
"- 风险模型 *risk_model* (optional)\n",
"- 基准指数的标的权重向量*bm*\n",
"- 组合标的的权重上下限 *lbound, ubound*\n",
"- 组合风险暴露矩阵 *risk_exposure* (optional)\n",
"- 组合风险暴露的上下限 *risk_target* (optional)\n",
"- 风险厌恶系数 *lam* (optional)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"NOTE 1: 组合标的的权重上下限 *lbound, ubound* 是指绝对权重向量的上下限。\n",
"- 代码中会计算主动权重上下限,即 *$\\omega_L$=lbound - $\\omega_b$*, *$\\omega_U$=ubound - $\\omega_b$*。最后会把$\\omega_b$加回到优化问题的解,得到组合标的最优权重。\n",
"- 代码中也会计算主动收益的风险上下限, 即*risk_target_lbound - risk_exposure $\\omega_b$*, *risk_target_ubound + risk_exposure $\\omega_b$*。"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"NOTE 2: 为了计算组合的方差,*mean_variance_builder*接受两种输入参数:\n",
"- 标的收益率的协方差矩阵$\\Sigma$,由此可以计算得到\n",
"\n",
"\\begin{equation*}\n",
" \\sigma = \\omega_a^T\\Sigma \\omega_a\n",
"\\end{equation*}\n",
"\n",
"其中$\\Sigma$对应入参中的risk_model['cov']。\n",
"\n",
"- 风险模型:因子收益率的协方差矩阵$F$, 特质收益率的协方差矩阵$\\Delta$(对角矩阵)\n",
"\\begin{equation*}\n",
" \\sigma = \\omega_a^T \\left(X F X^T + \\Delta \\right) \\omega_a\n",
"\\end{equation*}\n",
"\n",
"由于一般情况下风险因子的数量小于标的股票的数量,所以$\\omega_a^T X F X^T \\omega_a$的时间复杂度要小于$\\omega_a^T\\Sigma \\omega_a$, 所以第二种方法效率更高。\n",
"\n",
"其中, $F$对应入参中的risk_model['factor_cov'], $\\Delta$对应risk_model['idsync'],$X$对应risk_model['factor_loading']"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": []
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"from alphamind.portfolio.meanvariancebuilder import mean_variance_builder\n",
"\n",
"\"\"\"\n",
"问题初始化\n",
"\"\"\"\n",
"# 假设有3个标的\n",
"# 假设标的预期收益向量\n",
"expect_return = np.array([0.1, 0.2, 0.3])\n",
"\n",
"# 假设收益的协方差矩阵\n",
"cov = np.array([[0.02, 0.01, 0.02],\n",
" [0.01, 0.02, 0.03],\n",
" [0.02, 0.03, 0.02]])\n",
"\n",
"# 假设收益的非系统性方差(Idiosyncratic Risk)\n",
"ids_var = np.diag([0.01, 0.02, 0.03])\n",
"\n",
"# 最终的协方差矩阵为\n",
"cov += ids_var\n",
"\n",
"# 假设标的风险暴露矩阵, 有两个风险因子\n",
"risk_exposure = np.array([[1., 1., 1.],\n",
" [1., 0., 1.]]).T\n",
"\n",
"# 假设基准指数的权重向量\n",
"bm = np.array([0.3, 0.3, 0.4])\n",
"\n",
"# 约束条件\n",
"# 约束条件1 - 标的绝对权重的上下限\n",
"lbound = np.array([0., 0., 0.])\n",
"ubound = np.array([0.4, 0.4, 0.5])\n",
"\n",
"# 约束条件2 - 组合风险暴露的上下限\n",
"risk_target = (np.array([bm.sum(), 0.3]), np.array([bm.sum(), 0.7]))\n",
"\n",
"# 建立风险模型,假设直接使用标的的协方差矩阵计算组合的方差\n",
"risk_model = dict(cov=cov, factor_cov=None, factor_loading=None, idsync=None)\n",
"\n",
"\"\"\"\n",
"问题求解\n",
"\"\"\"\n",
"status, _, x = mean_variance_builder(expect_return, risk_model, bm, lbound, ubound, risk_exposure, risk_target)\n"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Optimal weight is [0.09999998 0.4 0.5 ]\n",
"Risk exposure of optimal potfolio is [0.99999998 0.59999998]\n"
]
}
],
"source": [
"print('Optimal weight is {0}'.format(x))\n",
"print('Risk exposure of optimal potfolio is {0}'.format(x @ risk_exposure))"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.5"
}
},
"nbformat": 4,
"nbformat_minor": 1
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment