pub struct DrawdownTracker { /* private fields */ }Expand description
Tracks peak equity and computes current drawdown percentage.
Implementations§
Source§impl DrawdownTracker
impl DrawdownTracker
Sourcepub fn new(initial_equity: Decimal) -> Self
pub fn new(initial_equity: Decimal) -> Self
Creates a new DrawdownTracker with the given initial (and peak) equity.
Sourcepub fn update(&mut self, equity: Decimal)
pub fn update(&mut self, equity: Decimal)
Updates the tracker with the latest equity value, updating the peak if higher.
Sourcepub fn drawdown_duration(&self) -> usize
pub fn drawdown_duration(&self) -> usize
Returns the number of update() calls since the last new equity peak.
A value of 0 means the last update set a new peak. Higher values indicate how long the portfolio has been in drawdown (in update units).
Sourcepub fn current_drawdown_pct(&self) -> Decimal
pub fn current_drawdown_pct(&self) -> Decimal
Returns current drawdown as a percentage: (peak - current) / peak * 100.
Returns 0 if peak_equity is zero.
Sourcepub fn current_equity(&self) -> Decimal
pub fn current_equity(&self) -> Decimal
Returns the current equity value.
Sourcepub fn is_below_threshold(&self, max_dd_pct: Decimal) -> bool
pub fn is_below_threshold(&self, max_dd_pct: Decimal) -> bool
Returns true if the current drawdown percentage does not exceed max_dd_pct.
Sourcepub fn reset_peak(&mut self)
pub fn reset_peak(&mut self)
Resets the peak to the current equity value.
Useful for daily or session-boundary resets where you want drawdown measured from the start of the new session rather than the all-time high.
Sourcepub fn worst_drawdown_pct(&self) -> Decimal
pub fn worst_drawdown_pct(&self) -> Decimal
Returns the worst (highest) drawdown percentage seen since construction or last reset.
Sourcepub fn update_count(&self) -> usize
pub fn update_count(&self) -> usize
Returns the total number of equity updates since construction or last reset.
Sourcepub fn win_rate(&self) -> Option<Decimal>
pub fn win_rate(&self) -> Option<Decimal>
Returns the fraction of updates where equity was at or above peak (not in drawdown).
win_rate = (update_count - drawdown_update_count) / update_count
Returns None if no updates have been processed.
Sourcepub fn underwater_pct(&self) -> Decimal
pub fn underwater_pct(&self) -> Decimal
Returns how far below peak current equity is, as a percentage.
underwater_pct = (peak - current) / peak × 100
Returns Decimal::ZERO when at or above peak.
Sourcepub fn reset(&mut self, initial: Decimal)
pub fn reset(&mut self, initial: Decimal)
Fully resets the tracker as if it were freshly constructed with initial equity.
Sourcepub fn volatility(&self) -> Option<f64>
pub fn volatility(&self) -> Option<f64>
Returns the sample standard deviation of per-update equity changes.
Uses Welford’s online algorithm internally. Returns None until at least
two updates have been processed (can’t compute variance from one sample).
Sourcepub fn recovery_factor(&self, net_profit_pct: Decimal) -> Option<Decimal>
pub fn recovery_factor(&self, net_profit_pct: Decimal) -> Option<Decimal>
Returns the recovery factor: net_profit_pct / worst_drawdown_pct.
A higher value indicates better risk-adjusted performance.
Returns None when worst_drawdown_pct is zero (no drawdown has occurred).
Sourcepub fn calmar_ratio(&self, annualized_return: Decimal) -> Option<Decimal>
pub fn calmar_ratio(&self, annualized_return: Decimal) -> Option<Decimal>
Returns the Calmar ratio: annualized_return / worst_drawdown_pct.
Higher values indicate better risk-adjusted performance. Returns None when
worst_drawdown_pct is zero (no drawdown has occurred).
Sourcepub fn in_drawdown(&self) -> bool
pub fn in_drawdown(&self) -> bool
Returns true if the current equity is strictly below the peak (i.e. in drawdown).
Sourcepub fn update_with_returns(&mut self, equities: &[Decimal])
pub fn update_with_returns(&mut self, equities: &[Decimal])
Applies a sequence of equity values in order, as if each were an individual update call.
Useful for batch processing historical equity curves without a manual loop.
Sourcepub fn drawdown_count(&self) -> usize
pub fn drawdown_count(&self) -> usize
Returns the number of consecutive updates where equity was below the peak.
Equivalent to DrawdownTracker::drawdown_duration. Provided as a semantic
alias for call sites that prefer “count” over “duration”.
Sourcepub fn sharpe_ratio(
&self,
annualized_return: Decimal,
annualized_vol: Decimal,
) -> Option<Decimal>
pub fn sharpe_ratio( &self, annualized_return: Decimal, annualized_vol: Decimal, ) -> Option<Decimal>
Returns the Sharpe ratio: annualized_return / annualized_vol.
Returns None when annualized_vol is zero to avoid division by zero.
Sourcepub fn recovery_to_peak_pct(&self) -> Decimal
pub fn recovery_to_peak_pct(&self) -> Decimal
Returns the percentage gain required from the current equity to recover to the peak.
Formula: (peak / current - 1) * 100. Returns Decimal::ZERO when already at peak
or when current equity is zero (to avoid division by zero).
Sourcepub fn time_underwater_pct(&self) -> Decimal
pub fn time_underwater_pct(&self) -> Decimal
Fraction of equity updates spent below peak: drawdown_update_count / update_count.
Returns Decimal::ZERO when no updates have been processed.
Sourcepub fn avg_drawdown_pct(&self) -> Option<Decimal>
pub fn avg_drawdown_pct(&self) -> Option<Decimal>
Average drawdown percentage across all updates that had a non-zero drawdown.
Returns None when no drawdown updates have been recorded.
Sourcepub fn max_loss_streak(&self) -> usize
pub fn max_loss_streak(&self) -> usize
Longest consecutive run of updates where equity was below peak.
Sourcepub fn consecutive_gain_updates(&self) -> usize
pub fn consecutive_gain_updates(&self) -> usize
Returns the current consecutive run of updates where equity increased from the prior update.
Resets to zero on any non-increasing update. Useful for detecting sustained rallies.
Sourcepub fn equity_ratio(&self) -> Decimal
pub fn equity_ratio(&self) -> Decimal
Returns current_equity / peak_equity, useful for position sizing formulas.
Returns Decimal::ONE when peak is zero (no drawdown state yet). A value below 1
indicates the portfolio is in drawdown; exactly 1 means at peak.
Sourcepub fn new_peak_count(&self) -> usize
pub fn new_peak_count(&self) -> usize
Returns how many times a new equity peak has been set since construction or last reset.
Sourcepub fn pain_index(&self) -> Decimal
pub fn pain_index(&self) -> Decimal
Returns the “pain index”: mean absolute drawdown across all updates.
pain_index = drawdown_pct_sum / update_count
Represents the average percentage loss a holder experienced over the equity curve.
Returns Decimal::ZERO when no updates have been processed.
Sourcepub fn above_high_water_mark(&self, equity: Decimal) -> bool
pub fn above_high_water_mark(&self, equity: Decimal) -> bool
Returns true if equity is strictly greater than the current peak (new high-water mark).
Useful for triggering high-water-mark-based fee calculations or performance resets.
Note: this does NOT update the tracker — call update(equity) to advance the peak.
Sourcepub fn max_single_loss(&self) -> Option<f64>
pub fn max_single_loss(&self) -> Option<f64>
Returns the largest single-step equity drop seen across all updates.
Returns the magnitude (positive number) of the worst per-update loss.
Returns None if no loss has occurred or fewer than two updates have been processed.
Sourcepub fn loss_rate(&self) -> Option<f64>
pub fn loss_rate(&self) -> Option<f64>
Returns the fraction of equity updates that decreased equity (loss rate).
A value of 0.0 means equity never decreased; 1.0 means it always decreased.
Returns None if no updates have been processed.
Note: uses the drawdown update count as a proxy for loss updates — specifically the number of updates where equity was below peak, not strictly below the prior update.
Sourcepub fn consecutive_loss_updates(&self) -> usize
pub fn consecutive_loss_updates(&self) -> usize
Returns the current number of consecutive updates where equity decreased.
Resets to zero on any update where equity increases or stays the same.
A current losing streak indicator complementing DrawdownTracker::consecutive_gain_updates.
Sourcepub fn equity_change_mean(&self) -> Option<f64>
pub fn equity_change_mean(&self) -> Option<f64>
Returns the running mean of per-update equity changes.
Computed via Welford’s online algorithm. Returns None until at least one
equity change has been recorded (requires 2+ updates).
Sourcepub fn stress_test(&self, shock_pct: Decimal) -> Decimal
pub fn stress_test(&self, shock_pct: Decimal) -> Decimal
Returns the hypothetical drawdown percentage if equity dropped by shock_pct from current.
stress_drawdown = current_drawdown + shock_pct × (1 - current_drawdown/100)
This estimates the total drawdown from peak if the current equity fell an additional
shock_pct percent. Returns the result as a percentage (0–100+).
Sourcepub fn max_gain_streak(&self) -> usize
pub fn max_gain_streak(&self) -> usize
Returns the longest consecutive run of equity increases seen since construction or reset.
Sourcepub fn total_gain_sum(&self) -> f64
pub fn total_gain_sum(&self) -> f64
Returns the cumulative sum of all positive per-update equity changes.
Returns 0.0 if no gains have been recorded.
Sourcepub fn total_loss_sum(&self) -> f64
pub fn total_loss_sum(&self) -> f64
Returns the cumulative sum of absolute values of all negative per-update equity changes.
Returns 0.0 if no losses have been recorded.
Sourcepub fn gain_to_loss_ratio(&self) -> Option<f64>
pub fn gain_to_loss_ratio(&self) -> Option<f64>
Returns total_gain_sum / total_loss_sum. Returns None if no losses recorded.
Sourcepub fn expectancy(&self) -> Option<f64>
pub fn expectancy(&self) -> Option<f64>
Trading expectancy: win_rate × avg_gain − loss_rate × avg_loss.
Returns None if fewer than 2 equity changes have been recorded.
Sourcepub fn recovery_speed(&self) -> Option<f64>
pub fn recovery_speed(&self) -> Option<f64>
Average number of updates required to recover from a drawdown to a new peak.
Returns None if no drawdown has ever been fully recovered.
Sourcepub fn peak_hit_count(&self) -> usize
pub fn peak_hit_count(&self) -> usize
Number of times a new equity peak has been set.
This equals the number of update() calls where equity exceeded the prior peak.
Sourcepub fn avg_recovery_drawdown_pct(&self) -> Option<Decimal>
pub fn avg_recovery_drawdown_pct(&self) -> Option<Decimal>
Average drawdown percentage at the moment each recovery began.
Returns None if no drawdown has ever been fully recovered.
Sourcepub fn max_gain_pct(&self) -> f64
pub fn max_gain_pct(&self) -> f64
Largest single-step equity gain expressed as a percentage of the prior equity.
Returns 0.0 if no gain has been recorded yet.
Sourcepub fn avg_drawdown_duration(&self) -> Option<f64>
pub fn avg_drawdown_duration(&self) -> Option<f64>
Average number of updates spent in each drawdown episode.
Returns None if no drawdown episode has been entered yet.
Sourcepub fn breakeven_equity(&self) -> Decimal
pub fn breakeven_equity(&self) -> Decimal
The peak equity level the current equity must reach to exit drawdown.
Equals the all-time peak. If equity is already at peak, this is the current equity.
Sourcepub fn loss_streak(&self) -> usize
pub fn loss_streak(&self) -> usize
Current consecutive count of updates where equity decreased.
Resets to 0 as soon as equity increases or stays flat.
Sourcepub fn net_return_pct(&self) -> Option<f64>
pub fn net_return_pct(&self) -> Option<f64>
Net return as a percentage: (current_equity - initial_equity) / initial_equity * 100.
Returns None if initial_equity is zero.
Sourcepub fn consecutive_flat_count(&self) -> usize
pub fn consecutive_flat_count(&self) -> usize
Current count of consecutive updates where equity did not change.
Sourcepub fn total_updates(&self) -> usize
pub fn total_updates(&self) -> usize
Total number of update() calls processed since construction or last reset().
Sourcepub fn pct_time_in_drawdown(&self) -> f64
pub fn pct_time_in_drawdown(&self) -> f64
Percentage of all updates spent below peak equity (in drawdown).
Returns 0.0 if no updates have been processed.
Sourcepub fn equity_cagr(&self, periods_per_year: usize) -> Option<f64>
pub fn equity_cagr(&self, periods_per_year: usize) -> Option<f64>
Compound Annual Growth Rate (CAGR) of equity.
CAGR = (current / initial) ^ (periods_per_year / update_count) - 1.
Returns None if initial_equity is zero or non-positive, or fewer than 2 updates.
Sourcepub fn is_recovering(&self) -> bool
pub fn is_recovering(&self) -> bool
Returns true when equity is below its peak but gained on the last update.
Sourcepub fn drawdown_ratio(&self) -> Decimal
pub fn drawdown_ratio(&self) -> Decimal
Current drawdown as a fraction of the worst recorded drawdown.
Returns Decimal::ZERO if no drawdown has been recorded yet.
Sourcepub fn equity_multiple(&self) -> Decimal
pub fn equity_multiple(&self) -> Decimal
Current equity as a multiple of initial equity (e.g., 1.5 = 50% gain).
Sourcepub fn avg_gain_pct(&self) -> Option<f64>
pub fn avg_gain_pct(&self) -> Option<f64>
Average per-update equity gain across all positive updates.
Uses win_rate and update_count to estimate the number of positive updates.
Returns None if there have been no positive updates recorded.
Sourcepub fn is_at_peak(&self) -> bool
pub fn is_at_peak(&self) -> bool
Returns true if the current equity equals the peak (no drawdown).
Sourcepub fn below_initial_equity(&self) -> bool
pub fn below_initial_equity(&self) -> bool
Returns true if the current equity is below the initial equity at construction.
Sourcepub fn return_drawdown_ratio(&self) -> Option<f64>
pub fn return_drawdown_ratio(&self) -> Option<f64>
Net return divided by max drawdown percentage (simplified Calmar-like ratio).
Returns None if max drawdown is zero or there are fewer than 2 updates.
Sourcepub fn consecutive_flat_pct(&self) -> f64
pub fn consecutive_flat_pct(&self) -> f64
Percentage of total updates where equity was unchanged (flat).
Returns 0.0 if no updates have been recorded.
Sourcepub fn current_streak(&self) -> i64
pub fn current_streak(&self) -> i64
Current consecutive streak length: positive = gains, negative = losses, 0 = flat.
Sourcepub fn max_loss_pct_single(&self) -> Option<f64>
pub fn max_loss_pct_single(&self) -> Option<f64>
The single largest equity loss as a percentage of the equity at the time of the loss.
Returns None if no loss has been recorded (min_equity_delta >= 0).
Sourcepub fn win_loss_ratio(&self) -> Option<f64>
pub fn win_loss_ratio(&self) -> Option<f64>
Win rate divided by loss rate (win probability / loss probability).
Returns None if either rate is unavailable or loss rate is zero.
Sourcepub fn best_drawdown_recovery(&self) -> Option<f64>
pub fn best_drawdown_recovery(&self) -> Option<f64>
Max single gain percentage divided by worst drawdown percentage (reward/risk ratio).
Returns None if no drawdown or no gain has been recorded.
Sourcepub fn recovery_count(&self) -> usize
pub fn recovery_count(&self) -> usize
Total number of completed drawdown recovery events.
Sourcepub fn avg_gain_loss_ratio(&self) -> Option<f64>
pub fn avg_gain_loss_ratio(&self) -> Option<f64>
Ratio of average gain to average loss per update.
Returns None if either average is unavailable or average loss is zero.
Sourcepub fn time_to_recover_est(&self) -> Option<usize>
pub fn time_to_recover_est(&self) -> Option<usize>
Estimated number of updates to recover from the current drawdown.
Based on average gain size and current distance from peak.
Returns None if not in drawdown, no gain history, or average gain is zero.
Sourcepub fn current_drawdown_absolute(&self) -> Decimal
pub fn current_drawdown_absolute(&self) -> Decimal
Current distance of equity below the peak in absolute terms.
Sourcepub fn median_drawdown_pct(drawdowns: &[Decimal]) -> Option<Decimal>
pub fn median_drawdown_pct(drawdowns: &[Decimal]) -> Option<Decimal>
Median of a slice of drawdown percentages.
The input need not be sorted. Returns None if the slice is empty.
Sourcepub fn sortino_ratio(returns: &[Decimal], target: Decimal) -> Option<f64>
pub fn sortino_ratio(returns: &[Decimal], target: Decimal) -> Option<f64>
Sortino ratio from a slice of period returns.
sortino = (mean_return - target) / downside_deviation
where downside deviation is the standard deviation of returns below target.
Returns None if returns is empty or downside deviation is zero.
Sourcepub fn returns_volatility(
returns: &[Decimal],
periods_per_year: u32,
) -> Option<f64>
pub fn returns_volatility( returns: &[Decimal], periods_per_year: u32, ) -> Option<f64>
Annualised volatility from a slice of period returns.
volatility = std_dev(returns) * sqrt(periods_per_year)
Returns None if returns has fewer than 2 elements.
Sourcepub fn omega_ratio(returns: &[Decimal], threshold: Decimal) -> Option<f64>
pub fn omega_ratio(returns: &[Decimal], threshold: Decimal) -> Option<f64>
Omega ratio: sum of returns above threshold / abs(sum of returns below threshold).
Values > 1 indicate more upside than downside relative to the threshold.
Returns None if returns is empty or total downside is zero.
Sourcepub fn information_ratio(
returns: &[Decimal],
benchmark: &[Decimal],
) -> Option<f64>
pub fn information_ratio( returns: &[Decimal], benchmark: &[Decimal], ) -> Option<f64>
Information ratio: (mean(returns) - mean(benchmark)) / std_dev(returns - benchmark).
Measures risk-adjusted excess return over a benchmark. Returns None if fewer than 2
matched return pairs exist or tracking error is zero.
Sourcepub fn annualized_volatility(&self, periods_per_year: u32) -> Option<f64>
pub fn annualized_volatility(&self, periods_per_year: u32) -> Option<f64>
Annualized volatility of equity changes: std_dev_of_changes * sqrt(periods_per_year).
Returns None if fewer than 2 updates have been recorded.
Sourcepub fn pain_ratio(&self, annualized_return_pct: Decimal) -> Option<Decimal>
pub fn pain_ratio(&self, annualized_return_pct: Decimal) -> Option<Decimal>
Pain ratio: annualized_return_pct / pain_index.
A higher ratio indicates better risk-adjusted performance relative to
sustained drawdown. Returns None if the pain index is zero (no drawdowns).
Sourcepub fn time_above_watermark_pct(&self) -> Decimal
pub fn time_above_watermark_pct(&self) -> Decimal
Fraction of all updates where equity was at or above the peak (above water).
Complement of time_underwater_pct.
Returns Decimal::ONE when no updates have been processed.
Sourcepub fn equity_change_std_dev(&self) -> Option<f64>
pub fn equity_change_std_dev(&self) -> Option<f64>
Sample standard deviation of per-update equity changes.
Uses the Welford running variance accumulator. Returns None when
fewer than 2 equity changes have been recorded.
Sourcepub fn gain_streak_ratio(&self) -> Option<f64>
pub fn gain_streak_ratio(&self) -> Option<f64>
Ratio of the longest gain streak to total updates.
Higher values indicate equity spent a larger fraction of updates trending upward.
Returns None when no updates have been processed.
Source§impl DrawdownTracker
impl DrawdownTracker
Sourcepub fn gain_loss_asymmetry(&self) -> Option<f64>
pub fn gain_loss_asymmetry(&self) -> Option<f64>
Ratio of average equity gain per gain-update to average equity loss per loss-update.
Values > 1 mean average gains outsize average losses (positive asymmetry).
Returns None if there are no recorded losses.
Sourcepub fn streaks(&self) -> (usize, usize, usize, usize)
pub fn streaks(&self) -> (usize, usize, usize, usize)
Returns (current_gain_streak, max_gain_streak, current_loss_streak, max_loss_streak).
A “gain streak” is a consecutive run of updates where equity increased.
The tracker maintains gain_streak and max_drawdown_streak (loss streak).
Sourcepub fn sharpe_proxy(
&self,
annualized_return: f64,
periods_per_year: u32,
) -> Option<f64>
pub fn sharpe_proxy( &self, annualized_return: f64, periods_per_year: u32, ) -> Option<f64>
Quick Sharpe proxy: annualized_return / annualized_volatility(periods_per_year).
Uses the Welford-tracked equity change volatility maintained by the tracker.
Returns None if volatility is unavailable or zero.
Sourcepub fn max_consecutive_underwater(&self) -> usize
pub fn max_consecutive_underwater(&self) -> usize
Longest single underwater streak in number of consecutive updates below peak.
Returns 0 if there have been no updates below peak.
Sourcepub fn underwater_duration_avg(&self) -> Option<f64>
pub fn underwater_duration_avg(&self) -> Option<f64>
Average duration of underwater periods: drawdown_update_count / drawdown_count.
Returns None if there have been no drawdown periods.
Sourcepub fn equity_efficiency(&self) -> f64
pub fn equity_efficiency(&self) -> f64
Equity efficiency: ratio of current equity to peak equity [0.0, 1.0].
A value of 1.0 means at the peak; values below 1.0 indicate drawdown depth.
Sourcepub fn sortino_proxy(
&self,
annualized_return: f64,
periods_per_year: u32,
) -> Option<f64>
pub fn sortino_proxy( &self, annualized_return: f64, periods_per_year: u32, ) -> Option<f64>
Sortino-style proxy: annualized_return / downside_volatility.
Downside vol uses only negative equity changes in the Welford variance.
Returns None if downside volatility is zero or unavailable.
Sourcepub fn gain_loss_ratio(&self) -> Option<f64>
👎Deprecated since 2.1.0: Use gain_to_loss_ratio instead
pub fn gain_loss_ratio(&self) -> Option<f64>
Use gain_to_loss_ratio instead
Ratio of cumulative gains to cumulative losses: total_gain_sum / total_loss_sum.
Alias for gain_to_loss_ratio.
Sourcepub fn recovery_efficiency(&self) -> Option<f64>
pub fn recovery_efficiency(&self) -> Option<f64>
Recovery efficiency: completed_recoveries / drawdown_count.
A ratio of 1.0 means every drawdown was fully recovered.
Returns None if no drawdowns have occurred.
Sourcepub fn drawdown_velocity(&self) -> Option<f64>
pub fn drawdown_velocity(&self) -> Option<f64>
Rate of change of drawdown per update: current_drawdown_pct / updates_since_peak.
Returns None if at peak (no drawdown) or no updates have been counted.
Sourcepub fn streak_win_rate(&self) -> Option<f64>
pub fn streak_win_rate(&self) -> Option<f64>
Fraction of streak length dominated by gains: max_gain_streak / (max_gain_streak + max_drawdown_streak).
Returns None if neither streak has been recorded.
Sourcepub fn equity_change_std(&self) -> Option<f64>
👎Deprecated since 2.1.0: Use equity_change_std_dev instead
pub fn equity_change_std(&self) -> Option<f64>
Use equity_change_std_dev instead
Sample standard deviation of per-update equity changes (Welford online algorithm).
Alias for equity_change_std_dev.
Sourcepub fn avg_loss_pct(&self) -> Option<f64>
pub fn avg_loss_pct(&self) -> Option<f64>
Average loss per loss-update (absolute value). Returns None if no losses have been
recorded.
Trait Implementations§
Source§impl Clone for DrawdownTracker
impl Clone for DrawdownTracker
Source§fn clone(&self) -> DrawdownTracker
fn clone(&self) -> DrawdownTracker
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more