{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "49280759",
   "metadata": {},
   "source": [
    "# 投资组合优化\n",
    "\n",
    "对应案例: [投资组合优化](/docs/case-studies/finance/portfolio-optimization-case/)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "57f074a1",
   "metadata": {},
   "source": [
    "## 1. 环境准备"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "624696da",
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np, pandas as pd, matplotlib.pyplot as plt\n",
    "from scipy.optimize import minimize\n",
    "np.random.seed(42)\n",
    "n_assets=10; names=[f'Stock_{i}' for i in range(n_assets)]\n",
    "corr=np.array([[0.5**abs(i-j) for j in range(n_assets)] for i in range(n_assets)])\n",
    "L=np.linalg.cholesky(corr)\n",
    "raw=np.random.randn(500,n_assets)@L.T\n",
    "mu=np.array([0.0002*(1+0.3*i) for i in range(n_agents)]); sigma=np.array([0.01*(1+0.2*i) for i in range(n_assets)])\n",
    "returns=pd.DataFrame(raw*sigma+mu,columns=names)\n",
    "print('Ready')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "62decbb8",
   "metadata": {},
   "outputs": [],
   "source": [
    "mu_ann=returns.mean()*252; cov_ann=returns.cov()*252\n",
    "def perf(w): ret=np.dot(w,mu_ann); risk=np.sqrt(w@cov_ann@w); return ret,risk,ret/risk if risk>0 else 0"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "badac80b",
   "metadata": {},
   "source": [
    "## 2. 有效前沿"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "24557e22",
   "metadata": {},
   "outputs": [],
   "source": [
    "n_ports=3000; all_w=np.random.dirichlet(np.ones(n_assets),n_ports)\n",
    "rets,risks=[],[]\n",
    "for w in all_w:\n",
    "    r,risk,_=perf(w); rets.append(r); risks.append(risk)\n",
    "plt.figure(figsize=(10,6))\n",
    "sc=plt.scatter(risks,rets,c=np.array(rets)/np.array(risks),cmap='viridis',alpha=0.5,s=10)\n",
    "plt.colorbar(sc,label='Sharpe')\n",
    "plt.xlabel('Risk'); plt.ylabel('Return'); plt.title('Efficient Frontier'); plt.show()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "2bae9590",
   "metadata": {},
   "source": [
    "## 3. 最小方差 & 最大夏普"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "553d68ed",
   "metadata": {},
   "outputs": [],
   "source": [
    "def minvar(mu,cov):\n",
    "    n=len(mu); obj=lambda w:perf(w)[1]\n",
    "    cons={'type':'eq','fun':lambda w:sum(w)-1}\n",
    "    bnds=tuple((0,1) for _ in range(n))\n",
    "    return minimize(obj,[1/n]*n,bounds=bnds,constraints=cons).x\n",
    "def maxsharpe(mu,cov):\n",
    "    n=len(mu); obj=lambda w:-perf(w)[2]\n",
    "    cons={'type':'eq','fun':lambda w:sum(w)-1}\n",
    "    bnds=tuple((0,1) for _ in range(n))\n",
    "    return minimize(obj,[1/n]*n,bounds=bnds,constraints=cons).x\n",
    "w_mv=minvar(mu_ann.values,cov_ann.values)\n",
    "w_ms=maxsharpe(mu_ann.values,cov_ann.values)\n",
    "print(f'MinVar: ret={perf(w_mv)[0]:.1%} risk={perf(w_mv)[1]:.1%}')\n",
    "print(f'MaxSharpe: ret={perf(w_ms)[0]:.1%} risk={perf(w_ms)[1]:.1%} sharpe={perf(w_ms)[2]:.2f}')"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9f06a83e",
   "metadata": {},
   "source": [
    "---\n",
    "*更多分析见 [案例文档](/docs/case-studies/finance/portfolio-optimization-case/)*"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python",
   "version": "3.10.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
