fix(report): correct periodic returns, injection metrics and live view
- Monthly/yearly returns chain from the previous period's close (the first trading day of every period was dropped; up to ~9pp/yr error). - With cash injections, metrics/drawdowns/periodic returns are time-weighted on the no-injection curve; capitalFlows reports invested/profit separately. - Benchmarks cover exactly the strategies' dates. - CAGR uses calendar time, so gaps in live records do not inflate it. - Backtests skip the per-trade fee for rebalances below the live minimum order and keep a ruined portfolio at zero. - live: exact strategy match, ineligible strategies hidden, currency, startDate, same-window benchmark, stale-price fallback, equity anchored at the initial capital. - PIT membership falls back to the cached history when the Wikipedia change log cannot be parsed (the table is no longer on the page). Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
12
metrics.py
12
metrics.py
@@ -7,8 +7,16 @@ def total_return(equity: pd.Series) -> float:
|
||||
|
||||
|
||||
def annualized_return(equity: pd.Series, periods: int = 252) -> float:
|
||||
n = len(equity)
|
||||
return (1 + total_return(equity)) ** (periods / n) - 1
|
||||
"""CAGR. Uses elapsed calendar time when the index is dated, so gaps in a
|
||||
live record (missed days) do not inflate the annualized figure."""
|
||||
growth = 1 + total_return(equity)
|
||||
if growth <= 0:
|
||||
return -1.0
|
||||
if isinstance(equity.index, pd.DatetimeIndex) and len(equity) > 1:
|
||||
years = (equity.index[-1] - equity.index[0]).days / 365.25
|
||||
if years > 0:
|
||||
return growth ** (1 / years) - 1
|
||||
return growth ** (periods / len(equity)) - 1
|
||||
|
||||
|
||||
def annualized_volatility(returns: pd.Series, periods: int = 252) -> float:
|
||||
|
||||
Reference in New Issue
Block a user