mirror of
https://github.com/ZmnSCPxj/clboss.git
synced 2026-08-13 12:33:20 +02:00
contrib: clboss-xrebalance-survival splits curves by regime sample count
Both P(changed|...) curves -- the absolute-gap cap curve and the gap/span frac curve -- now break each bucket's contradiction rate into nN sub-columns: the rate among regimes backed by 2, 3-5, and 6+ observations (n2 / n3-5 / n6+). The horizon (min(cap, frac*span)) extrapolates from a regime's span no matter how many points define it, gated only by min-samples=2. So a flat headline rate can hide thin two-observation regimes -- the ones a longer frac or cap trusts the most -- misbehaving. The sub-columns surface that before lengthening either knob. A trailing ~ marks a sub-rate with fewer than 30 trials. Adds nrec (regime record count) to each replayed trial and a sample_bin helper; the curve aggregator now tracks per-bucket sub-bin trials and contradictions. Other tables are unchanged.
This commit is contained in:
parent
b90d366b8e
commit
fb226dd419
1 changed files with 45 additions and 8 deletions
|
|
@ -28,6 +28,13 @@ Outputs:
|
|||
4. P(changed | gap/span) -- tests the frac*span rule itself: if
|
||||
this curve is cleaner than (3), frac is the knob that matters;
|
||||
if (3) dominates, the cap is.
|
||||
Both (3) and (4) split each bucket's rate into nN sub-columns:
|
||||
the contradiction rate among regimes backed by N observations
|
||||
(n2 / n3-5 / n6+). The horizon extrapolates from span no matter
|
||||
how many points define it, so a flat headline rate can still
|
||||
hide thin 2-observation regimes misbehaving -- the sub-columns
|
||||
expose that before you lengthen frac or the cap. ('~' marks a
|
||||
sub-rate with < 30 trials.)
|
||||
5. policy-fail walls vs liquidity walls (inbound-fee exclusions
|
||||
should survive far longer).
|
||||
6. visit-frequency terciles for the long-gap buckets (the tail is
|
||||
|
|
@ -103,6 +110,24 @@ REL_BUCKETS = [
|
|||
(float("inf"), ">8x"),
|
||||
]
|
||||
|
||||
# Sub-bins for the P(changed|...) curves: split each gap bucket's
|
||||
# rate by how many observations back the regime (and hence its span).
|
||||
# The horizon extrapolates from span regardless of point count, so a
|
||||
# flat headline rate can hide thin 2-observation regimes misbehaving.
|
||||
SAMPLE_BINS = [
|
||||
(2, "n2"),
|
||||
(5, "n3-5"),
|
||||
(INF, "n6+"),
|
||||
]
|
||||
SAMPLE_HDR = tuple(label for _, label in SAMPLE_BINS)
|
||||
|
||||
|
||||
def sample_bin(nrec):
|
||||
for limit, label in SAMPLE_BINS:
|
||||
if nrec <= limit:
|
||||
return label
|
||||
return SAMPLE_BINS[-1][1]
|
||||
|
||||
|
||||
def bucket_of(value, buckets):
|
||||
for limit, label in buckets:
|
||||
|
|
@ -191,6 +216,7 @@ def replay(rows, frac, cap, min_samples):
|
|||
yield {
|
||||
"gap": gap,
|
||||
"span": span,
|
||||
"nrec": reg["nfail"] + reg["nok"],
|
||||
"contradiction": contradiction,
|
||||
"side": "drain" if isf else "refill",
|
||||
"asserting": asserting,
|
||||
|
|
@ -314,22 +340,32 @@ def main():
|
|||
agg = {}
|
||||
for t in trial_list:
|
||||
b = keyfn(t)
|
||||
a = agg.setdefault(b, [0, 0, 0, 0])
|
||||
a[0] += 1
|
||||
a = agg.setdefault(b, {"tot": [0, 0, 0, 0], "smp": {}})
|
||||
a["tot"][0] += 1
|
||||
if t["contradiction"]:
|
||||
a[1] += 1
|
||||
a[2 if t["side"] == "refill" else 3] += 1
|
||||
a["tot"][1] += 1
|
||||
a["tot"][2 if t["side"] == "refill" else 3] += 1
|
||||
sb = a["smp"].setdefault(sample_bin(t["nrec"]), [0, 0])
|
||||
sb[0] += 1
|
||||
if t["contradiction"]:
|
||||
sb[1] += 1
|
||||
rows = []
|
||||
for limit, label in buckets:
|
||||
if label not in agg:
|
||||
continue
|
||||
n, ch, re, dr = agg[label]
|
||||
rows.append((label, n, ch, rate(ch, n), re, dr))
|
||||
n, ch, re, dr = agg[label]["tot"]
|
||||
smp = agg[label]["smp"]
|
||||
subs = []
|
||||
for _, sbl in SAMPLE_BINS:
|
||||
stot, sch = smp.get(sbl, [0, 0])
|
||||
subs.append(rate(sch, stot))
|
||||
rows.append((label, n, ch, rate(ch, n), *subs, re, dr))
|
||||
return rows
|
||||
|
||||
print(fmt_table(
|
||||
"P(changed | gap) [the cap-setting curve]",
|
||||
("gap", "trials", "changed", "rate", "refill", "drain"),
|
||||
("gap", "trials", "changed", "rate") + SAMPLE_HDR
|
||||
+ ("refill", "drain"),
|
||||
curve(curve_trials, ABS_BUCKETS,
|
||||
lambda t: bucket_of(t["gap"], ABS_BUCKETS))))
|
||||
|
||||
|
|
@ -339,7 +375,8 @@ def main():
|
|||
print(fmt_table(
|
||||
"P(changed | gap/span) [tests the frac*span rule;"
|
||||
" %d no-span trials excluded]" % nospan,
|
||||
("gap/span", "trials", "changed", "rate", "refill", "drain"),
|
||||
("gap/span", "trials", "changed", "rate") + SAMPLE_HDR
|
||||
+ ("refill", "drain"),
|
||||
curve(spanned, REL_BUCKETS,
|
||||
lambda t: bucket_of(t["gap"] / t["span"],
|
||||
REL_BUCKETS))))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue