Skip to content

ENH: Extract strategy performance method compute_stats #281

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Aug 3, 2021

Conversation

crazy25000
Copy link
Contributor

@crazy25000 crazy25000 commented Mar 20, 2021

Resolves #194
Resolves #71

Extracted methods compute_drawdown_duration_peaks, compute_stats, and class _Stats from backtesting.py to a new file so that they're available to users.

This will give us the ability to explicitly get performance metrics and have direct access to the data.

TODO:

  • Update unit tests
  • flake8 passes
  • mypy passes
  • Add long/short trade statistics
    • Need info about which metrics we want (pips, duration, wins, losses...etc)
  • Update documentation

Copy link
Owner

@kernc kernc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Add long/short trade statistics
    • Need info about which metrics we want (pips, duration, wins, losses...etc)

I'm not in favor of supplying extra new keys in the stats series. It's long as it is.

Instead the idea is, the curious user will be able to use the newly exposed backtesting.lib.compute_stats() to compute stats on any subset of trades they are interested in:

stats = bt.run()

long_trades = stats._trades.query('Size > 0')
long_stats = compute_stats(long_trades, stats._equity_curve.Equity, data)

@kernc
Copy link
Owner

kernc commented Mar 21, 2021

long_stats = compute_stats(long_trades, stats._equity_curve.Equity, data)

Maybe even better to expose backtesting.lib.compute_stats() such that it takes simply

compute_stats(trades: pd.DataFrame,  # trades subset
              stats: pd.Series,      # previous stats
              risk_free_rate: float = 0) -> pd.Series

and obtain equity and OHLC data simply from stats passed in.

@kernc
Copy link
Owner

kernc commented Mar 21, 2021

obtain equity and OHLC data simply from stats passed in

Particularly OHLC data is potentially too heavy (e.g. pickling for multiprocessing) to bake into returned stats. Better pass that separately.

@crazy25000
Copy link
Contributor Author

  • Add long/short trade statistics

    • Need info about which metrics we want (pips, duration, wins, losses...etc)

I'm not in favor of supplying extra new keys in the stats series. It's long as it is.

Instead the idea is, the curious user will be able to use the newly exposed backtesting.lib.compute_stats() to compute stats on any subset of trades they are interested in:

stats = bt.run()

long_trades = stats._trades.query('Size > 0')
long_stats = compute_stats(long_trades, stats._equity_curve.Equity, data)

I agree, it would be better to provide the information and let users calculate metrics they need. I wasn't sure if we had to add the long/short stats based on the original issue conversation.

@crazy25000 crazy25000 changed the title ENH: Extract strategy performance methods, add long & short trade statistics ENH: Extract strategy performance method compute_stats Mar 24, 2021
@kernc kernc linked an issue Mar 25, 2021 that may be closed by this pull request
Comment on lines 33 to 37
def compute_stats(
trades: List[pd.DataFrame],
equity: np.ndarray,
ohlc_data: pd.DataFrame,
risk_free_rate: float = 0) -> pd.Series:
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good. Now let's expose+document this function publicly in backtesting.lib. The user will be able to pass trades: pd.DataFrame as obtained by this exact method (stats._trades), so you have to figure out a way for that.

Comment on lines 90 to 92
>>> broker = stats._strategy._broker
>>> equity = pd.Series(broker._equity).bfill().fillna(broker._cash).values
>>> perf = compute_stats(trades=broker.closed_trades, equity=equity, ohlc_data=GOOG)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kernc passing stats._strategy._broker.closed_trades makes it compatible as is. If we want to pass stats._trades, we'd need to convert the DataFrame to a list of Trade.

@crazy25000 crazy25000 closed this Apr 30, 2021
@crazy25000 crazy25000 deleted the extract-compute-stats branch April 30, 2021 01:24
@crazy25000 crazy25000 restored the extract-compute-stats branch April 30, 2021 01:24
@crazy25000 crazy25000 reopened this Apr 30, 2021
@crazy25000
Copy link
Contributor Author

Oops 😛

@crazy25000 crazy25000 requested a review from kernc July 3, 2021 22:39
@kernc
Copy link
Owner

kernc commented Aug 3, 2021

@crazy25000 Apologies for the late review. 🌞 Many thanks for your work on this! 🥮

@kernc kernc merged commit 77f4c46 into kernc:master Aug 3, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Separate statistics for long and short trades? Sharpe Ratio does not take risk-free rate as a parameter
2 participants