I‘ve tried your formula with some example rides (in brackets ‚original‘ TSS):
10 hour Ride was Load 500 (500)
2 hour Ride was Load 250 (90)
15m commute was Load 90 (13)
So, I will stick with TSS, because longer rides will reflect it better due to greater fatigue, as @Gerald mentioned. However, as stated above, if your formula works better for you because you do more short rides, you can create your own fitness chart and load calculation.
It’s the other way around. TSS in the last few hours of a long activity is the same as the value in the first few hours, despite the added fatigue as the duration increases. So it under values the stress from long durations.
Yes, original TSS doesn’t account for fatigue already acquired. Neither does my formula. My formula doesn’t fix this particular problem, it fixes others though.
I‘ve tried your formula with some example rides (in brackets ‚original‘ TSS):
10 hour Ride was Load 500 (500)
2 hour Ride was Load 250 (90)
15m commute was Load 90 (13)
I am sorry but it looks like you are misinterpreting my formula. My formula gives the same results for rides with the same power. Specifically 2 hour ride will have 5x smaller area under the curve as 10 hour ride at the same power (obviously?). It looks like you are doing something very wrong.
Can you describe the rides you calculated (power, duration) so I can verify those?
Area under the curve depends on duration (obviously). The differences appear in rides with mixed intensities. My formula is akin to splitting the ride to multiple parts and calculating TSS for every one of them.
Right, thank you. I was overexcited and made a mistake when copy-pasting the steps.
Area below squared power curve doesn’t require square root at the end. Just express power as % of FTP and take the area below.
In your examples assuming 200W is 71% of FTP (to produce 0.5 IF) the area below squared curve is:
To get TSS scale you need to multiply the results by 100.
I am sorry for the confusion, square root was artifact of my notes and I haven’t checked carefully enough. It should be “multiply the result by 100” instead.
The idea is that this way the result is the same for every interval with monotonous power and the score for the whole ride is the sum of those intervals (+/- depending if we apply 30 seconds smoothing or not). This is in the spirit of original TSS idea but solves the problem of rest/very easy periods increasing the total score.
Original TSS gives a lower score for uninterrupted interval than two intervals half as short with rest between This is clearly nonsense. We can eliminate this nonsense and keep the rest.
Sure, it would be very nice to also have a function that scores 20m work - 20m easy higher than 10m work - 10min easy - 10min work - 10min easy but this requires a different kind of function (similar to CTL but operating on seconds not days) and it’s a research project to develop it. Original TSS can’t do it either - it’s not aware of order of intense segments. I am just trying to solve the most glaring issue. My formula is equivalent of stopping and restarting your bike computer multiple times during the ride and summing up the resulting TSS of those shorter parts.
Anyway, it looks like I can program and fix it myself so I will go do that and come back if I encounter any issues. Thank you for linking me to the resources, it’s very helpful and looks like exactly the functionality I am after!
You can actually update the default activity training load from a custom activity field script. Return your custom value but also update the value on the activity:
activity.icu_training_load = ...
Then your custom calc will automatically show up on all the usual charts.
Thank you! It’s awesome it’s designed this way.
I still think TSS is based on a simple math mistake, it should be duration * NP and NP should be average of squared values expressed as % of FTP.
I kinda given up convincing people and started enjoying their mental gymnastics around why TSS kinda works but not quite or why it’s fine to remove 0s at the end but not in the middle of the workout (TSS function is not order aware so it’s just silly exercise). I am very happy you designed the software in the way to let users insert custom values. I am a subscriber and will soon be double subscriber (for my girlfriend as well) and couldn’t be happier with what we are getting here.
You don’t have to convince us, most of the advanced users already know that.
But I assure you that as soon as you introduce a different way of calculating TSS as a default one, the forum will be flooded with ‘Bug Reports’. Simply because it deviates from the big players (TP, WKO, Strava…) who are ‘considered’ the only source of truth. It off course has to do with the fact that elite’s have been using this for decades.
OK, smart people, this is a person whose exposure to program languages began and ended with Fortran. Yes, I’m that old.
So, as I am interested in @PiotrekNL’ s idea and thinking of implementing it: where and how is David’s method done? I’d be grateful for a simple explanation / demonstration…
Oh, and more in line with my knowledge: @MedTechCD and @Gerald : my view of load metrics like TSS is that they are constraints not targets. That is, train according to Gerald’s schema but limit the changes to those that raise TSS this week by no more than about 3-5% compared to the previous week.
Thank you very much, @R2Tom . You are so helpful. I can certainly do this, Yippee.
So, imposing on your patience again: if I replace the line
activity.icu_training_load = tss/36
with
activity.icu_training_AltTSS = tss/36,
then I will have both the original load [TSS] and this new datum [AltTSS]?
Incidentally, where does the /36 come from?
And to get a new fitness graph based on AltTSS, then I just have to wait until I have enough new days for the graph to make sense and make a custom chart with the appropriate moving average functions?
I just need a few days so I can find time for it.
Btw, my idea in this thread is just very minimalistic improvement over TSS fixing its most glaring hole without really adjusting it.
My more promising idea is:
-instead of squaring power use the following function:
(P - 0.5)^2 for P bigger than 0.5 and 0 for P lower than 0.5 where P is power in % of FTP.
-calculate area under it - see @R2Tom 's code above.
This improves on TSS in two ways:
-it fixes the issue mentioned in this OP
-it stops overrating weak efforts weighting stronger efforts more. For example with this new function you need to ride 4 hours at 75% of FTP to get the same score as one hour at 100% of FTP.
Riding below 50% of FTP doesn’t increase the score as it should because there is 0 stimulus from it according to some papers I’ve seen (minimum stimulus is seemingly estimated to occur at 40%-60% of VO2max depending how well trained you are but again I am not physiologist so take that into account).
Of course the choice of 0.5 is completely arbitrary (maybe 0.3 or 0.4 works better if you want to weigh easier effort a bit more) although the choice of the function in the original TSS was also completely arbitrary so there is that
I am sure it would be promising area of research to find a perfect physiologically correct function and it will likely be a different function for every kind of stimulus you can get, for fatigue etc. but then again I am also sure those simple adjustments make TSS a sensible metric unlike the original which can easily be ballooned by doing one 5 minutes interval every ride and then filling the rest with free-wheeling or riding at 50 Watts.
Gerald, the point is that if you have a very rigid schedule, for example when riding a trainer or running close to your house then yeah, it’s easy to eyeball your training load and then just do a bit more (longer and/or stronger) in small increments.
The problems start when you don’t have rigid schedule, for example when you ride a bike outside in a nice area and do a lot of 2-5 hours rides. Then it’s useful to measure load somehow and a TSS-like metric would be very helpful.
The problem with TSS is that it completely fails in the case of this flexible/ever changin schedule and only works in a rigid schedule case where, as you noted, it’s not needed in the first place.