diff --git a/README.md b/README.md index 6afa775c..43f47bdc 100644 --- a/README.md +++ b/README.md @@ -10,34 +10,25 @@ **QuantStats** Python library that performs portfolio profiling, allowing quants and portfolio managers to understand their performance better by providing them with in-depth analytics and risk metrics. -[Changelog »](./CHANGELOG.md) -### QuantStats is comprised of 3 main modules: - -1. `quantstats.stats` - for calculating various performance metrics, like Sharpe ratio, Win rate, Volatility, etc. -2. `quantstats.plots` - for visualizing performance, drawdowns, rolling statistics, monthly returns, etc. -3. `quantstats.reports` - for generating metrics reports, batch plotting, and creating tear sheets that can be saved as an HTML file. - ---- - -### **NEW! Monte Carlo Simulations** - -Monte Carlo Simulation -Run probabilistic risk analysis with built-in Monte Carlo simulations: +## Navigation +- [Quick Start](#quick-start) +- [Understanding Returns](#understanding-returns-important) +- [Documentation](docs/docs_and_api_ref.md) + - [NEW! Monte Carlo Simulations](docs/montecarlo.md) +- [Installation](#installation) +- [Questions and Contributions](#questions-and-contributions) +- [Changelog »](./CHANGELOG.md) -```python -mc = qs.stats.montecarlo(returns, sims=1000, bust=-0.20, goal=0.50) -print(f"Bust probability: {mc.bust_probability:.1%}") -print(f"Goal probability: {mc.goal_probability:.1%}") -mc.plot() -``` -[Full Monte Carlo documentation »](./docs/montecarlo.md) +## Quick Start ---- +### QuantStats is comprised of 3 main modules: -## Quick Start +1. `quantstats.stats` - for calculating various performance metrics, like Sharpe ratio, Win rate, Volatility, etc. +2. `quantstats.plots` - for visualizing performance, drawdowns, rolling statistics, monthly returns, etc. +3. `quantstats.reports` - for generating metrics reports, batch plotting, and creating tear sheets that can be saved as an HTML file. ```python %matplotlib inline @@ -47,13 +38,13 @@ import quantstats as qs qs.extend_pandas() # fetch the daily returns for a stock -stock = qs.utils.download_returns('META') +returns = qs.utils.download_returns('META') # show sharpe ratio -qs.stats.sharpe(stock) +qs.stats.sharpe(returns) # or using extend_pandas() :) -stock.sharpe() +returns.sharpe() ``` Output: @@ -71,9 +62,15 @@ qs.plots.snapshot(stock, title='Facebook Performance', show=True) # stock.plot_snapshot(title='Facebook Performance', show=True) ``` -Output: +Output (full-size version [here](https://github.com/ranaroussi/quantstats/blob/main/docs/snapshot.webp?raw=true)): -![Snapshot plot](https://github.com/ranaroussi/quantstats/blob/main/docs/snapshot.webp?raw=true) +

+ Snapshot plot +

### Creating a report @@ -92,113 +89,39 @@ Let's create an html tearsheet: qs.reports.html(stock, "SPY") ``` -Output will generate something like this: - -![HTML tearsheet](https://github.com/ranaroussi/quantstats/blob/main/docs/report.webp?raw=true) - -[View original html file](https://rawcdn.githack.com/ranaroussi/quantstats/main/docs/tearsheet.html) - -### Available methods +Output (full-size version [here](https://rawcdn.githack.com/ranaroussi/quantstats/main/docs/tearsheet.html)): -To view a complete list of available methods, run: +

+ HTML tearsheet +

+### The Returns object +As seen in previous examples, QuantStat's primary input is a time-series: ```python -[f for f in dir(qs.stats) if f[0] != '_'] +returns = qs.utils.download_returns('META') +qs.stats.sharpe(returns) ``` - +Or a dataframe (several series with a shared index): ```python -['avg_loss', - 'avg_return', - 'avg_win', - 'best', - 'cagr', - 'calmar', - 'common_sense_ratio', - 'comp', - 'compare', - 'compsum', - 'conditional_value_at_risk', - 'consecutive_losses', - 'consecutive_wins', - 'cpc_index', - 'cvar', - 'drawdown_details', - 'expected_return', - 'expected_shortfall', - 'exposure', - 'gain_to_pain_ratio', - 'geometric_mean', - 'ghpr', - 'greeks', - 'implied_volatility', - 'information_ratio', - 'kelly_criterion', - 'kurtosis', - 'max_drawdown', - 'monthly_returns', - 'montecarlo', - 'montecarlo_cagr', - 'montecarlo_drawdown', - 'montecarlo_sharpe', - 'outlier_loss_ratio', - 'outlier_win_ratio', - 'outliers', - 'payoff_ratio', - 'profit_factor', - 'profit_ratio', - 'r2', - 'r_squared', - 'rar', - 'recovery_factor', - 'remove_outliers', - 'risk_of_ruin', - 'risk_return_ratio', - 'rolling_greeks', - 'ror', - 'sharpe', - 'skew', - 'sortino', - 'adjusted_sortino', - 'tail_ratio', - 'to_drawdown_series', - 'ulcer_index', - 'ulcer_performance_index', - 'upi', - 'value_at_risk', - 'var', - 'volatility', - 'win_loss_ratio', - 'win_rate', - 'worst'] +returns = DataFrame() +returns["META"] = qs.utils.download_returns('META') +returns["TSLA"] = qs.utils.download_returns('TSLA') +qs.stats.sharpe(returns) ``` -```python -[f for f in dir(qs.plots) if f[0] != '_'] -``` +Quantstats makes several notable assumptions about this object by default: +1. This is a daily (`datetime64[s]` index) time-series of returns (`float64`). These returns are the percent gain from the previous period (e.g. 10% growth -> 0.1, NOT 1.1). +2. There are 252 periods (rows) in a year (not 365!) corresponding to the number of trading days in the U.S. stock market. Many methods assume this amount of periods by default; if you have substantially more or less data in your time-series, the annualization math may be skewed. +3. For an example of correctly shaped returns, see time-series returned by `qs.utils.download_returns()` -```python -['daily_returns', - 'distribution', - 'drawdown', - 'drawdowns_periods', - 'earnings', - 'histogram', - 'log_returns', - 'monthly_heatmap', - 'montecarlo', - 'montecarlo_distribution', - 'returns', - 'rolling_beta', - 'rolling_sharpe', - 'rolling_sortino', - 'rolling_volatility', - 'snapshot', - 'yearly_returns'] -``` -**\*\*\* Full documentation coming soon \*\*\*** +## Additional Notes -### Important: Period-Based vs Trade-Based Metrics +### Period-Based vs Trade-Based Metrics QuantStats analyzes **return series** (daily, weekly, monthly returns), not discrete trade data. This means: @@ -216,17 +139,9 @@ For **discretionary traders** with multi-day trades, these period-based metrics This is consistent with how all return-based analytics work (Sharpe ratio, Sortino ratio, drawdown analysis, etc.) - they operate on return periods, not discrete trade entries/exits. ---- - -In the meantime, you can get insights as to optional parameters for each method, by using Python's `help` method: - -```python -help(qs.stats.conditional_value_at_risk) -``` +### Help on function conditional_value_at_risk in module quantstats.stats: ``` -Help on function conditional_value_at_risk in module quantstats.stats: - conditional_value_at_risk(returns, sigma=1, confidence=0.99) calculates the conditional daily value-at-risk (aka expected shortfall) quantifies the amount of tail risk an investment @@ -246,7 +161,7 @@ Install using `conda`: $ conda install -c ranaroussi quantstats ``` -## Requirements +### Requirements * [Python](https://www.python.org) >= 3.10 * [pandas](https://github.com/pydata/pandas) >= 1.5.0 @@ -258,7 +173,7 @@ $ conda install -c ranaroussi quantstats * [yfinance](https://github.com/ranaroussi/yfinance) >= 0.2.40 * [plotly](https://plot.ly/) >= 5.0.0 (optional, for using `plots.to_plotly()`) -## Questions? +## Questions and Contributions This is a new library... If you find a bug, please [open an issue](https://github.com/ranaroussi/quantstats/issues). @@ -266,11 +181,6 @@ This is a new library... If you find a bug, please If you'd like to contribute, a great place to look is the [issues marked with help-wanted](https://github.com/ranaroussi/quantstats/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22). -## Known Issues - -For some reason, I couldn't find a way to tell seaborn not to return the -monthly returns heatmap when instructed to save - so even if you save the plot (by passing `savefig={...}`) it will still show the plot. - ## Legal Stuff **QuantStats** is distributed under the **Apache Software License**. See the [LICENSE.txt](./LICENSE.txt) file in the release for details. diff --git a/docs/docs_and_api_ref.md b/docs/docs_and_api_ref.md new file mode 100644 index 00000000..e40f0641 --- /dev/null +++ b/docs/docs_and_api_ref.md @@ -0,0 +1,143 @@ +## Further References + + +Full documentation is still in the works. In the meantime... + +1. Many methods already contain detailed docstrings in the source code, so refer to those for further information on each method's parameters, return values, and additional information. + +2. AI-Generated Documentation can be found [here](https://deepwiki.com/ranaroussi/quantstats/1-overview). + +3. You can get insights as to optional parameters for each method, by using Python's `help` method: + +```python +help(qs.stats.conditional_value_at_risk) +``` + +## API Reference + +```python +import quantstats as qs + +qs.extend_pandas() + +df.cagr() +qs.cagr(df) +``` + +### Stats + +Many of the methods below in qs.stats can be extended onto Pandas' Time-series and DataFrame objects. For more information, refer to qs.extend_pandas() + +```python +[f for f in dir(qs.stats) if f[0] != '_'] +``` + +```python +['avg_loss', + 'avg_return', + 'avg_win', + 'best', + 'cagr', + 'calmar', + 'common_sense_ratio', + 'comp', + 'compare', + 'compsum', + 'conditional_value_at_risk', + 'consecutive_losses', + 'consecutive_wins', + 'cpc_index', + 'cvar', + 'drawdown_details', + 'expected_return', + 'expected_shortfall', + 'exposure', + 'gain_to_pain_ratio', + 'geometric_mean', + 'ghpr', + 'greeks', + 'implied_volatility', + 'information_ratio', + 'kelly_criterion', + 'kurtosis', + 'max_drawdown', + 'monthly_returns', + 'montecarlo', + 'montecarlo_cagr', + 'montecarlo_drawdown', + 'montecarlo_sharpe', + 'outlier_loss_ratio', + 'outlier_win_ratio', + 'outliers', + 'payoff_ratio', + 'profit_factor', + 'profit_ratio', + 'r2', + 'r_squared', + 'rar', + 'recovery_factor', + 'remove_outliers', + 'risk_of_ruin', + 'risk_return_ratio', + 'rolling_greeks', + 'ror', + 'sharpe', + 'skew', + 'sortino', + 'adjusted_sortino', + 'tail_ratio', + 'to_drawdown_series', + 'ulcer_index', + 'ulcer_performance_index', + 'upi', + 'value_at_risk', + 'var', + 'volatility', + 'win_loss_ratio', + 'win_rate', + 'worst'] +``` + +### Plots + +```python +[f for f in dir(qs.plots) if f[0] != '_'] +``` + +```python +['daily_returns', + 'distribution', + 'drawdown', + 'drawdowns_periods', + 'earnings', + 'histogram', + 'log_returns', + 'monthly_heatmap', + 'montecarlo', + 'montecarlo_distribution', + 'returns', + 'rolling_beta', + 'rolling_sharpe', + 'rolling_sortino', + 'rolling_volatility', + 'snapshot', + 'yearly_returns'] +``` + +### Reports + +```python +[f for f in dir(qs.reports) if f[0] != '_'] +``` + +```python +['Path', + 'StringIO', + 'basic', + 'full', 'html', + 'metrics', + 'plots', + 'relativedelta', + 'tempfile', + 'webbrowser'] +``` \ No newline at end of file