quantstats icon indicating copy to clipboard operation
quantstats copied to clipboard

utils.make_index : TypeError: unsupported operand type(s) for +: 'float' and 'str'

Open Sav-Coelho opened this issue 4 months ago • 8 comments

While trying to use make_index I am getting a TypeError: unsupported operand type(s) for +: 'float' and 'str' message. This is my code that caused the error:

import quantstats as qs
qs.extend_pandas()

IAC = {"SPY": 1.3, "AGG": -.3}

portfolio = qs.utils.make_index(IAC)

I even tested with other ticker combinations and directly entering the ticker and weights in make_index and the error repeats in the same way. I also tested in previous versions and the error repeats again. Does anyone know if there is an error in the package or is it my code?

imagem_2024-04-26_084831587

Sav-Coelho avatar Apr 26 '24 11:04 Sav-Coelho

I have the same error, it is not posible to run the tickers and weights of a portfolio

FPALMAG avatar Apr 29 '24 20:04 FPALMAG

I am also encountering this issue... nothing I have done is fixing it.

benjoergens avatar Apr 30 '24 01:04 benjoergens

Can you use a different way to generate the dictionary? try

IAC = dict(SPY = 1.3, AGG = -0.3)

Also it would be useful if you can copy the output error code as a text and paste it in here.

baobach avatar Apr 30 '24 07:04 baobach

Can you use a different way to generate the dictionary? try

IAC = dict(SPY = 1.3, AGG = -0.3)

Also it would be useful if you can copy the output error code as a text and paste it in here.

I tried generating the dict as above, but to no avail... Here is my error code as text:

/Users/benjoergens/PycharmProjects/Assignment/.venv/lib/python3.12/site-packages/quantstats/utils.py:379: FutureWarning: 'M' is deprecated and will be removed in a future version, please use 'ME' instead. rbdf = index.resample(rebalance).first() Traceback (most recent call last): File "/Users/benjoergens/PycharmProjects/Assignment/Assignment.py", line 117, in qs.utils.make_index(strategy) File "/Users/benjoergens/PycharmProjects/Assignment/.venv/lib/python3.12/site-packages/quantstats/utils.py", line 400, in make_index return index[index.index <= last_day].sum(axis=1) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/benjoergens/PycharmProjects/Assignment/.venv/lib/python3.12/site-packages/pandas/core/frame.py", line 11670, in sum result = super().sum(axis, skipna, numeric_only, min_count, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/benjoergens/PycharmProjects/Assignment/.venv/lib/python3.12/site-packages/pandas/core/generic.py", line 12506, in sum return self._min_count_stat_function( ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/benjoergens/PycharmProjects/Assignment/.venv/lib/python3.12/site-packages/pandas/core/generic.py", line 12489, in _min_count_stat_function return self._reduce( ^^^^^^^^^^^^^ File "/Users/benjoergens/PycharmProjects/Assignment/.venv/lib/python3.12/site-packages/pandas/core/frame.py", line 11562, in _reduce res = df._mgr.reduce(blk_func) ^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/benjoergens/PycharmProjects/Assignment/.venv/lib/python3.12/site-packages/pandas/core/internals/managers.py", line 1500, in reduce nbs = blk.reduce(func) ^^^^^^^^^^^^^^^^ File "/Users/benjoergens/PycharmProjects/Assignment/.venv/lib/python3.12/site-packages/pandas/core/internals/blocks.py", line 404, in reduce result = func(self.values) ^^^^^^^^^^^^^^^^^ File "/Users/benjoergens/PycharmProjects/Assignment/.venv/lib/python3.12/site-packages/pandas/core/frame.py", line 11481, in blk_func return op(values, axis=axis, skipna=skipna, **kwds) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/benjoergens/PycharmProjects/Assignment/.venv/lib/python3.12/site-packages/pandas/core/nanops.py", line 85, in _f return f(*args, **kwargs) ^^^^^^^^^^^^^^^^^^ File "/Users/benjoergens/PycharmProjects/Assignment/.venv/lib/python3.12/site-packages/pandas/core/nanops.py", line 404, in new_func result = func(values, axis=axis, skipna=skipna, mask=mask, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/benjoergens/PycharmProjects/Assignment/.venv/lib/python3.12/site-packages/pandas/core/nanops.py", line 477, in newfunc return func(values, axis=axis, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/benjoergens/PycharmProjects/Assignment/.venv/lib/python3.12/site-packages/pandas/core/nanops.py", line 646, in nansum the_sum = values.sum(axis, dtype=dtype_sum) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/Users/benjoergens/PycharmProjects/Assignment/.venv/lib/python3.12/site-packages/numpy/core/_methods.py", line 49, in _sum return umr_sum(a, axis, dtype, out, keepdims, initial, where) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ TypeError: unsupported operand type(s) for +: 'float' and 'str'

benjoergens avatar Apr 30 '24 15:04 benjoergens

Same error

Simplest code, latest 0.0.62 version

%matplotlib inline import quantstats as qs import pandas as pd

extend pandas functionality with metrics, etc.

qs.extend_pandas()

conservative = {"IVV": 0.5,"URTH": 0.5} qs.utils.make_index(ticker_weights=conservative, period="1y")

RobertHH-IS avatar May 01 '24 20:05 RobertHH-IS

I did a quick fix in the code and it works now. Fork, uninstall library, git clone, pip install -e . , make changes, save, works.

`def make_index( ticker_weights, rebalance="1M", period="max", returns=None, match_dates=False ): """ Makes an index out of the given tickers and weights. Optionally you can pass a dataframe with the returns. If returns is not given it try to download them with yfinance

Args:
    * ticker_weights (Dict): A python dict with tickers as keys
        and weights as values
    * rebalance: Pandas resample interval or None for never
    * period: time period of the returns to be downloaded
    * returns (Series, DataFrame): Optional. Returns If provided,
        it will fist check if returns for the given ticker are in
        this dataframe, if not it will try to download them with
        yfinance
Returns:
    * index_returns (Series, DataFrame): Returns for the index
"""
# Declare a returns variable
index = None
portfolio = {}

# Iterate over weights
for ticker in ticker_weights.keys():
    if (returns is None) or (ticker not in returns.columns):
        # Download the returns for this ticker, e.g. GOOG
        ticker_returns = download_returns(ticker, period)
    else:
        ticker_returns = returns[ticker]

    portfolio[ticker] = ticker_returns

# index members time-series
index = _pd.DataFrame(portfolio).dropna()

if match_dates:
    index = index[max(index.ne(0).idxmax()) :]

# no rebalance?
if rebalance is None:
    for ticker, weight in ticker_weights.items():
        index[ticker] = weight * index[ticker]
    return index.sum(axis=1)

last_day = index.index[-1]

# rebalance marker
rbdf = index.resample(rebalance).first()
rbdf["break"] = rbdf.index.strftime("%s")

# index returns with rebalance markers
index = _pd.concat([index, rbdf["break"]], axis=1)

# mark first day day
index["first_day"] = _pd.isna(index["break"]) & ~_pd.isna(index["break"].shift(1))
index.loc[index.index[0], "first_day"] = True

# multiply first day of each rebalance period by the weight
for ticker, weight in ticker_weights.items():
    index[ticker] = _np.where(
        index["first_day"], weight * index[ticker], index[ticker]
    )

# drop first marker and break column
index.drop(columns=["first_day", "break"], inplace=True)

# drop when all are NaN
index.dropna(how="all", inplace=True)

# Ensure only numeric columns are summed
numeric_cols = index.select_dtypes(include=[_np.number]).columns
return index[numeric_cols][index.index <= last_day].sum(axis=1)`

RobertHH-IS avatar May 01 '24 21:05 RobertHH-IS