Loading source
Pulling the file list, source metadata, and syntax-aware rendering for this listing.
Source from repo
Generate TradingView-style dark-theme candlestick charts with RSI, MACD, Bollinger Bands, and EMA/SMA using mplfinance.
Files
Skill
Size
Entrypoint
Format
Open file
Syntax-highlighted preview of this file as included in the skill package.
scripts/chart_template.py
1#!/usr/bin/env python32"""Generate TradingView-style candlestick chart.34Usage: Copy to scripts/, customize the Config section, run with:5python3 scripts/my_chart.py6"""7import os8import sys9import requests10import pandas as pd11import mplfinance as mpf12import time1314# ============================================================15# Proxy Auto-Configuration (for deployed environments)16# ============================================================17if not os.getenv("HTTP_PROXY") and os.getenv("PROXY_HOST"):18host = os.getenv("PROXY_HOST")19port = os.getenv("PROXY_PORT", "8080")20# Handle IPv6 addresses21if ":" in host and not host.startswith("["):22host = f"[{host}]"23proxy_url = f"http://{host}:{port}"24os.environ["HTTP_PROXY"] = proxy_url25os.environ["HTTPS_PROXY"] = proxy_url2627# ============================================================28# Config — customize these for each chart29# ============================================================30COIN_ID = "bitcoin"31DAYS = 3032INTERVAL = None # None for auto-select, or "daily"/"hourly"33OUTPUT_FILE = "output/btc_30d_chart.png"3435# ============================================================36# Smart Interval Selection37# ============================================================38def select_interval(days):39"""Auto-select optimal interval based on time range."""40if days <= 31:41return "hourly" # Max granularity for short term42else:43return "daily" # Efficient for longer periods4445if INTERVAL is None:46INTERVAL = select_interval(DAYS)4748# ============================================================49# Fetch OHLC from CoinGecko with Error Handling50# ============================================================51API_KEY = os.getenv("COINGECKO_API_KEY")52if not API_KEY:53print("ERROR: COINGECKO_API_KEY not set", file=sys.stderr)54sys.exit(1)5556now = int(time.time())57from_ts = now - (DAYS * 86400)5859url = f"https://pro-api.coingecko.com/api/v3/coins/{COIN_ID}/ohlc/range"60params = {"vs_currency": "usd", "from": from_ts, "to": now, "interval": INTERVAL}61headers = {"x-cg-pro-api-key": API_KEY}6263# Retry logic with exponential backoff64raw = None65for attempt in range(3):66try:67resp = requests.get(url, params=params, headers=headers, timeout=15)68resp.raise_for_status()69raw = resp.json()7071# Validate response72if not isinstance(raw, list) or len(raw) == 0:73raise ValueError("Empty or invalid data received from API")7475# Validate data format76if not all(isinstance(item, list) and len(item) == 5 for item in raw):77raise ValueError("Invalid OHLC data format")7879break # Success80except Exception as e:81if attempt == 2: # Last attempt82print(f"ERROR: Failed to fetch data after 3 attempts: {e}", file=sys.stderr)83sys.exit(1)84time.sleep(2 ** attempt) # Exponential backoff: 1s, 2s8586# ============================================================87# Build DataFrame88# ============================================================89df = pd.DataFrame(raw, columns=["Timestamp", "Open", "High", "Low", "Close"])90df["Date"] = pd.to_datetime(df["Timestamp"], unit="ms")91df.set_index("Date", inplace=True)92df.drop(columns=["Timestamp"], inplace=True)9394# ============================================================95# TradingView Style96# ============================================================97mc = mpf.make_marketcolors(98up='#26a69a', down='#ef5350',99edge='inherit', wick='inherit', volume='inherit', ohlc='inherit',100)101style = mpf.make_mpf_style(102marketcolors=mc,103facecolor='#131722', edgecolor='#131722', figcolor='#131722',104gridcolor='#1e222d', gridstyle='--', y_on_right=True,105rc={'axes.labelcolor': '#d1d4dc', 'xtick.color': '#d1d4dc',106'ytick.color': '#d1d4dc', 'font.size': 10},107)108109# ============================================================110# Plot111# ============================================================112os.makedirs("output", exist_ok=True)113114mpf.plot(115df, type='candle', style=style, volume=False,116title=f'\n{COIN_ID.upper()} — {DAYS}D Candlestick',117figsize=(14, 8),118savefig=dict(fname=OUTPUT_FILE, dpi=150, bbox_inches='tight',119facecolor='#131722', edgecolor='#131722'),120)121122print(f"Chart saved: {OUTPUT_FILE}")123