{"spec_id":"indicator-bollinger","library":"seaborn","language":"python","code":"\"\"\" anyplot.ai\nindicator-bollinger: Bollinger Bands Indicator Chart\nLibrary: seaborn 0.13.2 | Python 3.13.13\nQuality: 93/100 | Updated: 2026-05-17\n\"\"\"\n\nimport os\nimport sys\n\n\n# Prevent script name from shadowing seaborn package\ncwd = os.getcwd()\nsys.path = [p for p in sys.path if os.path.abspath(p) != os.path.abspath(os.path.dirname(__file__))]\n\nimport matplotlib.pyplot as plt\nimport numpy as np\nimport pandas as pd\nimport seaborn as sns\n\n\n# Theme configuration\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# Okabe-Ito palette\nBRAND = \"#009E73\"  # Close price (primary)\nSECONDARY = \"#C475FD\"  # SMA (middle band)\nTERTIARY = \"#4467A3\"  # Bollinger Bands\n\n# Apply theme\nsns.set_theme(\n    style=\"ticks\",\n    rc={\n        \"figure.facecolor\": PAGE_BG,\n        \"axes.facecolor\": PAGE_BG,\n        \"axes.edgecolor\": INK_SOFT,\n        \"axes.labelcolor\": INK,\n        \"text.color\": INK,\n        \"xtick.color\": INK_SOFT,\n        \"ytick.color\": INK_SOFT,\n        \"grid.color\": INK,\n        \"grid.alpha\": 0.10,\n        \"legend.facecolor\": ELEVATED_BG,\n        \"legend.edgecolor\": INK_SOFT,\n    },\n)\n\n# Data - Generate realistic stock price data with Bollinger Bands\nnp.random.seed(42)\n\n# Generate 120 trading days of price data\nn_days = 120\ndates = pd.date_range(start=\"2024-01-02\", periods=n_days, freq=\"B\")\n\n# Simulate price movement with trend and volatility\nreturns = np.random.normal(0.0005, 0.015, n_days)\nprice_base = 150\nprices = price_base * np.cumprod(1 + returns)\n\n# Add some volatility clustering (higher volatility periods)\nvolatility_boost = np.zeros(n_days)\nvolatility_boost[30:50] = np.random.normal(0, 0.01, 20)  # High volatility period\nvolatility_boost[80:95] = np.random.normal(0, 0.008, 15)  # Another volatile period\nprices = prices * (1 + volatility_boost)\n\n# Calculate Bollinger Bands (20-period SMA, 2 standard deviations)\nwindow = 20\nclose = pd.Series(prices)\nsma = close.rolling(window=window).mean()\nstd = close.rolling(window=window).std()\nupper_band = sma + 2 * std\nlower_band = sma - 2 * std\n\n# Create DataFrame\ndf = pd.DataFrame({\"date\": dates, \"close\": close, \"sma\": sma, \"upper_band\": upper_band, \"lower_band\": lower_band})\n\n# Drop NaN values from rolling calculation\ndf = df.dropna().reset_index(drop=True)\n\n# Create plot\nfig, ax = plt.subplots(figsize=(16, 9))\n\n# Plot Bollinger Bands fill between upper and lower\nax.fill_between(\n    df[\"date\"], df[\"lower_band\"], df[\"upper_band\"], alpha=0.15, color=TERTIARY, label=\"Bollinger Band Range\"\n)\n\n# Plot upper band\nax.plot(df[\"date\"], df[\"upper_band\"], color=TERTIARY, linewidth=2, alpha=0.7, label=\"Upper Band (+2σ)\")\n\n# Plot lower band\nax.plot(df[\"date\"], df[\"lower_band\"], color=TERTIARY, linewidth=2, alpha=0.7, label=\"Lower Band (-2σ)\")\n\n# Plot SMA (middle band) - dashed line\nax.plot(df[\"date\"], df[\"sma\"], color=SECONDARY, linewidth=2.5, linestyle=\"--\", label=\"20-Day SMA\")\n\n# Plot close price - prominent line\nax.plot(df[\"date\"], df[\"close\"], color=BRAND, linewidth=3, label=\"Close Price\")\n\n# Styling\nax.set_title(\"indicator-bollinger · seaborn · pyplots.ai\", fontsize=24, fontweight=\"bold\", pad=20)\nax.set_xlabel(\"Date\", fontsize=20)\nax.set_ylabel(\"Price ($)\", fontsize=20)\nax.tick_params(axis=\"both\", labelsize=16)\n\n# Format x-axis dates\nfig.autofmt_xdate(rotation=30)\n\n# Legend\nax.legend(fontsize=16, loc=\"upper left\", framealpha=0.95, frameon=True)\n\n# Grid\nax.yaxis.grid(True, alpha=0.15, linewidth=0.8)\nax.set_axisbelow(True)\n\n# Remove top and right spines\nax.spines[\"top\"].set_visible(False)\nax.spines[\"right\"].set_visible(False)\n\nplt.tight_layout()\n\n# Save to script directory\nscript_dir = os.path.dirname(os.path.abspath(__file__))\noutput_path = os.path.join(script_dir, f\"plot-{THEME}.png\")\nplt.savefig(output_path, dpi=300, bbox_inches=\"tight\", facecolor=PAGE_BG)\n"}