Skip to content
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

Pandas update: Fixed some bugs that caused future warnings in pandas #360

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@ Icon
/tests
.vscode
Icon
.DS_Store
36 changes: 11 additions & 25 deletions quantstats/_plotting/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,13 @@
pass

import matplotlib.dates as _mdates
from matplotlib.ticker import (
FormatStrFormatter as _FormatStrFormatter,
FuncFormatter as _FuncFormatter,
)

import pandas as _pd
import numpy as _np
import pandas as _pd
import seaborn as _sns
from .. import (
stats as _stats,
utils as _utils,
)
from matplotlib.ticker import FormatStrFormatter as _FormatStrFormatter
from matplotlib.ticker import FuncFormatter as _FuncFormatter

from .. import stats as _stats

_sns.set(
font_scale=1.1,
Expand Down Expand Up @@ -112,7 +106,6 @@ def plot_returns_bars(
savefig=None,
show=True,
):

if match_volatility and benchmark is None:
raise ValueError("match_volatility requires passing of " "benchmark.")
if match_volatility and benchmark is not None:
Expand Down Expand Up @@ -265,7 +258,6 @@ def plot_timeseries(
savefig=None,
show=True,
):

colors, ls, alpha = _get_colors(grayscale)

returns.fillna(0, inplace=True)
Expand Down Expand Up @@ -419,7 +411,6 @@ def plot_histogram(
savefig=None,
show=True,
):

# colors = ['#348dc1', '#003366', 'red']
# if grayscale:
# colors = ['silver', 'gray', 'black']
Expand Down Expand Up @@ -616,7 +607,6 @@ def plot_rolling_stats(
savefig=None,
show=True,
):

colors, _, _ = _get_colors(grayscale)

fig, ax = _plt.subplots(figsize=figsize)
Expand Down Expand Up @@ -745,7 +735,6 @@ def plot_rolling_beta(
savefig=None,
show=True,
):

colors, _, _ = _get_colors(grayscale)

fig, ax = _plt.subplots(figsize=figsize)
Expand Down Expand Up @@ -889,7 +878,6 @@ def plot_longest_drawdowns(
savefig=None,
show=True,
):

colors = ["#348dc1", "#003366", "red"]
if grayscale:
colors = ["#000000"] * 3
Expand Down Expand Up @@ -1001,7 +989,6 @@ def plot_distribution(
savefig=None,
show=True,
):

colors = _FLATUI_COLORS
if grayscale:
colors = ["#f9f9f9", "#dddddd", "#bbbbbb", "#999999", "#808080"]
Expand All @@ -1013,16 +1000,16 @@ def plot_distribution(
apply_fnc = _stats.comp if compounded else _np.sum

port["Weekly"] = port["Daily"].resample("W-MON").apply(apply_fnc)
port["Weekly"].ffill(inplace=True)
port["Weekly"] = port["Weekly"].ffill()

port["Monthly"] = port["Daily"].resample("M").apply(apply_fnc)
port["Monthly"].ffill(inplace=True)
port["Monthly"] = port["Daily"].resample("ME").apply(apply_fnc)
port["Monthly"] = port["Monthly"].ffill()

port["Quarterly"] = port["Daily"].resample("Q").apply(apply_fnc)
port["Quarterly"].ffill(inplace=True)
port["Quarterly"] = port["Daily"].resample("QE").apply(apply_fnc)
port["Quarterly"] = port["Quarterly"].ffill()

port["Yearly"] = port["Daily"].resample("A").apply(apply_fnc)
port["Yearly"].ffill(inplace=True)
port["Yearly"] = port["Daily"].resample("YE").apply(apply_fnc)
port["Yearly"] = port["Yearly"].ffill()

fig, ax = _plt.subplots(figsize=figsize)
ax.spines["top"].set_visible(False)
Expand Down Expand Up @@ -1118,7 +1105,6 @@ def plot_table(
savefig=None,
show=False,
):

if columns is not None:
try:
tbl.columns = columns
Expand Down
96 changes: 62 additions & 34 deletions quantstats/reports.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,29 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import pandas as _pd
import numpy as _np
from math import sqrt as _sqrt, ceil as _ceil
from datetime import datetime as _dt
from base64 import b64encode as _b64encode
import re as _regex
from tabulate import tabulate as _tabulate
from . import __version__, stats as _stats, utils as _utils, plots as _plots
from dateutil.relativedelta import relativedelta
from base64 import b64encode as _b64encode
from datetime import datetime as _dt
from io import StringIO
from math import ceil as _ceil
from math import sqrt as _sqrt

import numpy as _np
import pandas as _pd
from dateutil.relativedelta import relativedelta
from tabulate import tabulate as _tabulate

from . import __version__
from . import plots as _plots
from . import stats as _stats
from . import utils as _utils

try:
from IPython.display import display as iDisplay, HTML as iHTML
from IPython.display import HTML as iHTML
from IPython.display import display as iDisplay
except ImportError:
from IPython.core.display import display as iDisplay, HTML as iHTML
from IPython.core.display import HTML as iHTML
from IPython.core.display import display as iDisplay


def _get_trading_periods(periods_per_year=252):
Expand Down Expand Up @@ -66,7 +74,6 @@ def html(
match_dates=True,
**kwargs,
):

if output is None and not _utils._in_notebook():
raise ValueError("`output` must be specified")

Expand Down Expand Up @@ -501,7 +508,6 @@ def full(
match_dates=True,
**kwargs,
):

# prepare timeseries
if match_dates:
returns = returns.dropna()
Expand Down Expand Up @@ -651,7 +657,6 @@ def basic(
match_dates=True,
**kwargs,
):

# prepare timeseries
if match_dates:
returns = returns.dropna()
Expand Down Expand Up @@ -731,7 +736,6 @@ def metrics(
match_dates=True,
**kwargs,
):

if match_dates:
returns = returns.dropna()
returns.index = returns.index.tz_localize(None)
Expand Down Expand Up @@ -930,13 +934,20 @@ def metrics(
metrics["~~~~~~~~~~"] = blank

metrics["Expected Daily %%"] = (
_stats.expected_return(df, compounded=compounded, prepare_returns=False) * pct
_stats.expected_return(df, compounded=compounded, prepare_returns=False)
* pct
)
metrics["Expected Monthly %%"] = (
_stats.expected_return(df, compounded=compounded, aggregate="M", prepare_returns=False) * pct
_stats.expected_return(
df, compounded=compounded, aggregate="M", prepare_returns=False
)
* pct
)
metrics["Expected Yearly %%"] = (
_stats.expected_return(df, compounded=compounded, aggregate="A", prepare_returns=False) * pct
_stats.expected_return(
df, compounded=compounded, aggregate="A", prepare_returns=False
)
* pct
)
metrics["Kelly Criterion %"] = (
_stats.kelly_criterion(df, prepare_returns=False) * pct
Expand All @@ -957,7 +968,7 @@ def metrics(
metrics["Max Consecutive Losses *int"] = _stats.consecutive_losses(df)

metrics["Gain/Pain Ratio"] = _stats.gain_to_pain_ratio(df, rf)
metrics["Gain/Pain (1M)"] = _stats.gain_to_pain_ratio(df, rf, "M")
metrics["Gain/Pain (1M)"] = _stats.gain_to_pain_ratio(df, rf, "ME")
# if mode.lower() == 'full':
# metrics['GPR (3M)'] = _stats.gain_to_pain_ratio(df, rf, "Q")
# metrics['GPR (6M)'] = _stats.gain_to_pain_ratio(df, rf, "2Q")
Expand Down Expand Up @@ -1004,19 +1015,26 @@ def metrics(
# best/worst
if mode.lower() == "full":
metrics["~~~"] = blank
metrics["Best Day %"] = _stats.best(df, compounded=compounded, prepare_returns=False) * pct
metrics["Best Day %"] = (
_stats.best(df, compounded=compounded, prepare_returns=False) * pct
)
metrics["Worst Day %"] = _stats.worst(df, prepare_returns=False) * pct
metrics["Best Month %"] = (
_stats.best(df, compounded=compounded, aggregate="M", prepare_returns=False) * pct
_stats.best(df, compounded=compounded, aggregate="M", prepare_returns=False)
* pct
)
metrics["Worst Month %"] = (
_stats.worst(df, aggregate="M", prepare_returns=False) * pct
)
metrics["Best Year %"] = (
_stats.best(df, compounded=compounded, aggregate="A", prepare_returns=False) * pct
_stats.best(df, compounded=compounded, aggregate="A", prepare_returns=False)
* pct
)
metrics["Worst Year %"] = (
_stats.worst(df, compounded=compounded, aggregate="A", prepare_returns=False) * pct
_stats.worst(
df, compounded=compounded, aggregate="A", prepare_returns=False
)
* pct
)

# dd
Expand All @@ -1031,20 +1049,35 @@ def metrics(
if mode.lower() == "full":
metrics["~~~~~"] = blank
metrics["Avg. Up Month %"] = (
_stats.avg_win(df, compounded=compounded, aggregate="M", prepare_returns=False) * pct
_stats.avg_win(
df, compounded=compounded, aggregate="M", prepare_returns=False
)
* pct
)
metrics["Avg. Down Month %"] = (
_stats.avg_loss(df, compounded=compounded, aggregate="M", prepare_returns=False) * pct
_stats.avg_loss(
df, compounded=compounded, aggregate="M", prepare_returns=False
)
* pct
)
metrics["Win Days %%"] = _stats.win_rate(df, prepare_returns=False) * pct
metrics["Win Month %%"] = (
_stats.win_rate(df, compounded=compounded, aggregate="M", prepare_returns=False) * pct
_stats.win_rate(
df, compounded=compounded, aggregate="M", prepare_returns=False
)
* pct
)
metrics["Win Quarter %%"] = (
_stats.win_rate(df, compounded=compounded, aggregate="Q", prepare_returns=False) * pct
_stats.win_rate(
df, compounded=compounded, aggregate="Q", prepare_returns=False
)
* pct
)
metrics["Win Year %%"] = (
_stats.win_rate(df, compounded=compounded, aggregate="A", prepare_returns=False) * pct
_stats.win_rate(
df, compounded=compounded, aggregate="A", prepare_returns=False
)
* pct
)

if "benchmark" in df:
Expand Down Expand Up @@ -1212,7 +1245,6 @@ def plots(
match_dates=True,
**kwargs,
):

benchmark_colname = kwargs.get("benchmark_title", "Benchmark")
strategy_colname = kwargs.get("strategy_title", "Strategy")
active = kwargs.get("active", "False")
Expand Down Expand Up @@ -1579,9 +1611,7 @@ def _download_html(html, filename="quantstats-tearsheet.html"):
a.download="{{filename}}";
a.hidden=true;document.body.appendChild(a);
a.innerHTML="download report";
a.click();</script>""".replace(
"\n", ""
),
a.click();</script>""".replace("\n", ""),
)
jscode = jscode.replace("{{html}}", _regex.sub(" +", " ", html.replace("\n", "")))
if _utils._in_notebook():
Expand All @@ -1594,9 +1624,7 @@ def _open_html(html):
" ",
"""<script>
var win=window.open();win.document.body.innerHTML='{{html}}';
</script>""".replace(
"\n", ""
),
</script>""".replace("\n", ""),
)
jscode = jscode.replace("{{html}}", _regex.sub(" +", " ", html.replace("\n", "")))
if _utils._in_notebook():
Expand Down
11 changes: 6 additions & 5 deletions quantstats/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.

import io as _io
import datetime as _dt
import pandas as _pd
import inspect
import io as _io

import numpy as _np
import pandas as _pd
import yfinance as _yf

from . import stats as _stats
import inspect


def _mtd(df):
Expand Down Expand Up @@ -259,10 +261,9 @@ def _prepare_benchmark(benchmark=None, period="max", rf=0.0, prepare_returns=Tru
benchmark = benchmark[benchmark.columns[0]].copy()

if isinstance(period, _pd.DatetimeIndex) and set(period) != set(benchmark.index):

# Adjust Benchmark to Strategy frequency
benchmark_prices = to_prices(benchmark, base=1)
new_index = _pd.date_range(start=period[0], end=period[-1], freq="D")
new_index = _pd.date_range(start=period[0], end=period[-1], freq="d")
benchmark = (
benchmark_prices.reindex(new_index, method="bfill")
.reindex(period)
Expand Down