Files
Binance_Altcoin_Monitor/backend/app/chart_image.py
T
2026-05-26 09:38:23 +08:00

67 lines
2.2 KiB
Python

"""服务端生成日K+成交量 PNG,供大模型视觉解读。"""
import io
from datetime import datetime
from .kline_store import get_daily_candles
async def render_daily_chart_png_async(symbol: str, limit: int = 300) -> bytes:
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
candles, _ = await get_daily_candles(symbol, limit)
if not candles:
raise ValueError(f"no klines for {symbol}")
times = [datetime.fromtimestamp(c["time"] / 1000) for c in candles]
opens = [c["open"] for c in candles]
highs = [c["high"] for c in candles]
lows = [c["low"] for c in candles]
closes = [c["close"] for c in candles]
vols = [c.get("quote_volume") or c.get("volume") or 0 for c in candles]
fig, (ax1, ax2) = plt.subplots(
2, 1, figsize=(12, 7), gridspec_kw={"height_ratios": [3, 1]}, facecolor="#0d1118"
)
fig.subplots_adjust(hspace=0.08)
for i in range(len(candles)):
t = times[i]
o, h, l, cl = opens[i], highs[i], lows[i], closes[i]
color = "#0ecb81" if cl >= o else "#f6465d"
ax1.plot([t, t], [l, h], color=color, linewidth=0.8)
ax1.add_patch(
plt.Rectangle(
(mdates.date2num(t) - 0.3, min(o, cl)),
0.6,
abs(cl - o) or 0.001,
facecolor=color,
edgecolor=color,
)
)
ax1.set_facecolor("#0d1118")
ax1.tick_params(colors="#8b9cb3")
ax1.set_title(f"{symbol} 日K + 成交量", color="#e7ecf3", fontsize=14)
ax1.grid(True, alpha=0.2)
colors_vol = ["#0ecb81" if closes[i] >= opens[i] else "#f6465d" for i in range(len(candles))]
ax2.bar(times, vols, color=colors_vol, alpha=0.7, width=0.8)
ax2.set_facecolor("#0d1118")
ax2.tick_params(colors="#8b9cb3")
ax2.set_ylabel("成交额", color="#8b9cb3")
ax2.grid(True, alpha=0.2)
for ax in (ax1, ax2):
ax.xaxis.set_major_formatter(mdates.DateFormatter("%m-%d"))
fig.autofmt_xdate()
buf = io.BytesIO()
fig.savefig(buf, format="png", dpi=120, facecolor="#0d1118")
plt.close(fig)
buf.seek(0)
return buf.read()