{"spec_id":"line-annotated-events","library":"plotly","language":"python","code":"\"\"\" anyplot.ai\nline-annotated-events: Annotated Line Plot with Event Markers\nLibrary: plotly 6.7.0 | Python 3.13.13\nQuality: 89/100 | Updated: 2026-05-16\n\"\"\"\n\nimport numpy as np\nimport pandas as pd\nimport plotly.graph_objects as go\n\n\n# Data - Simulated stock price data with events\nnp.random.seed(42)\n\n# Generate daily stock prices over a year\ndates = pd.date_range(\"2024-01-01\", periods=252, freq=\"B\")  # Business days\nreturns = np.random.normal(0.0005, 0.015, len(dates))\nprices = 100 * np.exp(np.cumsum(returns))\n\n# Define significant events (earnings announcements, product launches)\nevents = [\n    {\"date\": pd.Timestamp(\"2024-01-25\"), \"label\": \"Q4 Earnings\"},\n    {\"date\": pd.Timestamp(\"2024-03-15\"), \"label\": \"Product Launch\"},\n    {\"date\": pd.Timestamp(\"2024-04-24\"), \"label\": \"Q1 Earnings\"},\n    {\"date\": pd.Timestamp(\"2024-06-10\"), \"label\": \"Expansion Announced\"},\n    {\"date\": pd.Timestamp(\"2024-07-25\"), \"label\": \"Q2 Earnings\"},\n    {\"date\": pd.Timestamp(\"2024-09-20\"), \"label\": \"Partnership Deal\"},\n    {\"date\": pd.Timestamp(\"2024-10-24\"), \"label\": \"Q3 Earnings\"},\n]\n\n# Create figure\nfig = go.Figure()\n\n# Add main price line\nfig.add_trace(\n    go.Scatter(\n        x=dates,\n        y=prices,\n        mode=\"lines\",\n        name=\"Stock Price\",\n        line={\"color\": \"#306998\", \"width\": 4},\n        hovertemplate=\"Date: %{x|%Y-%m-%d}<br>Price: $%{y:.2f}<extra></extra>\",\n    )\n)\n\n# Add vertical lines and markers for events with alternating heights\ny_range = prices.max() - prices.min()\nheights = [0.92, 0.82, 0.92, 0.82, 0.92, 0.82, 0.92]  # Alternating heights\n\nfor i, event in enumerate(events):\n    event_date = event[\"date\"]\n    event_label = event[\"label\"]\n    y_position = prices.min() + y_range * heights[i]\n\n    # Find the closest price at event date\n    closest_idx = np.abs(dates - event_date).argmin()\n    price_at_event = prices[closest_idx]\n\n    # Add vertical dashed line\n    fig.add_shape(\n        type=\"line\",\n        x0=event_date,\n        x1=event_date,\n        y0=prices.min() - y_range * 0.02,\n        y1=y_position - y_range * 0.02,\n        line={\"color\": \"#FFD43B\", \"width\": 3, \"dash\": \"dash\"},\n    )\n\n    # Add marker at the event date on the price line\n    fig.add_trace(\n        go.Scatter(\n            x=[event_date],\n            y=[price_at_event],\n            mode=\"markers\",\n            marker={\"size\": 18, \"color\": \"#FFD43B\", \"symbol\": \"diamond\", \"line\": {\"color\": \"#306998\", \"width\": 2}},\n            showlegend=False,\n            hovertemplate=f\"{event_label}<br>Date: %{{x|%Y-%m-%d}}<br>Price: $%{{y:.2f}}<extra></extra>\",\n        )\n    )\n\n    # Add annotation label\n    fig.add_annotation(\n        x=event_date,\n        y=y_position,\n        text=event_label,\n        showarrow=False,\n        font={\"size\": 20, \"color\": \"#333333\"},\n        bgcolor=\"rgba(255, 212, 59, 0.9)\",\n        bordercolor=\"#FFD43B\",\n        borderwidth=2,\n        borderpad=8,\n    )\n\n# Update layout\nfig.update_layout(\n    title={\"text\": \"line-annotated-events · plotly · pyplots.ai\", \"font\": {\"size\": 40}, \"x\": 0.5, \"xanchor\": \"center\"},\n    xaxis={\n        \"title\": {\"text\": \"Date\", \"font\": {\"size\": 36}},\n        \"tickfont\": {\"size\": 28},\n        \"showgrid\": True,\n        \"gridcolor\": \"rgba(0,0,0,0.1)\",\n        \"gridwidth\": 1,\n    },\n    yaxis={\n        \"title\": {\"text\": \"Stock Price (USD)\", \"font\": {\"size\": 36}},\n        \"tickfont\": {\"size\": 28},\n        \"tickprefix\": \"$\",\n        \"showgrid\": True,\n        \"gridcolor\": \"rgba(0,0,0,0.1)\",\n        \"gridwidth\": 1,\n    },\n    template=\"plotly_white\",\n    showlegend=True,\n    legend={\n        \"x\": 0.02,\n        \"y\": 0.98,\n        \"font\": {\"size\": 24},\n        \"bgcolor\": \"rgba(255,255,255,0.9)\",\n        \"bordercolor\": \"rgba(0,0,0,0.2)\",\n        \"borderwidth\": 1,\n    },\n    margin={\"l\": 120, \"r\": 50, \"t\": 120, \"b\": 100},\n    plot_bgcolor=\"white\",\n)\n\n# Save as PNG and HTML\nfig.write_image(\"plot.png\", width=1600, height=900, scale=3)\nfig.write_html(\"plot.html\", include_plotlyjs=True)\n"}