-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathindex.html
More file actions
316 lines (290 loc) · 16.5 KB
/
Copy pathindex.html
File metadata and controls
316 lines (290 loc) · 16.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chronoticker — Portfolio Backtester</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 100 100%22><text y=%22.9em%22 font-size=%2290%22>⏱️</text></svg>">
<meta name="theme-color" content="#0a0d1c">
<meta name="description" content="Backtest any allocation against the market — with time-weighted and money-weighted returns kept apart, real T-bill Sharpe, costs, inflation, and a win rate across every start date.">
<meta property="og:title" content="Chronoticker — Portfolio Backtester">
<meta property="og:description" content="How would your allocation have performed? With honest metrics, a century of history, and a base rate instead of an anecdote.">
<link rel="stylesheet" href="assets/deck.css">
<!-- Pinned: an unpinned "latest" silently moves a load-bearing dependency
under a site that has no build step and no lockfile to catch it. -->
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.7/dist/chart.umd.js"></script>
</head>
<body>
<header class="app-head">
<a class="kicker" href="https://observation-deck.netlify.app/">Observation Deck / Chronoticker</a>
<div class="head-row">
<h1>Chronoticker</h1>
<div class="modes" role="tablist" aria-label="What to measure">
<button type="button" role="tab" id="modeBacktest" aria-selected="true" aria-controls="backtestResults">Backtest</button>
<button type="button" role="tab" id="modeDuel" aria-selected="false" aria-controls="duelResults">All at once vs. spread out</button>
</div>
<a class="help-link" href="guide.html">Guide</a>
</div>
</header>
<!-- ── Front door ─────────────────────────────────────────────────────
Shown until the first run. The presets are the most compelling thing
in the tool and used to be 10px pills below the fold. -->
<section class="launchpad" id="launchpad">
<p class="launch-lede">
Describe an allocation and it is replayed against real daily closing prices —
nothing here is a projection. Start from one of these, or build your own below.
</p>
<div class="preset-grid" id="presetGrid">
<button type="button" class="preset-card" data-preset="century">
<span class="pc-name">A century of the market</span>
<span class="pc-desc">Every US stock, daily, back to 1926. The Depression and 1973 are inside the tool.</span>
<span class="pc-meta">1 holding · since 1926</span>
</button>
<button type="button" class="preset-card" data-preset="index">
<span class="pc-name">Just the index</span>
<span class="pc-desc">The S&P 500 and nothing else. The thing everything else is measured against.</span>
<span class="pc-meta">1 holding · since 1993</span>
</button>
<button type="button" class="preset-card" data-preset="mag7">
<span class="pc-name">Magnificent 7</span>
<span class="pc-desc">The famous megacaps. The tool will tell you how rigged this menu is.</span>
<span class="pc-meta">7 holdings · selection bias</span>
</button>
<button type="button" class="preset-card" data-preset="6040">
<span class="pc-name">Classic 60/40</span>
<span class="pc-desc">Sixty stocks, forty bonds. The default advice for thirty years.</span>
<span class="pc-meta">2 holdings · balanced</span>
</button>
<button type="button" class="preset-card" data-preset="allweather">
<span class="pc-name">All-weather</span>
<span class="pc-desc">Long bonds, gold and commodities alongside stocks, built to survive regimes.</span>
<span class="pc-meta">5 holdings · defensive</span>
</button>
<button type="button" class="preset-card" data-preset="global">
<span class="pc-name">Global 3-fund</span>
<span class="pc-desc">US, developed international, bonds. The whole world in three tickers.</span>
<span class="pc-meta">3 holdings · diversified</span>
</button>
</div>
</section>
<!-- ── Workbench ──────────────────────────────────────────────────── -->
<div class="workbench">
<!-- Control rail -->
<aside class="rail" aria-label="Controls">
<div class="rail-scroll">
<section class="panel">
<div class="panel-head">
<h2>Holdings</h2>
<span class="alloc-total" id="allocTotal">0%</span>
</div>
<div class="weight-bar" id="weightBar"></div>
<p class="weight-hint" id="weightHint"></p>
<div class="allocations" id="allocs"></div>
<div class="alloc-controls">
<button type="button" id="addAsset">+ Add holding</button>
<button type="button" id="equalWeights">Even out</button>
</div>
<div class="presets tight" id="allocPresets">
<span class="presets-label">Load</span>
<button type="button" data-preset="mag7">Mag 7</button>
<button type="button" data-preset="6040">60/40</button>
<button type="button" data-preset="allweather">All-weather</button>
<button type="button" data-preset="global">Global 3</button>
<button type="button" data-preset="index">Index</button>
<button type="button" data-preset="century">Century</button>
</div>
</section>
<section class="panel">
<div class="panel-head"><h2>Money</h2></div>
<div class="fields">
<div class="field" id="fieldInitial">
<label for="initial">Starting amount</label>
<div class="input-money"><span>$</span><input type="number" id="initial" value="10000" min="0" step="100"></div>
<span class="field-hint">Can be 0 if you are only contributing.</span>
</div>
<div class="field" id="fieldContribution">
<label for="contribution">Regular contribution</label>
<div class="input-money"><span>$</span><input type="number" id="contribution" value="0" min="0" step="50"></div>
<span class="field-hint">Leave at 0 for a lump sum.</span>
</div>
<div class="field" id="fieldCadence">
<label for="cadence">Contribution every</label>
<select id="cadence">
<option value="7">Week</option>
<option value="14">Two weeks</option>
<option value="30" selected>Month</option>
<option value="91">Quarter</option>
</select>
</div>
<div class="field" id="fieldTotal" hidden>
<label for="duelTotal">Total to invest</label>
<div class="input-money"><span>$</span><input type="number" id="duelTotal" value="120000" min="1" step="1000"></div>
</div>
<div class="field" id="fieldDeployments" hidden>
<label for="deployments">Spread over</label>
<select id="deployments">
<option value="6">6 instalments</option>
<option value="12" selected>12 instalments</option>
<option value="24">24 instalments</option>
<option value="36">36 instalments</option>
</select>
</div>
</div>
</section>
<section class="panel">
<div class="panel-head"><h2>Window</h2></div>
<div class="fields">
<div class="field">
<label for="lookback">Time range</label>
<select id="lookback">
<option value="6mo">6 months</option>
<option value="1y" selected>1 year</option>
<option value="2y">2 years</option>
<option value="5y">5 years</option>
<option value="10y">10 years</option>
<option value="20y">20 years</option>
<option value="30y">30 years</option>
<option value="max">Everything available</option>
<option value="custom">Custom dates…</option>
</select>
</div>
<div class="field" id="fieldFrom" hidden>
<label for="fromDate">From</label>
<input type="date" id="fromDate">
</div>
<div class="field" id="fieldTo" hidden>
<label for="toDate">To</label>
<input type="date" id="toDate">
</div>
</div>
<div class="presets tight" id="regimePresets">
<span class="presets-label">Jump to</span>
<button type="button" data-regime="dotcom">Dot-com bust</button>
<button type="button" data-regime="gfc">2008 crisis</button>
<button type="button" data-regime="lostdecade">Lost decade</button>
<button type="button" data-regime="covid">COVID crash</button>
<button type="button" data-regime="bear2022">2022 bear</button>
<button type="button" data-regime="stagflation">1973–74</button>
<button type="button" data-regime="depression">1929–32</button>
</div>
</section>
<section class="panel">
<div class="panel-head"><h2>Frictions & lens</h2></div>
<div class="fields">
<div class="field">
<label for="rebalance">Rebalance</label>
<select id="rebalance">
<option value="0" selected>Never (buy & hold)</option>
<option value="30">Monthly</option>
<option value="91">Quarterly</option>
<option value="365">Annually</option>
</select>
</div>
<div class="field">
<label for="costBps">Trading cost</label>
<select id="costBps">
<option value="0" selected>None (frictionless)</option>
<option value="5">5 bps — big liquid ETFs</option>
<option value="10">10 bps — typical retail</option>
<option value="25">25 bps — wide spreads</option>
</select>
</div>
<div class="field">
<label for="feeBps">Annual fee</label>
<select id="feeBps">
<option value="0" selected>None</option>
<option value="3">0.03% — index fund</option>
<option value="20">0.20% — typical ETF</option>
<option value="50">0.50% — active fund</option>
<option value="100">1.00% — adviser</option>
</select>
</div>
<div class="field">
<label for="measure">Measure in</label>
<select id="measure">
<option value="nominal" selected>Nominal dollars</option>
<option value="real">Today's dollars (inflation-adjusted)</option>
</select>
</div>
</div>
</section>
</div>
<div class="rail-foot">
<button id="run" class="btn-primary" type="button">
<span class="btn-label">Run</span>
<span class="btn-spinner" aria-hidden="true"></span>
</button>
<label class="autorun" for="autoRun" title="Re-run automatically when you change a control">
<input type="checkbox" id="autoRun" checked>
<span>Live</span>
</label>
</div>
</aside>
<!-- Results pane -->
<main class="stage">
<div class="data-status" id="status" role="status">Ready.</div>
<div class="results" id="results" hidden>
<div id="backtestResults" role="tabpanel" aria-labelledby="modeBacktest" tabindex="0">
<div class="hero" id="hero"></div>
<div class="coverage" id="coverage"></div>
<div class="assumptions" id="assumptions"></div>
<h2 class="section-label">
Growth
<span class="chart-tools">
<button type="button" id="chartScale" aria-pressed="false" title="Switch between linear and logarithmic value axis">Log</button>
<button type="button" id="chartDD" aria-pressed="true" title="Shade the deepest peak-to-trough fall">Drawdown</button>
<button type="button" id="chartReset" hidden>Reset zoom</button>
</span>
</h2>
<div class="chart-card">
<div class="chart-legend" id="chartLegend"></div>
<div class="chart-wrap"><canvas id="chart"></canvas></div>
<p class="chart-hint">Drag across the chart to zoom into a window · click a series to hide it</p>
</div>
<h2 class="section-label">The strategy</h2>
<div class="stat-group" id="statsStrategy"></div>
<h2 class="section-label">Was this window lucky?</h2>
<div id="sweepHost"></div>
<div id="noticeHost"></div>
<h2 class="section-label">Per holding</h2>
<div class="breakdown-wrap" id="breakdownHost"></div>
<div id="ledgerHost"></div>
</div>
<div id="duelResults" role="tabpanel" aria-labelledby="modeDuel" tabindex="0" hidden>
<h2 class="section-label">Verdict</h2>
<div class="stat-group" id="duelStats"></div>
<div class="story" id="duelStory"></div>
<h2 class="section-label">Both lenses</h2>
<div class="breakdown-wrap"><table class="duel-table" id="duelTable"></table></div>
<h2 class="section-label">Wealth over time</h2>
<div class="chart-card">
<div class="chart-legend" id="duelChartLegend"></div>
<div class="chart-wrap"><canvas id="duelChart"></canvas></div>
</div>
<h2 class="section-label">How often does spreading out win?</h2>
<div id="duelSweepHost"></div>
</div>
<div class="share-row">
<button type="button" id="copyLink">Copy link to this run</button>
<button type="button" id="exportCsv">Download the numbers (CSV)</button>
</div>
</div>
<div class="stage-empty" id="stageEmpty">
<div class="stage-empty-mark" aria-hidden="true">⏱</div>
<p>Pick an allocation and press <b>Run</b>.<br>
The <a href="guide.html">guide</a> explains what each number means — and what it does not.</p>
</div>
</main>
</div>
<footer class="footer">
<a href="https://observation-deck.netlify.app/">Observation Deck</a> ·
<a href="https://github.com/00xJS/Chronoticker">GitHub</a> ·
<a href="guide.html">Guide</a>
<div class="disclaimer">
Educational tool. Backtests describe the past and do not predict the future.
Nothing here is financial advice.
</div>
</footer>
<script type="module" src="assets/app.js"></script>
</body>
</html>