Skip to content

v0.0.86

Latest

Choose a tag to compare

@ranaroussi ranaroussi released this 27 Sep 19:40

Statistical corrections — these change reported numbers

  • Trade statistics on a DataFrame depended on the other columns in the frame (#556).

    avg_return(), avg_win() and avg_loss() masked the unselected cells to NaN and then
    called .dropna(), which drops whole rows on a DataFrame. Each column's average was
    therefore computed only over rows where every other column also qualified — so a strategy's
    average win was measured only on the days the benchmark also rose.

    Anyone calling reports.metrics() with a benchmark on DataFrame input got affected figures
    for Average Win/Loss, Payoff Ratio, Win/Loss Ratio, CPC Index and Kelly Criterion.
    .mean() already skips NaN column-wise, so the .dropna() is gone. On the reporter's data
    the Strategy Kelly moves from 0.21 to 0.25, matching the standalone call.

    Found from the data @none2003 attached to #556.

  • rolling_greeks() computed alpha from full-sample means instead of each window's own
    (#554). Every window shared one baseline, so rolling alpha only moved when rolling beta did.
    On a strategy that starts earning an extra 10bp a day halfway through, alpha read 0.00057
    before and 0.00056 after, where a regression on those windows gives 0.00035 and 0.00198.
    Rolling beta, and the beta-only rolling plots, are unchanged.

    Reported, diagnosed and fixed by @WatchTree-19.

  • A time-varying rf Series collided in the _prepare_returns() cache (#555). The key
    formatted rf with its repr, which pandas truncates to the first and last few rows, so two
    rate series of the same length differing only in between shared an entry and the second
    caller was handed the first one's excess returns. The result depended on call order:
    sharpe(rf=B) returned −0.4388 on a fresh cache and −0.1952 if sharpe(rf=A) ran first.
    A Series rf is now hashed like the data.

    Reported, diagnosed and fixed by @WatchTree-19.

If you use reports.metrics() with a benchmark on a DataFrame, or a time-varying risk-free
rate, upgrading is recommended.