How TendonGuard computes your risk
Every number on the dashboard comes from the steps below, applied in order. It's a transparent, deterministic heuristic — no machine learning, no black box: the same sessions always give the same numbers, every constant lives in one config file, and nothing derived is ever stored, so editing or deleting a session recomputes the whole picture.
1.One session → one number
Each session you log is reduced to a single load figure: how long you climbed, scaled by how hard it felt, scaled by how much that style stresses the finger tendons specifically.
session load = duration (min) × RPE / 10 × tendon factorRPE is your 1–10 rating of perceived exertion, so the intensity factor spans 0.1–1.0. The tendon factor is the climbing-specific part — an hour on the hangboard is not an hour of easy mileage:
| Session type | Tendon factor | What it covers |
|---|---|---|
| Hangboard / fingerboard | ×1.6 | Maximal finger-specific loading. Highest tendon stress. |
| Bouldering (hard / crimpy) | ×1.4 | Small holds, crimps, limit moves. |
| Bouldering (general) | ×1.1 | Mixed bouldering, moderate grades. |
| Sport / lead | ×1.0 | Roped climbing, sustained but lower peak finger load. |
| Endurance / ARC / volume | ×0.8 | High volume, low intensity. Aerobic capacity work. |
| Easy / technique / rehab | ×0.5 | Light movement, drills, recovery, rehab. |
Example: 60 min of hard bouldering at RPE 8 → 60 × 0.8 × 1.4 = 67.2 load units. The unit is arbitrary; it is only ever compared with your own history.
Several sessions on the same calendar day add up. A day with nothing logged counts as zero load, not as missing data — rest days are part of the pattern.
2.Daily loads → the trailing week
Daily loads are then rolled into a trailing 7-day total: for each day, that day's load plus the six before it. This total — not daily load — is what the two averages in the next step smooth.
weekly load(d) = sum of daily load over days d−6 … dSeven days is exactly one training cycle, so the weekly total is flat under any weekly-periodic schedule. Smoothing daily load instead (as the team-sport literature does, for athletes who train most days) made the ratio depend on the day of the week: an unchanged twice-a-week schedule read anywhere between 0.68 and 1.30 depending on when you looked.
3.Acute and chronic load
Acute load (what you have done lately) and chronic load (the baseline you are adapted to) are both exponentially-weighted moving averages of that weekly load, walked forward one day at a time with λ = 2/(N+1) (Williams et al. 2017):
acute(d) = 0.25 × weekly(d) + 0.75 × acute(d−1) λ = 2/(7+1)
chronic(d) = 0.069 × weekly(d) + 0.931 × chronic(d−1) λ = 2/(28+1)Both start from zero, which would make them read low for weeks, so both are bias-corrected: after n days each is divided by the total weight it has actually seen.
corrected(d) = raw(d) / (1 − (1 − λ)^n)Without that correction the slow chronic average lags for about eight weeks, and a month of perfectly flat training would read ACWR 1.13 — a ramp-up warning invented by the estimator, on exactly the return-from-a-layoff history that is the common case here.
Exponential averages rather than the coupled rolling sums of the original ACWR literature: summing the trailing 7 days inside the trailing 28 puts the same sessions on both sides of the ratio, and it stepped the ratio overnight the morning a big session fell out of the 7-day window — one big day sat at 1.45 for a week, then dropped 0.61 between two mornings with nothing behind the change. An exponential average decays instead of cliffing.
The walk starts at your first logged session — days before it are missing data, not rest days — and for a long history it is clipped to 112 days before the left edge of the trend chart, where the dropped tail is worth under 0.1 % of the estimate.
4.The ratio and the risk bands
ACWR = acute load / chronic loadAbove 1 you are doing more than your body is used to; below 1, less. The bands the dashboard shows:
| Band | ACWR | What it means |
|---|---|---|
| Detraining | 0 – 0.9 | You're well rested — fine to push, but you've ramped down lately. |
| Optimal | 0.9 – 1.18 | Load is in the sweet spot. Good window for hard sessions. |
| Caution | 1.18 – 1.28 | Acute load is climbing faster than your baseline. Watch finger soreness. |
| High risk | ≥ 1.28 | Spike in load relative to your baseline — elevated strain-injury risk. Prioritize rest before the next hard/crimpy session. |
These cut-points are deliberately not the familiar 0.8 / 1.3 / 1.5. Those come from the coupled rolling-sum estimator and don't transfer: here the chronic average tracks a rising baseline faster and the acute term is smoothed rather than summed, so the same training reads closer to 1. Two independent derivations agree on the values above — analytically, for a climber stepping to k× a settled baseline (the coupled thresholds sit at k = 0.75 / 1.44 / 1.80, where this estimator reads 0.90 / 1.16 / 1.26), and by quantile-matching over ~128,000 simulated climber-days. Both are pinned by unit tests. Carrying the old numbers over instead would have fired “high risk” 3.7× less often — a quieter dashboard, not a safer one.
5.When no band is shown
A ratio against a baseline you don't have yet is worse than no number, so the dashboard shows “building your baseline” until all three of these hold:
- 28 calendar days between your first logged session and today
- at least 8 sessions inside the last 28 days
- chronic load of at least 50
A provisional ratio is still shown while you build up, explicitly labelled as not yet reliable.
The density floors matter as much as the calendar one: one easy session four weeks ago plus a normal session today spans 28 days with chronic load above zero, and would band “high risk” off two data points.
6.Guardrail — consecutive high-finger-load days
This one is read straight off the raw sessions and ignores ACWR entirely. A day counts as high finger load when it holds at least one session with a tendon factor of 1.4 or more (Hangboard / fingerboard and Bouldering (hard / crimpy)). The warning fires when 2 or more such days run back to back — the classic pulley-injury pattern.
The run also has to have ended within 1 day of today. The banner is present-tense advice (“rest before the next hard session”), and a hard spell from three weeks ago already had its rest day.
7.Morning finger soreness
Sessions can carry an optional next-morning soreness report, 0–5 — a more direct injury signal than any ratio. Across the last 7 days the signal turns on when a single report reaches 3/5, or the mean of the reports reaches 2/5.
When it is on, the displayed band is escalated one level toward high risk, and never sits below “Caution” however rested the ratio looks. The dashboard says when it has done this, and names the band the ratio alone implied.
A reported 0 (“asked, no soreness”) counts toward the mean; a session with no report is simply absent from it.
8.What it doesn't know
The model sees only what you log: minutes, RPE, style and the optional soreness report. No wearables, no HRV or sleep, no grades or route data, and it never learns from other users — deliberately, so that every number on the dashboard traces back to the arithmetic above.