{"spec_id":"drawdown-basic","library":"letsplot","language":"python","code":"\"\"\" anyplot.ai\ndrawdown-basic: Drawdown Chart\nLibrary: letsplot 4.10.1 | Python 3.13.13\nQuality: 84/100 | Updated: 2026-05-23\n\"\"\"\n\nimport os\n\nimport numpy as np\nimport pandas as pd\nfrom lets_plot import (\n    LetsPlot,\n    aes,\n    element_blank,\n    element_line,\n    element_rect,\n    element_text,\n    geom_area,\n    geom_hline,\n    geom_line,\n    geom_point,\n    ggplot,\n    ggsave,\n    ggsize,\n    labs,\n    layer_tooltips,\n    scale_color_manual,\n    scale_shape_manual,\n    scale_x_datetime,\n    theme,\n    theme_minimal,\n)\n\n\nLetsPlot.setup_html()\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\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\nGRID_COLOR = \"#4A4A4433\" if THEME == \"light\" else \"#B8B7B033\"\n\n# Imprint palette — semantic exception: loss/down → red, recovery → green\nDRAWDOWN_COLOR = \"#AE3030\"  # palette pos 3\nRECOVERY_COLOR = \"#009E73\"  # palette pos 1\n\n# Data\nnp.random.seed(42)\nn_days = 500\ndates = pd.date_range(start=\"2022-01-01\", periods=n_days, freq=\"B\")\n\nreturns = np.random.normal(0.0005, 0.012, n_days)\nreturns[40:70] = np.random.normal(-0.008, 0.015, 30)\nreturns[70:120] = np.random.normal(0.012, 0.01, 50)\nreturns[180:230] = np.random.normal(-0.006, 0.018, 50)\nreturns[230:300] = np.random.normal(0.008, 0.012, 70)\nreturns[350:400] = np.random.normal(-0.007, 0.016, 50)\nreturns[400:450] = np.random.normal(0.009, 0.01, 50)\n\nprice = 100 * np.cumprod(1 + returns)\nrunning_max = np.maximum.accumulate(price)\ndrawdown = (price - running_max) / running_max * 100\n\ndf = pd.DataFrame({\"date\": dates, \"price\": price, \"drawdown\": drawdown})\n\nmax_dd_idx = int(np.argmin(drawdown))\nmax_dd_value = drawdown[max_dd_idx]\nmax_dd_date = dates[max_dd_idx].strftime(\"%Y-%m-%d\")\n\nrecovery_mask = (drawdown == 0) & (np.roll(drawdown, 1) < 0)\nrecovery_points = df[recovery_mask].copy()\nrecovery_points[\"marker_type\"] = \"Recovery Point\"\n\nmax_dd_df = df.iloc[[max_dd_idx]].copy()\nmax_dd_df[\"marker_type\"] = \"Max Drawdown\"\n\nmarkers_df = pd.concat([max_dd_df, recovery_points], ignore_index=True)\n\n# Plot\nmarker_tooltips = (\n    layer_tooltips().format(\"@drawdown\", \".1f\").line(\"@marker_type\").line(\"Date|@date\").line(\"Drawdown (%)|@drawdown\")\n)\n\nplot = (\n    ggplot(df, aes(x=\"date\", y=\"drawdown\"))\n    + geom_area(fill=DRAWDOWN_COLOR, alpha=0.30)\n    + geom_line(color=DRAWDOWN_COLOR, size=1.2)\n    + geom_hline(yintercept=0, color=INK_SOFT, size=0.8, linetype=\"dashed\")\n    + geom_point(\n        data=markers_df,\n        mapping=aes(x=\"date\", y=\"drawdown\", color=\"marker_type\", shape=\"marker_type\"),\n        size=5,\n        stroke=2.0,\n        fill=PAGE_BG,\n        alpha=0.8,\n        tooltips=marker_tooltips,\n    )\n    + scale_color_manual(name=\"\", values={\"Max Drawdown\": DRAWDOWN_COLOR, \"Recovery Point\": RECOVERY_COLOR})\n    + scale_shape_manual(name=\"\", values={\"Max Drawdown\": 16, \"Recovery Point\": 21})\n    + scale_x_datetime()\n    + labs(\n        x=\"Date\",\n        y=\"Drawdown (%)\",\n        title=\"drawdown-basic · python · letsplot · anyplot.ai\",\n        caption=f\"Max Drawdown: {max_dd_value:.1f}% on {max_dd_date}\",\n    )\n    + theme_minimal()\n    + theme(\n        plot_background=element_rect(fill=PAGE_BG, color=PAGE_BG),\n        panel_background=element_rect(fill=PAGE_BG),\n        panel_grid_major=element_line(color=GRID_COLOR, size=0.5),\n        panel_grid_major_x=element_blank(),\n        panel_grid_minor=element_blank(),\n        axis_title=element_text(size=12, color=INK),\n        axis_text=element_text(size=10, color=INK_SOFT),\n        plot_title=element_text(size=16, color=INK),\n        plot_caption=element_text(size=10, color=INK_MUTED),\n        legend_background=element_rect(fill=ELEVATED_BG),\n        legend_text=element_text(size=10, color=INK_SOFT),\n        legend_title=element_text(size=10, color=INK),\n        legend_position=\"top\",\n        axis_line=element_line(color=INK_SOFT),\n    )\n    + ggsize(800, 450)\n)\n\nggsave(plot, f\"plot-{THEME}.png\", path=\".\", scale=4)\nggsave(plot, f\"plot-{THEME}.html\", path=\".\")\n"}