Training-load metrics (TSS, CTL/ATL/TSB) and Strava archive parsing — zero runtime dependencies
Project description
trainingload
Training-load metrics and Strava archive parsing for endurance sport — with zero runtime dependencies.
trainingload is a small, typed Python toolkit for the math behind endurance
training analytics: Training Stress Score (TSS) for swim/bike/run/strength, the
Performance Management Chart (CTL / ATL / TSB), and a parser for Strava's bulk
data export. It's the load engine extracted from the production codebase of
Motus — an AI triathlon coach — and packaged so you
can drop it into a notebook, a script, or your own app.
No NumPy, no pandas, no web framework. Just the standard library.
Install
pip install trainingload
Requires Python 3.10+.
Quick start
from datetime import date
from trainingload import calculate_pmc
# Daily Training Stress Score -> fitness (CTL), fatigue (ATL), form (TSB)
series = calculate_pmc({
date(2026, 1, 1): 80.0,
date(2026, 1, 2): 120.0,
date(2026, 1, 3): 0.0, # rest day
})
today = series[-1]
print(today.ctl, today.atl, today.tsb)
What's inside
Three independent modules — use one or all three.
1. trainingload.tss — Training Stress Score
Sport-aware TSS from whatever data you have (power, pace, heart rate, or just duration), with sensible fallbacks.
from trainingload import TSSCalculator, TrainingZones
zones = TrainingZones(bike_ftp=250, run_threshold_pace=300, swim_css=95)
# Cycling from normalized power:
TSSCalculator.calculate_bike_tss(duration_seconds=3600, normalized_power=200, ftp=250) # 64.0
# Or let it pick the best method for the sport and data available:
TSSCalculator.estimate_tss(sport_type="run", duration_seconds=3600,
distance_meters=10000, zones=zones) # 69.4
# Show your work — which method, inputs and formula were used:
TSSCalculator.explain_tss_calculation(sport_type="bike", duration_seconds=3600,
tss=64.0, normalized_power=200, zones=zones)
2. trainingload.pmc — Performance Management Chart
CTL/ATL/TSB time series and a current-fitness snapshot from a map of daily TSS.
from datetime import date
from trainingload import fitness_summary, interpret_tsb, recommend_training
summary = fitness_summary(daily_tss) # {date: tss} -> ctl/atl/tsb + ramp rate
print(interpret_tsb(summary.tsb)) # e.g. "fresh"
print(recommend_training(summary.tsb, target_event_days=7))
- CTL (Chronic Training Load) — 42-day EMA of TSS → fitness
- ATL (Acute Training Load) — 7-day EMA of TSS → fatigue
- TSB (Training Stress Balance) — CTL − ATL → form
3. trainingload.strava — bulk-export parser
Turn the activities.csv from a Strava data export into typed records. Accepts
a file path or an in-memory stream (e.g. an upload), so it works server-side
or in a worker without touching disk.
from trainingload import StravaArchiveParser
parser = StravaArchiveParser()
activities = parser.parse_zip_activities("strava_export.zip")
meta = parser.parse_zip("strava_export.zip") # totals, date range, sport breakdown
End-to-end: Strava export → fitness curve
See examples/strava_to_pmc.py for the full flow —
parse the archive, score every activity, and print your current CTL/ATL/TSB:
python examples/strava_to_pmc.py path/to/strava_export.zip
Accuracy & credits
TSS, NP/IF, and the CTL/ATL/TSB model come from the endurance-training literature popularised by Hunter Allen & Andrew Coggan (Training and Racing with a Power Meter) and the TrainingPeaks Performance Management Chart. The implementations here are independent and intentionally transparent — every formula is documented in the source and covered by tests.
Trademark note. "TSS", "CTL", "ATL", "TSB", "NP" and "IF" are used in this project descriptively to refer to widely-documented training-load concepts. They are trademarks of Peaksware, LLC (TrainingPeaks). This project is not affiliated with, sponsored by, or endorsed by TrainingPeaks or Strava.
Built by Motus
trainingload powers the analytics inside Motus,
an AI coach for runners and triathletes. If you want the metrics in this library
turned into adaptive training plans, race predictions and a coach in your pocket,
give Motus a try
— and read the training-science guides on the Motus blog.
Contributing
Issues and pull requests are welcome — see CONTRIBUTING.md.
License
MIT © Motus
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file trainingload-0.1.0.tar.gz.
File metadata
- Download URL: trainingload-0.1.0.tar.gz
- Upload date:
- Size: 23.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2d1e50111b27b21593343791d3e4bc13147e549a62edaf28eaa5e658cfab271b
|
|
| MD5 |
768ced532e070d9dfb12875542628f60
|
|
| BLAKE2b-256 |
4b61ebf40dc5603f994bf647f58bbcc72c321b15c1ece4af61e99c79893357ce
|
Provenance
The following attestation bundles were made for trainingload-0.1.0.tar.gz:
Publisher:
release.yml on youloseman/trainingload
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
trainingload-0.1.0.tar.gz -
Subject digest:
2d1e50111b27b21593343791d3e4bc13147e549a62edaf28eaa5e658cfab271b - Sigstore transparency entry: 1738457957
- Sigstore integration time:
-
Permalink:
youloseman/trainingload@d15737153b230d84df61830b1de55811ee21cd32 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/youloseman
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d15737153b230d84df61830b1de55811ee21cd32 -
Trigger Event:
release
-
Statement type:
File details
Details for the file trainingload-0.1.0-py3-none-any.whl.
File metadata
- Download URL: trainingload-0.1.0-py3-none-any.whl
- Upload date:
- Size: 17.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
60bc5eabe9c92924bbb10b0a2f0b9da23245de5dcc39fddeb3e851d7a0c0f703
|
|
| MD5 |
afa2dde0741703edbd1dbea43740d7da
|
|
| BLAKE2b-256 |
fb8170cba1ca1d28441b8fd7b5df9942eb0533742f3dc24512f6123e89c3ca53
|
Provenance
The following attestation bundles were made for trainingload-0.1.0-py3-none-any.whl:
Publisher:
release.yml on youloseman/trainingload
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
trainingload-0.1.0-py3-none-any.whl -
Subject digest:
60bc5eabe9c92924bbb10b0a2f0b9da23245de5dcc39fddeb3e851d7a0c0f703 - Sigstore transparency entry: 1738457979
- Sigstore integration time:
-
Permalink:
youloseman/trainingload@d15737153b230d84df61830b1de55811ee21cd32 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/youloseman
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@d15737153b230d84df61830b1de55811ee21cd32 -
Trigger Event:
release
-
Statement type: