-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathguide.html
More file actions
314 lines (296 loc) · 16.9 KB
/
Copy pathguide.html
File metadata and controls
314 lines (296 loc) · 16.9 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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chronoticker — Guide</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">
<link rel="stylesheet" href="assets/deck.css">
<style>
/* Guide-only typography. Everything else comes from deck.css, which
index.html shares — the two pages used to carry duplicate copies
of the whole theme and drifted apart. */
/* Fills the card, matching index.html. This carried a 68ch measure,
which left 275px of dead space down the right-hand side of a 960px
card and read as text pinned to the left rather than as a column. */
.prose { max-width: none; }
.prose h2 {
font-size: 1.35rem;
margin: 42px 0 12px;
letter-spacing: -0.015em;
}
.prose h3 {
font-size: 1.02rem;
margin: 26px 0 8px;
color: var(--text);
}
.prose p { margin: 0 0 14px; color: var(--muted); }
.prose ul, .prose ol { margin: 0 0 14px; padding-left: 22px; color: var(--muted); }
.prose li { margin-bottom: 7px; }
.prose li::marker { color: var(--faint); }
.prose strong { color: var(--text); font-weight: 620; }
.prose code {
font-family: var(--font-mono);
font-size: 0.87em;
background: var(--bg-raised);
border: 1px solid var(--border);
border-radius: 5px;
padding: 0.1em 0.38em;
color: var(--accent);
}
.defs { display: flex; flex-direction: column; gap: 2px; margin: 0 0 16px; }
.def {
display: grid;
grid-template-columns: 190px 1fr;
gap: 16px;
padding: 13px 0;
border-bottom: 1px solid var(--border);
}
.def dt {
font-family: var(--font-mono);
font-size: 11px;
letter-spacing: 0.07em;
text-transform: uppercase;
color: var(--accent);
padding-top: 2px;
}
.def dd { margin: 0; font-size: 14.5px; color: var(--muted); }
.def dd strong { color: var(--text); }
.compare {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 12px;
margin: 18px 0;
}
.compare > div {
background: var(--card);
border: 1px solid var(--border);
border-top: 2px solid var(--tone);
border-radius: var(--radius-card);
padding: 16px 17px;
}
.compare .a { --tone: var(--accent); }
.compare .b { --tone: #5b8def; }
.compare h4 {
margin: 0 0 8px;
font-size: 15px;
color: var(--text);
}
.compare p { font-size: 14px; margin: 0 0 8px; color: var(--muted); }
.compare .eg {
font-family: var(--font-mono);
font-size: 12px;
color: var(--faint);
border-top: 1px solid var(--border);
padding-top: 9px;
margin-top: 4px;
}
@media (max-width: 640px) {
.def { grid-template-columns: 1fr; gap: 4px; }
.compare { grid-template-columns: 1fr; }
}
</style>
</head>
<body>
<div class="container">
<a class="kicker" href="https://observation-deck.netlify.app/">Observation Deck / Chronoticker</a>
<div class="top-bar">
<h1>Guide</h1>
<div class="spacer"></div>
<a class="help-link" href="index.html">← Back to the tool</a>
</div>
<div class="prose">
<h2>What this tool does</h2>
<p>
You describe a portfolio — which holdings, what weights, how much money, over what
period — and Chronoticker replays it against real daily closing prices. It shows what
that portfolio would have been worth, how rough the ride was, and how it compares to
simply buying the index.
</p>
<p>
<strong>It is a history tool, not a forecasting tool.</strong> Everything it prints is a
description of the past. The most useful thing it can teach you is not which allocation
won — it is how much of "winning" was the allocation and how much was the start date.
</p>
<h2>The one idea worth understanding</h2>
<p>
If you add money over time, your portfolio has <em>two different returns</em>, and mixing
them up is the single most common way a backtest lies to you.
</p>
<div class="compare">
<div class="a">
<h4>Growth rate — the strategy</h4>
<p>
How the <strong>allocation</strong> performed, per dollar, per year. Adding money
does not change it, because depositing cash is not investment skill.
</p>
<p>Use it to compare one allocation against another.</p>
<div class="eg">time-weighted · "CAGR"</div>
</div>
<div class="b">
<h4>Your return — the money</h4>
<p>
What <strong>your actual dollars</strong> earned, counting when each one arrived.
Money invested early is exposed longer, so timing matters here by design.
</p>
<p>Use it to answer "how did I do?"</p>
<div class="eg">money-weighted · "IRR"</div>
</div>
</div>
<p>
When they disagree, that gap is information. If your return beats the growth rate, your
contributions happened to land at good moments. If it trails, they landed at bad ones.
</p>
<p>
Chronoticker used to report only one number and label it CAGR, computed on the total
dollar balance — so a $500 monthly deposit was counted as investment performance. On a
ten-year S&P run that reported <strong>33.20%</strong> a year where the truth was
<strong>15.01%</strong>, and it understated the worst drawdown by more than twenty
percentage points. Both numbers are now computed separately and labelled.
</p>
<h2>Running one</h2>
<ol>
<li><strong>Pick holdings and weights.</strong> They must total 100%. <em>Equal weights</em> splits them evenly.</li>
<li><strong>Set the money.</strong> A starting amount, a regular contribution, or both. Either can be zero.</li>
<li><strong>Choose a time range.</strong> Presets are measured back from the most recent day of data, so a "5 years" window stays five years long even if the data refresh stalls. <em>Custom dates</em> lets you pin an exact period.</li>
<li><strong>Decide the rest.</strong> Rebalancing, trading costs, annual fee, and whether to measure in nominal or inflation-adjusted dollars.</li>
<li><strong>Press Run.</strong> The address bar updates to a link that reproduces exactly this run — copy it, bookmark it, send it to someone.</li>
</ol>
<h2>Reading the results</h2>
<h3>The assumption chips</h3>
<p>
The row of small labels under the date range states what the simulation is and is not
doing — whether costs are modelled, whether Sharpe uses a real cash rate, whether taxes
are ignored (they always are). Amber means "this is a simplification that flatters the
result." They sit next to the numbers on purpose.
</p>
<h3>The numbers</h3>
<dl class="defs">
<div class="def"><dt>Final value</dt><dd>What the portfolio is worth on the last day, after any costs and fees.</dd></div>
<div class="def"><dt>You put in</dt><dd>Every dollar you contributed, including the opening amount, and how many separate purchases that took.</dd></div>
<div class="def"><dt>Profit</dt><dd>Final value minus what you put in.</dd></div>
<div class="def"><dt>Your return</dt><dd>The money-weighted rate (IRR) — the annual rate that, applied to each contribution from the day it landed, produces the final value.</dd></div>
<div class="def"><dt>Growth rate</dt><dd>The time-weighted rate. The strategy's own return, immune to contribution timing.</dd></div>
<div class="def"><dt>Worst fall</dt><dd>The deepest peak-to-trough drop, with the dates it happened. <strong>The number people ignore and shouldn't.</strong> A 30% growth rate with a 70% fall is brutal to actually live through.</dd></div>
<div class="def"><dt>Volatility</dt><dd>How much the daily value jumps around, annualised. Broad index funds run 15–20%; single tech stocks are often double that.</dd></div>
<div class="def"><dt>Sharpe</dt><dd>Return per unit of risk, measured <strong>above what cash paid at the time</strong> using real Treasury-bill rates. Roughly: under 0.5 is poor, around 1 is good, above 2 is rare. Earlier versions assumed cash paid 0%, which quietly inflated this.</dd></div>
<div class="def"><dt>Best / worst day</dt><dd>The single biggest up and down day, with dates. A gut-check on tail risk.</dd></div>
<div class="def"><dt>Paid in friction</dt><dd>Trading costs plus management fees, in dollars. Only appears when you have modelled some.</dd></div>
</dl>
<h3>"Was this window lucky?"</h3>
<p>
This is the part most backtesters do not have, and it matters more than anything above it.
</p>
<p>
A single backtest is <strong>one observation</strong>. Chronoticker replays your exact
configuration starting from every other date the data allows and shows how often it
actually beat the benchmark. Green bars are windows you won, red are windows you lost,
and your own window is outlined.
</p>
<p>
If your allocation beat the index in 9 of 10 windows, that is evidence. If it beat it in
the one window you happened to choose, that is an anecdote. When there is not enough
history to form an honest base rate, the tool says so rather than showing a confident
percentage built on two overlapping windows.
</p>
<h3>"This menu is rigged in your favour"</h3>
<p>
If you use the megacap stocks, you will see this warning with a measured number attached.
Those ten names are on the menu because they are famous <em>now</em> — which means they
were selected using information from the end of the period you are testing. All ten beat
the S&P 500 over the past decade. You cannot build a losing buy-and-hold portfolio
out of them, and that says nothing whatsoever about your allocation skill.
</p>
<p>
The sector, bond, international and broad-market funds do not have this problem in
anything like the same degree: they were picked to span the investable world rather than
to be winners. Use them if you want a backtest that could have told you something.
</p>
<h2>All at once vs. spread out</h2>
<p>
The second mode answers a different question: you have a lump of money — invest it all
today, or feed it in over a year?
</p>
<p>
Both sides start with the same total counted as wealth, so the drawdowns are directly
comparable and the cash cushion is visible instead of hidden. Uninvested cash earns the
actual Treasury-bill rate of the day, because assuming idle cash earns nothing puts a
thumb on the scale for investing immediately.
</p>
<p>
The usual result: <strong>investing all at once wins on money, spreading out wins on
risk.</strong> Markets rise more often than they fall, so cash on the sidelines usually
misses gains — but a slower entry means a shallower worst-case fall. The win-rate strip
underneath shows how often each one came out ahead across every start date, so you can
see whether your window was typical or unusual.
</p>
<h2>Jump to a crisis</h2>
<p>
The regime buttons load specific historical windows: the dot-com bust, 2008, the lost
decade, the COVID crash, the 2022 bear market, 1973–74 stagflation, and the 1929–32
Depression.
</p>
<p>
Most holdings will not reach back that far — the funds mostly start in the 1990s or
2000s. <strong>A century of the market</strong> is the holding that does: a daily
total-return index of the entire US stock market back to July 1926, rebuilt from the
Fama/French research data. Selecting it and choosing the Depression window shows a
<strong>−84%</strong> fall over roughly three years. That is what a bad decade looks
like, and no ten-year backtest can show it to you.
</p>
<h2>Nominal or real</h2>
<p>
<strong>Nominal</strong> is dollars as printed. <strong>Today's dollars</strong> restates
everything in current purchasing power using the consumer price index. Over ten years the
gap is a few percent a year; over the long windows the deep index makes possible, it is
the difference between a good decade and a lost one. A portfolio that returned 8% a year
through the 1970s lost money in real terms.
</p>
<h2>Costs and fees</h2>
<p>
Both default to zero, which is unrealistic and clearly marked as such.
</p>
<ul>
<li><strong>Trading cost</strong> is charged on every purchase and every rebalance, as basis points of the amount traded.</li>
<li><strong>Annual fee</strong> accrues daily against the whole portfolio — an expense ratio, or an adviser.</li>
</ul>
<p>
One subtlety worth knowing: costs on a <em>purchase</em> are paid by you and show up in
your return and final value, but not in the strategy's growth rate — buying in is your
decision, not the strategy's. Costs on a <em>rebalance</em> come out of the portfolio and
do reduce the growth rate, because rebalancing is something the strategy chose to do.
That is what makes a costed comparison of rebalancing schedules mean anything, and it is
usually an unpleasant surprise.
</p>
<h2>Where the data comes from</h2>
<ul>
<li><strong>Stocks and funds</strong> — daily dividend- and split-adjusted closes from the Tiingo API, fetched by a nightly GitHub Action and committed to the repository as static JSON. The site makes no API calls at all.</li>
<li><strong>A century of the market</strong> — built from the Fama/French daily research factors (Mkt-RF + RF), giving total returns from 1 July 1926. Published monthly, so it lags the fund data by up to six weeks; the tool knows this and will not cry stale about it.</li>
<li><strong>Risk-free rate</strong> — the same Fama/French one-month Treasury-bill series, extended to the present with the daily three-month bill from FRED.</li>
<li><strong>Inflation</strong> — US consumer price index from FRED, monthly back to 1913.</li>
</ul>
<p>
If a refresh ever fails, results simply end at the last good day and the tool tells you
which holding is behind and by how long.
</p>
<h2>What this deliberately does not model</h2>
<ul>
<li><strong>Taxes.</strong> None, anywhere. Real after-tax returns are lower, and rebalancing in a taxable account is more expensive than shown.</li>
<li><strong>Bid-ask spreads and market impact</strong> beyond the flat cost you choose.</li>
<li><strong>Delisted and failed companies.</strong> Everything on the menu still exists. Real portfolios held things that went to zero, and no free data source covers them.</li>
<li><strong>Your behaviour.</strong> Every backtest assumes you held on through the worst fall it shows you. That assumption fails more often than any of the others.</li>
</ul>
<div class="disclaimer" style="margin-top:34px">
Educational tool. Backtests describe the past and do not predict the future.
Past performance does not guarantee future results. Nothing here is financial advice.
</div>
</div>
<div class="footer">
<a href="index.html">← Back to Chronoticker</a> ·
<a href="https://observation-deck.netlify.app/">Observation Deck</a> ·
<a href="https://github.com/00xJS/Chronoticker">GitHub</a>
</div>
</div>
</body>
</html>