AI-powered tool that generates publication-quality SVG charts matching PIMCO's InDesign style. Upload Excel/CSV data, write a plain-English brief, then iterate with natural language edits until the chart is exactly right. - Claude Opus 4.6 interprets briefs into structured ChartSpec JSON - Deterministic SVG renderer via drawsvg (no visual hallucinations) - Roboto/Roboto Condensed fonts base64-embedded in SVG - FastAPI + HTMX web frontend with live preview - Conversational refinement: "make lines thicker", "change title", etc. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
87 lines
2.7 KiB
Python
87 lines
2.7 KiB
Python
"""Test script: render a multi-line chart matching PIMCO Chart 1 (bond yields) using synthetic data."""
|
|
|
|
import sys
|
|
sys.path.insert(0, ".")
|
|
|
|
import pandas as pd
|
|
import numpy as np
|
|
from datetime import datetime, timedelta
|
|
from app.models.chart_spec import ChartSpec, PanelSpec, AxisSpec, SeriesSpec
|
|
from app.renderer.engine import render_chart
|
|
|
|
|
|
def generate_bond_yield_data() -> pd.DataFrame:
|
|
"""Generate synthetic 10-year government bond yield data resembling the PDF chart."""
|
|
np.random.seed(42)
|
|
dates = pd.date_range("2020-08-01", "2025-08-31", freq="B") # Business days
|
|
|
|
def random_walk(start, drift, vol, n):
|
|
returns = np.random.normal(drift, vol, n)
|
|
values = start + np.cumsum(returns)
|
|
# Smooth with rolling average
|
|
series = pd.Series(values)
|
|
return series.rolling(window=10, min_periods=1).mean().values
|
|
|
|
n = len(dates)
|
|
|
|
data = pd.DataFrame({
|
|
"Date": dates,
|
|
"U.S.": random_walk(0.7, 0.0025, 0.03, n),
|
|
"Australia": random_walk(0.9, 0.0025, 0.03, n),
|
|
"U.K.": random_walk(0.3, 0.0028, 0.035, n),
|
|
"Germany": random_walk(-0.4, 0.0020, 0.03, n),
|
|
"Japan": random_walk(0.0, 0.0008, 0.015, n),
|
|
})
|
|
|
|
# Clamp values to reasonable ranges
|
|
for col in ["U.S.", "Australia", "U.K.", "Germany", "Japan"]:
|
|
data[col] = data[col].clip(-1, 6)
|
|
|
|
return data
|
|
|
|
|
|
def main():
|
|
# Generate data
|
|
df = generate_bond_yield_data()
|
|
|
|
# Create chart spec matching the PDF Chart 1
|
|
spec = ChartSpec(
|
|
layout="single",
|
|
panels=[
|
|
PanelSpec(
|
|
title="10-year government bond yields",
|
|
subtitle=None,
|
|
x_axis=AxisSpec(
|
|
date_format="%b %Y",
|
|
),
|
|
y_axis=AxisSpec(
|
|
suffix="%",
|
|
min_val=-1,
|
|
max_val=6,
|
|
tick_interval=1,
|
|
),
|
|
series=[
|
|
SeriesSpec(label="U.S.", data_column="U.S.", color_index=0),
|
|
SeriesSpec(label="Australia", data_column="Australia", color_index=1),
|
|
SeriesSpec(label="U.K.", data_column="U.K.", color_index=2),
|
|
SeriesSpec(label="Germany", data_column="Germany", color_index=3),
|
|
SeriesSpec(label="Japan", data_column="Japan", color_index=4),
|
|
],
|
|
)
|
|
],
|
|
)
|
|
|
|
# Render
|
|
svg = render_chart(spec, {"_default": df})
|
|
|
|
# Save
|
|
output_path = "output/test_bond_yields.svg"
|
|
with open(output_path, "w") as f:
|
|
f.write(svg)
|
|
|
|
print(f"SVG saved to {output_path}")
|
|
print(f"SVG size: {len(svg):,} bytes")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|