{"spec_id":"indicator-macd","library":"matplotlib","language":"python","code":"\"\"\" anyplot.ai\nindicator-macd: MACD Technical Indicator Chart\nLibrary: matplotlib 3.10.9 | Python 3.13.13\nQuality: 90/100 | Updated: 2026-05-16\n\"\"\"\n\nimport os\nimport sys\n\n\nsys.path.pop(0)\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\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\n# imprint palette\nMACD_COLOR = \"#4467A3\"  # blue — MACD line\nSIGNAL_COLOR = \"#BD8233\"  # ochre — signal line (categorical contrast with MACD blue)\nPOSITIVE_COLOR = \"#009E73\"  # green — histogram bars above zero\nNEGATIVE_COLOR = \"#AE3030\"  # red — histogram bars below zero\n\n# Generate synthetic stock price data and calculate MACD\nnp.random.seed(42)\n\n# Create 150 trading days of price data (need 120 for display + 26 for EMA warmup)\nn_days = 150\ndates = pd.date_range(\"2024-06-01\", periods=n_days, freq=\"B\")\n\n# Generate realistic price movement with trend and volatility\nreturns = np.random.normal(0.0005, 0.015, n_days)\nprice = 100 * np.cumprod(1 + returns)\n\n\n# Calculate EMAs for MACD\ndef ema(data, span):\n    return pd.Series(data).ewm(span=span, adjust=False).mean().values\n\n\nema_12 = ema(price, 12)\nema_26 = ema(price, 26)\n\n# Calculate MACD components\nmacd_line = ema_12 - ema_26\nsignal_line = ema(macd_line, 9)\nhistogram = macd_line - signal_line\n\n# Use only the last 120 days (after EMAs have stabilized)\nstart_idx = 30\ndates = dates[start_idx:]\nmacd_line = macd_line[start_idx:]\nsignal_line = signal_line[start_idx:]\nhistogram = histogram[start_idx:]\n\n# Create figure with two subplots\nfig, (ax1, ax2) = plt.subplots(2, 1, figsize=(16, 9), facecolor=PAGE_BG, gridspec_kw={\"height_ratios\": [2, 1]})\n\n# Upper subplot: MACD and Signal lines\nax1.set_facecolor(PAGE_BG)\nax1.plot(dates, macd_line, color=MACD_COLOR, linewidth=3, label=\"MACD (12, 26)\")\nax1.plot(dates, signal_line, color=SIGNAL_COLOR, linewidth=3, label=\"Signal (9)\")\nax1.axhline(y=0, color=INK_SOFT, linestyle=\"--\", linewidth=1.5, alpha=0.5)\n\nax1.set_ylabel(\"MACD Value\", fontsize=20, color=INK)\nax1.tick_params(axis=\"both\", labelsize=16, colors=INK_SOFT)\nax1.spines[\"top\"].set_visible(False)\nax1.spines[\"right\"].set_visible(False)\nfor s in (\"left\", \"bottom\"):\n    ax1.spines[s].set_color(INK_SOFT)\nax1.yaxis.grid(True, alpha=0.10, linewidth=0.8, color=INK_SOFT)\n\n# Legend for upper subplot\nleg1 = ax1.legend(fontsize=16, loc=\"upper left\")\nif leg1:\n    leg1.get_frame().set_facecolor(ELEVATED_BG)\n    leg1.get_frame().set_edgecolor(INK_SOFT)\n    leg1.get_frame().set_alpha(0.95)\n    plt.setp(leg1.get_texts(), color=INK_SOFT)\n\n# Lower subplot: Histogram\nax2.set_facecolor(PAGE_BG)\ncolors = [POSITIVE_COLOR if h >= 0 else NEGATIVE_COLOR for h in histogram]\nax2.bar(dates, histogram, color=colors, alpha=0.8, width=0.8, label=\"Histogram\")\nax2.axhline(y=0, color=INK_SOFT, linestyle=\"-\", linewidth=1.5, alpha=0.7)\n\nax2.set_xlabel(\"Date\", fontsize=20, color=INK)\nax2.set_ylabel(\"Histogram\", fontsize=20, color=INK)\nax2.tick_params(axis=\"both\", labelsize=16, colors=INK_SOFT)\nax2.spines[\"top\"].set_visible(False)\nax2.spines[\"right\"].set_visible(False)\nfor s in (\"left\", \"bottom\"):\n    ax2.spines[s].set_color(INK_SOFT)\nax2.yaxis.grid(True, alpha=0.10, linewidth=0.8, color=INK_SOFT)\n\n# Format x-axis dates\nfig.autofmt_xdate(rotation=45, ha=\"right\")\n\n# Main title\nfig.suptitle(\"indicator-macd · matplotlib · anyplot.ai\", fontsize=24, fontweight=\"medium\", color=INK, y=0.98)\n\nplt.tight_layout(rect=[0, 0, 1, 0.96])\n\n# Save to script directory\nscript_dir = os.path.dirname(os.path.abspath(__file__))\nplt.savefig(os.path.join(script_dir, f\"plot-{THEME}.png\"), dpi=300, bbox_inches=\"tight\", facecolor=PAGE_BG)\n"}