Skip to content

design(v2.10+): freeze ML score-to-action policy, thresholding, sizing, abstention, and execution handoff #714

Description

@dmidlo

Parents: #605 #657 #712 #713
Related: #591 #594 #660 #681 #696#705 #708 #710#713

Problem

The project now governs historical feature construction, model training, protected evaluation, offline/online parity, and live validity. What is still missing is one canonical contract for the decision layer that converts a model output into a trade action.

A predictive model score is not itself an order. Thresholds, abstention, position sizing, turnover penalties, cost gates, portfolio projection, risk limits, and execution handoff can materially change realized behavior while the underlying model weights remain unchanged. These transformations therefore require independent versioned identity, causal fitting rules, and scientific qualification.

The ML decision layer must also remain separate from the 1,000 deterministic v33 proxy traders: those strategies are feature-generating fictional expert systems unless explicitly selected as a separate downstream trading policy.

Canonical decision-policy contract

Define immutable ModelDecisionPolicyV1 carrying at least:

Changing any threshold, sizing rule, cost estimate, portfolio constraint, or abstention mapping creates a successor policy identity even when the predictive model is unchanged.

Score versus action

For probabilistic long-direction score p_t, one simple ternary reference rule may be

a_t = +1 if p_t >= tau_long
a_t = -1 if p_t <= tau_short
a_t = 0 otherwise

with tau_short < tau_long and an explicit neutral/dead-band region.

Container-vetted fixture: p=.62, tau_long=.60, tau_short=.40 -> a=+1.

This is a reference pattern, not a mandated global policy. Thresholds are fitted/configured artifacts and obey #697/#698.

Edge after transaction costs

If the model emits expected return/edge mu_hat_t and the decision layer has a causally available expected execution/financing cost estimate c_hat_t, a trade gate may require

e_t = mu_hat_t - c_hat_t

and only permit a directional position when the signed expected net edge exceeds a frozen threshold.

A model with positive gross expected return is not necessarily tradeable after spread/slippage/fees/financing.

Container fixture: mu_hat=.0003, c_hat=.0004 gives net edge -0.0001, so an edge-positive-only policy must refuse the trade despite positive gross prediction.

Expected costs are model/scenario quantities, not future realized costs. Future realized slippage/financing belongs to later ledger/outcome evidence.

Reference risk-scaled sizing

One illustrative continuous sizing rule is

q_raw = k * (mu_hat - c_hat) / max(sigma_hat^2, epsilon)

followed by

q_target = clip(q_raw, -q_max, q_max)

and then the portfolio/account projection required by #704 and the applicable currency/margin constraints.

Container fixture with mu=.0015, cost=.0004, sigma=.01, k=.5 gives q_raw=5.5; with q_max=1, the target clips to 1. This demonstrates why clipping/risk limits are scientifically material policy semantics rather than mere implementation detail.

This is a reference fixture, not an assertion that Kelly-like sizing is the production default.

Turnover and hysteresis

A decision policy may optimize expected utility net of turnover, e.g. for candidate position q

J(q) = mu_hat*q - lambda*|q-q_prev| - C_expected(q,q_prev).

Container fixture with q_prev=1, mu_hat=.002, lambda=.0015, candidates {-1,0,1} and no additional cost term gives scores (-.005, -.0015, .002), so retaining q=1 is optimal. Exact objectives, candidate sets, and cost models must be frozen per policy.

Required separation of responsibilities

The architecture must preserve:

predictive model -> decision policy -> risk/account projection -> order intent -> execution policy -> fills/ledger.

Do not let the model-serving layer bypass:

Likewise, do not hide decision thresholds or sizing constants inside model code when they can change independently from the statistical model.

Abstention semantics

#713 abstention/refusal is upstream safety/validity state. ModelDecisionPolicyV1 must define what happens when inference is unavailable, but it cannot silently reinterpret refuse_inference as a neutral model prediction.

Keep at least:

  • model_abstained;
  • validity_refused;
  • policy_deadband;
  • cost_gate_rejected;
  • risk_projection_rejected;
  • jurisdiction_rejected;
  • execution_rejected;

as distinct reason classes where applicable.

Multi-pair/portfolio output

For models producing a raw target vector q_tilde, final desired positions should pass through one versioned constrained projection, e.g.

q* = argmin_q ||q-q_tilde||_W^2 + lambda ||q-q_prev||_1

subject to declared pair, currency, leverage, margin, concentration, family/model, turnover, and jurisdiction constraints.

The projection result, active constraints, and rejection/clipping reason must be retained. A constrained result is not the same semantic object as the unconstrained model score.

Calibration and fitting governance

Threshold choice, score calibration, cost-gate threshold, sizing coefficient, turnover penalty, risk budget, and portfolio constraints are all part of model selection when optimized from data. They must be fitted only on authorized training/validation evidence under #697/#698.

Protected test/live data cannot be used to tune a decision policy and then remain described as untouched evaluation.

Backtest and live parity

#712 parity must extend through the decision layer: given identical model output, policy identity, account state, eligibility state, and causal cost/risk inputs, historical replay and live inference must emit the same desired action/position/reason code under #640 numerical rules.

A model can pass feature parity but fail action parity if serving uses different thresholds or account constraints.

Synthetic-v33 interaction

The v33 1,000-strategy response bank remains a feature/proxy subsystem. If a future learned model consumes strategy.FXES-* features, the downstream ML decision must not be attributed to any specific FXES expert unless that is explicitly the decision policy.

Likewise, using an ensemble/vote over FXES outputs as a direct trading policy creates a separately versioned policy identity and must be evaluated under the same protected framework.

Evaluation decomposition

Report performance separately for:

  1. raw model statistical prediction;
  2. calibrated score where applicable;
  3. decision policy before costs;
  4. decision policy after simulated costs/financing;
  5. risk/account-projected target;
  6. executable/fill-realized outcome;
  7. live validity/abstention coverage.

This prevents improvements from being incorrectly attributed to the predictive model when they actually arise from thresholding, sizing, cost assumptions, or portfolio constraints.

Negative controls

Certification must fail/flag:

  • serving threshold differs from backtest without successor identity;
  • model abstention silently mapped to hold/zero prediction;
  • future realized transaction cost used as contemporaneous expected-cost gate;
  • positive gross score traded despite frozen cost gate showing negative expected net edge;
  • sizing exceeds design(v2.8): freeze leverage, margin, maintenance, liquidation, and account-solvency semantics for synthetic traders #704 margin/account caps;
  • model emits order directly bypassing risk/account projection;
  • threshold or sizing tuned on protected holdout;
  • portfolio projection changes position but reason/active constraint is lost;
  • online decision policy uses current adaptive threshold while historical backtest used fixed threshold under same policy ID;
  • v33 proxy strategy response is mislabeled as the learned model's own decision authority.

Acceptance

Metadata

Metadata

Assignees

No one assigned

    Labels

    data-qualityData quality assessment checks, reports, and validation workflowsscientific-validationFalsifiability, calibration, leakage, reproducibility, and scientific acceptance gatessynthetic-dataSynthetic data generation, constraints, and validation workflows

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions