{"spec_id":"frontier-efficient","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\nfrontier-efficient: Efficient Frontier for Portfolio Optimization\nLibrary: plotly 6.7.0 | Python 3.13.13\nQuality: 91/100 | Updated: 2026-05-17\n\"\"\"\n\nimport os\nimport sys\n\n\n# Remove current directory from path to avoid import collision with script filename\nsys.path = [p for p in sys.path if p not in (\"\", \".\", os.getcwd())]\n\nimport numpy as np\nimport plotly.graph_objects as go\n\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nELEVATED_BG = \"#FFFDF6\" if THEME == \"light\" else \"#242420\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\nGRID = \"rgba(26,26,23,0.10)\" if THEME == \"light\" else \"rgba(240,239,232,0.10)\"\n\n# Okabe-Ito palette\nBRAND = \"#009E73\"\nSECONDARY = \"#C475FD\"\nTERTIARY = \"#4467A3\"\nACCENT_1 = \"#BD8233\"\n\n# Data - Generate random portfolios and efficient frontier\nnp.random.seed(42)\n\n# Simulate 5 assets with expected returns and covariance\nn_assets = 5\nexpected_returns = np.array([0.08, 0.12, 0.15, 0.10, 0.18])\ncov_matrix = np.array(\n    [\n        [0.04, 0.01, 0.02, 0.01, 0.02],\n        [0.01, 0.06, 0.02, 0.01, 0.03],\n        [0.02, 0.02, 0.09, 0.02, 0.04],\n        [0.01, 0.01, 0.02, 0.05, 0.02],\n        [0.02, 0.03, 0.04, 0.02, 0.12],\n    ]\n)\n\n# Generate 300 random portfolios\nn_portfolios = 300\nportfolio_returns = []\nportfolio_risks = []\nportfolio_sharpes = []\nrisk_free_rate = 0.03\n\nfor _ in range(n_portfolios):\n    weights = np.random.random(n_assets)\n    weights /= weights.sum()\n    port_return = np.dot(weights, expected_returns)\n    port_risk = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))\n    sharpe = (port_return - risk_free_rate) / port_risk\n    portfolio_returns.append(port_return)\n    portfolio_risks.append(port_risk)\n    portfolio_sharpes.append(sharpe)\n\nportfolio_returns = np.array(portfolio_returns)\nportfolio_risks = np.array(portfolio_risks)\nportfolio_sharpes = np.array(portfolio_sharpes)\n\n# Generate efficient frontier by Monte Carlo approximation\nn_frontier_samples = 50000\nall_returns = []\nall_risks = []\n\nfor _ in range(n_frontier_samples):\n    weights = np.random.random(n_assets)\n    weights /= weights.sum()\n    port_return = np.dot(weights, expected_returns)\n    port_risk = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))\n    all_returns.append(port_return)\n    all_risks.append(port_risk)\n\nall_returns = np.array(all_returns)\nall_risks = np.array(all_risks)\n\n# Extract efficient frontier by binning returns and finding minimum risk\nreturn_bins = np.linspace(all_returns.min(), all_returns.max(), 40)\nfrontier_returns = []\nfrontier_risks = []\n\nfor i in range(len(return_bins) - 1):\n    mask = (all_returns >= return_bins[i]) & (all_returns < return_bins[i + 1])\n    if np.any(mask):\n        min_risk_idx = np.argmin(all_risks[mask])\n        indices = np.where(mask)[0]\n        frontier_returns.append(all_returns[indices[min_risk_idx]])\n        frontier_risks.append(all_risks[indices[min_risk_idx]])\n\nfrontier_returns = np.array(frontier_returns)\nfrontier_risks = np.array(frontier_risks)\n\n# Sort by risk for smooth curve\nsort_idx = np.argsort(frontier_risks)\nfrontier_returns = frontier_returns[sort_idx]\nfrontier_risks = frontier_risks[sort_idx]\n\n# Find key portfolios\nmin_var_idx = np.argmin(portfolio_risks)\nmax_sharpe_idx = np.argmax(portfolio_sharpes)\n\n# Capital Market Line\ncml_x = np.linspace(0, 0.35, 100)\nsharpe_slope = (portfolio_returns[max_sharpe_idx] - risk_free_rate) / portfolio_risks[max_sharpe_idx]\ncml_y = risk_free_rate + sharpe_slope * cml_x\n\n# Plot\nfig = go.Figure()\n\n# Random portfolios scatter colored by Sharpe ratio (using viridis for continuous)\nfig.add_trace(\n    go.Scatter(\n        x=portfolio_risks,\n        y=portfolio_returns,\n        mode=\"markers\",\n        marker={\n            \"size\": 10,\n            \"color\": portfolio_sharpes,\n            \"colorscale\": \"Viridis\",\n            \"colorbar\": {\n                \"title\": {\"text\": \"Sharpe Ratio\", \"font\": {\"size\": 18, \"color\": INK_SOFT}},\n                \"tickfont\": {\"size\": 14, \"color\": INK_SOFT},\n                \"thickness\": 20,\n                \"len\": 0.6,\n                \"tickcolor\": INK_SOFT,\n            },\n            \"opacity\": 0.7,\n            \"line\": {\"width\": 0.5, \"color\": PAGE_BG},\n        },\n        name=\"Random Portfolios\",\n        hovertemplate=\"Risk: %{x:.2%}<br>Return: %{y:.2%}<br>Sharpe: %{marker.color:.2f}<extra></extra>\",\n    )\n)\n\n# Efficient frontier curve\nfig.add_trace(\n    go.Scatter(\n        x=frontier_risks,\n        y=frontier_returns,\n        mode=\"lines\",\n        line={\"color\": BRAND, \"width\": 5},\n        name=\"Efficient Frontier\",\n        hovertemplate=\"Risk: %{x:.2%}<br>Return: %{y:.2%}<extra></extra>\",\n    )\n)\n\n# Capital Market Line\nfig.add_trace(\n    go.Scatter(\n        x=cml_x,\n        y=cml_y,\n        mode=\"lines\",\n        line={\"color\": SECONDARY, \"width\": 3, \"dash\": \"dash\"},\n        name=\"Capital Market Line\",\n        hovertemplate=\"Risk: %{x:.2%}<br>Return: %{y:.2%}<extra></extra>\",\n    )\n)\n\n# Minimum variance portfolio\nfig.add_trace(\n    go.Scatter(\n        x=[portfolio_risks[min_var_idx]],\n        y=[portfolio_returns[min_var_idx]],\n        mode=\"markers+text\",\n        marker={\"size\": 20, \"color\": TERTIARY, \"symbol\": \"diamond\", \"line\": {\"width\": 2, \"color\": PAGE_BG}},\n        text=[\"Min Variance\"],\n        textposition=\"top right\",\n        textfont={\"size\": 16, \"color\": TERTIARY},\n        name=\"Min Variance Portfolio\",\n        showlegend=True,\n    )\n)\n\n# Maximum Sharpe ratio portfolio\nfig.add_trace(\n    go.Scatter(\n        x=[portfolio_risks[max_sharpe_idx]],\n        y=[portfolio_returns[max_sharpe_idx]],\n        mode=\"markers+text\",\n        marker={\"size\": 20, \"color\": ACCENT_1, \"symbol\": \"star\", \"line\": {\"width\": 2, \"color\": PAGE_BG}},\n        text=[\"Max Sharpe\"],\n        textposition=\"top right\",\n        textfont={\"size\": 16, \"color\": ACCENT_1},\n        name=\"Max Sharpe Portfolio\",\n        showlegend=True,\n    )\n)\n\n# Risk-free rate point\nfig.add_trace(\n    go.Scatter(\n        x=[0],\n        y=[risk_free_rate],\n        mode=\"markers\",\n        marker={\"size\": 16, \"color\": INK_SOFT, \"symbol\": \"circle\", \"line\": {\"width\": 2, \"color\": PAGE_BG}},\n        name=f\"Risk-Free Rate ({risk_free_rate:.0%})\",\n        showlegend=True,\n    )\n)\n\n# Style\nfig.update_layout(\n    title={\n        \"text\": \"frontier-efficient · plotly · anyplot.ai\",\n        \"font\": {\"size\": 28, \"color\": INK},\n        \"x\": 0.5,\n        \"xanchor\": \"center\",\n    },\n    xaxis={\n        \"title\": {\"text\": \"Risk (Standard Deviation)\", \"font\": {\"size\": 22, \"color\": INK}},\n        \"tickfont\": {\"size\": 18, \"color\": INK_SOFT},\n        \"tickformat\": \".0%\",\n        \"range\": [0, 0.38],\n        \"gridcolor\": GRID,\n        \"gridwidth\": 1,\n        \"linecolor\": INK_SOFT,\n        \"zeroline\": False,\n    },\n    yaxis={\n        \"title\": {\"text\": \"Expected Return (Annual)\", \"font\": {\"size\": 22, \"color\": INK}},\n        \"tickfont\": {\"size\": 18, \"color\": INK_SOFT},\n        \"tickformat\": \".0%\",\n        \"range\": [0, 0.25],\n        \"gridcolor\": GRID,\n        \"gridwidth\": 1,\n        \"linecolor\": INK_SOFT,\n        \"zeroline\": False,\n    },\n    paper_bgcolor=PAGE_BG,\n    plot_bgcolor=PAGE_BG,\n    font={\"color\": INK},\n    legend={\n        \"font\": {\"size\": 16, \"color\": INK_SOFT},\n        \"x\": 0.02,\n        \"y\": 0.98,\n        \"bgcolor\": ELEVATED_BG,\n        \"bordercolor\": INK_SOFT,\n        \"borderwidth\": 1,\n    },\n    margin={\"l\": 80, \"r\": 100, \"t\": 80, \"b\": 80},\n    width=1600,\n    height=900,\n)\n\n# Save\nfig.write_image(f\"plot-{THEME}.png\", width=1600, height=900, scale=3)\nfig.write_html(f\"plot-{THEME}.html\", include_plotlyjs=\"cdn\")\n"}