Documentation
¶
Overview ¶
Package risk provides pure risk-policy evaluation and related domain contracts. It performs no I/O and owns no broker or runtime state; callers supply typed observations and policies, and retain responsibility for state mutation, persistence, transport, and enforcement.
Evaluators preserve missing, stale, and unapproved inputs as explicit non-passing outcomes. Fingerprint helpers identify the complete normalized policy projections used by callers.
Index ¶
- Constants
- func BuildAlertAuthorityScope(account, mode string) (string, error)
- func BuildAlertEpisodeKey(source AlertSource, kind AlertKind, identityParts ...string) (string, error)
- func BuildAlertOccurrenceKey(episodeKey string, identityParts ...string) (string, error)
- func OptionExtrinsicPerShare(right string, underlying *float64, strike, mark float64) (float64, bool)
- func OptionIntrinsicPerShare(right string, underlying, strike float64) float64
- func OptionSpreadPct(bid, ask *float64) (float64, bool)
- func RulebookHedgeLeg(l LegInput) bool
- func ValidateAlertAuthorityScope(value string) error
- func ValidateSizePlan(in SizeInput) error
- type AlertCandidate
- type AlertCandidateSnapshot
- type AlertCoverage
- type AlertCoverageFreshness
- type AlertCoverageState
- type AlertDestination
- type AlertEpisodeState
- type AlertEvidenceHealth
- type AlertKind
- type AlertPresentationCode
- type AlertSeverity
- type AlertSnapshotState
- type AlertSource
- type AlertSourceCoverage
- type CapitalObservation
- type CapitalRuntime
- type CapitalVerdict
- type Constitution
- type ConstitutionArtefact
- type ConstitutionCadence
- type ConstitutionCapital
- type ConstitutionDrawdown
- type ConstitutionInventory
- type ConstitutionLimit
- type ConstitutionMonthlyCadence
- type ConstitutionNudgeCadence
- type ConstitutionOverride
- type ConstitutionPolicyPin
- type ConstitutionRecon
- type EarningsInput
- type Evaluation
- type LegInput
- type MonthlyPulseCompletion
- type MonthlyPulseEvaluation
- type MonthlyPulseInput
- type NameInput
- type NudgeCandidate
- func CanonicalizeNudgeCandidate(candidate NudgeCandidate) (NudgeCandidate, error)
- func EvaluateConfirmedFlow(statementRowIdentity string, occurredAt time.Time) *NudgeCandidate
- func EvaluateDrawdownLatched(latchEpisode string, open bool, occurredAt time.Time) *NudgeCandidate
- func EvaluatePolicyDrift(mismatches []NudgePinMismatch, occurredAt time.Time) *NudgeCandidate
- func EvaluateReconcileDue(input ReconcileDueInput) *NudgeCandidate
- func EvaluateReconcileException(unresolved []ReconcileExceptionIdentity, occurredAt time.Time) *NudgeCandidate
- type NudgePinMismatch
- type PlannerMode
- type PlannerReadiness
- type Policy
- type PortfolioPosture
- type ReconcileDueInput
- type ReconcileExceptionIdentity
- type ReducePolicy
- type RegimeThresholds
- type RuleInputs
- type RuleOffender
- type RuleRow
- type RulebookPolicy
- type ShadowWouldBlockEvaluation
- type ShadowWouldBlockInput
- type Signal
- type SignalDirection
- type SignalID
- type SignalSeverity
- type SizeInput
- type SizeResult
- type SourceState
- type UnreconciledClock
Constants ¶
const ( CapitalTierOK = "ok" CapitalTierWarn = "warn" CapitalTierBlock = "block" CapitalTierUnknown = "unknown" CapitalTierUnapproved = "unapproved" )
CapitalTierOK and the related constants are capital-evaluation outcomes. Missing observations and unapproved policy remain explicit non-OK tiers.
const ( EnforcementShadow = "shadow" EnforcementAdvisory = "advisory" )
EnforcementShadow and EnforcementAdvisory are the enforcement classes a constitution control may declare. Validation rejects unsupported classes.
const ( NudgeKindReconcileDue = "reconcile_due" NudgeKindReconcileException = "reconcile_exception" NudgeKindShadowWouldBlock = "shadow_would_block" NudgeKindDrawdownLatched = "drawdown_latched" NudgeKindPolicyDrift = "policy_drift" NudgeKindConfirmedFlow = "confirmed_flow" NudgeKindMonthlyPulse = "monthly_pulse" NudgeStateDueSoon = "due_soon" NudgeStateOverdue = "overdue" NudgeStateOpen = "open" NudgeStateObserved = "observed" NudgeStateDue = "due" NudgeSeverityWatch = "watch" NudgeSeverityAct = "act" NudgeDestinationMonitor = "monitor" NudgeDestinationAlerts = "alerts" // NudgeDestinationBrief lands a process/governance nudge on the Brief tab, // where the reconcile clock, monthly pulse, and confirmed-flow context live. // Act-severity governance occurrences still land on Alerts. NudgeDestinationBrief = "brief" MonthlyPulseStatusNotDue = "not_due" MonthlyPulseStatusDue = "due" MonthlyPulseStatusCompleted = "completed" MonthlyPulseStatusBlocked = "blocked" MonthlyPulseEvidenceRender = "render" )
NudgeKindReconcileDue and the related constants define the closed nudge vocabulary accepted by CanonicalizeNudgeCandidate. Zero and unknown values are invalid.
const ( RuleStatusPass = "pass" RuleStatusInfo = "info" RuleStatusWatch = "watch" RuleStatusAct = "act" RuleStatusUnknown = "unknown" RuleStatusNotEvaluated = "not_evaluated" )
RuleStatusPass and the related constants are rule-row outcomes. Missing, pending, or partial inputs cannot produce a false pass.
const ( EarningsReasonTerminalNonReporting = "terminal_non_reporting" EarningsReasonBrokerNonIssuer = "broker_nonissuer" EarningsReasonNotApplicable = "earnings_not_applicable" RuleReasonOffSession = "off_session" RuleReasonNoLongBook = "no_long_book" )
These are the closed, policy-owned reasons that can make one canonical Rulebook row not applicable. Alert recovery accepts no free-form or future reason without an explicit policy change.
const ( RuleSingleNameExposure = "single_name_exposure" RuleOptionLinePremium = "option_line_premium" RuleCashSellOnly = "cash_sell_only" RuleExtrinsicBudget = "extrinsic_budget" RuleExpiryRunway = "expiry_runway" RuleCatalystCoverage = "catalyst_coverage" RuleOverwriteEarnings = "overwrite_earnings" RuleEarningsSizeFreeze = "earnings_size_freeze" RuleRedOnGreen = "red_on_green" RuleWinnerTrim = "winner_trim" RuleGreenDayAction = "green_day_action" RuleHedgeIntegrity = "hedge_integrity" RuleExitDiscipline = "exit_discipline" RuleFXExposure = "fx_exposure" )
RuleSingleNameExposure and the related constants identify rules in stable display order.
const ( UnderlyingSourceGreeksTick = "greeks_tick" UnderlyingSourceStockLegMark = "stock_leg_mark" )
UnderlyingSourceGreeksTick and UnderlyingSourceStockLegMark identify how a LegInput obtained its underlying price. The empty value has greeks-tick semantics for compatibility.
const ( RegimeBucketCalm = "calm" RegimeBucketEarlyWarning = "early_warning" RegimeBucketConfirmed = "confirmed" )
RegimeBucketCalm and the related constants are normalized regime buckets consumed by regime-conditional rules. The evaluator does not accept raw lifecycle stage names.
const (
AlertCandidateSnapshotVersion = "alert-candidate-snapshot-v3"
)
AlertCandidateSnapshotVersion identifies the scope-bound source-neutral alert candidate wire contract. It does not approve routing or pageability.
const ConstitutionKind = "ibkr.risk_policy"
ConstitutionKind identifies the operator-authored risk constitution schema.
const StressPolicyFingerprintVersion = "stress-policy-fp-v1"
StressPolicyFingerprintVersion labels fingerprints of the stress threshold policy and keeps that identity domain separate from the constitution.
Variables ¶
This section is empty.
Functions ¶
func BuildAlertAuthorityScope ¶
BuildAlertAuthorityScope binds private alert state to one normalized broker account/mode context without exposing either raw value. The canonicalization is intentionally part of the builder so case or surrounding whitespace cannot split one authority. Callers must still reject aggregate or unknown broker scopes before invoking it.
func BuildAlertEpisodeKey ¶
func BuildAlertEpisodeKey(source AlertSource, kind AlertKind, identityParts ...string) (string, error)
BuildAlertEpisodeKey hashes a producer-approved semantic identity into an opaque stable key. identityParts may contain sensitive source identities; callers must not persist or log them. Only the returned key belongs on the alert contract. Part order is significant.
func BuildAlertOccurrenceKey ¶
BuildAlertOccurrenceKey hashes a daemon-authored occurrence identity for one EpisodeKey. The daemon decides when opening, re-arm, or a page-worthy escalation starts a new occurrence; this helper only makes that decision opaque and stable across transport. The identity parts must not be persisted or logged outside the owning runtime. Because both keys are opaque digests, candidate validation cannot reconstruct this relationship; producers must use this helper and persist the result.
func OptionExtrinsicPerShare ¶
func OptionExtrinsicPerShare(right string, underlying *float64, strike, mark float64) (float64, bool)
OptionExtrinsicPerShare is mark minus intrinsic, floored at zero (a stale mark below intrinsic means the quote, not negative time value). ok=false when the underlying spot is unavailable or the mark is non-positive — callers must treat that as uncomputable, never as zero extrinsic.
func OptionIntrinsicPerShare ¶
OptionIntrinsicPerShare is the per-share in-the-money amount; 0 for an out-of-the-money option or an unrecognized right.
func OptionSpreadPct ¶
OptionSpreadPct is the bid/ask spread as a percentage of mid. Returns ok=false when either side is missing or the quote is crossed/locked.
func RulebookHedgeLeg ¶
RulebookHedgeLeg exposes the policy-owned hedge classification to daemon composition without duplicating rule 12's predicate. Callers map their typed position row into LegInput and receive the exact classification used by rules 1, 2, 4, 5, 12, and 13.
func ValidateAlertAuthorityScope ¶
ValidateAlertAuthorityScope accepts only the opaque value produced by BuildAlertAuthorityScope. Raw account or mode values never belong in a candidate snapshot, daemon registry document, or app inbox.
func ValidateSizePlan ¶
ValidateSizePlan checks the flag-level plan shape (side, prices, target, risk percent, lot, fx) without requiring account data. ComputeSize re-runs the full validation with NLV required; this exists so a runner can fail fast on bad input before paying an account-snapshot round-trip.
Types ¶
type AlertCandidate ¶
type AlertCandidate struct {
EpisodeKey string `json:"episode_key"`
OccurrenceKey string `json:"occurrence_key"`
EvidenceFingerprint string `json:"evidence_fingerprint"`
Source AlertSource `json:"source"`
Kind AlertKind `json:"kind"`
PresentationCode AlertPresentationCode `json:"presentation_code"`
State AlertEpisodeState `json:"state"`
Severity AlertSeverity `json:"severity"`
EvidenceHealth AlertEvidenceHealth `json:"evidence_health"`
Destination AlertDestination `json:"destination"`
EvidenceAsOf time.Time `json:"evidence_as_of"`
StateChangedAt time.Time `json:"state_changed_at"`
ObservedAt time.Time `json:"observed_at"`
}
AlertCandidate contains classified, redacted semantics only. It deliberately has no display copy, source subject, account, symbol, order, route, display ID, target ID, device ID, or delivery-attempt ID.
EpisodeKey is stable for the same root problem. EvidenceFingerprint changes when classified supporting evidence changes. OccurrenceKey changes when the daemon opens/reopens the root problem or classifies an escalation as a new page-worthy occurrence; it stays stable for evidence-only revisions and the occurrence's recovery. App delivery records bind this private occurrence key and create their own per-target attempt IDs; they never infer re-arm, page-worthy escalation, or use a display ID as authority. StateChangedAt is the daemon's semantic transition time.
func (AlertCandidate) MarshalJSON ¶
func (candidate AlertCandidate) MarshalJSON() ([]byte, error)
MarshalJSON validates candidate before encoding it.
func (*AlertCandidate) UnmarshalJSON ¶
func (candidate *AlertCandidate) UnmarshalJSON(data []byte) error
UnmarshalJSON rejects unknown or missing fields and validates the decoded candidate before assigning it to the receiver.
func (AlertCandidate) Validate ¶
func (candidate AlertCandidate) Validate() error
Validate checks the candidate's opaque identities, enum values, timestamps, and recovery coherence.
type AlertCandidateSnapshot ¶
type AlertCandidateSnapshot struct {
SchemaVersion string `json:"schema_version"`
AuthorityScope string `json:"authority_scope"`
AsOf time.Time `json:"as_of"`
CurrentState AlertSnapshotState `json:"current_state"`
Coverage AlertCoverage `json:"coverage"`
Sources []AlertSourceCoverage `json:"sources"`
Candidates []AlertCandidate `json:"candidates"`
}
AlertCandidateSnapshot is the versioned daemon-side measurement contract. CurrentState is validated from candidates and coverage: an empty result is Clear only with complete, current coverage; otherwise it is Unknown.
func (AlertCandidateSnapshot) IsClear ¶
func (snapshot AlertCandidateSnapshot) IsClear() bool
IsClear reports a trustworthy clear only for a fully valid snapshot. It is intentionally false for empty snapshots with incomplete or stale coverage.
func (AlertCandidateSnapshot) MarshalJSON ¶
func (snapshot AlertCandidateSnapshot) MarshalJSON() ([]byte, error)
MarshalJSON validates snapshot before encoding it.
func (*AlertCandidateSnapshot) UnmarshalJSON ¶
func (snapshot *AlertCandidateSnapshot) UnmarshalJSON(data []byte) error
UnmarshalJSON rejects unknown or missing fields and validates the decoded snapshot before assigning it to the receiver.
func (AlertCandidateSnapshot) Validate ¶
func (snapshot AlertCandidateSnapshot) Validate() error
Validate checks the complete snapshot contract and verifies that CurrentState is the state implied by its candidates and coverage.
type AlertCoverage ¶
type AlertCoverage struct {
State AlertCoverageState `json:"state"`
Freshness AlertCoverageFreshness `json:"freshness"`
AsOf time.Time `json:"as_of"`
ExpectedSources []AlertSource `json:"expected_sources"`
CoveredSources []AlertSource `json:"covered_sources"`
}
AlertCoverage makes the universe behind an empty candidate list explicit. CoveredSources must be a subset of ExpectedSources. Complete means the two sets are equal; unavailable means CoveredSources is empty.
func (AlertCoverage) MarshalJSON ¶
func (coverage AlertCoverage) MarshalJSON() ([]byte, error)
MarshalJSON validates coverage before encoding it.
func (*AlertCoverage) UnmarshalJSON ¶
func (coverage *AlertCoverage) UnmarshalJSON(data []byte) error
UnmarshalJSON rejects unknown or missing fields and validates the decoded coverage before assigning it to the receiver.
func (AlertCoverage) Validate ¶
func (coverage AlertCoverage) Validate() error
Validate checks coverage set membership and the coherence of state and freshness. CoveredSources must be non-nil even when it is empty.
type AlertCoverageFreshness ¶
type AlertCoverageFreshness string
AlertCoverageFreshness describes the timeliness of the covered sources. An unavailable source set must use AlertCoverageUnknown.
const ( AlertCoverageCurrent AlertCoverageFreshness = "current" AlertCoverageStale AlertCoverageFreshness = "stale" AlertCoverageUnknown AlertCoverageFreshness = "unknown" )
AlertCoverageCurrent and the related constants classify coverage freshness.
type AlertCoverageState ¶
type AlertCoverageState string
AlertCoverageState describes how much of the expected source set was evaluated. The zero value is invalid.
const ( AlertCoverageComplete AlertCoverageState = "complete" AlertCoveragePartial AlertCoverageState = "partial" )
AlertCoverageComplete and the related constants classify expected-source coverage.
type AlertDestination ¶
type AlertDestination string
AlertDestination names a redacted product surface, not a device or target. Per-target delivery identity belongs to the app delivery ledger.
const ( AlertDestinationMonitor AlertDestination = "monitor" AlertDestinationAlerts AlertDestination = "alerts" AlertDestinationBrief AlertDestination = "brief" )
AlertDestinationMonitor and the related constants name redacted product surfaces rather than delivery targets.
type AlertEpisodeState ¶
type AlertEpisodeState string
AlertEpisodeState is the daemon producer's lifecycle state. The daemon owns dwell, escalation, recovery, and re-arm; the app only persists delivery and receipt state for the producer-authored occurrence. A new opening/reopen or daemon-qualified page-worthy escalation starts a new occurrence; evidence- only revisions and recovery do not.
const ( AlertEpisodeOpen AlertEpisodeState = "open" AlertEpisodeEscalated AlertEpisodeState = "escalated" AlertEpisodeRecovered AlertEpisodeState = "recovered" )
AlertEpisodeOpen and the related constants describe a producer-owned episode transition.
type AlertEvidenceHealth ¶
type AlertEvidenceHealth string
AlertEvidenceHealth describes whether a candidate's supporting observation is usable and current. The zero value is invalid.
const ( AlertEvidenceCurrent AlertEvidenceHealth = "current" AlertEvidencePartial AlertEvidenceHealth = "partial" AlertEvidenceStale AlertEvidenceHealth = "stale" AlertEvidenceError AlertEvidenceHealth = "error" )
AlertEvidenceCurrent and the related constants classify the supporting evidence's usability.
type AlertKind ¶
type AlertKind string
AlertKind is the redacted semantic class of an operator condition. Source and kind remain independent so adapters do not recreate producer policy.
const ( AlertKindMarketState AlertKind = "market_state" AlertKindPortfolioRisk AlertKind = "portfolio_risk" AlertKindMarginSafety AlertKind = "margin_safety" AlertKindDrawdown AlertKind = "drawdown" AlertKindProtectionGap AlertKind = "protection_gap" AlertKindOrderIntegrity AlertKind = "order_integrity" AlertKindReconciliationException AlertKind = "reconciliation_exception" AlertKindGovernance AlertKind = "governance" AlertKindPolicyDrift AlertKind = "policy_drift" AlertKindDataHealth AlertKind = "data_health" AlertKindDeliveryHealth AlertKind = "delivery_health" )
AlertKindMarketState and the related constants classify the root operator condition independently of its producer.
type AlertPresentationCode ¶
type AlertPresentationCode string
AlertPresentationCode is a closed, redacted copy key. Adapters may map it to human text, but cannot receive or interpolate broker identifiers through it.
const ( AlertPresentationPortfolioStress AlertPresentationCode = "portfolio_stress" AlertPresentationMarginCushion AlertPresentationCode = "margin_cushion" AlertPresentationRegimeMarketStress AlertPresentationCode = "regime_market_stress" AlertPresentationRulebookSingleNameExposure AlertPresentationCode = "rulebook_single_name_exposure" AlertPresentationRulebookOptionLinePremium AlertPresentationCode = "rulebook_option_line_premium" AlertPresentationRulebookCashSellOnly AlertPresentationCode = "rulebook_cash_sell_only" AlertPresentationRulebookExtrinsicBudget AlertPresentationCode = "rulebook_extrinsic_budget" AlertPresentationRulebookExpiryRunway AlertPresentationCode = "rulebook_expiry_runway" AlertPresentationRulebookCatalystCoverage AlertPresentationCode = "rulebook_catalyst_coverage" AlertPresentationRulebookOverwriteEarnings AlertPresentationCode = "rulebook_overwrite_earnings" AlertPresentationRulebookEarningsSizeFreeze AlertPresentationCode = "rulebook_earnings_size_freeze" AlertPresentationRulebookRedOnGreen AlertPresentationCode = "rulebook_red_on_green" AlertPresentationRulebookWinnerTrim AlertPresentationCode = "rulebook_winner_trim" AlertPresentationRulebookGreenDayAction AlertPresentationCode = "rulebook_green_day_action" AlertPresentationRulebookHedgeIntegrity AlertPresentationCode = "rulebook_hedge_integrity" AlertPresentationRulebookExitDiscipline AlertPresentationCode = "rulebook_exit_discipline" AlertPresentationRulebookFXExposure AlertPresentationCode = "rulebook_fx_exposure" AlertPresentationProtectionOrphanedOrder AlertPresentationCode = "protection_orphaned_order" AlertPresentationProtectionReconciliationRequired AlertPresentationCode = "protection_reconciliation_required" AlertPresentationOrderIntegrityMismatch AlertPresentationCode = "order_integrity_mismatch" AlertPresentationDataHealthGateway AlertPresentationCode = "data_health_gateway" AlertPresentationDataHealthStorage AlertPresentationCode = "data_health_storage" AlertPresentationDataHealthProposals AlertPresentationCode = "data_health_proposals" AlertPresentationDataHealthOpportunities AlertPresentationCode = "data_health_opportunities" AlertPresentationDataHealthDataFarms AlertPresentationCode = "data_health_data_farms" AlertPresentationDataHealthRegime AlertPresentationCode = "data_health_regime" AlertPresentationDataHealthGamma AlertPresentationCode = "data_health_gamma" AlertPresentationDataHealthQuality AlertPresentationCode = "data_health_quality" AlertPresentationRiskPolicyLimitWouldBlock AlertPresentationCode = "risk_policy_limit_would_block" AlertPresentationRiskPolicyDrawdownLatched AlertPresentationCode = "risk_policy_drawdown_latched" AlertPresentationRiskPolicyDrift AlertPresentationCode = "risk_policy_drift" AlertPresentationReconciliationDue AlertPresentationCode = "reconciliation_due" AlertPresentationReconciliationException AlertPresentationCode = "reconciliation_exception" AlertPresentationReconciliationConfirmedFlow AlertPresentationCode = "reconciliation_confirmed_flow" AlertPresentationGovernanceMonthlyPulse AlertPresentationCode = "governance_monthly_pulse" AlertPresentationDeliveryHealth AlertPresentationCode = "delivery_health" AlertPresentationRulebookLegacyCondition AlertPresentationCode = "rulebook_condition" AlertPresentationRiskPolicyLegacyCondition AlertPresentationCode = "risk_policy_condition" AlertPresentationReconciliationLegacyCondition AlertPresentationCode = "reconciliation_condition" AlertPresentationGovernanceLegacyCondition AlertPresentationCode = "governance_condition" )
Alert presentation codes cover every producer-owned candidate class. The generic condition codes exist only to preserve lifecycle identity while a version-2 registry is upgraded; the next producer observation replaces them with the precise code without opening a new occurrence.
type AlertSeverity ¶
type AlertSeverity string
AlertSeverity expresses the producer-classified urgency of an alert candidate. The zero value is invalid.
const ( AlertSeverityObserve AlertSeverity = "observe" AlertSeverityWatch AlertSeverity = "watch" AlertSeverityAct AlertSeverity = "act" AlertSeverityUrgent AlertSeverity = "urgent" )
AlertSeverityObserve and the related constants rank candidate urgency.
type AlertSnapshotState ¶
type AlertSnapshotState string
AlertSnapshotState is the state derived from validated candidates and coverage. Clear requires complete, current coverage.
const ( AlertSnapshotClear AlertSnapshotState = "clear" AlertSnapshotActive AlertSnapshotState = "active" AlertSnapshotUnknown AlertSnapshotState = "unknown" )
AlertSnapshotClear and the related constants are derived snapshot states.
type AlertSource ¶
type AlertSource string
AlertSource names the daemon authority that produced a candidate. These are product subsystem names, never broker, account, symbol, order, or device identifiers.
const ( AlertSourceStress AlertSource = "canary" AlertSourceRegime AlertSource = "regime" AlertSourceRulebook AlertSource = "rulebook" AlertSourceRiskPolicy AlertSource = "risk_policy" AlertSourceProtection AlertSource = "protection" AlertSourceOrderIntegrity AlertSource = "order_integrity" AlertSourceReconciliation AlertSource = "reconciliation" AlertSourceGovernance AlertSource = "governance" AlertSourceDataHealth AlertSource = "data_health" AlertSourceDelivery AlertSource = "delivery" )
AlertSourceStress and the related constants identify candidate-producing subsystems without carrying private subject identity.
AlertSourceStress keeps the wire value "canary" for the same reason stressEpisodeIdentity keeps "portfolio_canary": BuildAlertEpisodeKey hashes the source into the episode key, so changing this string produces a different key for the same condition with no mapping from the old one. The identity parts are raw account/mode values that no stored document carries, so no registry or ledger migration can recompute the new key from the old — every open portfolio-stress episode would be abandoned mid-flight and reopen as a fresh occurrence, re-paging the operator for an alert they already hold. The Go identifier is the name; this literal is a persisted identity.
type AlertSourceCoverage ¶
type AlertSourceCoverage struct {
Source AlertSource `json:"source"`
Status string `json:"status"`
Reason string `json:"reason"`
EvidenceHealth AlertEvidenceHealth `json:"evidence_health"`
InputAsOf time.Time `json:"input_as_of"`
ObservedAt time.Time `json:"observed_at"`
EvidenceAsOf time.Time `json:"evidence_as_of"`
FreshUntil time.Time `json:"fresh_until"`
Covered bool `json:"covered"`
}
AlertSourceCoverage names the health of one expected producer in the same snapshot as its candidates. Times are absent only before that producer has been observed in the current authority scope.
func (AlertSourceCoverage) MarshalJSON ¶
func (source AlertSourceCoverage) MarshalJSON() ([]byte, error)
MarshalJSON validates source coverage before encoding it.
func (*AlertSourceCoverage) UnmarshalJSON ¶
func (source *AlertSourceCoverage) UnmarshalJSON(data []byte) error
UnmarshalJSON rejects unknown or missing fields. Snapshot validation applies the final timestamp and aggregate-coverage coherence checks.
func (AlertSourceCoverage) Validate ¶
func (source AlertSourceCoverage) Validate(snapshotAsOf time.Time) error
Validate checks one source row without interpreting producer-specific status or reason codes. Those codes remain bounded lowercase identifiers and cannot carry free text or private identity.
type CapitalObservation ¶
CapitalObservation is one equity reading in base currency.
type CapitalRuntime ¶
type CapitalRuntime struct {
// AdjustedPeakBase is the peak of (equity − cumulative external flows).
AdjustedPeakBase float64
PeakAsOf time.Time
// CumExternalFlowsBase is the policy-version-selected cumulative flow
// input: declared events through v2, statement truth plus bridges in v3.
CumExternalFlowsBase float64
// Seeded is false until the first equity observation establishes the
// peak; an unseeded state evaluates unknown, never ok.
Seeded bool
// BlockLatched persists across restarts and mark recovery; only a
// journaled human reset clears it.
BlockLatched bool
// LastReconciledAt is the last human or automatic reconcile evidence;
// zero means never reconciled.
LastReconciledAt time.Time
// UnreconciledOverrideUntil is populated only from an active, unexpired
// one-shot override on capital.max_unreconciled_days. No other override
// control reaches evaluation.
UnreconciledOverrideUntil time.Time
}
CapitalRuntime is the daemon-owned runtime state the evaluator consumes: the cash-flow-adjusted peak, effective cumulative external flows, the drawdown latch, and reconciliation recency. The daemon owns mutation; the evaluator only reads.
type CapitalVerdict ¶
type CapitalVerdict struct {
Tier string
// EffectiveRiskCapitalBase = min(declared, equity − floor); nil when
// unapproved inputs or no usable equity observation.
EffectiveRiskCapitalBase *float64
// DrawdownBase and ConsumedPct measure from the cash-flow-adjusted
// peak; ConsumedPct is drawdown / declared risk capital × 100.
DrawdownBase *float64
ConsumedPct *float64
EquityStale bool
// ReconcileStale means the declared-events ledger is older than
// capital.max_unreconciled_days (or never attested).
ReconcileStale bool
Unapproved []string
Reasons []string
}
CapitalVerdict is the pure evaluation result.
func EvaluateCapital ¶
func EvaluateCapital(c *Constitution, rt CapitalRuntime, obs *CapitalObservation, now time.Time) CapitalVerdict
EvaluateCapital applies the constitution to the runtime state and the latest observation. Invariants: absence of data or of approved numbers never yields ok; the latch dominates everything except unapproved disclosure; risk-reducing exemptions are the caller's concern (order classification lives on the preview path, not here).
type Constitution ¶
type Constitution struct {
Kind string `toml:"kind" json:"kind"`
SchemaVersion int `toml:"schema_version" json:"schema_version"`
PolicyID string `toml:"policy_id" json:"policy_id"`
PolicyVersion int `toml:"policy_version" json:"policy_version"`
Capital ConstitutionCapital `toml:"capital" json:"capital"`
Drawdown ConstitutionDrawdown `toml:"drawdown" json:"drawdown"`
Override ConstitutionOverride `toml:"override" json:"override"`
Recon ConstitutionRecon `toml:"recon" json:"recon"`
Cadence ConstitutionCadence `toml:"cadence" json:"cadence"`
Inventory ConstitutionInventory `toml:"inventory" json:"inventory"`
}
Constitution is the typed operator-authored capital policy. Material limits are pointers: nil means unapproved, and validation never backfills them.
func (Constitution) EffectiveBlockEnforcement ¶
func (c Constitution) EffectiveBlockEnforcement() string
EffectiveBlockEnforcement resolves the block tier's enforcement class; empty defaults to shadow — the fail-safe direction (observe and journal, never gate).
func (Constitution) FingerprintKey ¶
func (c Constitution) FingerprintKey() string
FingerprintKey hashes an explicit JSON projection of the full policy (risk.Policy / protection-policy discipline — the rulebook's %.4f variant is the outlier, not the model). Absent material keys marshal as null and are part of the identity: an unapproved gap is policy state.
func (Constitution) UnapprovedKeys ¶
func (c Constitution) UnapprovedKeys() []string
UnapprovedKeys lists the material keys the operator has not chosen yet. Order matches the explain view.
func (Constitution) Validate ¶
func (c Constitution) Validate() error
Validate rejects a structurally unusable constitution. It never backfills material keys: a file that is valid but incomplete loads with unapproved gaps, which is the intended state until the operator writes each number.
type ConstitutionArtefact ¶
type ConstitutionArtefact struct {
Class string `toml:"class" json:"class,omitempty"`
}
ConstitutionArtefact declares one cadence artefact. An empty Class means the artefact is undeclared; validation accepts advisory as the only non-empty class.
type ConstitutionCadence ¶
type ConstitutionCadence struct {
Morning ConstitutionArtefact `toml:"morning" json:"morning"`
EOD ConstitutionArtefact `toml:"eod" json:"eod"`
Weekly ConstitutionArtefact `toml:"weekly" json:"weekly"`
// Nudges and Monthly are policy-version-4-only. Pointers preserve the
// distinction between an absent table and an explicitly authored one, so
// old policies can reject the new keys and v4 can report missing material.
Nudges *ConstitutionNudgeCadence `toml:"nudges" json:"nudges,omitempty"`
Monthly *ConstitutionMonthlyCadence `toml:"monthly" json:"monthly,omitempty"`
}
ConstitutionCadence declares operating-cadence artefacts whose completion can be journaled. Artefact validation accepts only advisory declarations.
type ConstitutionCapital ¶
type ConstitutionCapital struct {
BaseCurrency string `toml:"base_currency" json:"base_currency"`
ProtectedFloor *float64 `toml:"protected_floor" json:"protected_floor"`
DeclaredRiskCapital *float64 `toml:"declared_risk_capital" json:"declared_risk_capital"`
// MaxEquityAgeMinutes bounds trust in the last equity observation;
// beyond it the evaluator marks the capital state stale and does not pass it.
MaxEquityAgeMinutes *int `toml:"max_equity_age_minutes" json:"max_equity_age_minutes"`
// MaxUnreconciledDays bounds trust in the declared capital-event ledger
// between reconciliation evidence; expiry is reported as stale.
MaxUnreconciledDays *int `toml:"max_unreconciled_days" json:"max_unreconciled_days"`
}
ConstitutionCapital anchors the capital authority: an internal protected equity floor and a declared (human-authorized) risk capital, both in the account base currency. Effective risk capital = min(declared_risk_capital, equity − protected_floor); nothing — deposits, profits, live events — raises the declared number without a fingerprinted policy revision.
type ConstitutionDrawdown ¶
type ConstitutionDrawdown struct {
WarnConsumedPct *float64 `toml:"warn_consumed_pct" json:"warn_consumed_pct"`
BlockConsumedPct *float64 `toml:"block_consumed_pct" json:"block_consumed_pct"`
// BlockEnforcement is shadow (default when empty) or advisory in v1.
BlockEnforcement string `toml:"block_enforcement" json:"block_enforcement"`
}
ConstitutionDrawdown is the two-tier response ladder. Both thresholds are percentages of declared risk capital consumed from the cash-flow-adjusted equity peak. Warn is advisory and self-clearing; block latches in daemon state and clears only through a journaled human reset that re-bases the peak.
type ConstitutionInventory ¶
type ConstitutionInventory struct {
Rulebook *ConstitutionPolicyPin `toml:"rulebook" json:"rulebook,omitempty"`
Protection *ConstitutionPolicyPin `toml:"protection" json:"protection,omitempty"`
Stress *ConstitutionPolicyPin `toml:"stress" json:"stress,omitempty"`
}
ConstitutionInventory pins the sibling policies by identity so the policy view can disclose drift between what the constitution was approved against and what is live. Pins are identity references, not threshold copies: the siblings stay authoritative for their own numbers.
type ConstitutionLimit ¶
type ConstitutionLimit struct {
Key string `json:"key"`
Value string `json:"value"`
Meaning string `json:"meaning"`
Source string `json:"source"` // file | default | unapproved
Enforcement string `json:"enforcement"` // advisory | shadow | structural
}
ConstitutionLimit is one row of the generated human view (`canary policy show --explain`): a limit key, its effective value, what it means in plain English, where the value came from, and its enforcement class. Observation and override columns are overlaid by the daemon; this layer is pure policy so every surface renders identical meanings.
func ConstitutionLimits ¶
func ConstitutionLimits(c *Constitution) []ConstitutionLimit
ConstitutionLimits renders every material limit and governance field of the constitution. A nil policy (no file) yields the same rows with every value unapproved, so the view never hides what is missing.
type ConstitutionMonthlyCadence ¶
type ConstitutionMonthlyCadence struct {
Class *string `toml:"class" json:"class"`
DayOfMonth *int `toml:"day_of_month" json:"day_of_month"`
NudgeAtLocal *string `toml:"nudge_at_local" json:"nudge_at_local"`
}
ConstitutionMonthlyCadence declares the one standing monthly touchpoint. DayOfMonth is limited to 1..28 so every configured month has the day.
type ConstitutionNudgeCadence ¶
type ConstitutionNudgeCadence struct {
Timezone *string `toml:"timezone" json:"timezone"`
ReconcileWarningDays *int `toml:"reconcile_warning_days" json:"reconcile_warning_days"`
}
ConstitutionNudgeCadence owns the local clock used by cadence-driven nudges and the rolling warning horizon for reconciliation. Neither field has a code default.
type ConstitutionOverride ¶
type ConstitutionOverride struct {
MaxDurationHours *int `toml:"max_duration_hours" json:"max_duration_hours"`
}
ConstitutionOverride caps the one-shot exception mechanism: human-only, single named control, reason required, hard expiry. The mechanism itself (origin gating, journaling) is code-owned; only the lifetime cap is policy.
type ConstitutionPolicyPin ¶
type ConstitutionPolicyPin struct {
ID string `toml:"id" json:"id"`
Version string `toml:"version" json:"version"`
}
ConstitutionPolicyPin identifies one sibling policy version. Version is a string so integer-versioned (rulebook, protection) and string-versioned (stress) policies pin uniformly.
type ConstitutionRecon ¶
type ConstitutionRecon struct {
// A statement flow and a declared event match on amount when they
// differ by at most max(amount_tolerance_pct% of the statement
// amount, amount_tolerance_min in base currency).
AmountTolerancePct *float64 `toml:"amount_tolerance_pct" json:"amount_tolerance_pct"`
AmountToleranceMin *float64 `toml:"amount_tolerance_min" json:"amount_tolerance_min"`
// DateWindowBusinessDays bounds how far apart the statement value
// date and the declared effective date may sit (weekday count).
DateWindowBusinessDays *int `toml:"date_window_business_days" json:"date_window_business_days"`
// MaxReportAgeDays bounds how old the newest ingested statement may
// be for a recon report to back a reconcile sign-off.
MaxReportAgeDays *int `toml:"max_report_age_days" json:"max_report_age_days"`
// MaxEquityDivergencePct bounds the absolute same-day difference between
// broker statement equity and the runtime observation before v3 may
// automatically accept a clean report as reconcile evidence.
MaxEquityDivergencePct *float64 `toml:"max_equity_divergence_pct" json:"max_equity_divergence_pct"`
}
ConstitutionRecon sets what counts as a reconciliation exception when broker statement flows are matched against the declared capital-event ledger (internal-docs/design/post-trade-truth.md). These are policy, not plumbing: they decide which differences the operator must look at.
type EarningsInput ¶
type EarningsInput struct {
Known bool
// NotApplicable marks fresh exact broker identity proving that this held
// contract is a nonissuer security. It is independent from reviewed
// terminal/non-reporting issuer evidence.
NotApplicable bool
// TerminalNonReporting marks reviewed exact-contract evidence that no
// future issuer earnings event applies. It is neither a known date nor an
// unknown: rules 6-8 disclose an exemption for the relevant name.
TerminalNonReporting bool
Date time.Time // ET calendar date (midnight ET)
TimeOfDay string // "amc" | "bmo" | "" (unspecified)
Estimated bool
Stale bool
// SessionsUntil is the number of US equity sessions from today (ET) to
// the earnings date inclusive, computed by the daemon via marketcal.
// nil when unknown.
SessionsUntil *int
// Source is the daemon's closed provenance vocabulary. verified_terminal
// means exact-contract authority was present; TerminalNonReporting is true
// only when that authority is current, identity-matched, and conflict-free.
Source string
// Reason is a stable typed explanation for unknown/stale evidence. It is
// disclosure only and never turns absence into a pass.
Reason string
}
EarningsInput is the per-name earnings context mapped by the daemon.
type Evaluation ¶
Evaluation is the pure result: rows in rulebook order plus the hardest-first ranking (indexes into Rows).
func EvaluateRulebook ¶
func EvaluateRulebook(in RuleInputs, pol RulebookPolicy) Evaluation
EvaluateRulebook computes all 14 rules. It never returns fewer than 14 rows; degraded inputs degrade statuses, not row presence.
type LegInput ¶
type LegInput struct {
Desc string // "NOW 20260717 C 130"
Right string // C | P
Strike float64
Expiry time.Time // ET calendar date
DTE int
Quantity float64 // signed contracts
Multiplier float64
Mark float64
Underlying *float64
Delta *float64
// MarketValueBase is the signed base-currency mark value of the leg.
MarketValueBase float64
// ExtrinsicBase is the base-currency extrinsic value for long legs;
// nil when uncomputable (missing underlying or mark) — never zero it.
ExtrinsicBase *float64
// CostBasisBase is the base-currency premium paid for the leg (avg cost
// is multiplier-inclusive on options — do not re-multiply); nil when the
// gateway didn't deliver it.
CostBasisBase *float64
// FXToBase converts the leg's quote currency into base; nil when the FX
// path is unknown (rule 1's lower bound then treats the leg as
// unbounded).
FXToBase *float64
// UnderlyingSource discloses where Underlying came from: empty or
// UnderlyingSourceGreeksTick for the per-leg model tick,
// UnderlyingSourceStockLegMark for the same-name stock-leg join. Derived
// spots support OTM-ness and extrinsic; they never classify hedge legs.
UnderlyingSource string
// HedgeListed marks the underlying as being on the policy hedge list.
HedgeListed bool
}
LegInput is one option leg of a name.
type MonthlyPulseCompletion ¶
type MonthlyPulseCompletion struct {
Month string
PolicyFingerprint string
// CompletedAt and Evidence are daemon-authored from paired brief render
// evidence. Origin enforcement remains outside this pure evaluator.
CompletedAt time.Time
Evidence string
}
MonthlyPulseCompletion carries daemon-authored evidence that the pulse for one policy fingerprint and local calendar month was completed. The pure evaluator validates the evidence fields but cannot establish their origin.
type MonthlyPulseEvaluation ¶
type MonthlyPulseEvaluation struct {
Status string
Month string
DueAt time.Time
Candidate *NudgeCandidate
}
MonthlyPulseEvaluation reports the local policy month, its resolved due instant, and an optional due candidate. Invalid or ambiguous schedules are blocked rather than assigned a fallback time.
func EvaluateMonthlyPulse ¶
func EvaluateMonthlyPulse(input MonthlyPulseInput) MonthlyPulseEvaluation
EvaluateMonthlyPulse derives the monthly cadence state. Completion is accepted only for the current month and policy fingerprint at or after the unambiguous due instant.
type MonthlyPulseInput ¶
type MonthlyPulseInput struct {
Now time.Time
Cadence ConstitutionCadence
PolicyFingerprint string
// PolicyEvidenceReady means current readable policy pins all match. Before
// due it is ignored; from due onward false blocks both due and completion.
PolicyEvidenceReady bool
Completion *MonthlyPulseCompletion
}
MonthlyPulseInput supplies the current instant, approved cadence, policy identity, evidence readiness, and optional completion evidence.
type NameInput ¶
type NameInput struct {
Symbol string
// StockConID and StockSecType preserve the held underlying stock's broker
// identity for exact-contract classifications. Zero means no stock leg or
// no broker identity; symbol alone never activates such a classification.
StockConID int
StockSecType string
// ExposureBase = stock + Σ delta×contracts×multiplier×spot, base ccy.
ExposureBase float64
// ExposureBaseComplete reports whether ExposureBase covers every leg the
// aggregator saw (false when any priced leg was excluded: delta without
// spot, markless stock, missing FX). Rule 1's lower bound refuses to
// build on a partial sum — "proven ≥" must never overstate.
ExposureBaseComplete bool
// GreeksGapNotionalBase is |notional| of option legs missing delta —
// exposure understatement risk.
GreeksGapNotionalBase float64
MarketValueBase float64
HasStockLeg bool
// StockDayChangePct is the stock leg's quote-enriched day change; nil
// for option-only names or when enrichment failed.
StockDayChangePct *float64
Legs []LegInput
}
NameInput is the per-underlying aggregation the daemon maps from PositionGroup/UnderlyingExposure. ExposureBase must be the same value the canary's concentration check reads.
type NudgeCandidate ¶
type NudgeCandidate struct {
Fingerprint string `json:"fingerprint"`
Kind string `json:"kind"`
State string `json:"state"`
Severity string `json:"severity"`
Title string `json:"title"`
Body string `json:"body"`
OccurredAt time.Time `json:"occurred_at,omitzero"`
DueAt time.Time `json:"due_at,omitzero"`
ExpiresAt time.Time `json:"expires_at,omitzero"`
Destination string `json:"destination"`
}
NudgeCandidate is the pure semantic result consumed by daemon adapters. It deliberately has no details, URL, raw source identity, money, symbol, account, or order fields. CanonicalizeNudgeCandidate replaces Title, Body, Severity, and Destination from the candidate's kind and state.
func CanonicalizeNudgeCandidate ¶
func CanonicalizeNudgeCandidate(candidate NudgeCandidate) (NudgeCandidate, error)
CanonicalizeNudgeCandidate validates the narrow candidate contract and replaces all caller-authored display fields with approved template copy. It is pure so RPC and other adapters share the same semantic boundary.
func EvaluateConfirmedFlow ¶
func EvaluateConfirmedFlow(statementRowIdentity string, occurredAt time.Time) *NudgeCandidate
EvaluateConfirmedFlow returns a candidate keyed by a normalized, non-empty statement-row identity. The identity is hashed and is not copied into the returned candidate.
func EvaluateDrawdownLatched ¶
func EvaluateDrawdownLatched(latchEpisode string, open bool, occurredAt time.Time) *NudgeCandidate
EvaluateDrawdownLatched returns an open drawdown candidate for a non-empty latch episode. It returns nil when the latch is closed or unidentified.
func EvaluatePolicyDrift ¶
func EvaluatePolicyDrift(mismatches []NudgePinMismatch, occurredAt time.Time) *NudgeCandidate
EvaluatePolicyDrift returns one order-independent candidate for valid policy identity mismatches. Equal or incomplete identities are ignored.
func EvaluateReconcileDue ¶
func EvaluateReconcileDue(input ReconcileDueInput) *NudgeCandidate
EvaluateReconcileDue uses an exact rolling duration. Equality at the deadline remains due-soon; overdue begins only when Now.After(Deadline).
func EvaluateReconcileException ¶
func EvaluateReconcileException(unresolved []ReconcileExceptionIdentity, occurredAt time.Time) *NudgeCandidate
EvaluateReconcileException returns one order-independent candidate for the valid unresolved identities. It returns nil when no usable identity remains.
type NudgePinMismatch ¶
type NudgePinMismatch struct {
Policy string
PinnedID string
PinnedVersion string
LiveID string
LiveVersion string
}
NudgePinMismatch compares one constitution pin with the corresponding live policy identity.
type PlannerMode ¶
type PlannerMode string
PlannerMode identifies the action family a downstream planner may prepare. It conveys no broker-write authority.
const ( PlannerModeNone PlannerMode = "none" PlannerModeStage PlannerMode = "stage" PlannerModeDefend PlannerMode = "defend" PlannerModeRebalance PlannerMode = "rebalance" PlannerModeDeploy PlannerMode = "deploy" PlannerModeConfirmData PlannerMode = "confirm_data" )
PlannerModeNone and the related constants enumerate planner action modes.
type PlannerReadiness ¶
type PlannerReadiness string
PlannerReadiness describes how close a planner is to presenting an action. Ready still conveys no broker-write authority.
const ( PlannerReadinessNone PlannerReadiness = "none" PlannerReadinessWatch PlannerReadiness = "watch" PlannerReadinessPrestage PlannerReadiness = "prestage" PlannerReadinessReady PlannerReadiness = "ready" PlannerReadinessBlocked PlannerReadiness = "blocked" )
PlannerReadinessNone and the related constants enumerate preparation states.
type Policy ¶
type Policy struct {
Name string `json:"name"`
Profile string `json:"profile"`
Version string `json:"version"`
MarginUrgentPct float64 `json:"margin_urgent_pct"`
MarginActPct float64 `json:"margin_act_pct"`
MarginWatchPct float64 `json:"margin_watch_pct"`
MarginTargetPct float64 `json:"margin_target_pct"`
GrossExposureWatchPct float64 `json:"gross_exposure_watch_pct"`
NetDeltaWatchPct float64 `json:"net_delta_watch_pct"`
GrossDeltaWatchPct float64 `json:"gross_delta_watch_pct"`
GrossExposureStressActPct float64 `json:"gross_exposure_stress_act_pct"`
NetDeltaStressActPct float64 `json:"net_delta_stress_act_pct"`
GrossDeltaStressActPct float64 `json:"gross_delta_stress_act_pct"`
GrossExposureStressUrgentPct float64 `json:"gross_exposure_stress_urgent_pct"`
NetDeltaStressUrgentPct float64 `json:"net_delta_stress_urgent_pct"`
GrossDeltaStressUrgentPct float64 `json:"gross_delta_stress_urgent_pct"`
SingleNameExposureWatchPct float64 `json:"single_name_exposure_watch_pct"`
SingleNameDeltaWatchPct float64 `json:"single_name_delta_watch_pct"`
SingleNameTargetPct float64 `json:"single_name_target_pct"`
OptionGreeksMinCoveragePct float64 `json:"option_greeks_min_coverage_pct"`
SPYDropPct float64 `json:"spy_drop_pct"`
SPYHardDropPct float64 `json:"spy_hard_drop_pct"`
SPYCrashPct float64 `json:"spy_crash_pct"`
SPYRallyPct float64 `json:"spy_rally_pct"`
SPYHardRallyPct float64 `json:"spy_hard_rally_pct"`
VIXSpikePct float64 `json:"vix_spike_pct"`
VIXHardSpikePct float64 `json:"vix_hard_spike_pct"`
VIXCrushPct float64 `json:"vix_crush_pct"`
VIXHardCrushPct float64 `json:"vix_hard_crush_pct"`
DailyPnLWatchPct float64 `json:"daily_pnl_watch_pct"`
DailyPnLActPct float64 `json:"daily_pnl_act_pct"`
HeldStressMaterialPct float64 `json:"held_stress_material_pct"`
HeldUnderlyingPnLWatchPct float64 `json:"held_underlying_pnl_watch_pct"`
HeldUnderlyingPnLActPct float64 `json:"held_underlying_pnl_act_pct"`
HeldOptionNearDTE int `json:"held_option_near_dte"`
HeldOptionDeltaWatchPct float64 `json:"held_option_delta_watch_pct"`
HeldOptionDeltaActPct float64 `json:"held_option_delta_act_pct"`
HeldLiquidityStockSpreadPct float64 `json:"held_liquidity_stock_spread_pct"`
HeldLiquidityOptionSpreadPctOfMid float64 `json:"held_liquidity_option_spread_pct_of_mid"`
Reduce ReducePolicy `json:"reduce"`
}
Policy holds the shared stress thresholds used by live monitors and protection proposal policy.
func DefaultPolicy ¶
func DefaultPolicy() Policy
DefaultPolicy returns the complete compiled stress policy.
func (Policy) FingerprintKey ¶
FingerprintKey returns a deterministic digest of the policy profile, version, and every threshold field. Name is represented through the PolicyProfile fallback and is otherwise not part of the digest.
func (Policy) PolicyProfile ¶
PolicyProfile returns Profile, falling back to Name for older policy values.
func (Policy) PolicyVersion ¶
PolicyVersion returns the policy's version label.
type PortfolioPosture ¶
type PortfolioPosture string
PortfolioPosture summarizes the portfolio response implied by a set of signals. The zero value is unspecified.
const ( PortfolioPostureNeutral PortfolioPosture = "neutral" PortfolioPostureThreat PortfolioPosture = "threat" PortfolioPostureRebalance PortfolioPosture = "rebalance" PortfolioPostureOpportunity PortfolioPosture = "opportunity" PortfolioPostureThreatOpportunity PortfolioPosture = "threat_opportunity" PortfolioPostureConfirmData PortfolioPosture = "confirm_data" )
PortfolioPostureNeutral and the related constants enumerate portfolio response summaries.
type ReconcileDueInput ¶
ReconcileDueInput supplies the current instant, reconciliation deadline, and approved warning horizon. A nil WarningDays leaves the evaluation inactive.
type ReconcileExceptionIdentity ¶
ReconcileExceptionIdentity contains only the identity/material fields the daemon has already allowlisted for semantic dedupe. They are normalized and hashed; none is copied into the candidate.
type ReducePolicy ¶
type ReducePolicy struct {
FrontDTE int `json:"front_dte"`
MidDTE int `json:"mid_dte"`
HedgeOffsetMinPct float64 `json:"hedge_offset_min_pct"`
HedgeOffsetMaxPct float64 `json:"hedge_offset_max_pct"`
MaxOptionSpreadAbs float64 `json:"max_option_spread_abs"`
MaxOptionSpreadPctOfMid float64 `json:"max_option_spread_pct_of_mid"`
OrderType string `json:"order_type"`
TIF string `json:"tif"`
AllowMarketOrders bool `json:"allow_market_orders"`
}
ReducePolicy contains the option-selection and order-shape constraints used when constructing risk-reduction proposals. It does not authorize an order.
type RegimeThresholds ¶
type RegimeThresholds struct {
CashSellOnlyPct float64 `toml:"cash_sell_only_pct" json:"cash_sell_only_pct"`
ExtrinsicWatchPct float64 `toml:"extrinsic_watch_pct" json:"extrinsic_watch_pct"`
ExtrinsicActPct float64 `toml:"extrinsic_act_pct" json:"extrinsic_act_pct"`
HedgeBandMinPct float64 `toml:"hedge_band_min_pct" json:"hedge_band_min_pct"`
HedgeBandMaxPct float64 `toml:"hedge_band_max_pct" json:"hedge_band_max_pct"`
}
RegimeThresholds is one stage's threshold set for the regime-conditional rules: rule 3 cash floor, rule 4 extrinsic budget (ex-hedge), rule 12 hedge band.
type RuleInputs ¶
type RuleInputs struct {
AsOf time.Time
BaseCurrency string
Positions SourceState
Account SourceState
NLVBase *float64
CashBase *float64
DailyPnLBase *float64
Names []NameInput
// SessionOpen: US equity regular session per marketcal.
SessionOpen bool
// SPYDayChangePct is the market tape for rule 9; nil when unavailable.
SPYDayChangePct *float64
Earnings map[string]EarningsInput
// RegimeStage is the bucketed regime lifecycle stage (RegimeBucket*);
// empty when no stage has ever been observed. RegimeStageCarried marks a
// stage older than the policy max age or restored from the persisted
// store — carried stages evaluate worse-of(carried set, calm set).
RegimeStage string
RegimeStageAsOf time.Time
RegimeStageCarried bool
// NonBaseNLVBase is the base-currency net liquidation held in non-base
// currencies (rule 14). nil = unavailable (absent currency report,
// missing FX) — never zero it: an empty currency report on a book with
// non-base legs is a data gap, not a base-only book.
NonBaseNLVBase *float64
// NonBaseCurrencies names the currencies behind NonBaseNLVBase.
NonBaseCurrencies []string
}
RuleInputs is the full mapped snapshot for one evaluation.
type RuleOffender ¶
type RuleOffender struct {
Symbol string `json:"symbol"`
Leg string `json:"leg,omitempty"`
Observed float64 `json:"observed"`
ImpactBase float64 `json:"impact_base,omitempty"`
Note string `json:"note,omitempty"`
}
RuleOffender is one name or leg contributing to a breach, worst first.
type RuleRow ¶
type RuleRow struct {
ID string `json:"id"`
Number int `json:"number"`
Title string `json:"title"`
Status string `json:"status"`
Observed *float64 `json:"observed,omitempty"`
Threshold *float64 `json:"threshold,omitempty"`
Unit string `json:"unit,omitempty"`
Evidence string `json:"evidence"`
Reason string `json:"reason,omitempty"`
Offenders []RuleOffender `json:"offenders,omitempty"`
Exempt []RuleOffender `json:"exempt,omitempty"`
ImpactBase float64 `json:"impact_base,omitempty"`
Notes []string `json:"notes,omitempty"`
// ObservedIsLowerBound marks Observed as a provable minimum computed
// from partial inputs ("≥ X%"), not an exact measurement. Only breaches
// may carry it — a lower bound can indict, never acquit.
ObservedIsLowerBound bool `json:"observed_is_lower_bound,omitempty"`
}
RuleRow is one rule's verdict.
type RulebookPolicy ¶
type RulebookPolicy struct {
ID string `toml:"id" json:"id"`
Version int `toml:"version" json:"version"`
// Rule 1 — single_name_exposure (% of NLV, delta-dollar exposure).
SingleNameWatchPct float64 `toml:"single_name_watch_pct" json:"single_name_watch_pct"`
SingleNameActPct float64 `toml:"single_name_act_pct" json:"single_name_act_pct"`
// Rule 2 — option_line_premium (% of NLV, long option line market value).
// Hedge-classified legs (rule12HedgeLeg) evaluate against the hedge tier;
// rule 12 owns hedge sizing, this tier only bounds premium at risk.
OptionLineWatchPct float64 `toml:"option_line_watch_pct" json:"option_line_watch_pct"`
OptionLineActPct float64 `toml:"option_line_act_pct" json:"option_line_act_pct"`
HedgeLineWatchPct float64 `toml:"hedge_line_watch_pct" json:"hedge_line_watch_pct"`
HedgeLineActPct float64 `toml:"hedge_line_act_pct" json:"hedge_line_act_pct"`
// Rule 5 — expiry_runway (calendar DTE bounds for long options).
RunwayWatchDTE int `toml:"runway_watch_dte" json:"runway_watch_dte"`
RunwayActDTE int `toml:"runway_act_dte" json:"runway_act_dte"`
RunwayITMDeltaFloor float64 `toml:"runway_itm_delta_floor" json:"runway_itm_delta_floor"`
// Rule 7 — overwrite_earnings short-put act tier: a spanning short put
// escalates from watch to act when its assignment notional reaches the
// line share of NLV, or a name's spanning short puts together reach the
// name share.
ShortPutActLinePctNLV float64 `toml:"short_put_act_line_pct_nlv" json:"short_put_act_line_pct_nlv"`
ShortPutActNamePctNLV float64 `toml:"short_put_act_name_pct_nlv" json:"short_put_act_name_pct_nlv"`
// Rule 8 — earnings_size_freeze (US sessions to earnings).
EarningsFreezeSessions int `toml:"earnings_freeze_sessions" json:"earnings_freeze_sessions"`
// Rules 9/10 — tape thresholds (day-change %).
RedOnGreenNameDropPct float64 `toml:"red_on_green_name_drop_pct" json:"red_on_green_name_drop_pct"`
RedOnGreenSPYUpPct float64 `toml:"red_on_green_spy_up_pct" json:"red_on_green_spy_up_pct"`
WinnerTrimDayUpPct float64 `toml:"winner_trim_day_up_pct" json:"winner_trim_day_up_pct"`
WinnerTrimMinExpoPct float64 `toml:"winner_trim_min_exposure_pct" json:"winner_trim_min_exposure_pct"`
// Rules 3/4/12 — regime-conditional threshold sets. A fresh regime stage
// selects its set; a carried or never-seen stage evaluates the carried set
// AND the calm set
// and keeps the worse verdict, so stale regime data can hold or tighten
// a verdict but never relax it.
RegimeCalm RegimeThresholds `toml:"regime_calm" json:"regime_calm"`
RegimeEarlyWarning RegimeThresholds `toml:"regime_early_warning" json:"regime_early_warning"`
RegimeConfirmed RegimeThresholds `toml:"regime_confirmed" json:"regime_confirmed"`
// RegimeStageMaxAgeMinutes bounds trust in the latched regime stage;
// older stages evaluate as carried (worse-of semantics above).
RegimeStageMaxAgeMinutes int `toml:"regime_stage_max_age_minutes" json:"regime_stage_max_age_minutes"`
// Rule 13 — exit_discipline (% of premium paid lost on a long line).
ExitWatchLossPct float64 `toml:"exit_watch_loss_pct" json:"exit_watch_loss_pct"`
ExitActLossPct float64 `toml:"exit_act_loss_pct" json:"exit_act_loss_pct"`
// Rule 14 — fx_exposure (% of NLV held in non-base currencies). This is a
// watch-only structural condition.
FXExposureWatchPct float64 `toml:"fx_exposure_watch_pct" json:"fx_exposure_watch_pct"`
// HedgeSymbols is the policy-owned index list whose long puts classify
// as hedges (rules 1, 2, 5, 12, 13). Uppercased on load.
HedgeSymbols []string `toml:"hedge_symbols" json:"hedge_symbols"`
// GreeksGapFloorPctNLV is the materiality floor: a name whose legs
// missing delta exceed this notional share of NLV renders its
// exposure-dependent rows unknown instead of silently understating.
GreeksGapFloorPctNLV float64 `toml:"greeks_gap_floor_pct_nlv" json:"greeks_gap_floor_pct_nlv"`
// EarningsStaleDays bounds trust in a fetched earnings date; older
// observations flip rules 6-8 to unknown until refreshed or overridden.
EarningsStaleDays int `toml:"earnings_stale_days" json:"earnings_stale_days"`
}
RulebookPolicy carries the compiled thresholds for the daily trading rulebook. The TOML tags reserve the planned operator policy loader; no such loader is shipped today. It owns rulebook verdict thresholds, not the source observations that callers map into RuleInputs.
func DefaultRulebookPolicy ¶
func DefaultRulebookPolicy() RulebookPolicy
DefaultRulebookPolicy returns a complete baseline policy.
func (RulebookPolicy) FingerprintKey ¶
func (p RulebookPolicy) FingerprintKey() string
FingerprintKey hashes the full policy so every result discloses exactly which thresholds produced it (mirrors risk.Policy.FingerprintKey). Every field must appear here: a threshold outside the fingerprint is a silent policy change.
func (RulebookPolicy) IsHedgeSymbol ¶
func (p RulebookPolicy) IsHedgeSymbol(sym string) bool
IsHedgeSymbol reports whether sym is on the policy hedge list.
func (*RulebookPolicy) Normalize ¶
func (p *RulebookPolicy) Normalize()
Normalize uppercases and sorts the hedge list so fingerprints are stable regardless of TOML ordering.
func (RulebookPolicy) SetForBucket ¶
func (p RulebookPolicy) SetForBucket(bucket string) RegimeThresholds
SetForBucket returns the threshold set for a regime bucket; unrecognized buckets fall to the early-warning set (middle, disclosed by the caller), never silently to calm.
type ShadowWouldBlockEvaluation ¶
type ShadowWouldBlockEvaluation struct {
Candidate *NudgeCandidate
Count int
}
ShadowWouldBlockEvaluation carries the updated episode count and, only for the first qualifying preview, its candidate.
func EvaluateShadowWouldBlock ¶
func EvaluateShadowWouldBlock(input ShadowWouldBlockInput) ShadowWouldBlockEvaluation
EvaluateShadowWouldBlock emits one candidate for the first qualifying preview in a policy/latch episode. Later qualifying previews increment the episode count without repeating the candidate.
type ShadowWouldBlockInput ¶
type ShadowWouldBlockInput struct {
PolicyFingerprint string
LatchEpisode string
RiskIncreasing bool
Exempt bool
WouldBlock bool
PriorCount int
OccurredAt time.Time
}
ShadowWouldBlockInput describes one risk-increasing preview against a stable policy and latch episode. PriorCount is the previously persisted episode count and negative values are treated as zero.
type Signal ¶
type Signal struct {
ID SignalID `json:"id"`
Direction SignalDirection `json:"direction"`
Posture PortfolioPosture `json:"posture,omitempty"`
Severity SignalSeverity `json:"severity"`
Subject string `json:"subject,omitempty"`
Metric string `json:"metric,omitempty"`
Observed *float64 `json:"observed,omitempty"`
Threshold *float64 `json:"threshold,omitempty"`
Target *float64 `json:"target,omitempty"`
Unit string `json:"unit,omitempty"`
Evidence string `json:"evidence,omitempty"`
Confidence string `json:"confidence,omitempty"`
ConfidenceImpact string `json:"confidence_impact,omitempty"`
BlockedBy []string `json:"blocked_by,omitempty"`
}
Signal is a typed, serializable risk observation. Optional numeric fields remain nil when unavailable; callers must not interpret their absence as zero. BlockedBy explains which missing or degraded inputs limited the signal.
type SignalDirection ¶
type SignalDirection string
SignalDirection describes whether a signal supports defense, deployment, rebalancing, mixed action, or data-quality confirmation.
const ( DirectionDefensive SignalDirection = "defensive" DirectionConstructive SignalDirection = "constructive" DirectionRebalance SignalDirection = "rebalance" DirectionMixed SignalDirection = "mixed" DirectionDataQuality SignalDirection = "data_quality" )
DirectionDefensive and the related constants enumerate signal directions.
type SignalID ¶
type SignalID string
SignalID identifies a stable risk or data-quality condition.
const ( SignalMarginCushionLow SignalID = "margin_cushion_low" SignalLookAheadCushionLow SignalID = "lookahead_cushion_low" SignalMarketSelloffViolent SignalID = "market_selloff_violent" SignalVolSpikeConfirmed SignalID = "vol_spike_confirmed" SignalMarketRallyViolent SignalID = "market_rally_violent" SignalVolCrushConfirmed SignalID = "vol_crush_confirmed" SignalRegimeStressConfirmed SignalID = "regime_stress_confirmed" SignalRegimeStressEarly SignalID = "regime_stress_early" SignalFXCarryUnwind SignalID = "fx_carry_unwind" SignalGammaRed SignalID = "gamma_red" SignalGrossExposureHigh SignalID = "gross_exposure_high" SignalNetDeltaHigh SignalID = "net_delta_high" SignalGrossDeltaHigh SignalID = "gross_delta_high" SignalSingleNameExposureHigh SignalID = "single_name_exposure_high" SignalSingleNameDeltaHigh SignalID = "single_name_delta_high" SignalHeldUnderlyingPnLShock SignalID = "held_underlying_pnl_shock" SignalHeldOptionExpiryConcentration SignalID = "held_option_expiry_concentration" SignalHeldLiquidityDegraded SignalID = "held_liquidity_degraded" SignalOptionGreeksDegraded SignalID = "option_greeks_degraded" SignalShortConvexityHigh SignalID = "short_convexity_high" SignalPortfolioPnLShock SignalID = "portfolio_pnl_shock" SignalRiskDataDegraded SignalID = "risk_data_degraded" SignalMarketDataStale SignalID = "market_data_stale" )
SignalMarginCushionLow and the related constants identify supported risk and data-quality conditions.
type SignalSeverity ¶
type SignalSeverity string
SignalSeverity ranks the urgency of a risk signal. The zero value is unspecified.
const ( SeverityObserve SignalSeverity = "observe" SeverityWatch SignalSeverity = "watch" SeverityAct SignalSeverity = "act" SeverityUrgent SignalSeverity = "urgent" )
SeverityObserve and the related constants enumerate signal urgency.
type SizeInput ¶
type SizeInput struct {
Symbol string
Side string // "long" | "short"
Entry float64 // quote currency
Stop float64 // quote currency
Target float64 // optional take-profit; 0 disables the R block
RiskPct float64 // percent of NLV; (0, 100]
Lot int // round shares down to this multiple; >= 1
FX float64 // quote-currency units per 1 base-currency unit; > 0
NLV float64 // base currency
BuyingPower float64 // base currency (0 disables BP check)
Currency string // base currency code, surfaced in output only
}
SizeInput is the validated input to ComputeSize. Fields mirror the CLI flags one-for-one so the pure function is testable without the runner.
Target is optional. When set, ComputeSize derives the R-multiple (reward-to-risk ratio = profit-to-stop distance / entry-to-stop distance) and the breakeven win rate. Long trades require target > entry; short trades require target < entry.
type SizeResult ¶
type SizeResult struct {
Symbol string `json:"symbol"`
Side string `json:"side"`
Entry float64 `json:"entry"`
Stop float64 `json:"stop"`
Target *float64 `json:"target,omitempty"`
RiskPct float64 `json:"risk_pct"`
Lot int `json:"lot"`
FX float64 `json:"fx"`
NLV float64 `json:"nlv"`
BaseCurrency string `json:"base_currency,omitempty"`
RiskBase float64 `json:"risk_base"` // NLV * pct/100
RiskQuote float64 `json:"risk_quote"` // RiskBase * fx
Notional float64 `json:"notional"` // shares * entry
MaxLoss float64 `json:"max_loss"` // shares * per_share_risk (quote ccy)
R *float64 `json:"r,omitempty"` // (|target-entry|) / (|entry-stop|)
RewardQuote *float64 `json:"reward_quote,omitempty"`
RewardBase *float64 `json:"reward_base,omitempty"`
BreakevenWinRate *float64 `json:"breakeven_win_rate,omitempty"` // 1 / (1+R), fraction
Status string `json:"status"` // "ok" | "tight_risk" | "exceeds_buying_power"
}
SizeResult is the wire shape of `canary size --json` and the input to the CLI text renderer.
Target / R / RewardQuote / RewardBase / BreakevenWinRate are populated only when the input carries a non-zero Target. R is the reward-to-risk ratio (|target − entry| / |entry − stop|). BreakevenWinRate is 1 / (1 + R).
func ComputeSize ¶
func ComputeSize(in SizeInput) (SizeResult, error)
ComputeSize validates and applies fixed-fractional sizing. It returns a result with zero shares and status tight_risk when the risk budget is below one lot; buying power excess is reported in Status rather than as an error.
type SourceState ¶
SourceState is the mapped health of one input source.
type UnreconciledClock ¶
UnreconciledClock is the shared pure projection of the constitution's unreconciled horizon. Approved is false when the operator has not declared capital.max_unreconciled_days. A zero LastReconciledAt is stale with no fabricated year-one deadline.
func EvaluateUnreconciledClock ¶
func EvaluateUnreconciledClock(maxDays *int, lastReconciledAt, overrideUntil, now time.Time) UnreconciledClock
EvaluateUnreconciledClock computes the deadline used by both capital evaluation and reporting. The one-shot outage override may only extend the ordinary deadline; it can never shorten it.