{"spec_id":"indicator-ema","library":"pygal","language":"python","code":"\"\"\" anyplot.ai\nindicator-ema: Exponential Moving Average (EMA) Indicator Chart\nLibrary: pygal 3.1.0 | Python 3.13.13\nQuality: 86/100 | Updated: 2026-05-19\n\"\"\"\n\nimport os\nimport sys\n\n\n# Prevent the local pygal.py from shadowing the installed pygal package\n_here = os.path.dirname(os.path.abspath(__file__))\nsys.path = [p for p in sys.path if os.path.abspath(p or \".\") != _here]\n\nimport numpy as np\nimport pandas as pd\nimport pygal\nfrom pygal.style import Style\n\n\nTHEME = os.getenv(\"ANYPLOT_THEME\", \"light\")\nPAGE_BG = \"#FAF8F1\" if THEME == \"light\" else \"#1A1A17\"\nINK = \"#1A1A17\" if THEME == \"light\" else \"#F0EFE8\"\nINK_MUTED = \"#6B6A63\" if THEME == \"light\" else \"#A8A79F\"\n\nIMPRINT = (\"#009E73\", \"#C475FD\", \"#4467A3\", \"#BD8233\", \"#AE3030\", \"#2ABCCD\", \"#954477\")\n\n# Data\nnp.random.seed(42)\ndates = pd.date_range(start=\"2024-01-02\", periods=120, freq=\"B\")\ninitial_price = 150.0\nreturns = np.random.normal(0.0008, 0.018, 120)\nprices = initial_price * np.cumprod(1 + returns)\n\nclose = prices\nema_12 = pd.Series(close).ewm(span=12, adjust=False).mean().values\nema_26 = pd.Series(close).ewm(span=26, adjust=False).mean().values\n\n# Detect EMA crossover points\ncrossover_vals = [None] * len(close)\nfor i in range(1, len(ema_12)):\n    prev_diff = ema_12[i - 1] - ema_26[i - 1]\n    curr_diff = ema_12[i] - ema_26[i]\n    if prev_diff * curr_diff < 0:\n        crossover_vals[i] = float(close[i])\n\n# Style\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=72,\n    label_font_size=48,\n    major_label_font_size=42,\n    legend_font_size=48,\n    value_font_size=36,\n    tooltip_font_size=36,\n    stroke_width=6,\n    opacity=0.9,\n    opacity_hover=1.0,\n)\n\n# Chart\nchart = pygal.Line(\n    width=4800,\n    height=2700,\n    style=custom_style,\n    title=\"indicator-ema · python · pygal · anyplot.ai\",\n    x_title=\"Date\",\n    y_title=\"Price ($)\",\n    show_dots=False,\n    show_x_guides=True,\n    show_y_guides=True,\n    stroke_style={\"width\": 6},\n    legend_at_bottom=True,\n    legend_at_bottom_columns=4,\n    x_label_rotation=45,\n    truncate_label=10,\n    show_minor_x_labels=False,\n    dots_size=10,\n)\n\nchart.x_labels = [d.strftime(\"%Y-%m-%d\") for d in dates]\nchart.x_labels_major = [dates[i].strftime(\"%Y-%m-%d\") for i in range(0, len(dates), 20)]\n\nchart.add(\"Close Price\", close.tolist(), stroke_style={\"width\": 8})\nchart.add(\"EMA 12-day\", ema_12.tolist(), stroke_style={\"width\": 5, \"dasharray\": \"10,5\"})\nchart.add(\"EMA 26-day\", ema_26.tolist(), stroke_style={\"width\": 5, \"dasharray\": \"5,5\"})\nchart.add(\"Crossovers\", crossover_vals, show_dots=True, stroke=False)\n\n# Save\nchart.render_to_png(f\"plot-{THEME}.png\")\nwith open(f\"plot-{THEME}.html\", \"wb\") as f:\n    f.write(chart.render())\n"}