Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 136 additions & 0 deletions plots/line-yield-curve/implementations/javascript/highcharts.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
// anyplot.ai
// line-yield-curve: Yield Curve (Interest Rate Term Structure)
// Library: highcharts 12.6.0 | JavaScript 22.22.3
// Quality: 91/100 | Created: 2026-06-10

//# anyplot-orientation: landscape

const theme = window.ANYPLOT_THEME;
const t = window.ANYPLOT_TOKENS;

// U.S. Treasury yield curve snapshots (maturity years → annualized yield %)
const matValues = [0.083, 0.25, 0.5, 1, 2, 3, 5, 7, 10, 20, 30];
const matLabels = ["1M", "3M", "6M", "1Y", "2Y", "3Y", "5Y", "7Y", "10Y", "20Y", "30Y"];

// Log-transform x-positions for proper time spacing on a linear axis
// (equivalent to a log axis, but avoids Highcharts' auto label-culling on log axes)
const logX = matValues.map((v) => Math.log10(v) * 10);
// logX ≈ [-10.8, -6.0, -3.0, 0.0, 3.0, 4.8, 7.0, 8.5, 10.0, 13.0, 14.8]

// Three historical U.S. Treasury snapshots showing different curve shapes
const jan2021 = [0.05, 0.04, 0.05, 0.07, 0.13, 0.21, 0.46, 0.73, 1.07, 1.63, 1.83]; // Normal
const nov2022 = [3.42, 4.32, 4.60, 4.75, 4.57, 4.43, 4.13, 4.01, 3.96, 4.13, 3.93]; // Inverted
const jun2024 = [5.27, 5.37, 5.38, 5.10, 4.73, 4.48, 4.31, 4.30, 4.28, 4.52, 4.41]; // Flat

const toPoints = (yields) => logX.map((lx, i) => ({ x: lx, y: yields[i] }));

// Title length = 84 chars → fontSize = round(22 * 67 / 84) = 18px
Highcharts.chart("container", {
chart: {
type: "line",
backgroundColor: "transparent",
animation: false,
style: { fontFamily: "inherit" }
},
credits: { enabled: false },
colors: t.palette,

title: {
text: "U.S. Treasury Yield Curves · line-yield-curve · javascript · highcharts · anyplot.ai",
style: { color: t.ink, fontSize: "18px", fontWeight: "600" }
},

xAxis: {
tickPositions: logX,
labels: {
formatter: function () {
// Map log-transformed tick back to maturity label
const idx = logX.reduce(
(best, v, i) => Math.abs(v - this.value) < Math.abs(logX[best] - this.value) ? i : best,
0
);
return matLabels[idx];
},
style: { color: t.inkSoft, fontSize: "13px" }
},
title: {
text: "Maturity",
style: { color: t.inkSoft, fontSize: "16px" }
},
lineColor: t.inkSoft,
tickColor: t.inkSoft,
gridLineColor: "transparent",
plotBands: [
{
// Shade the short-to-medium term zone where Nov 2022 was deeply inverted
from: logX[0],
to: logX[4], // 1M to 2Y
color: theme === "light" ? "rgba(174,48,48,0.07)" : "rgba(174,48,48,0.15)",
label: {
text: "Inversion zone",
style: { color: t.inkSoft, fontSize: "11px", fontStyle: "italic" },
align: "center",
verticalAlign: "top",
y: 18
}
}
]
},

yAxis: {
title: {
text: "Yield (%)",
style: { color: t.inkSoft, fontSize: "16px" }
},
labels: {
formatter: function () { return this.value.toFixed(1) + "%"; },
style: { color: t.inkSoft, fontSize: "14px" }
},
gridLineColor: t.grid,
min: 0
},

legend: {
enabled: true,
layout: "horizontal",
align: "right",
verticalAlign: "top",
itemStyle: { color: t.inkSoft, fontSize: "14px", fontWeight: "normal" },
itemHoverStyle: { color: t.ink },
backgroundColor: t.elevatedBg,
borderColor: t.grid,
borderRadius: 4,
borderWidth: 1
},

plotOptions: {
series: {
animation: false,
lineWidth: 2.5,
marker: {
enabled: true,
radius: 5,
symbol: "circle",
lineWidth: 1,
lineColor: "transparent"
}
}
},

series: [
{ name: "Jan 2021 — Normal", data: toPoints(jan2021) },
{ name: "Nov 2022 — Inverted", data: toPoints(nov2022) },
{ name: "Jun 2024 — Flat", data: toPoints(jun2024) }
],

tooltip: {
formatter: function () {
const idx = logX.reduce(
(best, v, i) => Math.abs(v - this.x) < Math.abs(logX[best] - this.x) ? i : best, 0
);
return "<b>" + this.series.name + "</b><br/>" +
"Maturity: " + matLabels[idx] + "<br/>" +
"Yield: " + Highcharts.numberFormat(this.y, 2) + "%";
}
}
});
244 changes: 244 additions & 0 deletions plots/line-yield-curve/metadata/javascript/highcharts.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,244 @@
library: highcharts
language: javascript
specification_id: line-yield-curve
created: '2026-06-10T00:48:32Z'
updated: '2026-06-10T00:54:26Z'
generated_by: claude-sonnet
workflow_run: 27245126495
issue: 4664
language_version: 22.22.3
library_version: 12.6.0
preview_url_light: https://storage.googleapis.com/anyplot-images/plots/line-yield-curve/javascript/highcharts/plot-light.png
preview_url_dark: https://storage.googleapis.com/anyplot-images/plots/line-yield-curve/javascript/highcharts/plot-dark.png
preview_html_light: https://storage.googleapis.com/anyplot-images/plots/line-yield-curve/javascript/highcharts/plot-light.html
preview_html_dark: https://storage.googleapis.com/anyplot-images/plots/line-yield-curve/javascript/highcharts/plot-dark.html
quality_score: 91
review:
strengths:
- Accurate historical U.S. Treasury data covering three distinct rate environments
(COVID near-zero, rate-hike inversion, higher-for-longer flat)
- Clever log10 x-axis transform with custom maturity tick formatter — correctly
reflects the non-linear time spacing of bond maturities
- Theme-adaptive inversion zone plot band with correct alpha for light and dark
surfaces
- 'Perfect Imprint palette compliance: brand green first, canonical order, t.palette
for all series'
- 'All spec-required features implemented: log-spaced axis, custom tick labels,
multi-curve comparison, inversion highlighting, dated legend'
weaknesses:
- Inversion zone band label at fontSize 11px CSS is below the recommended minimum
(~13px) — appears slightly small in both renders; increase to 13px for consistency
with tick labels
image_description: |-
Light render (plot-light.png):
Background: Warm off-white #FAF8F1 — correct
Chrome: Title "U.S. Treasury Yield Curves · line-yield-curve · javascript · highcharts · anyplot.ai" in dark text, clearly readable. Axis labels "Maturity" (x) and "Yield (%)" (y) in muted dark text. Tick labels 1M–30Y on x-axis and 0.0%–6.0% on y-axis all readable. Legend top-right with colored markers and descriptive series names.
Data: First series (Jan 2021 Normal) is brand green #009E73 — upward-sloping near-zero rates. Second (Nov 2022 Inverted) is lavender #C475FD — high rates with inversion. Third (Jun 2024 Flat) is blue #4467A3 — flat high-rate curve. Plot band (1M–2Y) shaded light pink/red highlights inversion zone with italic label "Inversion zone".
Legibility verdict: PASS — all text readable, no light-on-light issues

Dark render (plot-dark.png):
Background: Warm near-black #1A1A17 — correct
Chrome: Title and all axis labels/ticks rendered in light colors against dark background — no dark-on-dark failures. Legend text is light-colored with dark elevated background box. Grid lines are subtle and visible. "Inversion zone" label remains visible.
Data: All three series colors identical to light render — green, lavender, blue (Imprint palette unchanged). Plot band uses darker reddish alpha (rgba(174,48,48,0.15)) visible against dark surface.
Legibility verdict: PASS — all text readable in dark theme, no dark-on-dark failures detected
criteria_checklist:
visual_quality:
score: 29
max: 30
items:
- id: VQ-01
name: Text Legibility
score: 7
max: 8
passed: true
comment: All fonts explicitly set and readable in both themes; minor deduction
for Inversion zone band label at 11px CSS (below recommended ~13px minimum)
- id: VQ-02
name: No Overlap
score: 6
max: 6
passed: true
comment: No text or element collisions in either render
- id: VQ-03
name: Element Visibility
score: 6
max: 6
passed: true
comment: Lines and markers well-proportioned for 11 data points; lineWidth
2.5 and marker radius 5 appropriate
- id: VQ-04
name: Color Accessibility
score: 2
max: 2
passed: true
comment: Imprint palette provides good CVD-safe hue separation across green/lavender/blue
- id: VQ-05
name: Layout & Canvas
score: 4
max: 4
passed: true
comment: Plot fills canvas well, balanced margins, legend top-right, no content
clipped
- id: VQ-06
name: Axis Labels & Title
score: 2
max: 2
passed: true
comment: Yield (%) with units, Maturity descriptive, custom tick formatter
shows meaningful labels
- id: VQ-07
name: Palette Compliance
score: 2
max: 2
passed: true
comment: 'First series #009E73, second #C475FD, third #4467A3 — Imprint canonical
order; transparent background; text and grid via t.ink/t.inkSoft/t.grid
tokens; correct in both renders'
design_excellence:
score: 13
max: 20
items:
- id: DE-01
name: Aesthetic Sophistication
score: 5
max: 8
passed: true
comment: 'Above well-configured default: plot band and descriptive curve labels
add narrative sophistication. Doesn''t reach clearly-above-defaults territory'
- id: DE-02
name: Visual Refinement
score: 4
max: 6
passed: true
comment: X-axis gridlines suppressed, Y-axis grid subtle, legend has rounded
corners and border, italic Inversion zone label
- id: DE-03
name: Data Storytelling
score: 4
max: 6
passed: true
comment: Three curves labeled Normal/Inverted/Flat with dates; plot band creates
focal point at inversion; clear economic narrative
spec_compliance:
score: 15
max: 15
items:
- id: SC-01
name: Plot Type
score: 5
max: 5
passed: true
comment: Correct multi-series line chart for yield curves
- id: SC-02
name: Required Features
score: 4
max: 4
passed: true
comment: Log-spaced x-axis, maturity tick labels, 3 curves, inversion band
with label, dated legend
- id: SC-03
name: Data Mapping
score: 3
max: 3
passed: true
comment: maturity_years log-transformed for x, yield % on y, all 11 points
per curve shown
- id: SC-04
name: Title & Legend
score: 3
max: 3
passed: true
comment: Title follows Descriptive · spec-id · javascript · highcharts · anyplot.ai
format; legend labels describe date and curve shape
data_quality:
score: 15
max: 15
items:
- id: DQ-01
name: Feature Coverage
score: 6
max: 6
passed: true
comment: 'All three canonical yield curve shapes: normal upward-sloping, inverted,
flat'
- id: DQ-02
name: Realistic Context
score: 5
max: 5
passed: true
comment: Real U.S. Treasury data from three distinct macroeconomic regimes;
neutral financial topic
- id: DQ-03
name: Appropriate Scale
score: 4
max: 4
passed: true
comment: Jan 2021 near-zero (0.04-1.83%), Nov 2022 inversion peak (3.42-4.75%),
Jun 2024 flat (4.28-5.38%) — factually accurate
code_quality:
score: 10
max: 10
items:
- id: CQ-01
name: KISS Structure
score: 3
max: 3
passed: true
comment: Data arrays → log transform → Highcharts.chart() call; toPoints is
a one-liner expression
- id: CQ-02
name: Reproducibility
score: 2
max: 2
passed: true
comment: All data hardcoded; fully deterministic
- id: CQ-03
name: Clean Imports
score: 2
max: 2
passed: true
comment: No imports; all globals used
- id: CQ-04
name: Code Elegance
score: 2
max: 2
passed: true
comment: Clean, no over-engineering; appropriate comment on log transform
- id: CQ-05
name: Output & API
score: 1
max: 1
passed: true
comment: Highcharts.chart(container) with animation:false on chart and series;
credits disabled; no explicit dimensions
library_mastery:
score: 9
max: 10
items:
- id: LM-01
name: Idiomatic Usage
score: 5
max: 5
passed: true
comment: Expert use of ANYPLOT_TOKENS for chrome; plotBands with label; custom
formatter for ticks and tooltip; legend styling with backgroundColor/borderColor/borderRadius
- id: LM-02
name: Distinctive Features
score: 4
max: 5
passed: true
comment: plotBands with theme-adaptive alpha; custom tickPositions with formatter;
tooltip formatter with maturity resolution — strong Highcharts-specific
feature use
verdict: APPROVED
impl_tags:
dependencies: []
techniques:
- manual-ticks
- html-export
patterns:
- data-generation
dataprep: []
styling:
- alpha-blending
- grid-styling
Loading