Skip to content

Commit 2395d7b

Browse files
Make the bench map readable: count crowded cells, name small ones
The map printed every study as a numbered chip in its cell. That works at a dozen studies per cell and fails completely past a hundred: the chips shrink below the size their own labels need, overlap, and the cell becomes a white smear that tells the reader less than a bare number would. Four of the nine cells were unreadable that way, on the landing page. Now a cell shows its chips only while they fit (24 or fewer) and otherwise prints its count large and plainly. The two cells worth reading study-by-study - the ten greens, and the seven None x Fragile - keep their chips; the crowded four become legible numbers. Three- and four-digit study numbers also get a smaller face so they stay inside their chip instead of spilling over the edge. The detail did not disappear, it moved somewhere better. The live map already filters to a cell when you click its count, so the README now links each cell straight to that view: GitHub strips image maps and will not run links inside an SVG, so one picture cannot be clicked square by square - a small table of links under it can. docs/index.html gains the deep link that makes those land right (?signal=Real&tradability=Mirage), validated against the axes in bench.json and ignored if absent. Two things found while in there: * The live page injected the corpus total into its own <h1> and document title at runtime, so the count sweep never saw it in the source. Removed. * Its footer still said "Study 03's Mixed signal counts with Weak" - written when exactly one study carried a Mixed stamp, and long since untrue. It now states the rule without naming a study. Both gates pass; the extracted page script passes node --check.
1 parent 6845d42 commit 2395d7b

5 files changed

Lines changed: 88 additions & 30 deletions

File tree

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,18 @@ every study and is the only place worth counting.
4949

5050
[![The bench map — every study placed on a Signal × Tradability grid](docs/bench_map.png)](https://guillain-rdcde.github.io/Open-Alpha-Lab/)
5151

52+
**Open a cell** — each link lands on the live map already filtered to that square, listing
53+
every study in it:
54+
55+
| | Investable | Fragile | Mirage |
56+
|---|:--:|:--:|:--:|
57+
| **Real** | [open →](https://guillain-rdcde.github.io/Open-Alpha-Lab/?signal=Real&tradability=Investable) | [open →](https://guillain-rdcde.github.io/Open-Alpha-Lab/?signal=Real&tradability=Fragile) | [open →](https://guillain-rdcde.github.io/Open-Alpha-Lab/?signal=Real&tradability=Mirage) |
58+
| **Weak** || [open →](https://guillain-rdcde.github.io/Open-Alpha-Lab/?signal=Weak&tradability=Fragile) | [open →](https://guillain-rdcde.github.io/Open-Alpha-Lab/?signal=Weak&tradability=Mirage) |
59+
| **None** || [open →](https://guillain-rdcde.github.io/Open-Alpha-Lab/?signal=None&tradability=Fragile) | [open →](https://guillain-rdcde.github.io/Open-Alpha-Lab/?signal=None&tradability=Mirage) |
60+
5261
> **[Explore the live map](https://guillain-rdcde.github.io/Open-Alpha-Lab/)** — the same grid, but zoomable:
5362
> **click any chip to open its study**, search by name or claim, and filter the whole bench by verdict.
54-
> (The static image above never gets less readable; the interactive page is where it scales.)
63+
> (GitHub can't make one image clickable square by square, which is what the table above is for.)
5564
5665
---
5766

docs/bench.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ every verdict below links back to the study that earned it.*
99
![The bench map — every study on a Signal × Tradability grid](bench_map.png)
1010

1111
*(Regenerate with `python tools/make_bench_figures.py` — it parses the
12-
[ledger](REFERENCE.md), so it's always in sync.)*
12+
[ledger](REFERENCE.md), so it's always in sync. A cell shows its studies by number while
13+
they still fit and just counts them when they don't; the
14+
**[live map](https://guillain-rdcde.github.io/Open-Alpha-Lab/)** is where you click into
15+
one and read what's inside.)*
1316

1417
> **Counting happens in one place.** This page describes shape, not totals. The
1518
> [ledger](REFERENCE.md) is the only complete list, the map above is redrawn from it, and

docs/bench_map.png

-103 KB
Loading

docs/index.html

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,21 @@ <h2>The studies</h2>
342342
return cell;
343343
}
344344

345+
// Deep link into one cell: index.html?signal=Real&tradability=Mirage
346+
// The static map on the README cannot be clicked cell by cell — GitHub strips image maps
347+
// and will not run links inside an SVG — so the README links each cell here instead, and
348+
// this is what makes those links land on the right filter instead of the whole bench.
349+
function applyDeepLink(){
350+
const p=new URLSearchParams(location.search);
351+
const sig=p.get("signal"), trad=p.get("tradability");
352+
if(!sig && !trad) return;
353+
if(sig && DATA.signals.includes(sig)) state.signal=new Set([sig]);
354+
if(trad && DATA.tradabilities.includes(trad)) state.tradability=new Set([trad]);
355+
syncPills();
356+
const cell=document.querySelector(`.cell[data-sig="${sig}"][data-trad="${trad}"]`);
357+
if(cell) cell.scrollIntoView({block:"center"});
358+
}
359+
345360
function focusCell(sig,trad){
346361
// toggle: clicking the same cell again clears it
347362
const same = state.signal.size===1 && state.signal.has(sig)
@@ -550,15 +565,17 @@ <h2>The studies</h2>
550565

551566
fetch("bench.json").then(r=>r.json()).then(d=>{
552567
DATA=d; REPO=d.repo;
553-
document.title=`Open-Alpha-Lab — ${d.total} trading ideas, one protocol`;
554-
document.getElementById("title").textContent=`${d.total} famous trading ideas, one protocol`;
568+
// No corpus total in the title. The cells carry the counts, and a total in the heading
569+
// is one more place that has to be kept in step with everything else.
570+
document.title="Open-Alpha-Lab — the bench, live";
571+
document.getElementById("title").textContent="famous trading ideas, one protocol";
555572
document.getElementById("repolink").href=d.repo;
556573
const sp=(d.special||[]).map(s=>`${String(s.num).padStart(2,"0")} ${s.name} (${s.signal}/${s.tradability})`).join(", ");
557574
document.getElementById("footer").innerHTML =
558575
(sp?`Not on the grid: ${sp}. · `:"") +
559-
"Study 03's “Mixed” signal counts with Weak (same amber bucket). · " +
560-
"Generated from the README table by <code>tools/make_bench_figures.py</code> — always in sync.";
561-
buildGrid(); wire(); apply();
576+
"A “Mixed” signal counts with Weak (same amber bucket). · " +
577+
"Generated from the ledger by <code>tools/make_bench_figures.py</code> — always in sync.";
578+
buildGrid(); wire(); applyDeepLink(); apply();
562579
}).catch(e=>{
563580
document.getElementById("grid").innerHTML =
564581
"<p style='color:#c0392b'>Could not load <code>bench.json</code>. "+

tools/make_bench_figures.py

Lines changed: 52 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,12 @@ def cell_color(sig: str, trad: str):
173173
return _lerp(GREEN, AMBER, s) if s <= 1 else _lerp(AMBER, RED, s - 1)
174174

175175

176+
# Most chips a cell can show and still be read. Above this the chip radius falls below
177+
# the size its own two-digit label needs, so the labels collide and the cell becomes a
178+
# smear. 24 keeps a 5x5-ish block at a radius the numbers still fit inside.
179+
CHIP_CAP = 24
180+
181+
176182
def _chip_layout(n: int):
177183
"""(n_cols, n_rows) for n chips in one cell — at most 6 per row."""
178184
cols = min(6, max(1, math.ceil(math.sqrt(1.8 * n))))
@@ -207,31 +213,53 @@ def draw(grid, special, total: int, out: Path = OUT) -> None:
207213
)
208214
ax.add_patch(box)
209215

210-
# count, top-right corner of the cell
211-
ax.text(x0 + w - 0.055, y0 + h - 0.058, str(len(members)),
212-
ha="right", va="top", fontsize=21, fontweight="bold",
213-
color=col if not empty else GREY, alpha=0.92)
214-
215216
if empty:
217+
ax.text(x0 + w - 0.055, y0 + h - 0.058, "0",
218+
ha="right", va="top", fontsize=21, fontweight="bold",
219+
color=GREY, alpha=0.92)
216220
ax.text(x0 + w / 2, y0 + h / 2, "—", ha="center", va="center",
217221
fontsize=16, color=GREY, alpha=0.55)
218222
continue
219223

220-
# numbered chips, centred in the cell (leaving the count corner room)
221-
ncols, nrows = _chip_layout(len(members))
222-
r = min(0.072, 0.40 / max(ncols, nrows)) # chip radius
223-
step_x = min(2.55 * r, (w - 0.16) / max(ncols - 1, 1)) if ncols > 1 else 0
224-
step_y = min(2.55 * r, (h - 0.30) / max(nrows - 1, 1)) if nrows > 1 else 0
225-
cx0 = x0 + w / 2 - step_x * (ncols - 1) / 2
226-
cy0 = y0 + (h - 0.10) / 2 + step_y * (nrows - 1) / 2
227-
for k, st in enumerate(sorted(members, key=lambda s: s["num"])):
228-
cx = cx0 + (k % ncols) * step_x
229-
cy = cy0 - (k // ncols) * step_y
230-
ax.add_patch(Circle((cx, cy), r, facecolor=col,
231-
edgecolor="white", linewidth=1.1, zorder=3))
232-
ax.text(cx, cy, f"{st['num']:02d}", ha="center", va="center",
233-
fontsize=max(7.5, 118 * r), fontweight="bold",
234-
color="white", zorder=4)
224+
# How a cell is drawn depends on whether its chips can still be read.
225+
#
226+
# Every cell used to print every chip. That works while a cell holds a dozen
227+
# studies and fails completely past a hundred: the chips shrink below their own
228+
# labels, overlap, and the cell turns into a white smear that says less than a
229+
# bare number would. Four cells on this bench were unreadable that way.
230+
#
231+
# So: draw the chips only while they fit, and otherwise make the count itself
232+
# the content. The detail has a better home anyway -- the live page, where the
233+
# cell is clickable and the studies are listed.
234+
legible = len(members) <= CHIP_CAP
235+
if legible:
236+
ax.text(x0 + w - 0.055, y0 + h - 0.058, str(len(members)),
237+
ha="right", va="top", fontsize=21, fontweight="bold",
238+
color=col, alpha=0.92)
239+
ncols, nrows = _chip_layout(len(members))
240+
r = min(0.072, 0.40 / max(ncols, nrows)) # chip radius
241+
step_x = min(2.55 * r, (w - 0.16) / max(ncols - 1, 1)) if ncols > 1 else 0
242+
step_y = min(2.55 * r, (h - 0.30) / max(nrows - 1, 1)) if nrows > 1 else 0
243+
cx0 = x0 + w / 2 - step_x * (ncols - 1) / 2
244+
cy0 = y0 + (h - 0.10) / 2 + step_y * (nrows - 1) / 2
245+
for k, st in enumerate(sorted(members, key=lambda s: s["num"])):
246+
cx = cx0 + (k % ncols) * step_x
247+
cy = cy0 - (k // ncols) * step_y
248+
ax.add_patch(Circle((cx, cy), r, facecolor=col,
249+
edgecolor="white", linewidth=1.1, zorder=3))
250+
label = f"{st['num']:02d}"
251+
# A four-digit study number needs a smaller face than a two-digit one
252+
# or it runs out over the edge of its own chip.
253+
shrink = {2: 1.0, 3: 0.80, 4: 0.62}.get(len(label), 0.62)
254+
ax.text(cx, cy, label, ha="center", va="center",
255+
fontsize=max(6.5, 118 * r * shrink), fontweight="bold",
256+
color="white", zorder=4)
257+
else:
258+
ax.text(x0 + w / 2, y0 + h / 2 + 0.045, str(len(members)),
259+
ha="center", va="center", fontsize=46, fontweight="bold",
260+
color=col, alpha=0.95)
261+
ax.text(x0 + w / 2, y0 + h / 2 - 0.115, "studies",
262+
ha="center", va="center", fontsize=12, color=col, alpha=0.75)
235263

236264
# ----- axis headers -------------------------------------------------
237265
for j, trad in enumerate(TRADABILITIES):
@@ -255,9 +283,10 @@ def draw(grid, special, total: int, out: Path = OUT) -> None:
255283
# totals at once. The chips themselves show the size; the ledger is where you count.
256284
ax.text(1.5, 4.07, "Famous trading ideas, one protocol",
257285
ha="center", va="top", fontsize=20, fontweight="bold", color=INK)
258-
ax.text(1.5, 3.88, "Each chip is a study — its number in the ledger. "
259-
"Same test bench, two stamps each.",
260-
ha="center", va="top", fontsize=11.5, color="#57606a")
286+
ax.text(1.5, 3.88, "Same test bench, two stamps each. Small cells name their studies; "
287+
"crowded ones just count them —\nopen the live map to click into any "
288+
"cell and see what's in it.",
289+
ha="center", va="top", fontsize=11.5, color="#57606a", linespacing=1.45)
261290

262291
notes = []
263292
if special:

0 commit comments

Comments
 (0)