{"spec_id":"frontier-efficient","library":"seaborn","language":"python","code":"\"\"\" anyplot.ai\nfrontier-efficient: Efficient Frontier for Portfolio Optimization\nLibrary: seaborn 0.13.2 | Python 3.13.13\nQuality: 92/100 | Updated: 2026-05-17\n\"\"\"\n\nimport os\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport seaborn as sns\nfrom scipy.optimize import minimize\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\"\n\nBRAND = \"#009E73\"  # Okabe-Ito position 1\nACCENT_1 = \"#C475FD\"  # Okabe-Ito position 2 (orange)\nACCENT_2 = \"#4467A3\"  # Okabe-Ito position 3 (blue)\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.10, 0.15, 0.07])\n# Generate a valid positive semi-definite covariance matrix\nvolatilities = np.array([0.15, 0.22, 0.18, 0.28, 0.12])\ncorrelation = np.array(\n    [\n        [1.0, 0.3, 0.2, 0.4, 0.1],\n        [0.3, 1.0, 0.5, 0.3, 0.2],\n        [0.2, 0.5, 1.0, 0.4, 0.3],\n        [0.4, 0.3, 0.4, 1.0, 0.2],\n        [0.1, 0.2, 0.3, 0.2, 1.0],\n    ]\n)\ncov_matrix = np.outer(volatilities, volatilities) * correlation\n\n# Generate random portfolios\nn_portfolios = 300\nportfolio_returns = []\nportfolio_risks = []\nportfolio_sharpe = []\nrisk_free_rate = 0.02\n\nfor _ in range(n_portfolios):\n    weights = np.random.random(n_assets)\n    weights /= np.sum(weights)\n    ret = np.dot(weights, expected_returns)\n    risk = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights)))\n    sharpe = (ret - risk_free_rate) / risk\n    portfolio_returns.append(ret)\n    portfolio_risks.append(risk)\n    portfolio_sharpe.append(sharpe)\n\nportfolio_returns = np.array(portfolio_returns)\nportfolio_risks = np.array(portfolio_risks)\nportfolio_sharpe = np.array(portfolio_sharpe)\n\n\n# Optimization objective functions\ndef calc_vol(w):\n    return np.sqrt(np.dot(w.T, np.dot(cov_matrix, w)))\n\n\ndef calc_neg_sharpe(w):\n    ret = np.dot(w, expected_returns)\n    vol = np.sqrt(np.dot(w.T, np.dot(cov_matrix, w)))\n    return -(ret - risk_free_rate) / vol\n\n\n# Find minimum variance portfolio\nconstraints = {\"type\": \"eq\", \"fun\": lambda x: np.sum(x) - 1}\nbounds = tuple((0, 1) for _ in range(n_assets))\ninit_weights = np.array([1 / n_assets] * n_assets)\n\nmin_var_result = minimize(calc_vol, init_weights, method=\"SLSQP\", bounds=bounds, constraints=constraints)\nmin_var_weights = min_var_result.x\nmin_var_risk = calc_vol(min_var_weights)\nmin_var_return = np.dot(min_var_weights, expected_returns)\n\n# Find maximum Sharpe ratio (tangency) portfolio\nmax_sharpe_result = minimize(calc_neg_sharpe, init_weights, method=\"SLSQP\", bounds=bounds, constraints=constraints)\nmax_sharpe_weights = max_sharpe_result.x\nmax_sharpe_risk = calc_vol(max_sharpe_weights)\nmax_sharpe_return = np.dot(max_sharpe_weights, expected_returns)\n\n# Generate efficient frontier curve\ntarget_returns = np.linspace(min_var_return, max(expected_returns) * 0.98, 50)\nfrontier_risks = []\nfrontier_returns = []\n\nfor target in target_returns:\n    constraints_ef = [\n        {\"type\": \"eq\", \"fun\": lambda x: np.sum(x) - 1},\n        {\"type\": \"eq\", \"fun\": lambda x, t=target: np.dot(x, expected_returns) - t},\n    ]\n    result = minimize(calc_vol, init_weights, method=\"SLSQP\", bounds=bounds, constraints=constraints_ef)\n    if result.success:\n        frontier_risks.append(calc_vol(result.x))\n        frontier_returns.append(target)\n\nfrontier_risks = np.array(frontier_risks)\nfrontier_returns = np.array(frontier_returns)\n\n# Plot\nsns.set_theme(\n    style=\"whitegrid\",\n    rc={\n        \"figure.facecolor\": PAGE_BG,\n        \"axes.facecolor\": PAGE_BG,\n        \"axes.edgecolor\": INK_SOFT,\n        \"axes.labelcolor\": INK,\n        \"text.color\": INK,\n        \"xtick.color\": INK_SOFT,\n        \"ytick.color\": INK_SOFT,\n        \"grid.color\": INK,\n        \"grid.alpha\": 0.10,\n        \"legend.facecolor\": ELEVATED_BG,\n        \"legend.edgecolor\": INK_SOFT,\n    },\n)\n\nfig, ax = plt.subplots(figsize=(16, 9), facecolor=PAGE_BG)\n\n# Scatter plot of random portfolios colored by Sharpe ratio\nscatter = ax.scatter(\n    portfolio_risks * 100,\n    portfolio_returns * 100,\n    c=portfolio_sharpe,\n    cmap=\"viridis\",\n    s=100,\n    alpha=0.6,\n    edgecolors=PAGE_BG,\n    linewidth=0.5,\n)\n\n# Colorbar for Sharpe ratio\ncbar = plt.colorbar(scatter, ax=ax)\ncbar.set_label(\"Sharpe Ratio\", fontsize=18, color=INK)\ncbar.ax.tick_params(labelsize=14, colors=INK_SOFT)\n\n# Plot efficient frontier curve (use brand color)\nax.plot(frontier_risks * 100, frontier_returns * 100, color=BRAND, linewidth=4, label=\"Efficient Frontier\", zorder=5)\n\n# Mark minimum variance portfolio\nax.scatter(\n    min_var_risk * 100,\n    min_var_return * 100,\n    color=ACCENT_2,\n    s=400,\n    marker=\"*\",\n    edgecolors=PAGE_BG,\n    linewidths=2,\n    zorder=10,\n    label=\"Min Variance Portfolio\",\n)\n\n# Mark maximum Sharpe ratio (tangency) portfolio\nax.scatter(\n    max_sharpe_risk * 100,\n    max_sharpe_return * 100,\n    color=ACCENT_1,\n    s=400,\n    marker=\"*\",\n    edgecolors=PAGE_BG,\n    linewidths=2,\n    zorder=10,\n    label=\"Max Sharpe Portfolio\",\n)\n\n# Capital Market Line\ncml_x = np.array([0, max_sharpe_risk * 100 * 1.5])\ncml_slope = (max_sharpe_return - risk_free_rate) / max_sharpe_risk\ncml_y = risk_free_rate * 100 + cml_slope * cml_x\nax.plot(cml_x, cml_y, color=ACCENT_2, linewidth=2.5, linestyle=\"--\", label=\"Capital Market Line\", zorder=4)\n\n# Mark risk-free rate\nax.scatter(0, risk_free_rate * 100, color=ACCENT_2, s=250, marker=\"o\", edgecolors=PAGE_BG, linewidths=2, zorder=10)\nax.annotate(\n    f\"Risk-Free\\n({risk_free_rate * 100:.0f}%)\",\n    xy=(0, risk_free_rate * 100),\n    xytext=(2, risk_free_rate * 100 + 1.5),\n    fontsize=14,\n    color=INK,\n)\n\n# Style\nax.set_xlabel(\"Risk (Standard Deviation, %)\", fontsize=20, color=INK)\nax.set_ylabel(\"Expected Return (%)\", fontsize=20, color=INK)\nax.set_title(\"frontier-efficient · seaborn · anyplot.ai\", fontsize=24, fontweight=\"medium\", color=INK)\nax.tick_params(axis=\"both\", labelsize=16, colors=INK_SOFT)\nax.legend(loc=\"lower right\", fontsize=14, framealpha=0.95)\nax.set_xlim(-1, 35)\nax.set_ylim(0, 18)\nax.grid(True, alpha=0.10, linestyle=\"-\")\n\nplt.tight_layout()\nplt.savefig(f\"plot-{THEME}.png\", dpi=300, bbox_inches=\"tight\", facecolor=PAGE_BG)\n"}