Skip to content

aether_quant.cycle

The research cycle: generations sharing a book, the admission rule, decay, the forward record, the glide's calibration, pre-registered rounds and holdout cells.

The research cycle: generations sharing a book, the admission rule, decay, the forward record, the glide's calibration, pre-registered rounds and holdout cells.

AdmissionEvidence dataclass

What the admission rule (R-ADMIT1) reads about a generation: its selection, hold and edge passes, forward record, decay state and guard.

decay_state class-attribute instance-attribute

decay_state: str = 'healthy'

edge_pass class-attribute instance-attribute

edge_pass: bool = False

forward_alpha_t class-attribute instance-attribute

forward_alpha_t: float | None = None

forward_ok_sessions class-attribute instance-attribute

forward_ok_sessions: int = 0

guard_tripped class-attribute instance-attribute

guard_tripped: bool = False

hold_pass class-attribute instance-attribute

hold_pass: bool = False

holdouts_spent class-attribute instance-attribute

holdouts_spent: bool = False

mean_diff_vs_incumbent class-attribute instance-attribute

mean_diff_vs_incumbent: float | None = None

no_data_share class-attribute instance-attribute

no_data_share: float = 0.0

score class-attribute instance-attribute

score: float | None = None

selection_pass class-attribute instance-attribute

selection_pass: bool = False

Cell dataclass

One research cell: a universe side and a date window, holdout or free, that trials are scored on.

end instance-attribute

end: str

name instance-attribute

name: str

side instance-attribute

side: str

split class-attribute instance-attribute

split: str | None = None

start instance-attribute

start: str

universe class-attribute instance-attribute

universe: str = 'equity'

DecayConfig dataclass

Settings of the CUSUM decay monitor: the alarm threshold, the watch fraction and the minimum sessions before a verdict.

dead_multiple class-attribute instance-attribute

dead_multiple: float = 2.0

min_sessions class-attribute instance-attribute

min_sessions: int = 60

recover_sessions class-attribute instance-attribute

recover_sessions: int = 40

slack class-attribute instance-attribute

slack: float = 0.5

threshold class-attribute instance-attribute

threshold: float = 26.0

watch_fraction class-attribute instance-attribute

watch_fraction: float = 0.5

DecayReport dataclass

The decay monitor's state for one generation (healthy, watch, decaying), with its statistic and the sessions it saw.

ew_sharpe instance-attribute

ew_sharpe: float | None

reason instance-attribute

reason: str

sessions instance-attribute

sessions: int

state instance-attribute

state: str

statistic instance-attribute

statistic: float

Generation dataclass

One model generation in the registry: its kind, admission tier, lifecycle stage, definition and admission evidence.

admission class-attribute instance-attribute

admission: Mapping = field(default_factory=dict)

born instance-attribute

born: str

definition class-attribute instance-attribute

definition: Mapping = field(default_factory=dict)

expected_sharpe class-attribute instance-attribute

expected_sharpe: float = 0.0

freeze_path class-attribute instance-attribute

freeze_path: str | None = None

id instance-attribute

id: str

kind instance-attribute

kind: str

needs class-attribute instance-attribute

needs: str | None = None

note class-attribute instance-attribute

note: str = ''

procedure_sha256 instance-attribute

procedure_sha256: str

stage instance-attribute

stage: str

tier instance-attribute

tier: str

vintages class-attribute instance-attribute

vintages: tuple[str, ...] = ()

GlidePolicy dataclass

How capital moves between generations: the glide length, a newcomer's entry share, the retirement floor and the paper caps.

accelerate_on_decaying class-attribute instance-attribute

accelerate_on_decaying: float = 1.0

blend_every class-attribute instance-attribute

blend_every: int = 21

entry_share class-attribute instance-attribute

entry_share: float = 0.3

glide_sessions class-attribute instance-attribute

glide_sessions: int = 252

half_life_sessions class-attribute instance-attribute

half_life_sessions: int = 126

hold_on_watch class-attribute instance-attribute

hold_on_watch: bool = False

max_generations class-attribute instance-attribute

max_generations: int = 4

min_evidence_sessions class-attribute instance-attribute

min_evidence_sessions: int = 60

mode class-attribute instance-attribute

mode: str = 'ladder'

prior_sessions class-attribute instance-attribute

prior_sessions: float = 252.0

retire_share class-attribute instance-attribute

retire_share: float = 0.05

score_floor class-attribute instance-attribute

score_floor: float = 0.0

tier2_paper_cap class-attribute instance-attribute

tier2_paper_cap: float = 0.3

MissingInput

Bases: FileNotFoundError

A builder's input isn't on this host.

NoSessionToRecord

Bases: RuntimeError

The run found no session it may write (an override that is not a session, or an empty calendar). A scheduled run must fail loudly on this: a silent exit is how a record loses a session.

RoundSpec dataclass

A pre-registered research round: its name, cell, side, trials, rules file and the bar a trial must clear.

bar instance-attribute

bar: str

cell instance-attribute

cell: str

disclosures class-attribute instance-attribute

disclosures: tuple[str, ...] = ()

ledger instance-attribute

ledger: Path

min_ic_names class-attribute instance-attribute

min_ic_names: int = 20

min_live_names class-attribute instance-attribute

min_live_names: int = 150

name instance-attribute

name: str

no_ic_clause class-attribute instance-attribute

no_ic_clause: tuple[str, ...] = ()

out_dir instance-attribute

out_dir: Path

pbo_blocks class-attribute instance-attribute

pbo_blocks: int = 16

prior_columns class-attribute instance-attribute

prior_columns: tuple[str, ...] = ()

prior_daily class-attribute instance-attribute

prior_daily: tuple[str, ...] = ()

raw class-attribute instance-attribute

raw: Mapping = field(default_factory=dict)

rule instance-attribute

rule: str

side instance-attribute

side: str

track class-attribute instance-attribute

track: str = 'W'

trials instance-attribute

trials: Mapping[str, Mapping]

window_label class-attribute instance-attribute

window_label: str = 'v660_selection'

admitted_to_shadow

admitted_to_shadow(evidence: AdmissionEvidence) -> bool

Selection and the one holdout read; or, once the holdouts are spent, selection and a year of forward sessions.

allocation_row

allocation_row(generations: Mapping[str, Generation], shares_before: Mapping[str, float], states: Mapping[str, Mapping], caps: Mapping[str, float], rows_by_generation: Mapping[str, Mapping[str, float]], policy: GlidePolicy, *, decided_today: bool, sessions_since_blend: int, records: Mapping[str, Mapping] | None = None) -> dict[str, Any]

Today's shares, by the policy's mode, and a blended row when one is due. A row retargets every name, so it isn't written daily.

append_event

append_event(path: Path, *, event: str, session: str, candidate: str, payload: Mapping[str, Any], created_at: str) -> dict[str, Any]

Links a row to the chain. The session is in the hashed payload, so rewriting a date breaks it.

append_lifecycle

append_lifecycle(path: Path, *, event: str, payload: Mapping[str, Any], created_at: str) -> dict[str, Any]

A hash-chained line for each change of stage or vintage, so the record of how a generation reached the book can't be edited later without showing.

append_row

append_row(path: Path, *, session: str, candidate: str, payload: Mapping[str, Any], created_at: str) -> dict[str, Any]

Links a row to the chain and appends it. The row's own session is in the payload, so a rewrite of a date breaks the hash.

apply_gate

apply_gate(table: DataFrame, gate: str | None, cell: WideCell) -> pd.DataFrame

An optional gate on the finished table. regime: no signal while BTC is below its 120-session average.

assert_cell_open

assert_cell_open(cell_name: str, freeze_path: Path | None, freeze_digest: str | None) -> Cell

The gate itself. A later cell needs the digest of the freeze file, and that file must be the one on disk.

average_run_lengths

average_run_lengths(*, expected_sharpe: float, config: DecayConfig | None = None, paths: int = 2000, seed: int = 1, horizon: int = 2520, decayed_sharpe: float | None = None) -> dict[str, Any]

Simulated sessions to the first decaying alarm: with the alpha intact (a false alarm) and after it falls to decayed_sharpe, default zero. Paths that never alarm count at horizon.

blank_stale

blank_stale(known: DataFrame, closes: DataFrame, *, rows: int = STALE_ROWS) -> pd.DataFrame

known_closes carries the last price forward, so a name whose bars stopped would keep a signal forever. A cell with no bar over the last rows rows goes NaN. Looks backward only, and it never reads why the bars stopped.

blend_due

blend_due(*, decided_today: bool, sessions_since_blend: int, guard_tripped: bool, policy: GlidePolicy) -> bool

Whether to write a blended row. A row retargets every name and resets drift, so not daily: on a generation's decision day, every blend_every sessions, or on a guard trip.

blend_generation_rows

blend_generation_rows(rows_by_generation: Mapping[str, Mapping[str, float]], shares: Mapping[str, float]) -> dict[str, float]

The book: each generation's weights times its share, summed per name. A generation with no row counts as flat; a name that nets to zero leaves the row.

build_trial_table

build_trial_table(builder: str, params: Mapping[str, Any] | None, cell: WideCell) -> pd.DataFrame

One builder's table on this cell. cross_asset_trend takes its tickers from the params.

cap_lifted

cap_lifted(evidence: AdmissionEvidence) -> bool

A tier-2 generation takes over only on forward alpha, read at fixed checkpoints so the looks are countable.

caps_for

caps_for(generations: Mapping[str, Generation], evidence: Mapping[str, AdmissionEvidence], policy: GlidePolicy) -> dict[str, float]

Each generation's share cap under the admission rule, from its tier, evidence and the policy's paper cap.

clause_overrides

clause_overrides(spec: RoundSpec) -> dict[str, dict]

Per trial: its own minimum of live names, and whether it has no IC clause. Empty for a round that sets neither, so earlier rounds recompute unchanged.

coin_side

coin_side(ticker: str, project_coins: Iterable[str] = ()) -> str

The same split for coins, by base asset: BTCUSD and BTCUSDT are one coin.

count_unrun_trials

count_unrun_trials(spec: RoundSpec, unscored: Sequence[str], *, reason: str = 'did not run') -> list[str]

A pre-registered trial counts in N whether it ran or not. Appends a row only for those the ledger doesn't hold yet.

cusum_lower

cusum_lower(returns: ndarray, *, expected_sharpe: float, threshold: float, slack: float = 0.5) -> float

Today's statistic as a share of the threshold: 1.0 is an alarm.

cusum_path

cusum_path(returns: ndarray, *, expected_sharpe: float, slack: float = 0.5) -> np.ndarray

The running statistic: it rises while returns fall short and rests at zero, so old good years can't hide today's loss.

decay_state

decay_state(returns: Sequence[float], *, expected_sharpe: float, previous: str = 'healthy', config: DecayConfig | None = None) -> DecayReport

A generation's state today. previous carries the hysteresis, so a state can't flicker on one good week.

decide

decide(definition: Mapping[str, Any], known: DataFrame, date: str) -> dict[str, float]

The frozen rule's weights at date, through the research pipeline. known holds only what was public by that session's close.

decide_generation

decide_generation(definition: Mapping[str, Any], panel: ResearchPanel, date: str) -> dict[str, float]

The frozen rule's weights at date. Unlike forward_ledger.decide, it passes a score table and top_k through, so a cross-sectional rule can't silently become a different one.

default_configs

default_configs() -> list[dict]

The grid of simulated worlds (Sharpe, alpha half-life, correlation, zero-alpha probability) the glide calibration runs over.

default_policies

default_policies() -> list[dict]

The handover policies the glide calibration compares: fixed glides of several lengths and the evidence-driven variants.

definition_sha256

definition_sha256(definition: Mapping[str, Any]) -> str

SHA-256 of a forward definition's canonical JSON (sorted keys, no spaces): the identity a ledger row is bound to.

due_actions

due_actions(generations: Mapping[str, Mapping], judged: Mapping[str, Any], *, session: str | None, sessions_behind: int = 0, sessions_since_retrain: int | None = None, broker_keys: bool = False, policy_enabled: bool = False, record_started: bool = True) -> list[dict]

What a person or a job should do next, most urgent first.

dynamic_generation_shares

dynamic_generation_shares(shares: Mapping[str, float], stages: Mapping[str, str], states: Mapping[str, str], evidence: Mapping[str, Mapping], caps: Mapping[str, float], policy: GlidePolicy, *, sessions: int = 1) -> dict[str, float]

The dynamic mode. evidence holds, per generation, ew_sharpe, sessions and prior. A generation out of a holding stage, dead or tripped drops to zero at once, whatever its score; winding_down aims for zero. With no positive score and no generation past min_evidence_sessions, nothing is known yet, so shares hold.

dynamic_targets

dynamic_targets(scores: Mapping[str, float], caps: Mapping[str, float], policy: GlidePolicy) -> dict[str, float]

Each generation's target: proportional to its score above the floor, for the best max_generations. What a capped generation can't hold goes to the others, and what none may hold stays in T-bills.

evaluate_policies

evaluate_policies(configs: Sequence[Mapping], policies: Sequence[Mapping], *, paths: int = 2000, seed: int = 1, years: int = 8, workers: int = 1) -> dict[str, Any]

{policy: median regret, time above half of capital on a zero-alpha generation, generations holding capital, turnover}. Every policy meets the same fixed-seed worlds, across all the configs.

evidence_for

evidence_for(generation: Generation, judged: Mapping[str, Any], *, incumbent_returns: Mapping[str, float] | None, own_returns: Mapping[str, float], holdouts_spent: bool, state: Mapping[str, Any]) -> AdmissionEvidence

The admission rule's inputs from the record, with the flags a round's verdict set. The mean difference is on sessions both have.

ew_sharpe

ew_sharpe(state: tuple[float, float, float, int], *, sessions_per_year: float = 252.0) -> float | None

The annualised Sharpe of that record. None until it holds EW_MIN_SESSIONS or if it has no variance.

ew_update

ew_update(state: tuple[float, float, float, int], value: float, half_life: float = EW_HALF_LIFE_SESSIONS) -> tuple[float, float, float, int]

One more session of an exponentially weighted record: (weight, weighted sum, weighted squares, sessions). A non-finite return leaves it as it is.

family_of

family_of(spec: RoundSpec) -> str

The holdout family of a round's cell: crypto for the crypto universe, equity otherwise.

freeze_digest_of

freeze_digest_of(path: Path) -> str

SHA-256 of a freeze file's bytes, the digest a holdout read must quote.

gate_report

gate_report(scores: Mapping[str, Mapping], placebos: Mapping[str, Mapping], daily: DataFrame, *, trials: Sequence[str], min_live_names: int = 150, overrides: Mapping[str, Mapping] | None = None) -> dict[str, Any]

R-SLEEVE3 from stored scores: a pure function, so a past round can be recomputed and compared.

generation_state

generation_state(generation: Generation, mine: Sequence[Mapping], *, config: DecayConfig | None = None, guard_max_drawdown: float = GUARD_MAX_DRAWDOWN) -> dict[str, Any]

The decay report, with the guard first: a drawdown past the owner's ceiling is tripped, whatever the statistic says, and it latches.

glide2_policies

glide2_policies() -> list[dict]

R-GLIDE2's grid: the dynamic mode, and the two it must be judged against. Four generations may hold capital at once.

has_session

has_session(rows: Sequence[dict], candidate: str, session: str) -> bool

Whether the ledger already holds a row for this candidate and session.

held_by_lag

held_by_lag(mine: Sequence[Mapping], classes: Mapping[str, str], initial: Mapping[str, float], *, lags: Mapping[str, int] = FILL_LAG_SESSIONS) -> dict[str, float]

The weights in place at this session's start, class by class: each class holds what it decided as long ago as its order takes to fill.

holdouts_spent

holdouts_spent(path: Path) -> list[str]

Cells any freeze has read, from the once-only ledger.

install_command

install_command(platform: str, *, task_file: Path) -> list[str]

What registers the rendered job. Returned, not run, so a test can read it and a person can check it first.

is_rebalance

is_rebalance(sessions: Sequence[str], date: str, *, anchor: str, every: int) -> bool

Whether date is a decision day, counting sessions from the frozen file's last decision so the phase carries on unchanged.

judge_candidate

judge_candidate(rows: Sequence[dict], candidate: str) -> dict[str, Any]

Sessions recorded, Sharpe, alpha t against the benchmarks each row carries, and what this many sessions can and can't show.

judge_generations

judge_generations(rows: Sequence[Mapping]) -> dict[str, Any]

Chain first: a broken chain makes every figure meaningless.

judge_ledger

judge_ledger(rows: Sequence[dict], *, today_sessions: Sequence[str] = ()) -> dict[str, Any]

Chain check first: a broken chain makes every figure meaningless. today_sessions warns of a schedule that stopped.

last_row_for

last_row_for(rows: Sequence[dict], candidate: str) -> dict[str, Any] | None

The newest ledger row of a candidate, or None.

lifecycle_is_intact

lifecycle_is_intact(path: Path) -> tuple[bool, int | None]

Verify the hash chain of the lifecycle log: (valid, index of the first broken row or None).

live_rows

live_rows(signal: DataFrame, entry: Mapping[str, Any]) -> pd.DataFrame

The rows live names are counted on. A gated trial holds nothing while its gate is off, so the median over all rebalances would read the gate as a lack of names: it is counted on the rows where the gate is on (those with any value). An ungated trial counts every row, as before.

load_registry

load_registry(path: Path) -> dict[str, Generation]

Read ml/generations/registry.json into Generation records by name, refusing an unknown stage.

load_round

load_round(path: Path, *, root: Path = Path('.')) -> RoundSpec

The round, after its hash check. A changed file stops the round: no stage reads rules other than the ones recorded.

membership_mask

membership_mask(table: Mapping[str, list[tuple[str, str]]], sessions: list[str], columns: list[str]) -> pd.DataFrame

Session x ticker, True while a member. Names outside the membership table are False.

name_side

name_side(ticker: str, project_issuers: Iterable[str] = ()) -> str

A or B, fixed by a hash of the issuer: share classes and renames share a side, and it can't be tuned. A name any earlier phase has read is always A.

names_in_cell

names_in_cell(cell: Cell, tickers: Iterable[str], project: Iterable[str]) -> list[str]

The tickers a cell may trade: all of them for side AB, else those on the cell's side of the split.

next_stage

next_stage(generation: Generation, evidence: AdmissionEvidence) -> str

R-ADMIT1. Moves forward only on evidence, off the book at once on a guard trip or dead state, and never by more than the rule says. Non-finite evidence holds.

no_data_row

no_data_row(generation: Generation, rows: Sequence[Mapping], *, reason: str, benchmarks: Mapping[str, float], definition_sha: str = '') -> dict[str, Any]

A failed fetch is a row with its reason, never a gap. The held weights don't change.

oracle_daily

oracle_daily(world: Mapping[str, Any]) -> np.ndarray

The daily return of an oracle that always holds the generations with the best true Sharpe, the calibration's upper bound.

passes_earlier_clauses

passes_earlier_clauses(score: Mapping[str, Any], *, min_live_names: int, no_ic: bool = False) -> bool

Everything in R-SLEEVE3 before the placebos: live names, the Sharpe clauses, and the rank-IC t (not for a trial the round lists in no_ic_clause).

pbo_report

pbo_report(frames: Sequence[DataFrame], columns: Sequence[str], *, window: tuple[str, str], blocks: int = 16) -> dict[str, Any]

The probability of backtest overfitting over the named columns. A trial with no return on a date reads as flat, as a trial that didn't exist yet would be.

pick_glide2

pick_glide2(results: Mapping[str, Mapping], *, baseline: str = 'fixed_252', tie: float = 0.005) -> dict[str, Any]

R-GLIDE2: the dynamic policy with the lowest median regret among those no worse than the baseline on zero-alpha time, and it replaces the baseline only if its regret is no worse than the baseline's, within tie. Ties among dynamic policies go to less turnover. The owner asked for the dynamic form, so no worse is enough: it holds several generations, and the ladder can't.

pick_policy

pick_policy(results: Mapping[str, Mapping], *, max_zero_alpha_share: float = 0.2, tie: float = 0.005) -> dict[str, Any]

R-GLIDE1: the lowest median regret among policies whose time mostly on a zero-alpha generation is at most 20%. Ties go to fewer parameters. None qualifying: fixed 252.

r_hold1

r_hold1(reads: Mapping[str, Mapping]) -> dict[str, Any]

R-HOLD1's clauses: V3 Sharpe >= 0.50 and alpha t >= 2.0; V1 and V2 Sharpe > 0. A missing figure fails.

r_hold1_crypto

r_hold1_crypto(reads: Mapping[str, Mapping]) -> dict[str, Any]

R-HOLD1 for a crypto candidate: CV Sharpe >= 0.50 and alpha t >= 2.0. A missing figure fails.

ram_preflight

ram_preflight(host: str, *, total_bytes: int | None = None, min_gb: float = 14.0) -> dict[str, Any]

Whether this host may train. A local machine below the minimum refuses with the numbers: a retrain killed for memory hours in costs more than a clear no. Unknown RAM refuses too.

read_json_or

read_json_or(path: Path, default: Any) -> Any

A JSON file's content, or default when the file does not exist.

read_ledger

read_ledger(path: Path) -> list[dict]

The ledger's rows (one JSON object per line), or [] when the file does not exist.

read_lifecycle

read_lifecycle(path: Path) -> list[dict]

The lifecycle log's rows, or [] when the file does not exist.

record_holdout_read

record_holdout_read(path: Path, *, candidate: str, cells: tuple[str, ...], digest: str, created_at: str) -> None

The once-only ledger of holdout reads. write_freeze only refuses its own path, so a second freeze file would otherwise reopen a cell. Written before the read: a crash after it still counts as spent.

record_of

record_of(returns: Iterable[float], *, prior: float) -> dict[str, Any]

What the allocator reads about one generation: its exponentially weighted Sharpe, its sessions of record, and what it claimed at admission.

render_schedule

render_schedule(platform: str, *, repo: Path, python: str = 'python', host: str = 'local') -> str

The text of a weekly retrain-if-due job, Sunday 03:00. It renders only: aq cycle schedule install is what registers it, on a machine that passes the preflight.

repair_shares

repair_shares(shares: Mapping[str, float]) -> dict[str, float]

An allocation that is a valid one: a NaN or negative share is zero, and a total above one is scaled down to one (formal/AetherFormal/DynamicTargets.lean, repair_valid). V6.6.7 (#375): an invalid allocation used to be returned as it was, so a tripped or dead generation kept its share, and an over-allocated book stayed over-allocated.

replay_dynamic

replay_dynamic(rows_by_generation: Mapping[str, Mapping[str, Mapping[str, float]]], returns_by_generation: Mapping[str, Mapping[str, float]], sessions: Sequence[str], *, born: Mapping[str, str], priors: Mapping[str, float], policy: GlidePolicy, initial: Mapping[str, float] | None = None) -> dict[str, Any]

The blended file the dynamic mode would have written, reading only returns known by each session. Used by the running functions, so a backtest of it tests what would trade. {"rows", "shares", "scores"}, with shares and scores on each session a row is written.

replay_handover

replay_handover(rows_by_generation: Mapping[str, Mapping[str, Mapping[str, float]]], sessions: Sequence[str], *, incumbent: str, successor: str, start: str, policy: GlidePolicy) -> dict[str, Any]

The blended weight file a handover would have written: incumbent holds the book until start, then the ladder moves it to successor. Uses the running functions, so a backtest of this file tests what would trade. {"rows": {date: weights}, "shares": {date: shares}}.

resolve_glide_policy

resolve_glide_policy(raw: Mapping | None) -> GlidePolicy

A GlidePolicy from config, every share clipped to [0, 1] and every missing or non-finite value at its default.

resolve_session

resolve_session(sessions: Sequence[str], now_date: str, override: str | None = None) -> str | None

The session a run records. An override must be a real session. Otherwise the newest session on or before today, so a schedule delayed past midnight UTC, or a weekend dispatch, still records the session it was for. Never a future date, and never an older gap: only the newest session can be written.

retrain_due

retrain_due(*, sessions_since_retrain: int | None, decay_states: Mapping[str, str], every_sessions: int = RETRAIN_EVERY_SESSIONS) -> dict[str, Any]

By the calendar, or because the book's generation is decaying. It reports; it starts nothing.

retrain_stages

retrain_stages(*, data_present: bool) -> list[str]

A fresh checkout builds its own data first, from public sources and the user's own SEC contact: this is what lets anyone retrain.

row_for_generation

row_for_generation(generation: Generation, rows: Sequence[Mapping], session: str, sessions: Sequence[str], marks: DataFrame, benchmarks: Mapping[str, float], *, decision: Mapping[str, float] | None = None, definition_sha: str = '') -> dict[str, Any]

One session's payload. A rule with no needs decides here, on the runner; one with needs reads the decision a host dated earlier.

rows_for

rows_for(rows: Sequence[Mapping], generation: str) -> list[dict]

The payloads of one generation's ledger rows, oldest first.

rules_sha_path

rules_sha_path(path: Path) -> Path

The .sha256 file that pins a round's rules file.

run_policy

run_policy(world: Mapping[str, Any], policy: Mapping[str, Any]) -> dict[str, Any]

A path of shares and what they earned, net of turnover cost, with blended rows only when due and the deadband on.

save_registry

save_registry(path: Path, generations: Mapping[str, Generation]) -> None

Atomic, sorted, LF: one registry has one hash, and a crash can't leave half a file.

score_file_table

score_file_table(path: Path, index: Sequence[str] | Index, columns: Sequence[str] | Index) -> pd.DataFrame | None

A model's walk-forward scores as a session x ticker table, or None when the file isn't there.

session_for_outage

session_for_outage(now: datetime) -> str

With no calendar (the fetch failed), the last weekday whose US close has passed. Dating an outage row by the calendar day would let a run at 02:00 UTC use up that day's own session.

session_return

session_return(held: Mapping[str, float], marks: DataFrame, previous: str, date: str, *, cost_bps: float, traded: float = 0.0) -> float | None

What the weights held earned between two sessions' marks, less the cost of today's trade. None if a held name has no mark.

session_return_covered

session_return_covered(held: Mapping[str, float], marks: DataFrame, previous: str, date: str, *, classes: Mapping[str, str], traded: Mapping[str, float], cost_by_class: Mapping[str, float] = COST_BPS_BY_CLASS, min_coverage: float = MIN_COVERAGE) -> dict[str, Any]

What the held weights earned between two marks, less the cost of what traded. One delisted holding doesn't blank every row until the next decision: the rest counts while at least min_coverage of the gross has a mark. Below that the session is no_data, never a guess.

sessions_since_retrain

sessions_since_retrain(run_root: Path, sessions: Sequence[str]) -> int | None

Sessions recorded since the newest real retrain finished. A smoke run registers no procedure, so it never counts. None with none on record.

share_cap

share_cap(generation: Generation, evidence: AdmissionEvidence, tier2_cap: float = 0.3) -> float

What the generation may hold of the paper book: all of it with a full pass or as the installed book, the tier-2 cap until its forward alpha lifts it, otherwise nothing. A tier-none generation is observed only and holds nothing under any evidence (Problems #335): a lifted cap is a tier-2 privilege.

shrunk_sharpe

shrunk_sharpe(observed: float | None, sessions: int, prior: float, prior_sessions: float) -> float

What a generation's Sharpe is believed to be: its record and its claim, weighted by sessions of record against prior_sessions. No usable record leaves the claim.

simulate_generations

simulate_generations(config: Mapping[str, Any], seed: int, *, years: int = 8) -> dict[str, Any]

{"true_sharpe": sessions x generations, "returns": sessions x generations, "born": first session of each}. A generation exists from its birth.

spec_of

spec_of(spec: RoundSpec, trial: str, universe: Sequence[str]) -> SleeveSpec

The SleeveSpec a round's trial runs as, from its registered entry.

stage_freeze

stage_freeze(spec: RoundSpec, candidate: Mapping[str, Any], *, holdout_ledger: Path, code_digests: Mapping[str, str] | None = None) -> tuple[Path, str]

Freezes one candidate, by rule. Refuses once any holdout has been read: the same data can't back a second candidate. Returns (path, digest).

stage_gate

stage_gate(spec: RoundSpec) -> dict[str, Any]

Apply the round's selection gate to the scored and placebo-tested trials, and write the survivors.

stage_hold

stage_hold(spec: RoundSpec, trial: str, *, root: Path, freeze_path: Path, digest: str, holdout_ledger: Path, created_at: str, score_dir: Path, read_cell: Callable[[str], object] | None = None, alpha_fn: Callable[[Series], Mapping] | None = None) -> dict[str, Any]

The one read of the holdouts. It records the read before opening anything: a crash after this still counts as spent.

stage_pbo

stage_pbo(spec: RoundSpec, *, root: Path = Path('.')) -> dict[str, Any]

PBO by CSCV over the round's trials (and prior rounds' daily returns on the same cell), written beside the gate.

stage_placebo

stage_placebo(spec: RoundSpec, *, cell: WideCell, score_dir: Path, draws: int = 100, force: bool = False, emit: Callable[[str], None] = print) -> dict[str, Any]

R-SLEEVE3's placebos, only for trials that pass every earlier clause.

stage_report

stage_report(spec: RoundSpec, *, alpha_fn: Callable[[Series], Mapping] | None = None) -> dict[str, Any]

The verdict in plain figures: survivors, PBO, and what this round can and can't exclude, per trial and at the best trial.

stage_score

stage_score(spec: RoundSpec, *, cell: WideCell, score_dir: Path, only: Sequence[str] = (), force: bool = False, ic_fn: Callable[..., Any] | None = None, emit: Callable[[str], None] = print) -> dict[str, Any]

Scores each trial not yet scored, saving after each one. A table that can't be built stays unscored and is named by the gate.

status_view

status_view(generations: Mapping[str, Mapping], judged: Mapping[str, Any], actions: Sequence[Mapping], *, session: str | None, policy: Mapping[str, Any]) -> dict[str, Any]

The one view aq cycle status, the API and the dashboard all read. No secret and no path outside the repo.

step_toward

step_toward(shares: Mapping[str, float], targets: Mapping[str, float], fraction: float, retire_share: float) -> dict[str, float]

A fixed fraction of the way to the targets, so nothing jumps. A blend of two allocations that each sum to at most one sums to at most one (proved in Lean). A generation headed to nothing is gone below retire_share, as it couldn't trade its residue.

total_memory_bytes

total_memory_bytes() -> int | None

This machine's RAM, or None if it can't be read. Stdlib only, so the check works before anything heavy is installed.

trial_table

trial_table(spec: RoundSpec, trial: str, cell: WideCell, built: dict[str, DataFrame], *, score_dir: Path, score_suffix: str = '') -> pd.DataFrame | None

One trial's table on this cell, or None when it can't be built yet (a model that didn't run). built holds earlier trials, which a composite may name. Masked to the cell's members, so nothing outside them can be held.

turnover

turnover(before: Mapping[str, float], after: Mapping[str, float]) -> float

Sum of absolute weight changes between two books, the traded fraction of NAV.

universe_for

universe_for(spec: RoundSpec, trial: str) -> tuple[str, ...]

What a trial trades: its own universe, else the coins of a crypto cell, else the eleven sectors.

update_generation_shares

update_generation_shares(shares: Mapping[str, float], stages: Mapping[str, str], states: Mapping[str, str], caps: Mapping[str, float], policy: GlidePolicy, *, sessions: int = 1) -> dict[str, float]

The shares after sessions sessions. A generation out of a holding stage, or dead, or with a guard trip (state tripped), drops to zero at once; a new ramping generation enters at entry_share; below retire_share a generation is gone, and what it held passes to the ramping one up to its cap. What no one may hold stays in T-bills.

window_rows

window_rows(index: Iterable[str], cell: Cell, *, warmup: int = WARMUP_SESSIONS) -> list[str]

The cell's sessions plus the warmup before them, which give a signal its history. A warm-up row can never hold a position: weights start at cell.start. Nothing after cell.end exists in the panel at all.

write_freeze

write_freeze(path: Path, payload: Mapping[str, Any]) -> str

Writes the freeze file once and returns its digest. Refuses to overwrite: a second freeze would be a second look.

write_rules

write_rules(payload: Mapping[str, Any], path: Path) -> str

Writes a round's rule file once, with its hash beside it. A second write refuses: a changed rule needs a dated amendment.