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

Support Series and DataFrame with DatetimeIndex #12

Closed
Peque opened this issue Aug 4, 2021 · 3 comments · Fixed by #13
Closed

Support Series and DataFrame with DatetimeIndex #12

Peque opened this issue Aug 4, 2021 · 3 comments · Fixed by #13

Comments

@Peque
Copy link

Peque commented Aug 4, 2021

In example:

s = Series(
    index=date_range("2021", "2022", freq="MS", closed="left"),
    data=[-100] + [20] * 11,
)
xirr(s)  # 5.09623547168478

df = DataFrame(
    index=date_range("2021", "2022", freq="MS", closed="left"),
    data={
        "one": [-100] + [20] * 11,
        "two": [-80] + [19] * 11,
    },
)
xirr(df)  # Series(index=["one", "two"], data=[5.09623547168478, 8.780801977141174])

For the DataFrame I am suggesting returning a Series type simply because that is what i.e. df.sum() would return (applying .sum() to all columns).

Feel free to close if is out of scope for this module! (I would understand that) 😊

@Anexen
Copy link
Owner

Anexen commented Aug 5, 2021

Hi @Peque,
I can support the Series with DatetimeIndex and the case with DataFrame will be simply df.apply(xirr)

You can use the following code with the current implementation:

# for Series
xirr(s.reset_index())
xirr(s.index, s)

# for DataFrame
df.apply(lambda col: xirr(col.reset_index()))
df.apply(lambda col: xirr(col.index, col)

@Peque
Copy link
Author

Peque commented Aug 5, 2021

@Anexen Do you think it would make sense to return NaN instead of raising exceptions?

This would allow for df.apply(xirr) to work fine when possible.

In example:

from pandas import DataFrame
from pandas import date_range
from pyxirr import xirr

timezone = "Europe/Madrid"
index = date_range("2000-01-01", periods=10, freq="Y", closed="left", tz=timezone)
df = DataFrame(index=index, data={"a": 10, "b": 10})
df.iloc[0]["a"] = -25
df.apply(xirr)

Would return 0.3774630471754315, NaN.

@Anexen
Copy link
Owner

Anexen commented Aug 5, 2021

@Peque , I don't think so. I would like a clear separation between "Invalid input" case and "does not converge" case.

You can use something like this:

def suppress(func):
    def wrapper(*args, **kwargs):
        try:
            return func(*args, **kwargs)
        except InvalidPaymentsError:
            return None
    return wrapper
    
df.apply(suppress(xirr))

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 a pull request may close this issue.

2 participants