pub struct PositionTracker { /* private fields */ }Expand description
Stateful refinement layer on top of compute_guidance.
compute_guidance is pure and scores a single snapshot. The tracker
remembers each position (keyed by position_id) and adds two rules that
require history:
- Trailing give-back — once a position has been a meaningful winner
(peak ≥
TrailingConfig::arm_ratio) and then surrenders enough of that peak (TrailingConfig::giveback_frac), upgrade aHoldtoReduceto bank the remaining profit. The stateless rule can’t see the prior peak, so it would justHold. - Sticky exit — once we’ve advised
Exit, a later snapshot that merely drifts back inside the bands keepsExitrather than flip- flopping toHoldon a one-tick bounce.
Snapshots without a position_id are not tracked; their guidance passes
through unchanged (fully backward compatible).
Implementations§
Source§impl PositionTracker
impl PositionTracker
Sourcepub fn new() -> Self
pub fn new() -> Self
New tracker with default TrailingConfig.
Sourcepub fn with_config(config: TrailingConfig) -> Self
pub fn with_config(config: TrailingConfig) -> Self
New tracker with explicit config.
Sourcepub async fn tracked(&self) -> usize
pub async fn tracked(&self) -> usize
Number of positions currently tracked (after pruning). For metrics/tests.
Sourcepub async fn finalize(&self, position_id: &str) -> Option<PositionState>
pub async fn finalize(&self, position_id: &str) -> Option<PositionState>
Remove and return a position’s accumulated state. Call this when the
position closes so its guidance history can be joined with the realized
outcome (see PositionOutcome::from_close). Returns None if the
position was never tracked.
Sourcepub async fn observe(&self, event: &PositionEvent, base: Guidance) -> Guidance
pub async fn observe(&self, event: &PositionEvent, base: Guidance) -> Guidance
Refine stateless base guidance using this position’s history, record
the updated state, and return the (possibly upgraded) guidance.
Positions without a position_id are returned unchanged and not
tracked. The critical section is pure (no .await while the lock is
held), so this stays cheap under load.