Repository navigation
Guard + Runway, second version; slow retrospective correction experiment (off by default) - #16
Merged
Merged
Conversation
… slow retrospective correction experiment guardAndRunway: the volatility band now lowers only the forecast the low guard checks (a banded point below the suspend threshold suspends; the banded minimum is the guard's minimum). The correction is sized, and the forecast shown, from the unbanded forecast. The runway reserve fades out linearly from no carbs on board to 20 g, instead of closing at any carbs. slowRetrospectiveCorrection (new, off by default): ISF x (1 - 0.05 x level), within 0.7-1.3, where level is the 24 h EWMA of the unexplained glucose change (insulin counteraction less carb effect, per 5 min, at the scheduled ISF) over the glucose history passed in, up to 72 h. Stateless: it needs 72 h of glucose, carbs from 72 h plus the longest absorption time, and doses from 72 h plus the insulin activity duration.
…full carb history requirements
…ead of crashing run() now checks that the carb ratio and ISF timelines start at or before the oldest carb entry, before any forecast is built. Previously CarbMath hit preconditionFailure. The slow retrospective correction experiment's 72 h carb history makes this case easier to reach.
This was referenced Nov 1, 2026
ps2
added a commit
to LoopKit/Loop
that referenced
this pull request
Nov 2, 2026
…uard (#2643) Slow retrospective correction (LoopKit/LoopAlgorithm#16) becomes an algorithm experiment. When it is on, Loop reads 72 hours of glucose, carbs from 72 hours plus the longest absorption time, and doses from 72 hours plus the insulin activity duration, with schedule history covering them, since the experiment keeps no state. Its level and ISF multiplier are recorded on the dosing decision, and the bolus screen and forecast details forecasts use the multiplier so they match the algorithm's. Guard + Runway is labeled v2, its description says what changed, and its recorded parameters carry version 2. The forecast details screen draws the forecast the low guard checks as a dotted line while Guard + Runway is selected, and no longer lowers the comparison forecast by the band, since the second version no longer lowers the displayed forecast.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
guardAndRunway(changed)predictedGlucose. The displayed forecast no longer carries the band's dip and taper.GuardAndRunwayOutput.guarded(_:)still gives the guard's view.In LoopEval's generator (166 people × 2 trainings) the change is neutral against the current version: TIR +0.04, time below 70 +0.02, time below 54 +0.01.
slowRetrospectiveCorrection(new)A day-scale estimate of how much more or less insulin the person needs than their settings say.
1 − 0.05 × level, kept within 0.7–1.3.AlgorithmOutput.slowRetrospectiveCorrectionreports the level and the multiplier.In the generator, on top of this PR's
guardAndRunway, it gives TIR +1.5, time below 70 +0.23 and time below 54 +0.08. That is +0.46 TIR [+0.13, +0.74] more than raising insulin needs reaches at the same time below 70. In a four-day replay of one person running Guard + Runway, it gave TIR +6 at the same insulin and no time below 70.Implementation notes
History. The experiment keeps no state; it is recomputed from the inputs on every run, so it needs a long history:
With 12 h of history the level reaches only about 40 % of its working value.
Carbs for the whole history. A meal whose entry is dropped while its absorption is still inside the glucose history reads as unexplained rise and pushes the level up. In a replay that moved the multiplier by about 0.04 for a day.
Timeline coverage. The carb ratio and ISF timelines must start at or before the oldest carb entry.
runnow checks this and fails with the newAlgorithmError.carbRatioOrSensitivityStartsAfterCarbEntry; before,CarbStatusconstruction hitpreconditionFailure. The check applies with or without experiments, and Loop should handle the new case.Cost. Two forecasts per run when the multiplier is not 1, each over the full history: 23 ms median, 207 ms worst, on a Mac (release build).
Agreement with LoopEval. Each cycle of a four-day closed-loop replay was run through this package: multiplier difference median 0.0007, 98.5 % of doses identical, worst difference 0.05 U.