Participant policy — the trio's tunables and invariants

--- name: participant-policy version: 0.1.0 description: Operator-facing policy documentation for the SPEC-103 §3.6 market-participant trio (value-funder / contrarian-bettor / diversifier) — the shared risk-envelope...

Source: skills/participant-policy/SKILL.md

Participant policy — the trio’s tunables and invariants

The SPEC-103 §3.6 market-participant trio (participant_value_funder, participant_contrarian_bettor, participant_diversifier) acts as the platform’s exchange-side economic agents. Each holds a budget, honours a risk envelope, and emits one specific action class against one specific bias the unaided market exhibits:

Participant Signal Action Bias countered
Value Funder thinness × inverse-current-fund signal(kind='fund') on under-funded thin gaps platform-wide neglect of underexplored directions
Contrarian Bettor consensus vs. model residual markets.trade on the under-priced side crowd over-confidence on consensus markets
Diversifier mechanism-family monoculture in a gap signal(kind='fund') on under-represented families + QF top-up within-gap mechanism monoculture

The trio exhausts the design surface — each counters a different failure mode. The numbers below are what makes that work in practice.

Participant execution is agent-owned. The substrate stores durable market participant rows, risk envelopes, ledgers, signals, and settlement mechanics; the runtime loop that decides whether to fund, diversify, or trade should run from this agent skill bundle and write back through substrate verbs. Per-row risk envelopes are stored in market_participants.risk_envelope; runtime defaults may still be overridden by deployment config.

Shared risk-envelope tunables

All three honour the same envelope shape; the defaults vary by participant and the ordering is load-bearing.

max_position_size — value-funder 500, diversifier 300, contrarian 200

Cap on tokens any single trade or fund signal can move.

The descending order matches the strategies’ inverse variance: value-funder allocates over gaps (broad, slow theses); diversifier over families within a gap (narrower, QF-amplified); contrarian over binary markets (highest variance per token). A single wrong contrarian bet can blow through a quarter’s gains in one settlement — the tight per-position cap is the only thing keeping a streak of bad calibrations from being existential. Flattening these to one value silently breaks the implicit risk-scaling.

max_drawdown — contrarian 0.25, diversifier 0.25, value-funder 0.30

Fraction of starting balance that triggers a pause-all-new-bids state. Contrarian and diversifier pause earlier because their strategies should be more predictable than the value-funder’s; a 25% drawdown for either is a strong signal of strategy malfunction. The value-funder tolerates 30% because gap-level theses take longer to resolve and can drift further before reverting. Above 0.5 you’ve effectively disabled the circuit-breaker; under 0.15 you’ll trip on routine market noise within a week.

concentration_cap — contrarian 0.30, value-funder 0.20, diversifier 0.15

Fraction of portfolio that may sit in one artifact. Inverse of the position-size order, also load-bearing. Defines an implicit minimum portfolio: contrarian needs ≥4 markets, value-funder ≥5 gaps, diversifier ≥7 gaps. A diversifier with 30% in one gap is not diversifying anything.

Value-Funder–specific

FUND_FLOOR = 100 tokens — env SCIDEX_VALUE_FUNDER_FUND_FLOOR

Eligibility cutoff: only gaps with current_fund < FUND_FLOOR get allocations. Channels capital to genuinely orphaned gaps rather than dogpiling already-funded ones. Cross-references the gap-roi-realloc-policy “underfunded” band — raising one without the other lets the realloc worker reclaim value-funder allocations the moment they land.

  • Higher (200–500): stretch into mid-funded gaps when the under-funded tail is small and budget is idle.

  • Lower (25–50): last-resort backstop only.

top-N = 5 — implicit per-deployment constant

Number of value-score-ranked gaps funded per tick. Per-gap dose is budget_remaining / N; raising N spreads thinner. Not env-overridable today because it interacts with allocation arithmetic — revisit if deployments diverge.

Contrarian-Bettor–specific

sigma_threshold = 2.0contrarian_decide.decide(sigma_threshold=...)

σ multiples of model uncertainty the consensus must deviate by to trigger a stake. Two sigma ≈ outer 5% of the bettor’s confidence interval — if the per-market posterior is approximately Gaussian. In heavy-tailed regimes the same “2σ” is much looser; check the empirical distribution before lowering. Raising to 2.5–3.0 narrows to only the strongest crowd errors; lowering to 1.5–1.8 chases more noise.

STAKE_SIZE = 50 tokens — per-trade nominal

Stake before envelope-clipping. 50 against max_position_size=200 means up to 4 stake-quotas per market. Larger (100+) = fewer/bigger trades when calibration is strong; smaller (10–25) = more update samples while the Bayesian prior is wide.

model_decay = 0.95 — Bayesian prior decay per tick

0.95^14 ≈ 0.49 so older information halves over ~14 ticks. Higher (≥0.98) for stable markets; lower (0.85–0.90) where regime change is common (e.g. drug development after a major preclinical readout).

Diversifier-specific

Monoculture trigger: dominant_family_share ≥ 0.70 — implicit

gap.exploration_invited fires when one mechanism family commands ≥70% of hypotheses on a gap. Above 70% = tolerate moderate monoculture (use when total hypothesis volume is low); below 55–65% = intervene early (use in mature domains with multiple established families). Crosses the SPEC-104 diversity_score “monoculture-suspect” band at the same point — keep them aligned.

SCIDEX_DIVERSITY_MIN = 0.3 — env SCIDEX_DIVERSITY_MIN

SPEC-104 Simpson-style diversity_score cutoff at which the upstream gap_diversity_trigger worker emits the event. The diversifier consumes; it doesn’t compute. Same phenomenon as the 70% trigger above from a different angle — they MUST move together.

RECOVERY_THRESHOLD = 0.5 — close diversifier positions

diversity_score at which the diversifier stops funding. The hysteresis (intervene at 0.3, withdraw at 0.5) prevents thrashing. Equal values cause chatter; reversed values cause the diversifier to fund already-healthy gaps. Invariant: RECOVERY_THRESHOLD > SCIDEX_DIVERSITY_MIN.

ALLOCATION_UNIT = 50, EXPLORATION_GRANT = 100, diversity_bonus cap = 1.5×

Per-hypothesis base allocation (deliberately mirrors contrarian STAKE_SIZE); QF top-up for empty families (2× the per-hypothesis unit because attracting a new hypothesis is harder than topping up existing); cap on the SPEC-104 §3.4 diversity_bonus multiplier. The 1.5× cap prevents a feedback loop where the diversifier over-funds the first hypothesis in a new family until its own funding becomes the dominant signal. Above 2× the loop closes.

Load-bearing invariants

  1. max_position_size: value-funder > diversifier > contrarian. The per-position cap is the only thing keeping high-variance binary contrarian trades from killing the portfolio.

  2. concentration_cap: contrarian > value-funder > diversifier. Inverse of position-size. Defines implicit minimum portfolios; if the live market landscape doesn’t support those counts, the participant cannot deploy a full book.

  3. RECOVERY_THRESHOLD > SCIDEX_DIVERSITY_MIN. Diversifier hysteresis; equal/reversed causes oscillation or self-defeating allocations.

  4. 70%-monoculture trigger ↔ SCIDEX_DIVERSITY_MIN = 0.3. Same phenomenon, two angles. Must move together.

  5. sigma_threshold ≥ 2.0 requires Gaussian posteriors. In heavy-tailed markets 2σ is much looser than 5%. Check before lowering.

  6. diversity_bonus_cap ≤ 2.0. Above 2× the diversifier dominates its own funding signal.

Operator playbook

Symptom: value-funder budget sits idle, few allocations emit. Diagnose: is FUND_FLOOR too low? Check gap count where current_fund < 100. Lever: raise FUND_FLOOR, or check whether gap-roi-realloc-policy is clawing back faster than allocation.

Symptom: contrarian in continuous drawdown. Diagnose: is model variance calibrated? Compare emitted model_sigma to observed settlement spread. Lever: raise sigma_threshold to 2.5, tighten STAKE_SIZE, or investigate whether the Bayesian update is being applied at all.

Symptom: diversifier oscillating on the same gap. Diagnose: are SCIDEX_DIVERSITY_MIN and RECOVERY_THRESHOLD too close? Lever: widen the hysteresis (raise recovery to 0.6+, or lower the trigger to 0.25).

Symptom: new mechanism families never attract hypotheses. Diagnose: is EXPLORATION_GRANT reaching the QF round? Check signal(kind='fund') events with metadata.purpose='diversity_exploration'. Lever: raise EXPLORATION_GRANT, or audit QF matching per SPEC-104 §3.8.

Symptom: participant repeatedly hits max_drawdown. Diagnose: deployment-wide or this participant only? Lever: not this policy. Drawdown is a strategy-malfunction signal; pause-and-investigate is the correct circuit-breaker response. Loosening the envelope masks the underlying problem.

Tuning protocol

  1. Tune ONE class at a time (envelope OR per-participant defaults).

  2. All six invariants above MUST still hold after the change. The taxonomy + skill-design-quality tests enforce some structurally.

  3. Wait ≥2 weeks before assessing impact — ROI signals compound through trust-score-weight-policy slowly and the QF round is weekly cadence.

  4. 50% changes from default need a Senate proposal citing this policy and the symptom-and-lever pair. Don’t unilaterally rebalance the trio.

Why this is one policy doc, not three workers’ constants

Per SPEC-199 §4.3, Wave-3 converts hardcoded policy constants into operator-facing policy skills with env-var overrides. The participant trio is the 26th explicit Wave-3 externalization — three skills in one doc because the tunables are cross-coupled: changing the diversifier’s SCIDEX_DIVERSITY_MIN without looking at the contrarian’s sigma_threshold can leave the platform with two participants chasing the same noise. The policy skill is what makes that coupling explicit so the runtime selector (skill_taxonomy.taxonomy_for) routes @ops / @analyst queries to the right doctrine rather than three drifting tables.

This also closes the iter-220 design-quality directive: each of the three participant SKILL.md files scored 1.8 / 5.0 on the “no-hardcoded-constants” axis. With the constants in this doctrine and the three skills rewritten to point to it, that’s a 3-for-1 design-quality lift in one PR.

Cross-references

  • SPEC-103 §3.6 — market-participant trio architecture

  • SPEC-104 §3.4 + §3.8 — diversity score, QF round, exploration invitations

  • participant_value_funder — consumer of FUND_FLOOR + top-N

  • participant_contrarian_bettor — consumer of sigma_threshold, STAKE_SIZE, model_decay

  • participant_diversifier — consumer of SCIDEX_DIVERSITY_MIN, RECOVERY_THRESHOLD, ALLOCATION_UNIT, EXPLORATION_GRANT, diversity_bonus cap

  • gap-roi-realloc-policy — downstream reallocator interacting with FUND_FLOOR

  • trust-score-weight-policy — downstream aggregator consuming participant_roi

  • docs/architecture/skill-taxonomy.md — this skill: category: policy / permission_level: policy (iter-221)

  • docs/design/spec-199-skill-first-architecture.md §4.1 — Wave-3 catalog (this PR adds the 26th entry)