More Bolus, Less Basal: What Happens When oref Loops Run More Frequently

One-minute sensors are ordinary now, and the assumption that comes with them is that a loop fed faster data will do a better job. I have spent a while testing that. What changes most when you run a loop faster is not how much insulin it asks for but what form it arrives in: far more of it as microboluses, far less as basal, with the basal cut to pay for most of the difference. The total does go up as well, by rather less than the bolus numbers suggest, and how much is shaped by two settings that are rarely considered together. The speed of the data barely comes into it.

That distinction matters, and not only for bookkeeping. A bolus that has gone in cannot be recalled. A basal you have turned down can be turned back up.

How the arms were run

The problem with testing this normally is that you cannot wear the same sensor twice. Compare a one-minute setup against a five-minute one and you have changed the sensor, the site, the calibration and the day, and any difference could be any of those.

So I put three instances of the same app on one phone, all reading one Libre 3+ that reports every minute. All three take a virtual pump, so they compute and record doses without delivering any. They differ only in how often they are allowed to decide and how closely spaced their automated boluses may be. I will write that as decisions by interval, so 5×5 means deciding every five minutes with a five-minute minimum between boluses, and 1×1 means deciding every minute with a one-minute minimum.

Alongside that, for the first run only, a second phone carried my actual therapy on a Dexcom G7 reporting every five minutes. That is the one attached to the pump, and it is the loop that gave me all the insulin I actually received throughout. It is a reference point rather than a comparison, since it differs from the other three in sensor, site, phone and pump at once, and nothing in what follows rests on it.

The three on the one phone see the same glucose value at the same instant. Over the whole experiment they agreed at 36,324 of 36,324 matched timestamps. That is a check that the inputs really were identical, not 36,324 independent pieces of evidence; the comparisons below rest on 11 and 14 days. So when they disagree about insulin, it is the software disagreeing with itself, and the person, the meal and the day have all cancelled out.

They ran eleven days on Boost, then fourteen days with the dosing engine swapped for stock OpenAPSSMB, which is the oref1 algorithm most AndroidAPS users are running. Both are from the same family: Boost is a fork of that line and the two carry the same bolus-interval gate, with different logic in between. They do not share a dose ceiling, though. Boost has a bolus cap of its own, separate from the minutes-of-basal setting, and seven of its eight dosing tiers bound to that instead, which allows considerably bigger single doses. So everything below is about oref-derived loops, and I would not assume any of it carries across to a commercial system or to Loop, which size doses differently. For that second run it is just the one phone and the one sensor: my own therapy stayed on Boost and is not part of it.

What happened

Insulin asked for a day, by arm, split into automated boluses and enacted basal, for each engine and each setting of the maximum bolus size
Same person, same sensor, same glucose. The only thing that differs between the bars in each panel is how often the software was allowed to decide and to dose. These three ran on a virtual pump, so the bars are what each asked the virtual pump to deliver. The coloured part is boluses and the grey part is the basal the arm enacted, which is why the bolus ratio and the total ratio are such different numbers.

Every instance that was allowed to dose more often asked for more insulin. Under Boost, going from a five-minute interval to three raised it by 16 per cent and going to one minute by 32. Under stock OpenAPSSMB the same change gave between 36 and 183 per cent more, depending on a setting I will come to.

Worth being clear about that word. These three were on a virtual pump, so what went up is what the software asked for, not what went into anybody. I come back to why that distinction does real work at the end.

Those percentages are boluses. An oref loop also takes basal away, and counting that changes every one of them, which is what the section on withheld basal below does.

The pre-registration, written before any of this ran, said the arms would differ in the granularity and the timing of delivery and not in the total. That was my expectation and it was wrong.

The comparison that isolates one cause is between the two one-minute arms, because they decide at the same rate and differ only in how closely spaced their boluses may be. That gave 14 per cent more insulin in Boost and between 21 and 58 per cent more in the stock engine. So the minimum interval between automated boluses is doing real work on its own.

What I cannot tell you from these three is how much of the rest is the decision rate. Going from the five-minute arm to the three-minute one changes both things at once, the loop decides five times as often and the boluses may fall three times as close together, and nothing here separates them. The arm that would, deciding every minute but held to a five-minute interval, is not one I ran on the shared sensor. It is running now on my own pump, and it goes in the next piece.

Maximum bolus size

Halfway through the second experiment I raised the maximum size of a single automated bolus, from twenty minutes’ worth of basal to forty-five for the ordinary SMB path and sixty for the unannounced meal path. I did it because I had been watching the first five days and had formed a view about what was causing the extra insulin: that the low cap was itself blocking the bigger boluses the slower arm wanted to give, and so flattering the fast arm by comparison. Raising it was a test of that.

Under the tighter cap, running at one minute gave 2.83 times the insulin of the five-minute arm. After I raised it, the same comparison gave 1.65. Most of the gap closed, on the strength of a number that has nothing to do with cadence and is not described anywhere as a rate limit.

I should be straight about the weakness in that, because it is the thing a reviewer went for hardest and they were right to. I changed the setting because I had seen a result and formed a theory about it. That is the worst way to run an experiment: if those five days happened to be an unusual run, the lower figure afterwards could be the run reverting rather than the cap doing anything. And the ratio was in fact already drifting down across those five days, from 2.92 to 2.32.

What makes me think it was the cap is the shape. The last day before the change is 2.32 and the first day after is 1.88, a fall of 0.44 in one day against about 0.15 a day over the preceding four, so the biggest single jump in the whole series sits exactly on the boundary. Then it stops: the eight days that follow sit flat at about 1.68 with no trend at all. And the two sets of daily numbers do not overlap anywhere. That is more like something happening at the boundary than a slide continuing, but it is not proof, and I would not have designed it this way.

The effect factored into how often a bolus is given and how large each one is
Every row is one contrast. The blue bar is how much more often a bolus was given, the orange bar is how large each one was, and the two multiply to the figure on the right.

The reason is visible once you split the effect into its two parts. Running faster does two things: it gives more opportunities to dose, and it changes how big each dose is. The first is almost the same everywhere, because all the arms take up their permission to dose in much the same way. Everything that differs between the rows is in the second.

Under the tight cap the three arms gave almost identical boluses, 0.171, 0.165 and 0.150 units, because the ceiling was cutting all of them off. And when the ceiling binds on every arm, nothing is left to damp the effect: the fast arm gets three times the opportunities and delivers nearly three times the insulin. Raise the cap and the slow arm’s dose grows by two thirds while the fast arm’s grows by less than a tenth, because the fast arm has already drawn the outstanding requirement down and rarely reaches any ceiling at all. The damping comes back, and the gap narrows.

So the two settings are doing one job between them. The bolus interval sets how many chances the loop can have. The maximum bolus size sets how much of each one can get through. Neither is documented as a rate limit, and between them that is the job they are doing.

Basal the arms withheld

Those figures count boluses, and a bolus is half of what an oref loop controls. It also switches the basal off, and it decides both things on the same cycle. A loop asked every minute is therefore asked every minute whether to suspend, so some of that extra bolus insulin may be paid for out of the basal rather than added on top of it.

To check that I needed the basal profile the instances were working from, and it is not written into the record. It can be recovered from it. Whenever oref pushes the basal above the profile it announces both the rate it is setting and the requirement behind it, and on that path the rate is the profile plus twice the requirement, so every one of those decisions hands back one reading of the profile in force at that hour. A fortnight of them gives a profile that agrees with itself to the second decimal place in most hours of the day, and it came to just under 16 units a day.

Agreeing with itself is not the same as being right, so I checked it against the profile my pump was actually running, which is in my own records. It reproduces it exactly on 18 to 22 hours of the 24, depending on the period, and the daily total comes out 1 to 3 per cent low. The hours that differ are overnight, and I have not worked out why. It turns out not to matter: rerunning the whole calculation on the real profile instead of the reconstructed one changes every number below by nothing at all, to three decimal places. The profile is applied to all three arms equally and only in the small fraction of minutes where no temporary rate was running, so it cancels out.

With that, the basal each arm enacted can be added up minute by minute and put next to its boluses. Enacted, not delivered: these arms are on virtual pumps, so this is the basal each would have run. Under the stock engine with the tight cap:

stock oref, tight capfive-minute armthree-minute armone-minute arm
boluses11.8 U21.1 U33.3 U
basal the arm ran15.3 U8.4 U3.9 U
total27.1 U29.5 U37.2 U
share taken as boluses44%72%90%

The scheduled basal was 15.7 units a day. The five-minute arm ran almost exactly that, withholding 0.4 of it. The virtual one-minute arm withheld 11.8 and spent the fortnight enacting basal at about a fifth of the scheduled profile.

Put the two channels together and the headline shrinks a long way. The one-minute arm’s 2.8 times as much bolus insulin becomes 1.37 times as much insulin in total. Boost’s 1.32 becomes 1.09, and its three-minute arm, 16 per cent up on boluses, comes out at 1.02 with a range that includes no difference at all. The offset is easy to check from the table: 21.5 units more bolus, 11.4 units less basal, so 53 per cent of the extra was paid for by the basal. Across all six comparisons that figure runs from 41 to 79 per cent, lowest where the extra bolus insulin is largest.

That is the cap doing its job rather than anything going wrong. maxSMBBasalMinutes is a number of minutes of basal, and that path hands you a bolus now and then reduces the basal below the scheduled profile so the same insulin is not counted twice. A loop asked every minute takes that option every minute. Worth being careful with the framing: scheduled basal is not insulin you were definitely going to receive, because an AID system recalculates it every cycle anyway. What the data show is that SMB delivery is offset by later basal running below profile.

What is left over is still real. In five of the six comparisons the faster arm had a higher total insulin estimate, by 9 to 37 per cent, with the day-level interval above one; in the sixth it spans one and is unproven. The extra is roughly a third of what counting boluses alone would have told you.

Moving insulin from the basal channel to the bolus channel is not a free operation either, even where the total is unchanged. A bolus that has gone in cannot be recalled, and a basal that has been turned down can be turned back up. Those two behave differently if glucose turns after the dose rather than before it.

Why the engines differ

Boost was less affected than the stock engine at every cadence, and the reason is the same mechanism again.

Stock OpenAPSSMB sizes an automated bolus as half the outstanding requirement, capped at a number of minutes’ worth of basal. Nothing in that expression refers to how long it has been since the last dose, which is why asking it more often gets you more. Boost bounds its doses somewhere else entirely. Its own bolus cap governs seven of its eight dosing tiers, and inside its meal states there are further per-cycle caps below that, written in units rather than as a share of anything. Those are worked out per person rather than being fixed. The code’s defaults are one unit for the commit shot and a quarter of a unit for each holding dose, these three instances were running 4.5 and 2.19, and across everyone on it the commit cap runs from 2 to 6 units. A cap in units bounds what a single cycle can give however large the computed requirement, where a share of that requirement does not.

Which is why Boost sits at 0.42 in that orange column while the stock engine sits between 0.58 and 0.97 depending on where the operator has put a number. Both engines have numbers you can move, in other words. What differs is that one bounds a dose in units and the other bounds it as a share of a requirement. One thing to be clear about: the minutes-of-basal ceiling was configured during the Boost fortnight too, but it is not what was bounding Boost, whose doses reach 4.5 U against a basal-derived value of 0.30. So the cap comparison in this piece is between the two oref periods, and the Boost numbers are not a third setting of it.

When the extra insulin arrives

That is the obvious alternative and it is worth testing, because if the whole thing were a head start the story would be about timing rather than about settings. A one-minute loop should start dosing into a rise sooner than a five-minute one, and it should also stop sooner when glucose turns. Since all three instances read the same glucose at the same instant, a rise is the same event for all of them and I can just look. A rise here means glucose up by at least 15 mg/dL over a quarter of an hour, a fall the same downwards, with onsets kept at least an hour apart so the windows never overlap. “Still speeding up” means the last quarter hour moved further than the quarter hour before it. All of that is measured on the raw shared readings rather than on anything the algorithm computes.

The stopping half happens almost entirely through the basal, as the section on withheld basal set out. Boluses barely feature in it: insulin handed out while glucose was falling comes to 0.33 units a day on the five-minute arm and 0.28 on the one-minute arm, out of daily totals of 18.8 and 36.0, one to two per cent either way.

Timing it from the start of a fall gets you nowhere, because by then the fast arm is usually already suspended: 98 per cent of the time, against 91 for the five-minute arm. But every switch to zero is in the record with a timestamp, so you can just ask when they happen and what glucose was doing.

The one-minute arm switches basal off 53 times a day against the five-minute arm’s 32, and it does it in a completely different situation. The five-minute arm turns basal off when glucose is flat or turning over, a median of 1 mg/dL down over the previous quarter hour, and a third of the time it is already falling. The one-minute arm turns it off while glucose is still climbing at 5 mg/dL a quarter hour, and still speeding up.

Which is a strange thing to do if you are predicting a low. Nearly three quarters of the one-minute arm’s suspensions start within five minutes of one of its own boluses, against a quarter of the five-minute arm’s, and oref turns the basal down when it microboluses so you do not get the same insulin twice. Sitting within five minutes of a bolus does not prove each suspension was caused by it. But the pattern is far more consistent with basal being cut alongside frequent SMB delivery than with the fast arm spotting a fall earlier, which is the same reallocation as before seen from the other end.

The starting half is real but small: the one-minute arm reaches its first bolus about two minutes sooner after a rise begins.

But a two-minute head start is not enough to explain the effect, and what it hides is what happens inside those opening minutes. In the first five minutes the five-minute arm gives 0.65 boluses per rise and the one-minute arm gives 2.39. It is not arriving earlier so much as arriving repeatedly, and the extra insulin is heavily front-loaded because of it: 46 per cent of the hour’s excess lands in the first ten minutes, which are a sixth of the hour.

It does not stop there either. The one-minute arm is still giving 1.8 times as much between forty and sixty minutes, long after any head start is spent.

So a faster loop is not simply getting there first, and the excess is not spread evenly either. It doses several times into the opening of a rise where a slower loop doses once, and it carries on doing so for an hour. Whether you call that timing or frequency is a matter of words: a loop asked every minute is redistributing insulin in time by construction. What it is not is simply a two-minute head start.

Settings worth checking

If you are running a one-minute sensor and letting your loop decide every minute, the minimum interval between automated boluses clearly matters and is doing more work than you probably think. How much of the rest belongs to the decision rate itself, these arms cannot say, for the reason given earlier: the arm that would settle it is the one now running on my own pump. On this evidence, going from five minutes to one is worth between a third and nearly three times as many bolus units, depending on your engine and your bolus cap, and between 9 and 37 per cent more insulin in total once the basal it suspends is counted against it.

If you are running stock oref, look at maxSMBBasalMinutes and maxUAMSMBBasalMinutes together with the interval, because the pair of them strongly shapes the outcome and most people set them independently for unrelated reasons. On this evidence a tight cap makes a fast loop deliver more, because it removes the thing that was damping the extra opportunities.

And if you are thinking about moving to one-minute decisions, the faster feed appears to buy relatively little additional independent glucose information. That is a separate piece of work, and the answer is that interstitial glucose carries almost nothing at periods shorter than about half an hour, which Breton, Shields and Kovatchev established in 2008 and which I have since reproduced. What a faster cycle buys is a couple of minutes less waiting before the loop can act, which is real, and is a gain in scheduling.

What this does not tell you

These three instances were on a virtual pump. They computed doses and recorded them and delivered nothing, so what I have measured is what a dosing rule asks for when it is asked more often, which is a different thing from what happens to a person.

It is worth spelling out where that gap sits. Each instance’s own recorded insulin feeds its own insulin on board, which restrains its next decision. What it cannot do is reach me, so it cannot move my glucose, so the trace it reads on the next cycle is whatever my real loop produced and is unchanged by anything it decided. Half the loop is there and half is missing, and the missing half is the one that would normally pull an over-delivering arm back. When I ran the same comparison on my own therapy, with the insulin actually going in, the one-minute against three-minute contrast came out at 1.46 against the 1.14 the instances gave. In that single comparison the contrast was larger rather than smaller. It also differs in sensor, site, pump, handset and physiology at once, so why it was larger is unresolved, and it is the next piece of work. A second article and paper with the in-vivo testing will be coming soon.

This is also one person, who is me, and I wrote the software under test. The parallel instances take the person and the day out of the comparisons that carry the result, and nothing takes me out of the choice of what to run. Nothing here says any of these configurations is better or worse for anybody’s glucose. All of it is about how much insulin the algorithms ask for.

The full preprint, with the arms, the intervals and the pre-registrations, is at https://doi.org/10.5281/zenodo.22790736. The code that regenerates every figure is in the Boost repository, and so are the per-cycle and per-bolus records behind it, with the clock shifted so the calendar is gone and every interval survives, so anybody can check the arithmetic without my database.


Discover more from Diabettech - Diabetes and Technology

Subscribe to get the latest posts sent to your email.

Be the first to comment

Leave a Reply

Your email address will not be published.


*