5D Library › Ketone Metabolism, β-Hydroxybutyrate Signalling and the Bioenergetics of Intermittent Fasting · 中文
Chapter 8 Practice and a Pre-registered Trial
Note
One more reminder. The checklist below is only for adults without any of the conditions listed at the start of this book who have confirmed with their doctor that changing their meal timing is safe for them. It is a tool for recording and observing, not a treatment plan; it sets no weight target, keeps the interval without food to 16 hours at most, and involves no supplement or ketone product.
Part 1 A four-step daily checklist for personal metabolic flexibility
- Overnight fasting window. Record the hours from the last food of one day to the first food of the next. Within the scope of this book it does not exceed 16 hours. (Chapter 1)
- Morning glucose and ketones, and their ratio. If you already use a fingertip glucose meter and ketone meter for other reasons (for example on medical advice), you may record morning readings and compute the glucose–ketone index (GKI, glucose in mmol/L divided by BHB in mmol/L). There is no need to buy devices for this checklist. (Chapters 1 and 3)
- Electrolyte and fluid signals. Record any dizziness on standing, palpitations, headache or muscle cramps, and roughly how much you drink. If these signals appear, stop and consult a doctor rather than self-supplementing. (Chapter 6)
- Exercise recovery. Record morning resting heart rate, perceived fatigue (for example 0–10) and how your usual exercise felt. (Chapters 5 and 6)
Calculation
Step 2 applied to a fictional week of records, and how unstable the GKI is when ketones are low.
# Step 2 of the daily checklist: the glucose-ketone index, GKI = glucose (mmol/L) / BHB (mmol/L)
# (Meidenbauer et al. 2015). Glucose from a meter in mg/dL is divided by 18.016 to give mmol/L.
# A week of (fictional) fingertip readings on waking, after the previous evening's last meal:
log = [("Mon", 92, 0.2, 12.0), ("Tue", 88, 0.2, 13.0), ("Wed", 95, 0.2, 11.0), ("Thu", 86, 0.4, 15.5),
("Fri", 90, 0.5, 14.0), ("Sat", 98, 0.1, 10.5), ("Sun", 84, 0.3, 16.0)]
print("day glucose mg/dL mmol/L BHB mmol/L GKI overnight fast h")
for day, g, b, fast in log:
gm = g / 18.016
print(f"{day} {g:13d} {gm:6.2f} {b:10.1f} {gm / b:5.1f} {fast:5.1f}")
# The index is dominated by the denominator when BHB is low. Typical capillary BHB meters read in
# steps of 0.1 mmol/L, so a single step changes the GKI a lot at the low end:
g = 90 / 18.016
for b in (0.1, 0.2, 0.3, 1.0, 1.1):
print(f"BHB {b:.1f} mmol/L -> GKI {g / b:5.1f}")
pairs = sorted((fast, b) for _, _, b, fast in log)
n = len(pairs); mx = sum(p[0] for p in pairs) / n; my = sum(p[1] for p in pairs) / n
r = (sum((x - mx) * (y - my) for x, y in pairs) /
(sum((x - mx) ** 2 for x, _ in pairs) * sum((y - my) ** 2 for _, y in pairs)) ** 0.5)
print(f"correlation of overnight fast length with morning BHB this week: r = {r:.2f} (n = 7, descriptive only)")
# day glucose mg/dL mmol/L BHB mmol/L GKI overnight fast h
# Mon 92 5.11 0.2 25.5 12.0
# Tue 88 4.88 0.2 24.4 13.0
# Wed 95 5.27 0.2 26.4 11.0
# Thu 86 4.77 0.4 11.9 15.5
# Fri 90 5.00 0.5 10.0 14.0
# Sat 98 5.44 0.1 54.4 10.5
# Sun 84 4.66 0.3 15.5 16.0
# BHB 0.1 mmol/L -> GKI 50.0
# BHB 0.2 mmol/L -> GKI 25.0
# BHB 0.3 mmol/L -> GKI 16.7
# BHB 1.0 mmol/L -> GKI 5.0
# BHB 1.1 mmol/L -> GKI 4.5
# correlation of overnight fast length with morning BHB this week: r = 0.72 (n = 7, descriptive only)This fictional log shows two things. First, in ordinary people on waking, BHB is only 0.1–0.5 mmol/L and the GKI swings widely between about 10 and over 50. The middle lines of the program show why: common fingertip ketone meters read in steps of 0.1 mmol/L, so BHB moving from 0.1 to 0.2 halves the GKI from 50 to 25, while BHB moving from 1.0 to 1.1 changes it only from 5.0 to 4.5. At low ketone levels, the GKI mainly reflects the resolution of the meter, not metabolic state. Second, in this week, mornings after longer overnight fasts had higher ketones (correlation 0.72), but with only 7 data points this is description, not a conclusion.
Note
The GKI is not a health target. It was first proposed as a calculation tool for research on metabolic therapy for cancer (Meidenbauer et al. 2015); it has not been validated as a health indicator in the general population, and there is no “target value” for ordinary people. This book treats it only as a descriptive number, and points out how unstable it is when ketones are low.
Part 2 A pre-registered randomised crossover trial
Question
In adults with overweight, compared with eating the same food as three meals spread over a longer part of the day, does 16:8 early time-restricted eating with the same calories and protein (all eating done between 8:00 and 16:00) reduce day-to-day glucose variability measured by continuous glucose monitoring? And how does it change the daily curve of capillary blood BHB?
Why a crossover with provided meals
Chapter 5 showed that many effects of time-restricted eating cannot be separated from “eating less” when calories are not matched. This trial provides all meals, so the two schedules have exactly the same energy and nutrients and differ only in timing; and it uses a crossover design, so every participant experiences both schedules and serves as their own control, reducing the sample needed.
Design
| Element | Specification |
|---|---|
| Participants | Adults aged 25–60 with a body-mass index of 25.0–29.9; excluded: diabetes (including glycated haemoglobin at the diagnostic threshold), any glucose-lowering drug or SGLT2 inhibitor, pregnancy or breastfeeding, a history or positive screen for eating disorders, liver or kidney disease, heart-rhythm disorders, shift work, and the other conditions listed at the start of this book; not recruited from readers or customers of the author’s websites |
| Diet | All meals provided by a research kitchen; daily energy set at each person’s estimated maintenance needs (weight loss is not the aim); protein about 25 % of energy; the two schedules use identical food and differ only in timing |
| Early time-restricted eating | Breakfast 8:00, lunch 11:30, last meal starting 15:30 and finished by 16:00; from 16:00 to 8:00 the next morning only water or energy-free drinks |
| Three-meal control | The same food eaten at 8:00, 13:00 and 19:00, an overnight fast of about 13 hours |
| Periods | Two periods of 3 weeks each in random order, separated by a 2-week washout on the usual diet |
| Primary outcome | Mean MAGE (mean amplitude of glycaemic excursions, from continuous glucose monitoring) over days 8–21 of each period, computed by an algorithm fixed in advance (Service et al. 1970) |
| Secondary outcomes | Area under the daily curve of capillary BHB measured at 7, 10, 13, 16, 19 and 22 h (two days per period); mean glucose, coefficient of variation and time in range from continuous monitoring (Battelino et al. 2019); hunger ratings; sleep duration; adverse events |
| Blinding | Participants and kitchen staff cannot be blinded; glucose-monitoring data are processed by analysts unaware of the period assignment, with analysis code fixed before unblinding |
| Analysis | Linear mixed model with fixed effects for schedule, period and sequence and a random effect for participant; primary outcome at two-sided ; carry-over tested |
Calculation
Computing outcomes from raw data: MAGE on a synthetic day of continuous glucose readings, and the area under the capillary BHB curve. All data are invented, only to show the method.
# Computing the trial's outcomes from raw data: MAGE from a continuous glucose monitor (CGM) trace
# and the area under the capillary BHB curve. The CGM day below is SYNTHETIC (5-minute readings).
# MAGE (Service et al. 1970): the mean height of glucose excursions (here nadir-to-peak rises; one
# direction is counted), counting only
# excursions larger than one standard deviation of that day's readings. Software implementations
# differ in detail (smoothing, which direction is counted), so the trial will fix one in advance.
import math, statistics
def cgm_day(meals, base=5.0, rise=2.6, seed=3):
"""Synthetic glucose (mmol/L): each meal adds a gamma-shaped rise peaking ~45 min later."""
import random
rng = random.Random(seed); out = []
for i in range(288):
t = i * 5 / 60
g = base + 0.25 * math.sin(2 * math.pi * (t - 4) / 24)
for m in meals:
x = t - m
if x > 0: g += rise * (x / 0.75) * math.exp(1 - x / 0.75)
out.append(g + rng.gauss(0, 0.12))
return out
def mage(g):
sm = [statistics.mean(g[max(0, i - 2):i + 3]) for i in range(len(g))] # light smoothing
sd = statistics.pstdev(g)
turns = [sm[0]]
for i in range(1, len(sm) - 1):
if (sm[i] - sm[i - 1]) * (sm[i + 1] - sm[i]) < 0: turns.append(sm[i])
turns.append(sm[-1])
def compress(t): # keep only alternating peaks and nadirs
out = [t[0]]
for x in t[1:]:
if len(out) >= 2 and (out[-1] - out[-2]) * (x - out[-1]) >= 0: out[-1] = x
else: out.append(x)
return out
turns = compress(turns)
while len(turns) > 2: # drop swings smaller than 1 SD, then re-compress
small = [i for i in range(len(turns) - 1) if abs(turns[i + 1] - turns[i]) < sd]
if not small: break
i = small[0]
del turns[max(1, min(i, len(turns) - 3)):max(1, min(i, len(turns) - 3)) + 2]
turns = compress(turns)
swings = [turns[i + 1] - turns[i] for i in range(len(turns) - 1)]
ups = [s for s in swings if s > sd]
return (statistics.mean(ups) if ups else 0.0), sd
def auc(times_h, values):
return sum((times_h[i + 1] - times_h[i]) * (values[i] + values[i + 1]) / 2 for i in range(len(values) - 1))
for name, meals, rise in (("three meals 08, 13, 19 h", (8, 13, 19), 2.6), ("early TRE 08, 11.5, 15.5 h", (8, 11.5, 15.5), 2.6)):
m, sd = mage(cgm_day(meals, rise=rise))
print(f"{name:27s}: day SD {sd:.2f} mmol/L, MAGE {m:.2f} mmol/L")
# Capillary BHB measured at 07, 10, 13, 16, 19, 22 h (fictional values, mmol/L)
times = [7, 10, 13, 16, 19, 22]
for name, bhb in (("three meals", [0.2, 0.1, 0.1, 0.1, 0.1, 0.1]), ("early TRE", [0.3, 0.1, 0.1, 0.1, 0.2, 0.3])):
print(f"BHB area under the curve 07-22 h, {name:11s}: {auc(times, bhb):.2f} mmol/L x h")
# three meals 08, 13, 19 h : day SD 0.92 mmol/L, MAGE 2.99 mmol/L
# early TRE 08, 11.5, 15.5 h : day SD 1.00 mmol/L, MAGE 2.67 mmol/L
# BHB area under the curve 07-22 h, three meals: 1.65 mmol/L x h
# BHB area under the curve 07-22 h, early TRE : 2.40 mmol/L x hThe details of computing MAGE (whether to smooth, whether to count rising or falling excursions) differ between software packages, and the same data can give different values under different implementations, so the protocol must fix one algorithm and publish its code before the trial begins.
Sample size
Calculation
# Sample size for the pre-registered randomised crossover trial: early time-restricted eating
# (eTRE, all food 08:00-16:00) versus the same food spread over three meals (08:00, 13:00, 19:00),
# energy-matched with provided meals, two 3-week periods in random order, 2-week washout.
# Primary outcome: MAGE from continuous glucose monitoring, days 8-21 of each period.
# In a crossover the precision comes from the within-person difference: SD of the paired difference
# sigma_d. Effect expressed as d_z = delta / sigma_d. Normal approximation, two-sided alpha 0.05.
import math
from statistics import NormalDist
N = NormalDist()
def n_crossover(dz, alpha=0.05, power=0.90):
return math.ceil((N.inv_cdf(1 - alpha / 2) + N.inv_cdf(power)) ** 2 / dz ** 2) + 2 # +2: t correction
for delta, sd_diff in ((0.3, 0.8), (0.4, 0.8), (0.5, 0.8), (0.4, 1.0)):
dz = delta / sd_diff
print(f"difference {delta} mmol/L, SD of within-person difference {sd_diff}: d_z = {dz:.2f}"
f" -> {n_crossover(dz, power=0.8)} for 80 % power, {n_crossover(dz)} for 90 %")
n = n_crossover(0.4 / 0.8)
recruit = math.ceil(n / 0.80)
print(f"chosen: 0.4 mmol/L, SD 0.8, 90 % power -> {n} completers; allowing 20 % loss, recruit {recruit}")
print(f"(a parallel-group trial with between-person SD 1.0 would need about"
f" {math.ceil(2 * (N.inv_cdf(0.975) + N.inv_cdf(0.9)) ** 2 / 0.4 ** 2)} per arm)")
# difference 0.3 mmol/L, SD of within-person difference 0.8: d_z = 0.37 -> 58 for 80 % power, 77 for 90 %
# difference 0.4 mmol/L, SD of within-person difference 0.8: d_z = 0.50 -> 34 for 80 % power, 45 for 90 %
# difference 0.5 mmol/L, SD of within-person difference 0.8: d_z = 0.62 -> 23 for 80 % power, 29 for 90 %
# difference 0.4 mmol/L, SD of within-person difference 1.0: d_z = 0.40 -> 52 for 80 % power, 68 for 90 %
# chosen: 0.4 mmol/L, SD 0.8, 90 % power -> 45 completers; allowing 20 % loss, recruit 57
# (a parallel-group trial with between-person SD 1.0 would need about 132 per arm)With a smallest difference of interest of 0.4 mmol/L, a standard deviation of the within-person difference of 0.8 mmol/L and 90 % power, 45 people must complete both periods; allowing for 20 % loss, 57 are recruited. The standard deviation of the within-person difference is an assumption, to be checked in a 10-person pilot; if it is clearly larger than 0.8, the sample size will be recalculated before the main trial starts. For comparison, the same question in a parallel-group design would need about 132 per arm.
Decision rule
Calculation
# Decision rule for the crossover trial, fixed before any data exist.
# d = eTRE minus three-meal MAGE (mmol/L), from a mixed model with period and sequence terms,
# with its 95 % CI. Negative = smaller glucose excursions with eTRE.
SESOI = 0.4
def verdict(d, lo, hi, carryover_p):
if hi <= -SESOI: v = "eTRE lowers MAGE by at least the smallest worthwhile amount"
elif hi < 0: v = "eTRE lowers MAGE; size not shown to reach 0.4 mmol/L"
elif lo > 0: v = "eTRE RAISES MAGE"
elif lo >= -SESOI and hi <= SESOI: v = "no difference worth acting on"
else: v = "unclear"
flag = "; carry-over test p < 0.10: report first-period data as a sensitivity analysis" if carryover_p < 0.10 else ""
return f"MAGE difference {d:+.2f} ({lo:+.2f} to {hi:+.2f}) mmol/L: {v}{flag}"
# Invented results, to show in advance how each pattern will be reported:
for r in ((-0.62, -0.88, -0.41, 0.50), (-0.20, -0.45, 0.05, 0.30), (0.05, -0.18, 0.28, 0.04)):
print(verdict(*r))
print("Secondary outcomes (capillary BHB area under the curve, mean glucose, time in range, hunger,")
print("sleep) are reported with intervals; none of them can make the trial positive.")
# MAGE difference -0.62 (-0.88 to -0.41) mmol/L: eTRE lowers MAGE by at least the smallest worthwhile amount
# MAGE difference -0.20 (-0.45 to +0.05) mmol/L: unclear
# MAGE difference +0.05 (-0.18 to +0.28) mmol/L: no difference worth acting on; carry-over test p < 0.10: report first-period data as a sensitivity analysis
# Secondary outcomes (capillary BHB area under the curve, mean glucose, time in range, hunger,
# sleep) are reported with intervals; none of them can make the trial positive.The example results are invented. Only when the upper limit of the confidence interval for the MAGE difference lies below −0.4 mmol/L will the report say “early time-restricted eating lowered MAGE by at least the smallest worthwhile amount”; if the carry-over test suggests an effect of the first period lingering into the second, the report will also give a sensitivity analysis using first-period data only.
What this trial cannot show
First, the participants are adults with overweight but without diabetes; the results do not extend to people with diabetes, people on glucose-lowering drugs or people of normal weight. Second, meals are provided and energy is set at maintenance; this secures internal validity but differs from free living, so even a positive result would not show that self-organised time-restricted eating has the same effect. Third, MAGE is a measure of glucose variability; reducing it is not in itself an improvement in health outcomes. Fourth, each period lasts only 3 weeks, which says nothing about long-term effects. Fifth, the area under the ketone curve reflects how meal timing affects ketone production; it says nothing about any “autophagy” or “anti-ageing” effect.
Ethics and conflicts of interest
The trial requires approval from an independent ethics committee and written informed consent, and the protocol and analysis plan are to be registered before the first participant is enrolled (Nosek et al. 2018). A study physician reviews adverse events weekly; participants with symptoms of hypoglycaemia, fainting, palpitations or other discomfort may withdraw at any time and are assessed by the study physician.
Disclosure
The author runs two websites on ketogenic metabolism and NAD+, ketohackers.com and nadplusnadplus.com, and therefore has a direct commercial interest in the subject of this book. The book does not link to these sites and neither mentions nor recommends any product, supplement, testing device or course; the Chapter 8 trial is designed to be run and analysed by researchers independent of the author’s business; all the code and the study protocol are published openly for anyone to check. To limit the influence of this interest: participants are not recruited from readers or customers of the author’s websites; the meal plans and analysis code are published before enrolment; and the results, data and code will be published whatever they show.
References
Fan, Y. (2026). Ketone Metabolism, β-Hydroxybutyrate Signalling and the Bioenergetics of Intermittent Fasting: From the Randle Cycle and Epigenetic Inhibition to Autophagy Kinetics, Read Beside Classical Chinese Fasting Texts [酮体代谢、β-羟丁酸信号转导与间歇性禁食的生物能量学] (Version 1.0.0). 5D Library. https://doi.org/10.5281/zenodo.23753263 · Licensed under Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0).