aggregate_api 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. aggregate_api/__init__.py +41 -0
  2. aggregate_api/__main__.py +154 -0
  3. aggregate_api/app.py +206 -0
  4. aggregate_api/audit.py +395 -0
  5. aggregate_api/bounds.py +331 -0
  6. aggregate_api/cache.py +319 -0
  7. aggregate_api/capability.py +823 -0
  8. aggregate_api/completion.py +219 -0
  9. aggregate_api/config.py +363 -0
  10. aggregate_api/cors.py +61 -0
  11. aggregate_api/examples.py +620 -0
  12. aggregate_api/layer_pricing.py +840 -0
  13. aggregate_api/library.py +94 -0
  14. aggregate_api/library_notes.py +96 -0
  15. aggregate_api/models.py +1407 -0
  16. aggregate_api/net.py +281 -0
  17. aggregate_api/pnl.py +101 -0
  18. aggregate_api/pricing.py +778 -0
  19. aggregate_api/resources.py +257 -0
  20. aggregate_api/routes/__init__.py +8 -0
  21. aggregate_api/routes/decl.py +327 -0
  22. aggregate_api/routes/examples.py +82 -0
  23. aggregate_api/routes/meta.py +282 -0
  24. aggregate_api/routes/objects.py +4119 -0
  25. aggregate_api/routes/status.py +466 -0
  26. aggregate_api/serializers.py +565 -0
  27. aggregate_api/sessions.py +353 -0
  28. aggregate_api/static/aggregate-api-logo-512.png +0 -0
  29. aggregate_api/static/aggregate-api-logo.png +0 -0
  30. aggregate_api/static/aggregate-api-trim.png +0 -0
  31. aggregate_api/static/android-chrome-192x192.png +0 -0
  32. aggregate_api/static/android-chrome-512x512.png +0 -0
  33. aggregate_api/static/apple-touch-icon.png +0 -0
  34. aggregate_api/static/assets/bootstrap-icons-BeopsB42.woff +0 -0
  35. aggregate_api/static/assets/bootstrap-icons-mSm7cUeB.woff2 +0 -0
  36. aggregate_api/static/assets/bootstrap-ohb1VZ53.js +5 -0
  37. aggregate_api/static/assets/codemirror-h62DHGGa.js +14 -0
  38. aggregate_api/static/assets/csv-grid.worker-DKzHGXac.js +4 -0
  39. aggregate_api/static/assets/echarts-B7o9sc00.js +40 -0
  40. aggregate_api/static/assets/echarts-gl-DG1Uf6wE.js +4282 -0
  41. aggregate_api/static/assets/lite-CUlcD8p4.css +1 -0
  42. aggregate_api/static/assets/lite-Dd2TnT4M.js +1 -0
  43. aggregate_api/static/assets/main-Bxhxa55v.css +9 -0
  44. aggregate_api/static/assets/main-CmoEiPit.js +9 -0
  45. aggregate_api/static/assets/tables-BHCF7qIF.js +8 -0
  46. aggregate_api/static/assets/tables-CxvajLr7.css +1 -0
  47. aggregate_api/static/favicon-16x16.png +0 -0
  48. aggregate_api/static/favicon-32x32.png +0 -0
  49. aggregate_api/static/favicon.ico +0 -0
  50. aggregate_api/static/index.html +912 -0
  51. aggregate_api/static/lite.html +83 -0
  52. aggregate_api/static/logo.png +0 -0
  53. aggregate_api/static/site.webmanifest +14 -0
  54. aggregate_api/static/sw.js +78 -0
  55. aggregate_api/status.py +536 -0
  56. aggregate_api/status_page.html +546 -0
  57. aggregate_api/tables.py +316 -0
  58. aggregate_api-1.0.0.dist-info/METADATA +187 -0
  59. aggregate_api-1.0.0.dist-info/RECORD +63 -0
  60. aggregate_api-1.0.0.dist-info/WHEEL +5 -0
  61. aggregate_api-1.0.0.dist-info/entry_points.txt +2 -0
  62. aggregate_api-1.0.0.dist-info/licenses/LICENSE +28 -0
  63. aggregate_api-1.0.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,912 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <meta name="description" content="aggregate Loss Lab (aLL): build and explore compound probability distributions from a DecL program.">
7
+ <meta name="theme-color" content="#ffffff">
8
+ <title>aggregate Loss Lab</title>
9
+
10
+ <link rel="icon" type="image/x-icon" href="./favicon.ico">
11
+ <link rel="icon" type="image/png" sizes="32x32" href="./favicon-32x32.png">
12
+ <link rel="icon" type="image/png" sizes="16x16" href="./favicon-16x16.png">
13
+ <link rel="apple-touch-icon" href="./apple-touch-icon.png">
14
+ <link rel="manifest" href="./site.webmanifest">
15
+
16
+ <!-- The phone branch, inline and before the module script so it runs
17
+ before any bundle is fetched. One URL: a narrow, coarse-pointer
18
+ device (a phone, not a narrow desktop window and not a touch-screen
19
+ laptop) is sent to the lite page; `?full=1` forces the full app and
20
+ `?lite=1` forces lite, for desktop testing. Relative target, matching
21
+ `base: './'`, so it survives a sub-path deploy. -->
22
+ <script>
23
+ (function () {
24
+ var q = new URLSearchParams(location.search);
25
+ if (q.has('full')) return;
26
+ if (q.has('lite')
27
+ || matchMedia('(max-width: 640px) and (pointer: coarse)').matches) {
28
+ location.replace('./lite.html' + location.search + location.hash);
29
+ }
30
+ }());
31
+ </script>
32
+
33
+ <!-- Bootstrap, Bootstrap Icons, and our overrides are imported via
34
+ the JS entry point (Vite bundles them through main.js). No CDN
35
+ dependency at runtime. -->
36
+ <script type="module" crossorigin src="./assets/main-CmoEiPit.js"></script>
37
+ <link rel="modulepreload" crossorigin href="./assets/echarts-B7o9sc00.js">
38
+ <link rel="modulepreload" crossorigin href="./assets/tables-BHCF7qIF.js">
39
+ <link rel="modulepreload" crossorigin href="./assets/bootstrap-ohb1VZ53.js">
40
+ <link rel="modulepreload" crossorigin href="./assets/codemirror-h62DHGGa.js">
41
+ <link rel="stylesheet" crossorigin href="./assets/tables-CxvajLr7.css">
42
+ <link rel="stylesheet" crossorigin href="./assets/main-Bxhxa55v.css">
43
+ </head>
44
+ <body>
45
+
46
+ <!-- ============================================================
47
+ Header
48
+ ============================================================ -->
49
+ <header class="sticky-top bg-white border-bottom shadow-sm">
50
+ <nav class="navbar navbar-expand-lg py-1">
51
+ <div class="container-fluid px-3 px-md-4" style="max-width:1280px;">
52
+ <a href="/" class="d-flex align-items-center text-decoration-none me-auto">
53
+ <img src="./logo.png" alt="aggregate Loss Lab" style="height:40px;width:auto;">
54
+ <div class="d-flex flex-column px-3">
55
+ <div class="brand-title text-dark">aggregate Loss Lab</div>
56
+ <div class="brand-kicker">description to distribution</div>
57
+ </div>
58
+ </a>
59
+ <div class="nav-meta">
60
+ <!-- The perspective in force, beside the versions and there
61
+ for the same reason: it changes what every served table
62
+ says, it is set from a menu two clicks away, and until
63
+ a75 the only way to know which reading you were looking
64
+ at was to open that menu and look at the tick.
65
+
66
+ Both words are always shown, the active one lit, which
67
+ makes the pair a readout and a control at once: they
68
+ carry `data-perspective`, so the click wiring and the
69
+ active-state sync that already serve the menu items
70
+ pick them up with no second code path. Ctrl+Shift+V is
71
+ the third way in, and moves this too. -->
72
+ <span class="nav-perspective" id="nav-perspective">
73
+ <button type="button" class="nav-persp-btn" data-perspective="raw"
74
+ title="Raw: the frame as computed">Raw</button><span
75
+ class="nav-persp-bar" aria-hidden="true">|</span><button
76
+ type="button" class="nav-persp-btn" data-perspective="insurer"
77
+ title="Insurer: the business reading">Insurer</button>
78
+ <span class="dot" aria-hidden="true">·</span>
79
+ </span>
80
+ <!-- The two versions that matter, in the header rather than
81
+ behind About. Which library built the numbers on screen
82
+ is the first question of any session that spans a
83
+ version bump, and the api one answers "did the deploy
84
+ take" without a round trip through a panel. Filled from
85
+ /v1/meta; blank until it answers, and blank if it does
86
+ not, since a wrong version is worse than none. -->
87
+ <span class="nav-versions mono" id="nav-versions" title="aggregate and api versions"></span>
88
+ <div class="dropdown">
89
+ <button type="button" class="hamburger-btn" data-bs-toggle="dropdown"
90
+ aria-expanded="false" aria-label="menu" title="Menu">
91
+ <i class="bi bi-list"></i></button>
92
+ <ul class="dropdown-menu dropdown-menu-end">
93
+ <!-- Tables: the page-wide static / interactive choice. It lives here
94
+ rather than on each tab because it is a preference, not a per-table
95
+ decision, and a switch on every table would be a lot of chrome for
96
+ something nobody changes twice in a session. The Overview carries a
97
+ second affordance for the same value, next to the tables it steers. -->
98
+ <li><h6 class="dropdown-header">Tables</h6></li>
99
+ <!-- The two statics adjacent, Interactive last
100
+ (author, Round 5 item 15). Full precision is a
101
+ third state of the one preference rather than a
102
+ second preference: it answers the same question
103
+ the other two do, how should a table read, and
104
+ the interactive view is already exact. Reading
105
+ the menu top to bottom now goes printed, printed
106
+ with all the digits, then the instrument.
107
+
108
+ It is the one of the three that costs a fetch.
109
+ Every document carries the exact values under
110
+ include_raw, but which of the two the static
111
+ walker prints is decided when the document is
112
+ built, so `setTableView` refetches across that
113
+ boundary and only across it. -->
114
+ <li><button type="button" class="dropdown-item menu-check-item" data-table-view="static">
115
+ <i class="bi bi-check2"></i><span>Static</span>
116
+ <small class="text-muted">book-quality, printed</small></button></li>
117
+ <li><button type="button" class="dropdown-item menu-check-item" data-table-view="precise">
118
+ <i class="bi bi-check2"></i><span>Static, full precision</span>
119
+ <small class="text-muted">all digits</small></button></li>
120
+ <li><button type="button" class="dropdown-item menu-check-item" data-table-view="interactive">
121
+ <i class="bi bi-check2"></i><span>Interactive</span>
122
+ <small class="text-muted">sort, filter, search</small></button></li>
123
+ <li><hr class="dropdown-divider"></li>
124
+ <!-- Perspective: which business reading of an
125
+ exhibit to serve. The library owns the
126
+ translation (captions, row flags, drops,
127
+ relabeling), so this is a passthrough on the
128
+ exhibit route and reaches the leaves that take
129
+ it: PnL Summary / Waterfall / Ledger / Tail,
130
+ and More Tail behavior / Dependency. -->
131
+ <li><h6 class="dropdown-header">Perspective</h6></li>
132
+ <li><button type="button" class="dropdown-item menu-check-item" data-perspective="insurer">
133
+ <i class="bi bi-check2"></i><span>Insurer</span>
134
+ <small class="text-muted">the business reading</small></button></li>
135
+ <li><button type="button" class="dropdown-item menu-check-item" data-perspective="raw">
136
+ <i class="bi bi-check2"></i><span>Raw</span>
137
+ <small class="text-muted">the frame as computed</small></button></li>
138
+ <li><hr class="dropdown-divider"></li>
139
+ <!-- Editor: the emacs keys, in the same checked-item
140
+ form as Tables above and for the same reason,
141
+ a preference rather than a per-build decision.
142
+ Deliberately NOT a `form-switch` in here: a form
143
+ control inside a dropdown-menu keeps the menu
144
+ open on click unless the menu is given
145
+ data-bs-auto-close="outside", and a check-style
146
+ item that toggles and closes is the behavior
147
+ Tables already has. -->
148
+ <li><h6 class="dropdown-header">Editor</h6></li>
149
+ <li><button type="button" class="dropdown-item menu-check-item" id="emacs-item">
150
+ <i class="bi bi-check2"></i><span>Emacs keys</span>
151
+ <small class="text-muted">Ctrl+A/E/K/Y, N/P, F/B/D</small></button></li>
152
+ <li><hr class="dropdown-divider"></li>
153
+ <li><button type="button" class="dropdown-item" data-bs-toggle="offcanvas" data-bs-target="#helpPanel">Help</button></li>
154
+ <li><button type="button" class="dropdown-item" id="dl-agg">Download models</button></li>
155
+ <!-- "Download plot" stood here through a130. It is
156
+ the chart's own Download menu now, in the strip
157
+ beside the picture, which is where the reader is
158
+ looking and which reaches every chart: the
159
+ handler behind this item read a hard coded trio
160
+ of chart handles, so the Pricing group's kappa
161
+ curves could never be saved from it. -->
162
+ <li><button type="button" class="dropdown-item" data-bs-toggle="offcanvas" data-bs-target="#aboutPanel">About</button></li>
163
+ </ul>
164
+ </div>
165
+ </div>
166
+ </div>
167
+ </nav>
168
+ </header>
169
+
170
+ <!-- ============================================================
171
+ Main
172
+ ============================================================ -->
173
+ <main class="container-fluid px-3 px-md-4 py-3" style="max-width:1280px;">
174
+
175
+ <!-- The lede. One sentence naming what the app is for, with the terms
176
+ notice at the right edge linking to the About panel's disclaimer.
177
+ The notice sits here, above the input, because a terms line nobody
178
+ passes on the way in agrees nobody to anything; it stays small and
179
+ grey so the pitch leads. No box around either since a162: it sits
180
+ directly above the input box, which is all that has to be said.
181
+ The hero cards that stood here through a36 are gone, and the
182
+ random hero build behind them went at a93: the page lands on dice
183
+ of dice, in the editor from the first paint. The gallery is to
184
+ resurface inside the Examples dropdown. -->
185
+ <div class="lede-box">
186
+ <p class="lede">Model a book of insurance, investigate tail risk,
187
+ allocate margin, apply and price reinsurance.</p>
188
+ <p class="lede-terms">Use of this site signifies agreement with the
189
+ <a href="#aboutPanel" data-bs-toggle="offcanvas" data-bs-target="#aboutPanel">terms</a>.</p>
190
+ </div>
191
+
192
+ <!-- Editor box (CM6 mounts into #editor-host) -->
193
+ <div class="editor-wrap">
194
+ <div class="editor-box" id="editor-box">
195
+ <div id="editor-host"></div>
196
+ </div>
197
+ <i class="bi bi-x-circle editor-clear" id="editor-clear" title="clear" role="button" aria-label="clear editor"></i>
198
+ <!-- The history walk: up, the readout, down, stacked in the
199
+ editor's right margin. The nav belongs with the box it
200
+ navigates, not on the action row, which already carries Build,
201
+ Examples, Reformat and a five-wide derive group.
202
+
203
+ **The arrows are drawn to match the numbering, and this is the
204
+ one thing a later reader could get backwards.** The counter
205
+ counts up, so up steps to an OLDER program and a LOWER number,
206
+ down to a newer one and a higher number. Stacked, the two
207
+ buttons draw the list they walk: oldest above, newest below,
208
+ the way a notebook puts earlier cells higher and a terminal
209
+ puts newer output lower.
210
+
211
+ Through a115 this was keys only, which on an iPad is no route
212
+ at all: the on-screen keyboard has no arrow keys, so the
213
+ readout described a control the reader had no way to operate.
214
+
215
+ The readout is where it has been since Round 5 item 14: a bare
216
+ `[3/4]`, here rather than on the action row, because stepping
217
+ back to a program you have built before and building it looks
218
+ like nothing happened when the strip redraws to the same words.
219
+ On the row it was the one `.fb-text` outside `.fb-right`, so it
220
+ missed the rule that makes those hints small, grey and
221
+ monospaced. Empty until the first build, and empty again while
222
+ the walk is showing a stashed draft, which is not an entry and
223
+ has no number.
224
+
225
+ The wrapper keeps `pointer-events: none` so the editor's right
226
+ margin still takes a click through the gaps; only the two
227
+ buttons take it back. Both are present from the first paint,
228
+ greyed, so nothing moves when the first program lands.
229
+
230
+ **Circled arrows, not bare ones, and that is about the set
231
+ rather than about the arrow.** These two sit under
232
+ `bi-x-circle`, and at a126 they were bare `bi-arrow-up` /
233
+ `bi-arrow-down` inside bordered boxes, so the margin held an
234
+ icon and then a widget. Same family, same weight, same optical
235
+ size makes the three read as one column of marks. The boxes came
236
+ off in the same edit; see `.hist-step`. -->
237
+ <div class="editor-hist" id="history-nav">
238
+ <button type="button" class="hist-step" id="history-prev"
239
+ aria-label="step back through your history" disabled>
240
+ <i class="bi bi-arrow-up-circle" aria-hidden="true"></i></button>
241
+ <span class="editor-pos" id="history-pos" aria-live="polite"></span>
242
+ <button type="button" class="hist-step" id="history-next"
243
+ aria-label="step forward through your history" disabled>
244
+ <i class="bi bi-arrow-down-circle" aria-hidden="true"></i></button>
245
+ </div>
246
+ </div>
247
+
248
+ <!-- Action row. One band: through a46 this was the button row over a
249
+ separate feedback line, and between them they held one idea. The
250
+ key hints and the emacs switch ride on the right; they fold away
251
+ below sm, since phones have no Ctrl key.
252
+
253
+ Build carries no color. The accent means selected and nothing
254
+ else, and Build is not a selection: it leads by weight and by
255
+ being first. -->
256
+ <div class="btnrow">
257
+ <button id="build-btn" class="btn btn-outline-secondary btn-build">Build</button>
258
+
259
+ <div class="dropdown">
260
+ <button class="btn btn-outline-secondary dropdown-toggle"
261
+ data-bs-toggle="dropdown" aria-expanded="false">
262
+ <i class="bi bi-collection me-1"></i><span class="d-none d-sm-inline"> Examples</span></button>
263
+ <ul id="examples-menu" class="dropdown-menu shadow-sm examples-menu">
264
+ <li><span class="dropdown-item-text text-muted small">loading…</span></li>
265
+ </ul>
266
+ </div>
267
+
268
+ <!-- Reformat sits outside the derive group, and before it, which
269
+ is where the author asked for it. Outside because it is not a
270
+ derivation: it rewrites the text in the box into
271
+ `format_program` form and builds nothing, so filing it under
272
+ "derive" would mislabel the one button in the row that leaves
273
+ the object alone. -->
274
+ <button id="reformat-btn" class="btn btn-outline-secondary"
275
+ title="rewrite the program in canonical form">Reformat</button>
276
+
277
+ <!-- The derivations. Each returns DecL that lands in the editor, so
278
+ you read what was built and can edit it; none of them mutates
279
+ an object behind a cached id. They are grouped behind one label
280
+ because they are a family: five peer buttons in a row said they
281
+ were five unrelated verbs.
282
+
283
+ They replaced the log2 and bs dropdowns that stood here, which
284
+ nobody used. Sharpen writes the `hints{}` clause those knobs
285
+ used to set, and writes it into a program you can keep, so the
286
+ grid is pinned by an audit that explains itself rather than by
287
+ a menu choice that vanishes when you reload.
288
+
289
+ Reset used to close this group and came out at a58: the history
290
+ walk already steps back through the programs you built, and a
291
+ button that undid exactly one derivation was a second, weaker
292
+ way to do it. GCN took its place. The walk's own buttons live in
293
+ the editor's right margin as of a116, so it is no longer a pair
294
+ of keys a phone cannot type. -->
295
+ <span class="derive-label">derive</span>
296
+ <div class="btn-group" role="group" aria-label="derive a new program">
297
+ <button id="sharpen-btn" class="btn btn-outline-secondary"
298
+ title="audit the grid and move to a better one">Sharpen</button>
299
+ <button id="hints-btn" class="btn btn-outline-secondary"
300
+ title="pin the grid this object built on into its hints{} clause, so a reference to it means one fixed thing">Hints</button>
301
+ <!-- The PnL split button, following the GCN shape beside it:
302
+ one press for the common case, a menu for the rest, and
303
+ no label ever changes with state. Through a182 this was
304
+ one button that flipped between PnL and Explode on the
305
+ object's kind, and the flip failed in practice: type a
306
+ new program over a built P&L without building, and the
307
+ button still said Explode and still acted on the stale
308
+ object. `applyPnl` in main.js now derives from the box,
309
+ and `renderActionRow` greys each item off its own flag:
310
+ `can_pnl` the main press, `can_pnl_rate` the rate pair,
311
+ `can_xpnl` the exploded form. -->
312
+ <button id="pnl-btn" class="btn btn-outline-secondary"
313
+ title="wrap this object in a P&amp;L, ceded premiums as deposit amounts">PnL</button>
314
+ <button id="pnl-caret" type="button"
315
+ class="btn btn-outline-secondary dropdown-toggle dropdown-toggle-split"
316
+ data-bs-toggle="dropdown" aria-expanded="false"
317
+ aria-label="choose the P&amp;L form"></button>
318
+ <ul class="dropdown-menu shadow-sm">
319
+ <li><button class="dropdown-item" type="button"
320
+ data-pnl-form="pnl" data-pnl-premium="rate">
321
+ PnL (rate)</button></li>
322
+ <li><button class="dropdown-item" type="button"
323
+ data-pnl-form="xpnl" data-pnl-premium="deposit">
324
+ xPnL</button></li>
325
+ <li><button class="dropdown-item" type="button"
326
+ data-pnl-form="xpnl" data-pnl-premium="rate">
327
+ xPnL (rate)</button></li>
328
+ </ul>
329
+ <!-- GCN: read the program as a pair of views. The main button
330
+ takes the default (gross / ceded) and the caret offers the
331
+ other two, which is the split-button shape the author
332
+ asked for: one press for the common case, a menu for the
333
+ rest. Greys on `can_views`, which needs an OCCURRENCE
334
+ cession, not merely any cession. -->
335
+ <button id="gcn-btn" class="btn btn-outline-secondary"
336
+ title="read this program as a pair of views">GCN</button>
337
+ <button id="gcn-caret" type="button"
338
+ class="btn btn-outline-secondary dropdown-toggle dropdown-toggle-split"
339
+ data-bs-toggle="dropdown" aria-expanded="false"
340
+ aria-label="choose which pair of views"></button>
341
+ <ul class="dropdown-menu shadow-sm">
342
+ <li><button class="dropdown-item" type="button" data-views="grossceded">
343
+ Gross / Ceded</button></li>
344
+ <li><button class="dropdown-item" type="button" data-views="grossnet">
345
+ Gross / Net</button></li>
346
+ <li><button class="dropdown-item" type="button" data-views="netceded">
347
+ Net / Ceded</button></li>
348
+ </ul>
349
+ </div>
350
+
351
+ <!-- Two rows, split by kind rather than by how often each is
352
+ pressed: what you do to the program on top, where you go
353
+ underneath. Ctrl+K and Ctrl+Shift+↑↓ stay in the help panel
354
+ only; this is a reminder, not a second copy of the key table.
355
+
356
+ The emacs switch used to ride here. It is a preference, not an
357
+ action, so it moved into the hamburger beside the Tables
358
+ choice. -->
359
+ <span class="fb-right d-none d-sm-flex">
360
+ <span class="fb-text">Ctrl+Enter build<span class="sep">·</span>Ctrl+Space complete</span>
361
+ <!-- `.mod-key` is rewritten at startup to whichever modifier
362
+ CodeMirror's `Mod-` resolves to here, which is Cmd on a Mac
363
+ and on an iPad. See `modifierName` in editor.js. -->
364
+ <span class="fb-text"><span class="mod-key">Ctrl</span>+↑↓ history<span class="sep">·</span>Ctrl+Shift+U tables</span>
365
+ </span>
366
+ </div>
367
+
368
+ <!-- Status strip: what is built, and whether it is OK. One line, and a
369
+ second that folds:
370
+
371
+ 1. the object BasicBook Portfolio bs 4 log2 18 loss
372
+ mean 106,477 CV 0.2114 0.41s
373
+ 2. the note library warnings, then what a derivation did,
374
+ then the program's own tags{} as chips with its
375
+ note{} running on after them
376
+
377
+ **Line one is clusters, not a run of dots.** Through a157 it was one
378
+ mono run at one size joined by seven `·`, so eight facts read as
379
+ sixteen tokens of equal weight. Labels are in the UI face and grey,
380
+ values in mono and dark, and three different gaps bind a label to
381
+ its value more tightly than to the pair beside it.
382
+
383
+ **The verdict is said only when it is not clean, and said second.**
384
+ The left bar and the ground already state it twice, so a third copy
385
+ in words on a clean build is what the reader learns to skip. On warn
386
+ and fail the word appears right after the name, where its position
387
+ does not wander with the wrap.
388
+
389
+ **The clock is four characters in the corner.** Through a157 it was
390
+ a line and a sentence of its own, "Calculated in 0.412 seconds",
391
+ for a number nobody reads.
392
+
393
+ **The note folds behind the chevron**, which carries the count so a
394
+ closed strip still announces a warning without spending a line on
395
+ its text. It folds only when there is a built object: a program
396
+ picked out of the Examples menu puts its note{} and tags{} here
397
+ before anything is built, and hiding that would be a regression in
398
+ the examples flow. See `syncSummaryMore` in main.js.
399
+
400
+ main.js sets `is-warn` / `is-fail` on the wrapper from the build's
401
+ own verdict, which tints the whole strip: hue alone is too weak for
402
+ a state you must not miss. -->
403
+ <div class="status-strip" id="status-strip">
404
+ <div class="summary" id="summary">
405
+ <div class="summary-inner" id="summary-inner">
406
+ <span class="text-muted">Type DecL above and press
407
+ <span class="mono">Ctrl+Enter</span> to build.</span>
408
+ </div>
409
+ <button class="summary-more" id="summary-more" aria-expanded="false"
410
+ title="what this build said about itself"><span
411
+ id="summary-more-text"></span><i class="bi bi-chevron-down"></i></button>
412
+ <span class="summary-clock" id="summary-clock"></span>
413
+ </div>
414
+ <div class="summary-note" id="summary-note"></div>
415
+ </div>
416
+
417
+ <!-- An identity block stood here through a119, carrying the object's
418
+ tags and its note. Both are on the status strip now, drawn under
419
+ every group rather than under Overview alone and off the build
420
+ response rather than a second request. See the note above the
421
+ Overview loaders in main.js. -->
422
+
423
+ <!-- Output navigation: seven groups, each with its own sub-tab row.
424
+ The groups are editorial, a judgment about how insurance work
425
+ proceeds, and the app authors them. Which leaves are live inside
426
+ one is a fact about the object, so the library computes it and
427
+ main.js renders each row from the capability block. Nothing here
428
+ says what a kind can do.
429
+
430
+ The order is the demo flow, which is the order the work happens in:
431
+ look at the gross book, add reinsurance, decide what to charge for
432
+ what is left, then read the economics of the result. Bounds is
433
+ orthogonal to all four and sits late; More is the specialist
434
+ frames. Nothing may stand between a group strip and its sub menu.
435
+
436
+ This order is written twice, here and as the key order of
437
+ NAV_GROUPS in nav.js, which is also what Alt+1…7 indexes.
438
+ Lab is last and ships hidden; see its slot below.
439
+ `dev/scripts/check-nav.mjs` parses this list and asserts the two
440
+ agree, so they cannot drift apart again. -->
441
+ <!-- `data-label` repeats the visible label, and must keep matching it.
442
+ site.css draws it as a hidden bold ghost inside the button so every
443
+ tab is laid out at its selected width, whether or not it is the
444
+ selected one. Without it, selecting a tab makes it bold, bold makes
445
+ it wider, and every tab to its right moves: nothing with a mouse,
446
+ a moving target under a thumb. -->
447
+ <ul class="nav nav-pills out-tabs" role="tablist">
448
+ <li class="nav-item"><button class="nav-link active" data-bs-toggle="pill" data-bs-target="#t-overview" data-tab="overview" data-label="Overview" type="button">Overview</button></li>
449
+ <li class="nav-item"><button class="nav-link" data-bs-toggle="pill" data-bs-target="#t-reinsurance" data-tab="reinsurance" data-label="Re" type="button">Re</button></li>
450
+ <li class="nav-item"><button class="nav-link" data-bs-toggle="pill" data-bs-target="#t-pricing" data-tab="pricing" data-label="Pricing" type="button">Pricing</button></li>
451
+ <li class="nav-item"><button class="nav-link" data-bs-toggle="pill" data-bs-target="#t-economics" data-tab="economics" data-label="PnL" type="button">PnL</button></li>
452
+ <li class="nav-item"><button class="nav-link" data-bs-toggle="pill" data-bs-target="#t-bounds" data-tab="bounds" data-label="Bounds" type="button">Bounds</button></li>
453
+ <li class="nav-item"><button class="nav-link" data-bs-toggle="pill" data-bs-target="#t-more" data-tab="more" data-label="More" type="button">More</button></li>
454
+ <!-- Lab: where documents from installed plugin packages land. In the
455
+ strip statically and hidden, revealed by main.js when the boot
456
+ manifest from /v1/meta is non-empty. Appending a seventh tab
457
+ from JS after that fetch resolves would shift the layout on
458
+ every page load, and it would break check-nav.mjs's premise
459
+ that the strip lists every group the app knows about: the strip
460
+ still does, and the manifest decides only visibility. -->
461
+ <li class="nav-item d-none" id="tab-lab-slot"><button class="nav-link" data-bs-toggle="pill" data-bs-target="#t-lab" data-tab="lab" data-label="Lab" type="button">Lab</button></li>
462
+ </ul>
463
+
464
+ <div class="tab-content">
465
+ <!-- Overview: the landing group. The identity block used to sit
466
+ here, above the sub-tab row; it moved above the group strip at
467
+ a47 so nothing stands between the two menu levels. -->
468
+ <div class="tab-pane fade show active" id="t-overview">
469
+ <div class="sub-tabs" id="sub-overview"></div>
470
+ <div id="pane-overview" class="pane"></div>
471
+ </div>
472
+
473
+ <!-- PnL: a P&L's ledger, its ratios, and the margin walk. The pane
474
+ id, the tab key and the leaf ids stay `economics`: they are in
475
+ stored view state and in links already shared, and this was a
476
+ label change. -->
477
+ <div class="tab-pane fade" id="t-economics">
478
+ <div class="sub-tabs" id="sub-economics"></div>
479
+ <div id="pane-economics" class="pane"></div>
480
+ </div>
481
+
482
+ <!-- Reinsurance: the program description names the whole structure,
483
+ so like the Overview identity block it sits above the row. -->
484
+ <div class="tab-pane fade" id="t-reinsurance">
485
+ <div class="sub-tabs" id="sub-reinsurance"></div>
486
+ <div class="reins-desc" id="reins-desc"></div>
487
+ <!-- Quick Re: one row, one layer, straight into the editor.
488
+ Author's layout, Round 5 item 11.
489
+
490
+ There is **no text box for the clause**. Through a67 the
491
+ row wrote a clause into a local input and that input was
492
+ then ceded, so the same string was transferred twice before
493
+ anything happened. The author's ruling: press Add re and it
494
+ goes into the program above, which is where you read it and
495
+ where you adjust it. That box is a full editor with real
496
+ completion, so a second, worse one beside it earned nothing.
497
+
498
+ ONE layer, or ONE generated stack, and nothing else. The
499
+ row read one layer only through a192, on the reasoning that
500
+ a second layer here meant the sugar had failed. The author
501
+ reversed that on 2026-10-06: a generated stack is not a
502
+ second hand-typed layer, it is one press producing the
503
+ structure an underwriter would have written over that span,
504
+ and the arithmetic of it (double, snap to a quote-sheet
505
+ number, step the share up) is mechanical. Typing a six
506
+ layer tower by hand is the thing that stops a reader from
507
+ exploring a program. So Add re writes the span as one layer
508
+ and Tower writes it as a stack; a multi-layer program that
509
+ is not a stack is still typed upstairs, which is what that
510
+ box is for. Two *tiers* is different again and is supported
511
+ either way: cede on Occ, then switch to Agg and cede again,
512
+ each clause authoritative for its own tier.
513
+
514
+ Attach and detach each take ONE field with two readings:
515
+ `50%` is a probability and a bare number is currency, so
516
+ there is no mode switch and no second set of boxes to keep
517
+ in step. The share box reads the same way. No stepper
518
+ arrows, per the author: `<input type=number>` refuses the
519
+ `%` and the dual reading is worth more than the arrows.
520
+
521
+ The row reads as a sentence, and the operator words are
522
+ what make it one: 100% part of, from 50% attach to 95%
523
+ detach. The author's wording, round 7 item 2; the earlier
524
+ `part of ... attach, ... detach` left the reader to supply
525
+ the preposition and the layer read as three separate
526
+ answers rather than as one cover. -->
527
+ <!-- `part of` is FIXED, and is no longer the DecL token it used
528
+ to mirror. It showed `so` over a percentage and `po` over
529
+ an amount; `so` and `of` were retired upstream at
530
+ 1.0.0a249, so `po` is now the one placement keyword and the
531
+ `%` is what tells it a share from an amount. The row says
532
+ the one thing in English and `placementHead` writes the
533
+ token. Do not "fix" this back into sync with the clause.
534
+
535
+ See `resolveSpan`, `composeCession` and `composeTower` in
536
+ main.js. -->
537
+ <!-- The control band, one enclosure per group: the ask gets a
538
+ ground and a hairline and the answer sits plain underneath.
539
+ A wrapper rather than a class on `#reins-entry`, which
540
+ already carries `.tab-tools`'s --tabpad padding and would
541
+ otherwise be indented twice. See `.control-band` in
542
+ site.css. -->
543
+ <div class="control-band">
544
+ <div class="tab-tools reins-entry" id="reins-entry">
545
+ <div class="reins-row">
546
+ <span class="reins-lede">Quick Re</span>
547
+ <!-- The same segmented control as CoC / LR on Pricing,
548
+ which is what the author asked it to look like. -->
549
+ <div class="btn-group btn-group-sm" role="group"
550
+ aria-label="which tier to cede">
551
+ <input type="radio" class="btn-check" name="qr-basis"
552
+ id="qr-basis-occ" value="occurrence" checked>
553
+ <label class="btn btn-outline-secondary" for="qr-basis-occ">Occ</label>
554
+ <input type="radio" class="btn-check" name="qr-basis"
555
+ id="qr-basis-agg" value="aggregate">
556
+ <label class="btn btn-outline-secondary" for="qr-basis-agg">Agg</label>
557
+ </div>
558
+ <input id="qr-share" class="qr-field" type="text" inputmode="decimal"
559
+ autocomplete="off" spellcheck="false" value="100%"
560
+ aria-label="share or part of">
561
+ <span class="qr-op">placed, from</span>
562
+ <input id="qr-attach" class="qr-field" type="text" inputmode="decimal"
563
+ autocomplete="off" spellcheck="false" value="50%"
564
+ aria-label="attachment">
565
+ <span class="qr-op">attach to</span>
566
+ <input id="qr-detach" class="qr-field" type="text" inputmode="decimal"
567
+ autocomplete="off" spellcheck="false" value="95%"
568
+ aria-label="detachment">
569
+ <span class="qr-op">detach</span>
570
+ <button id="reins-btn" class="btn btn-primary btn-sm">Add re</button>
571
+ <!-- Outline, so Add re keeps the primary: one layer is
572
+ still the ordinary press and the stack is the one
573
+ you reach for deliberately. -->
574
+ <button id="tower-btn" class="btn btn-outline-primary btn-sm">Tower</button>
575
+ <!-- Both hint paragraphs folded into one tooltip, per the
576
+ author: the row explains itself on demand rather than
577
+ carrying two paragraphs nobody reads twice. -->
578
+ <button type="button" class="qr-help" id="qr-help"
579
+ data-bs-toggle="tooltip" data-bs-placement="top"
580
+ aria-label="how Quick Re reads these boxes"
581
+ title="A percentage is read as a probability, so attach 50% attaches at the median and detach 95% reaches the 95th percentile; a plain number is an amount, and the two mix freely. Quantiles are rounded to three figures, because a layer is something you write down. One clause per tier: the clause is folded into the program above, so an occurrence cession lands before the frequency clause and an aggregate one after it. Tower lays the same span out as a stack of roughly doubling layers, named Occ 1 upward, every bound snapped to a quote-sheet number, so the top of the stack reaches the detachment or the first round number above it; the share box places the bottom layer and the ladder steps up from there to 95%, since shares never fall as the attachment rises. Edit more complex structures directly in the program edit box.">?</button>
582
+ </div>
583
+ <!-- The clause Add re will write, kept current as you type.
584
+ Debounced, because a percentage costs a quantile lookup.
585
+ Populated from the defaults before anything is touched,
586
+ so the row says what it does without being used.
587
+
588
+ It stays on the single-layer reading even though Tower
589
+ sits beside it, which is the author's ruling: the one
590
+ layer names the bottom and the top of the program, which
591
+ is what you want to see while you are choosing them.
592
+ Tower's own clause is read where every cession is read,
593
+ in the program box above. Refusals from either button
594
+ still land here. -->
595
+ <p class="reins-entry-hint reins-preview" id="qr-preview"></p>
596
+ <!-- The last priced press, layer by layer: the standard
597
+ deviation load against the two distortion prices, which
598
+ of the three bound, and the quote that came out.
599
+
600
+ Here rather than as a sub-tab leaf, which is the
601
+ author's ruling of 2026-10-06. The rows belong to the
602
+ press and not to the object, so a leaf keyed to the
603
+ object would go on showing the previous book's quote
604
+ after a switch. This sits where the press happened, and
605
+ it empties whenever the row is reset. -->
606
+ <div id="qr-quotes" class="qr-quotes d-none"></div>
607
+ </div>
608
+ </div><!-- /.control-band. Left at the wrapper's own indent
609
+ rather than reindenting the forty lines above it, which
610
+ would bury the real change in whitespace. -->
611
+ <div id="pane-reinsurance" class="pane"></div>
612
+ </div>
613
+
614
+ <!-- Pricing: three leaves, laid out Calibrate Allocate | Evaluate.
615
+
616
+ Calibrate and Allocate share one form and one press. It fixes
617
+ capital with a probability or an asset level, takes one target,
618
+ and calibrates the standard distortion set; the two panes are
619
+ the receipt and the allocation of that same calibration, filled
620
+ from one POST. The basis group chooses which reinsurance view to
621
+ calibrate on; it is always present and always drawn, so the form
622
+ does not jump when you step from a reinsured example to a plain
623
+ one. The preview line under the form says what the pentagon
624
+ would be, kept current as you type, and is also where an
625
+ impossible anchor says so.
626
+
627
+ Evaluate goes the other way: the premium is already set, and
628
+ the panel reports the distortion in each family that values the
629
+ margin at zero. Its basis group names *which* premium is being
630
+ input, which is a narrower question than the gross versus net
631
+ reading the PnL group answers. Its asset anchor is what closes the
632
+ round trip with a calibration struck at the same level; left
633
+ blank it is the library's unlimited reading, which reports four
634
+ families rather than five. Both boxes open on the pricing in
635
+ hand, and are hidden for a P&L, whose ledger carries a premium
636
+ per row.
637
+
638
+ -->
639
+ <div class="tab-pane fade" id="t-pricing">
640
+ <div class="sub-tabs" id="sub-pricing"></div>
641
+
642
+ <!-- The pricing forms are built by `pricing-form.js` since
643
+ a100, into these hosts. They were three copies of one row
644
+ of markup, each stating its choice twice (a btn-group
645
+ naming the anchor and a span repeating it), and the Bounds
646
+ group had a fourth copy in a different spelling. One form
647
+ over `price_pentagon`'s signature serves every leaf that
648
+ asks for a price, here and under Bounds.
649
+
650
+ Four wrappers, and which of them is on screen is the leaf.
651
+ Calibrate and Stand-alone are two documents from one press
652
+ and share the first; Allocate is a second press, because a
653
+ decomposition off an occurrence joint is real work and is
654
+ not what a reader asking for a calibration ordered; Plot
655
+ asks the object rather than a form, so it carries no form
656
+ at all. -->
657
+ <div id="leaf-price">
658
+ <div class="control-band"><div id="price-form"></div></div>
659
+ <div id="pane-calibrate" class="pane"></div>
660
+ <div id="pane-standalone" class="pane d-none"></div>
661
+ </div>
662
+
663
+ <!-- A `Massive joint` placeholder sat here from a105 to a173,
664
+ greyed, waiting on the library to bring kappa to the
665
+ disk-backed one-sweep route. It is gone on the author's
666
+ ruling of 2026-09-29: a massive joint is a zarr store on
667
+ local disk, so it belongs to a local or VPN session and
668
+ never to a served app. The in-memory kappa this pane and
669
+ the Plot leaf draw was never the thing it was waiting
670
+ for. -->
671
+ <div id="leaf-allocate" class="d-none">
672
+ <div class="control-band"><div id="allocate-form"></div></div>
673
+ <div id="pane-allocate" class="pane"></div>
674
+ </div>
675
+
676
+ <div id="leaf-kappa" class="d-none">
677
+ <div id="pane-kappa" class="pane"></div>
678
+ </div>
679
+
680
+ <div id="leaf-evaluate" class="d-none">
681
+ <div class="control-band"><div id="evaluate-form"></div></div>
682
+ <div id="pane-evaluate" class="pane"></div>
683
+ </div>
684
+
685
+ <!-- Pr Ruin: the probability of eventual default, a teaching
686
+ pane. The premium half of the form is the shared pricing
687
+ component, the capital half is one probability box, and
688
+ the picture below tracks both through a debounced POST.
689
+ The chart pane and the stats strip are separate hosts so
690
+ the exhibit table redraws without touching the canvas. -->
691
+ <div id="leaf-ruin" class="d-none">
692
+ <div class="control-band"><div id="ruin-form"></div></div>
693
+ <div id="pane-ruin" class="pane"></div>
694
+ <div id="pane-ruin-stats" class="pane"></div>
695
+ </div>
696
+ </div>
697
+
698
+ <!-- Bounds: three leaves against the three classes in bounds.py.
699
+
700
+ Ordinary pricing picks a distortion and reports its number.
701
+ These ask the other question: hold the calibration fixed, let
702
+ the distortion range over everything consistent with it, and
703
+ report how wide the answer can be. So every leaf needs a
704
+ premium, which is the calibration, and none computes on
705
+ arrival: they are work, and a leaf that computed on the way in
706
+ would spend it every time you passed through. -->
707
+ <div class="tab-pane fade" id="t-bounds">
708
+ <div class="sub-tabs" id="sub-bounds"></div>
709
+ <!-- The hint is inside the band because it is a hint about the
710
+ control, and it cannot go inside `#bounds-form` itself:
711
+ `createPricingForm` empties its host. -->
712
+ <div class="control-band">
713
+ <div id="bounds-form"></div>
714
+ <span class="sub-hint" id="bounds-hint"></span>
715
+ </div>
716
+ <div id="pane-bounds" class="pane"></div>
717
+ </div>
718
+
719
+ <!-- More: the specialist frames. The sub-tab row is rendered by
720
+ main.js, since which leaves are live is per object. -->
721
+ <div class="tab-pane fade" id="t-more">
722
+ <div class="sub-tabs" id="sub-more"></div>
723
+ <div id="pane-more" class="pane"></div>
724
+ </div>
725
+
726
+ <!-- Lab. One pane, whatever the plugins registered: an exhibit
727
+ draws through the same envelope path as every other table leaf
728
+ and a chart through the same ChartDoc mount, so there is
729
+ nothing plugin-shaped in the markup. -->
730
+ <div class="tab-pane fade" id="t-lab">
731
+ <div class="sub-tabs" id="sub-lab"></div>
732
+ <div id="pane-lab" class="pane"></div>
733
+ </div>
734
+
735
+ </div>
736
+ </main>
737
+
738
+ <!-- ============================================================
739
+ Help offcanvas (opened by the header "?")
740
+ ============================================================ -->
741
+ <div class="offcanvas offcanvas-end help-panel" tabindex="-1" id="helpPanel" aria-labelledby="helpLabel">
742
+ <div class="offcanvas-header">
743
+ <h5 class="offcanvas-title" id="helpLabel">Quick help</h5>
744
+ <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
745
+ </div>
746
+ <div class="offcanvas-body help-body">
747
+ <p class="help-lead">The <strong>aggregate Loss Lab</strong>. Build and
748
+ explore compound <em>(aggregate)</em> loss distributions from simple
749
+ <strong>DecL</strong> programs.</p>
750
+
751
+ <h6>Try it</h6>
752
+ <div class="help-try">
753
+ <code id="help-example">agg Demo 100 claims 1000 xs 0 sev lognorm 90 cv 1.5 poisson</code>
754
+ <div class="mt-2 d-flex align-items-center gap-2">
755
+ <button id="help-load" class="btn btn-sm btn-primary">Load it</button>
756
+ <span class="text-muted form-gloss">then press <kbd>Ctrl</kbd>+<kbd>Enter</kbd></span>
757
+ </div>
758
+ </div>
759
+
760
+ <h6>Keys</h6>
761
+ <div class="help-keys">
762
+ <span><kbd>Ctrl</kbd>+<kbd>Enter</kbd></span><span>build</span>
763
+ <span><kbd>Ctrl</kbd>+<kbd>Space</kbd></span><span>autocomplete; <kbd>Tab</kbd> takes the suggestion</span>
764
+ <span><kbd>Ctrl</kbd>+<kbd>K</kbd></span><span>search the example library</span>
765
+ <span><kbd class="mod-key">Ctrl</kbd>+<kbd>↑</kbd> <kbd>↓</kbd></span><span>step through history (or the two arrows in the editor's right margin)</span>
766
+ <span><kbd class="mod-key">Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>↑</kbd> <kbd>↓</kbd></span><span>step through the example library (loads, does not build); the counter beside the editor says where you are, and walks whatever the Examples menu is filtered and searched down to</span>
767
+ <span><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>U</kbd></span><span>flip every table between static and interactive</span>
768
+ <span><kbd>Ctrl</kbd>+<kbd>Shift</kbd>+<kbd>V</kbd></span><span>flip every exhibit between the raw frame and the insurer reading; the pair beside the versions says which one you are on</span>
769
+ <span><kbd>Alt</kbd>+<kbd>1</kbd>…<kbd>6</kbd></span><span>jump to an output group, numbered in the order they are listed below</span>
770
+ <span><kbd>←</kbd> <kbd>→</kbd> <kbd>Home</kbd> <kbd>End</kbd></span><span>walk a group or leaf row once it has focus, skipping whatever is dark</span>
771
+ <span><kbd>✕</kbd></span><span>clear the editor; press it again on an empty box to clear your history</span>
772
+ </div>
773
+ <p class="small text-muted">Ctrl+Shift+V stands aside inside the program box and the
774
+ entry forms, where the browser claims it for paste, and works everywhere else.
775
+ Menu ▸ Editor ▸ Emacs keys adds Ctrl+A/E/K/Y, N/P and F/B/D in the
776
+ program box.</p>
777
+
778
+ <h6>Controls</h6>
779
+ <ul class="help-tabs">
780
+ <li><span class="t">Build</span>: run the program (same as Ctrl+Enter)</li>
781
+ <li><span class="t">Examples</span>: load a ready-made program. Type to search it,
782
+ or click the tag pills to narrow it; the arrow walk follows what is left on
783
+ screen</li>
784
+ <li><span class="t">Reformat</span>: rewrite the program in canonical form, keeping
785
+ its <code>note{}</code>, <code>hints{}</code> and <code>tags{}</code></li>
786
+ <li><span class="t">Sharpen</span>: audit the grid and move to a better one, writing
787
+ the <code>hints{}</code> clause that pins it</li>
788
+ <li><span class="t">Hints</span>: keep the grid you have and write it into
789
+ <code>hints{}</code>, so <code>agg.Name</code> elsewhere means one fixed thing</li>
790
+ <li><span class="t">PnL</span>: wrap what you built in a profit and loss account.
791
+ Once a P&amp;L is what you are reading the button becomes
792
+ <span class="t">Explode</span>, which opens it back into its parts</li>
793
+ <li><span class="t">GCN</span>: read a program with an occurrence cession as a pair
794
+ of views. The button takes gross / ceded; the caret beside it offers
795
+ gross / net and net / ceded</li>
796
+ </ul>
797
+ <p class="small text-muted">Each derivation writes DecL into the editor, so you can
798
+ read what it did, edit it, and build it again anywhere. The
799
+ <kbd>↑</kbd> in the editor's right margin walks back through the programs you
800
+ built, which is how you undo one.</p>
801
+
802
+ <h6>Output groups</h6>
803
+ <ul class="help-tabs">
804
+ <li><span class="t">Overview</span>: the distribution and its tail, then the moments
805
+ and whether to believe them (Plot, Summary, Validation, Stats, Tail)</li>
806
+ <li><span class="t">Re</span>: reinsurance, ceded and net by layer, with the shape and
807
+ the densities the cession leaves. The Quick Re row writes one layer into the
808
+ program above, on the occurrence or the aggregate tier</li>
809
+ <li><span class="t">Pricing</span>: calibrate a distortion set to a target, price
810
+ the parts stand-alone, allocate one premium across them, read the kappa curves
811
+ behind the split, or evaluate a premium already set</li>
812
+ <li><span class="t">PnL</span>: a P&amp;L's ledger, its ratios, and the margin
813
+ walk</li>
814
+ <li><span class="t">Bounds</span>: how much of a price the choice of distortion
815
+ decides, for the whole and for the parts</li>
816
+ <li><span class="t">More</span>: Density · Tail behavior · Window
817
+ · Dependency · Sharpen · Narrative</li>
818
+ </ul>
819
+ <p class="small text-muted">A group or a leaf greyed out is one this object cannot
820
+ answer; hover it to read why. Nothing is hidden, so the menu is always the same
821
+ shape.</p>
822
+
823
+ <h6>Tables and charts</h6>
824
+ <ul class="help-tabs">
825
+ <li><span class="t">Tables</span>: static, static at full precision, or interactive,
826
+ from the menu or with Ctrl+Shift+U. An interactive grid sorts, filters and
827
+ searches, and its toolbar copies or saves the underlying values rather than the
828
+ printed text</li>
829
+ <li><span class="t">Perspective</span>: Raw is the frame as computed, Insurer is the
830
+ business reading of it. The two words beside the versions are a readout and a
831
+ switch at once</li>
832
+ <li><span class="t">Charts</span>: the strip under a picture carries that panel's
833
+ axis readings, log x, log y, full range, reflect, return period, invert, and its
834
+ reference lines. Download saves the picture as a PNG</li>
835
+ <li><span class="t">Joint surface</span>: a relief adds contours, marginals, mesh,
836
+ wall grid and lights; cut cycles through the slices; a click reads that cell out
837
+ in the strip; double-click, or reset, puts the camera back. Download also writes
838
+ the drawn surface as GLB, OBJ or STL, and a SpaceMouse can fly it in Chromium</li>
839
+ </ul>
840
+ <p class="small text-muted">Menu ▸ Download models saves every program you built
841
+ this session as one <code>.agg</code> file.</p>
842
+
843
+ <h6>Learn more</h6>
844
+ <p class="help-links mb-0">
845
+ <a href="https://aggregate.readthedocs.io/en/latest/4_dec_Language_Reference.html" target="_blank" rel="noopener">DecL language reference</a> ·
846
+ <a href="https://github.com/mynl/aggregate" target="_blank" rel="noopener">aggregate library on github</a>
847
+ </p>
848
+
849
+ <p class="help-fair mb-0">This is a shared, free demo, so builds are
850
+ rate-limited. Want no limits? <code>aggregate</code> is open source, so you can
851
+ <a href="https://github.com/mynl/aggregate" target="_blank" rel="noopener">run it locally</a>.</p>
852
+ </div>
853
+ </div>
854
+
855
+ <!-- About panel (offcanvas from the right, like Help) -->
856
+ <div class="offcanvas offcanvas-end help-panel about-panel" tabindex="-1" id="aboutPanel" aria-labelledby="aboutLabel">
857
+ <div class="offcanvas-header">
858
+ <h5 class="offcanvas-title" id="aboutLabel">About</h5>
859
+ <button type="button" class="btn-close" data-bs-dismiss="offcanvas" aria-label="Close"></button>
860
+ </div>
861
+ <div class="offcanvas-body help-body">
862
+ <p class="help-lead">The <strong>aggregate Loss Lab</strong> (aLL): build and
863
+ explore compound <em>(aggregate)</em> loss distributions in the browser,
864
+ powered by the open-source <code>aggregate</code> library.</p>
865
+
866
+ <h6>Versions</h6>
867
+ <dl class="about-versions">
868
+ <dt>aggregate</dt><dd id="about-aggregate" class="mono">…</dd>
869
+ <dt>aggregate_api</dt><dd id="about-api" class="mono">…</dd>
870
+ <dt>csv-grid</dt><dd id="about-grid" class="mono">…</dd>
871
+ <dt>greater-tables</dt><dd id="about-tables" class="mono">…</dd>
872
+ <dt>ECharts</dt><dd id="about-echarts" class="mono">…</dd>
873
+ <dt>echarts-gl</dt><dd id="about-echarts-gl" class="mono">…</dd>
874
+ <dt>Bootstrap</dt><dd id="about-bootstrap" class="mono">…</dd>
875
+ <!-- Installed plugin packages and their versions, with a
876
+ one-line reason for any that failed to load. A failed
877
+ plugin has to be visible somewhere a human looks, or an
878
+ empty Lab tab becomes a debugging session. -->
879
+ <dt>plugins</dt><dd id="about-plugins" class="mono">…</dd>
880
+ </dl>
881
+
882
+ <!-- The site's terms. The BSD license disclaims warranties for
883
+ people who copy the code; a visitor here receives a service,
884
+ not the code, so the service needs its own words. The lede box
885
+ above the editor links to this section, which is what makes
886
+ "use signifies agreement" point at something. -->
887
+ <h6>Disclaimer</h6>
888
+ <p>aLL is a free research and educational tool built on the open
889
+ source <code>aggregate</code> library (BSD 3-Clause). All results
890
+ are provided as is, with no warranty of any kind. Nothing on this
891
+ site constitutes actuarial, financial, or other professional
892
+ advice, and no output is an actuarial communication within the
893
+ meaning of ASOP 41. Verify results independently before relying
894
+ on them. Submitted programs and sessions may be logged to operate
895
+ the service; do not submit confidential data. The service is
896
+ offered with no promise of availability and may change or be
897
+ withdrawn at any time. Third-party components are used under
898
+ their respective MIT, BSD, and Apache 2.0 licenses.</p>
899
+
900
+ <h6>Learn more</h6>
901
+ <p class="help-links mb-0">
902
+ <a href="https://aggregate.readthedocs.io/" target="_blank" rel="noopener">documentation</a> ·
903
+ <a href="https://aggregate.readthedocs.io/en/latest/4_dec_Language_Reference.html" target="_blank" rel="noopener">DecL reference</a> ·
904
+ <a href="https://github.com/mynl/aggregate" target="_blank" rel="noopener">github</a>
905
+ </p>
906
+ </div>
907
+ </div>
908
+
909
+ <!-- Vite entry point. main.js imports Bootstrap JS + icons, the
910
+ editor, and wires up the UI. -->
911
+ </body>
912
+ </html>