{"spec_id":"frontier-efficient","library":"pygal","language":"python","code":"\"\"\" anyplot.ai\nfrontier-efficient: Efficient Frontier for Portfolio Optimization\nLibrary: pygal 3.1.0 | Python 3.13.13\nQuality: 85/100 | Updated: 2026-05-17\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pygal\nfrom pygal.style import Style\n\n\n# Theme tokens\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_SOFT = \"#4A4A44\" if THEME == \"light\" else \"#B8B7B0\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\nIMPRINT = (\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\")\n\n# Data - Generate simulated portfolios and efficient frontier\nnp.random.seed(42)\n\n# Simulate 5 assets with expected returns and volatilities\nn_assets = 5\nexpected_returns = np.array([0.08, 0.12, 0.15, 0.10, 0.18])\nvolatilities = np.array([0.15, 0.20, 0.25, 0.18, 0.30])\n\n# Create correlation matrix and covariance matrix\ncorrelations = np.array(\n    [\n        [1.0, 0.3, 0.4, 0.2, 0.3],\n        [0.3, 1.0, 0.5, 0.3, 0.4],\n        [0.4, 0.5, 1.0, 0.3, 0.5],\n        [0.2, 0.3, 0.3, 1.0, 0.3],\n        [0.3, 0.4, 0.5, 0.3, 1.0],\n    ]\n)\ncov_matrix = np.outer(volatilities, volatilities) * correlations\n\n# Generate 300 random portfolios\nn_portfolios = 300\nportfolio_returns = []\nportfolio_risks = []\nportfolio_sharpes = []\nrisk_free_rate = 0.02\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\n# Generate efficient frontier by finding optimal portfolios at each risk level\nn_samples = 5000\nall_returns = []\nall_risks = []\nall_sharpes = []\n\nfor _ in range(n_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    sharpe = (port_return - risk_free_rate) / port_risk\n    all_returns.append(port_return)\n    all_risks.append(port_risk)\n    all_sharpes.append(sharpe)\n\n# Find efficient frontier points (pareto optimal)\nrisk_buckets = np.linspace(min(all_risks), max(all_risks), 40)\nfrontier_risks = []\nfrontier_returns = []\n\nfor i in range(len(risk_buckets) - 1):\n    mask = (np.array(all_risks) >= risk_buckets[i]) & (np.array(all_risks) < risk_buckets[i + 1])\n    if np.any(mask):\n        bucket_returns = np.array(all_returns)[mask]\n        best_idx = np.argmax(bucket_returns)\n        bucket_risks = np.array(all_risks)[mask]\n        frontier_risks.append(bucket_risks[best_idx])\n        frontier_returns.append(bucket_returns[best_idx])\n\n# Sort frontier by risk\nsorted_indices = np.argsort(frontier_risks)\nfrontier_risks = [frontier_risks[i] for i in sorted_indices]\nfrontier_returns = [frontier_returns[i] for i in sorted_indices]\n\n# Find minimum variance portfolio (lowest risk)\nmin_var_idx = np.argmin(all_risks)\nmin_var_risk = all_risks[min_var_idx]\nmin_var_return = all_returns[min_var_idx]\n\n# Find maximum Sharpe ratio portfolio\nmax_sharpe_idx = np.argmax(all_sharpes)\nmax_sharpe_risk = all_risks[max_sharpe_idx]\nmax_sharpe_return = all_returns[max_sharpe_idx]\n\n# Custom style - theme-adaptive tokens, Okabe-Ito palette\ncustom_style = Style(\n    background=PAGE_BG,\n    plot_background=PAGE_BG,\n    foreground=INK,\n    foreground_strong=INK,\n    foreground_subtle=INK_MUTED,\n    colors=IMPRINT,\n    title_font_size=28,\n    label_font_size=22,\n    major_label_font_size=18,\n    legend_font_size=16,\n    value_font_size=14,\n    stroke_width=3,\n)\n\n# Calculate appropriate axis ranges based on actual data\ndata_max_risk = max(max(portfolio_risks), max(frontier_risks), max_sharpe_risk, min_var_risk)\ndata_min_risk = min(min(portfolio_risks), min(frontier_risks), max_sharpe_risk, min_var_risk)\ndata_max_return = max(max(portfolio_returns), max(frontier_returns), max_sharpe_return, min_var_return)\ndata_min_return = min(min(portfolio_returns), min(frontier_returns), max_sharpe_return, min_var_return)\n\n# Add small padding for better visualization\nx_padding = (data_max_risk - data_min_risk) * 0.1\ny_padding = (data_max_return - data_min_return) * 0.1\n\n# Create XY chart (scatter plot capability)\nchart = pygal.XY(\n    width=4800,\n    height=2700,\n    style=custom_style,\n    title=\"frontier-efficient · pygal · anyplot.ai\",\n    x_title=\"Risk (Standard Deviation)\",\n    y_title=\"Expected Return\",\n    show_x_guides=True,\n    show_y_guides=True,\n    dots_size=8,\n    stroke=False,\n    legend_at_bottom=True,\n    legend_at_bottom_columns=6,\n    truncate_legend=-1,\n    x_value_formatter=lambda x: f\"{x:.1%}\",\n    y_value_formatter=lambda y: f\"{y:.1%}\",\n    range=(max(0, data_min_return - y_padding), data_max_return + y_padding),\n    xrange=(max(0, data_min_risk - x_padding), data_max_risk + x_padding),\n)\n\n# Add random portfolios grouped by Sharpe ratio\nsharpe_33 = np.percentile(portfolio_sharpes, 33)\nsharpe_66 = np.percentile(portfolio_sharpes, 66)\n\nlow_sharpe = [\n    (portfolio_risks[i], portfolio_returns[i]) for i in range(n_portfolios) if portfolio_sharpes[i] < sharpe_33\n]\nmid_sharpe = [\n    (portfolio_risks[i], portfolio_returns[i])\n    for i in range(n_portfolios)\n    if sharpe_33 <= portfolio_sharpes[i] < sharpe_66\n]\nhigh_sharpe = [\n    (portfolio_risks[i], portfolio_returns[i]) for i in range(n_portfolios) if portfolio_sharpes[i] >= sharpe_66\n]\n\nchart.add(f\"Low Sharpe (<{sharpe_33:.2f})\", low_sharpe, dots_size=8)\nchart.add(f\"Mid Sharpe ({sharpe_33:.2f}-{sharpe_66:.2f})\", mid_sharpe, dots_size=8)\nchart.add(f\"High Sharpe (≥{sharpe_66:.2f})\", high_sharpe, dots_size=8)\n\n# Add efficient frontier as connected line\nfrontier_points = list(zip(frontier_risks, frontier_returns, strict=False))\nchart.add(\"Efficient Frontier\", frontier_points, stroke=True, dots_size=0, stroke_style={\"width\": 8})\n\n# Add special marker points for key portfolios\nchart.add(\"Min Variance\", [(min_var_risk, min_var_return)], dots_size=25)\nchart.add(\"Max Sharpe\", [(max_sharpe_risk, max_sharpe_return)], dots_size=25)\n\n# Save outputs\nchart.render_to_png(f\"plot-{THEME}.png\")\n\n# Save HTML for interactive version\nwith open(f\"plot-{THEME}.html\", \"w\") as f:\n    f.write(chart.render().decode(\"utf-8\"))\n"}