Scrap yards quote per kilogram; exchanges quote gold per troy ounce, copper per pound, aluminum per tonne and steel per short ton. If you trade in scrap, the number you actually want — what a kilo of this is worth today — lives behind four unit conversions and a payout percentage. So I built the thing I wanted to glance at: a price board that looks like it's been running in a scrapyard office since 1987.
The problem
There is no free live feed for "scrap aluminum, per kg, in DKK." What exists is exchange futures in four incompatible units, no feed at all for alloys like brass, and yard payouts that are a fraction of contained-metal value. The gap between "the market" and "your price" is exactly the kind of arithmetic a computer should be doing continuously — and a human should be reading off a wall.
The number you want lives behind four unit conversions and a payout percentage — so put a computer between you and it.
How it works
Live quotes come from Yahoo Finance's public chart endpoint — COMEX gold, silver, copper and aluminum, NYMEX steel — each normalized to USD per kilogram. Materials with no feed of their own are derived from the ones that have one, with the alloy fractions in plain sight:
# normalize every exchange unit to per-kg KG_PER_TROY_OZ = 0.0311034768 # gold, silver KG_PER_LB = 0.45359237 # copper KG_PER_SHORT_TON = 907.18474 # US HRC steel # no exchange feed? derive from the ones that have one "brass": 0.65 * q["copper"] + 0.35 * c["zinc"] "stainless": 0.74 * q["steel"] + 0.08 * c["nickel"] + 0.18 * c["chromium"]
Each material carries two prices: market, the contained-metal value implied by the exchanges, and scrap est., that value times a per-material yard payout fraction you can tune in the admin panel. The board shows the scrap estimate by default — the whole point is your price, not the exchange's.
The board itself is plain ANSI escape codes, so it runs on the bare Linux console — no desktop, no GUI toolkit. Block-character digits, scanlines, a vignette, and a per-frame brightness shimmer at ~8 fps that a Pi Zero can afford. serve renders the same board as a web page with the same phosphor look, polling one shared quote fetcher — one process upstream no matter how many browsers watch. And because the terminal aesthetic deserves the commitment: prices come out in European format, decimal comma and all.
# one-shot table, converted to DKK with live FX recycling-ticker -c DKK # full-screen CRT board on the HDMI console + web board for the LAN recycling-ticker board -c DKK --serve # flash Pi OS Lite, clone, and make it a bootable appliance sudo ./install.sh board -c DKK
Around that core it grew the trimmings of a real appliance: an admin panel (manual items for lead and cables, payout percentages, alloy constants, currency switching), 90 days of price history with 7-day sparklines and tap-to-open 30-day charts, and threshold alerts that flash the board and push to your phone via ntfy. The installer registers a sandboxed systemd service under an unprivileged user, takes over tty1, and survives crashes and reboots. The admin panel can be locked with a PIN — stored salted with PBKDF2, checked in constant time, Origin-checked against cross-site requests. For a LAN toy, that's probably overkill; for a thing that runs unattended for months, it's the difference between a demo and an appliance.
What I'd do differently
- It's one 2,400-line Python file. Honest for a copy-to-the-Pi tool, but the fetcher, the renderer and the web server are three programs living in one namespace, and they've started to elbow each other.
- Yahoo's chart endpoint is public but unofficial — it can change shape any day. The cache-and-degrade path (
SIGNAL LOSTin the footer) makes that survivable, but a second quote source would make it boring. - The zinc/nickel/chromium reference prices are hand-set constants. They're editable in the admin panel, but nothing nudges you when the real metals drift away from them.
Roadmap
It does its job. If it grows: a second quote source behind the same fetcher, and maybe splitting the file once the elbowing gets worse. The Pi on the wall doesn't care either way.
Thanks for reading. Found a bug or have a sharper idea? get in touch — or run cat 0x0105 above for another small CLI.