santoshlite / Empyrial

An Open Source Portfolio Backtesting Engine for Everyone | 面向所有人的开源投资组合回测引擎
https://empyrial.gitbook.io/empyrial/
MIT License
914 stars 124 forks source link

Can't use empyrial function when specifying rebalance #118

Closed teegin-g closed 5 months ago

teegin-g commented 9 months ago

Describe the bug When I specify the rebalance parameter when creating a portfolio object, the empyrial function will return "ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all()."

To Reproduce

  1. I define portfolio as such from empyrial import empyrial, Engine import pandas as pd portfolio = Engine( start_date = "2018-08-01", portfolio = ["BABA", "PDD", "KO", "AMD","^IXIC"], optimizer = "EF", # rebalance every year rebalance = '1y' )
  2. I run the empyrial function and it returns an error. empyrial(portfolio)

ValueError Traceback (most recent call last) Cell In[39], line 1 ----> 1 empyrial(portfolio)

File ~\anaconda3\envs\myenv\lib\site-packages\empyrial\main.py:192, in empyrial(my_portfolio, rf, sigma_value, confidence_value, report, filename) 191 def empyrial(my_portfolio, rf=0.0, sigma_value=1, confidence_value=0.95, report=False, filename="empyrial_report.pdf"): --> 192 if my_portfolio.rebalance != None: 193 # we want to get the dataframe with the dates and weights 194 rebalance_schedule = my_portfolio.rebalance 196 columns = []

File ~\anaconda3\envs\myenv\lib\site-packages\pandas\core\generic.py:1527, in NDFrame.nonzero(self) 1525 @final 1526 def nonzero(self) -> NoReturn: -> 1527 raise ValueError( 1528 f"The truth value of a {type(self).name} is ambiguous. " 1529 "Use a.empty, a.bool(), a.item(), a.any() or a.all()." 1530 )

ValueError: The truth value of a DataFrame is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

Expected behavior However, when I remove the rebalance parameter, I get the expected output: metrics, graphs, everything, ex: from empyrial import empyrial, Engine import pandas as pd portfolio = Engine( start_date = "2018-08-01", portfolio = ["BABA", "PDD", "KO", "AMD","^IXIC"], optimizer = "EF" ) empyrial(portfolio)

Other details I found that if I modify this part: if my_portfolio.rebalance != None: [...] to if isinstance(my_portfolio.rebalance, pd.DataFrame): [...] It seems to work properly?

I'm running this via dataspell in an anaconda environment (2.5.0) on a windows PC. I'm an economics student and this is my first github post so let me know if you need any additional information

santoshlite commented 8 months ago

Sorry for the late reply, I'll try your suggestion to see if it works and don't break anything else and publish a new version solving this in the coming days. Thanks for pointing this out :)

pabloatb commented 6 months ago

Hi, is there any update on this error? Let me know if there's something I can help with. Thanks.

santoshlite commented 6 months ago

Hey sorry for that! I just released a new version (v2.1.4), which should fix that, keep me posted on how it goes :)

pabloatb commented 6 months ago

Great! that one is fixed but now I get: 'Series' object has no attribute 'append'

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_21060\3247741463.py in ?()
----> 1 empyrial(portfolio_EF)
      2 sharpe_ratios.append(empyrial.SR)

~\anaconda3\envs\GCPortfolio\Lib\site-packages\empyrial\main.py in ?(my_portfolio, rf, sigma_value, confidence_value, report, filename)
    228                 end_date=dates[i + 1],
    229             )
    230 
    231             # then append those returns
--> 232             returns = returns.append(add_returns)
    233     else:
    234       if not my_portfolio.data.empty:
    235               returns = get_returns_from_data(my_portfolio.data, my_portfolio.weights, my_portfolio.portfolio)

~\anaconda3\envs\GCPortfolio\Lib\site-packages\pandas\core\generic.py in ?(self, name)
   6200             and name not in self._accessors
   6201             and self._info_axis._can_hold_identifiers_and_holds_name(name)
   6202         ):
   6203             return self[name]
-> 6204         return object.__getattribute__(self, name)

AttributeError: 'Series' object has no attribute 'append'

What pandas version should I use? I have pandas 2.1.3 now

Thanks!

santoshlite commented 6 months ago

Would it be possible to share the the code you are running so I can try to reproduce the error

pabloatb commented 6 months ago

Here's the code: Portfolio Optimization Methods.zip If you get an error with yahoo finance, make sure that you have the last version. The error is in the section shown in the image image

Thanks for your help

santoshlite commented 5 months ago

Hey, sorry for the delay. It should work if you run the same code in the same cell as the one in which you declare the portfolio_EF. This happens because your portfolio weights and other parameters are changed at the end of running empyrial(portfolio_EF).

Best,

Santosh Passoubady

[image: Mailtrack] https://mailtrack.io?utm_source=gmail&utm_medium=signature&utm_campaign=signaturevirality11& Sender notified by Mailtrack https://mailtrack.io?utm_source=gmail&utm_medium=signature&utm_campaign=signaturevirality11& 03/04/24, 05:58:04 PM

On Thu, Feb 8, 2024 at 4:43 AM pabloatb @.***> wrote:

Portfolio Optimization Methods.zip https://github.com/ssantoshp/Empyrial/files/14207062/Portfolio.Optimization.Methods.zip Here's the code, if you get an error with yahoo finance, make sure that you have the last version. The error is in the section shown in the image image.png (view on web) https://github.com/ssantoshp/Empyrial/assets/26779858/7133492e-02b1-4fb4-b0c0-59d0354f9a2f

Thanks for your help

— Reply to this email directly, view it on GitHub https://github.com/ssantoshp/Empyrial/issues/118#issuecomment-1933697936, or unsubscribe https://github.com/notifications/unsubscribe-auth/AOWDTUNA3A3DGFB4KADLHRDYSSM3LAVCNFSM6AAAAABABXYY5WVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSMZTGY4TOOJTGY . You are receiving this because you commented.Message ID: @.***>

pabloatb commented 5 months ago

Hi, thanks for your time. You mean like this?

portfolio_EF = Engine(
    start_date = "2016-10-01",
    portfolio = ['ADBE', 'ANSS', 'ANET', 'BR', 'CDW', 'GLW', 'IPGP', 'KEYS', 'WDC', 'NVDA', 'NXPI', 'TRMB', 'ZBRA'],
    optimizer = "EF",
    rebalance = "1y",
)
empyrial(portfolio_EF)
sharpe_ratios.append(empyrial.SR)

Because doing that, still causes this error: Rebalance schedule: 2017-10-01 00:00:00 2018-10-01 00:00:00 2019-10-01 00:00:00 \ ADBE 0.04655 0.11264 0.11729
ANSS 0.04353 0.08173 0.11210
ANET 0.17353 0.13630 0.11972
BR 0.02403 0.08218 0.07852
CDW 0.06073 0.07910 0.14752
GLW 0.03052 0.03671 0.00091
IPGP 0.19182 0.05190 0.02547
KEYS 0.03512 0.08483 0.16119
WDC 0.05574 0.00000 0.00000
NVDA 0.20995 0.19158 0.09095
NXPI 0.00901 0.00000 0.00000
TRMB 0.04534 0.02908 0.00478
ZBRA 0.07413 0.11395 0.14155

  2020-09-30 00:00:00  2021-09-30 00:00:00  2022-09-30 00:00:00  \

ADBE 0.16974 0.12269 0.05442
ANSS 0.12500 0.07639 0.05062
ANET 0.05074 0.07929 0.17202
BR 0.05531 0.05985 0.07340
CDW 0.08521 0.10311 0.13226
GLW 0.00000 0.00000 0.00000
IPGP 0.02253 0.00000 0.00000
KEYS 0.10801 0.12894 0.18217
WDC 0.00000 0.00000 0.00000
NVDA 0.24619 0.21034 0.19938
NXPI 0.00000 0.00000 0.00000
TRMB 0.00894 0.05285 0.01776
ZBRA 0.12832 0.16655 0.11797

  2023-09-30 00:00:00  2024-03-12  

ADBE 0.10037 0.08380
ANSS 0.05270 0.04566
ANET 0.17649 0.18267
BR 0.07408 0.06980
CDW 0.12296 0.11972
GLW 0.00000 0.00000
IPGP 0.00000 0.00000
KEYS 0.09923 0.08951
WDC 0.00000 0.00000
NVDA 0.31647 0.34503
NXPI 0.00000 0.00764
TRMB 0.00000 0.00000
ZBRA 0.05771 0.05618

AttributeError Traceback (most recent call last) ~\AppData\Local\Temp\ipykernel_5284\500546861.py in ?() 3 portfolio = ['ADBE', 'ANSS', 'ANET', 'BR', 'CDW', 'GLW', 'IPGP', 'KEYS', 'WDC', 'NVDA', 'NXPI', 'TRMB', 'ZBRA'], 4 optimizer = "EF", 5 rebalance = "1y", 6 ) ----> 7 empyrial(portfolio_EF) 8 sharpe_ratios.append(empyrial.SR) 9 #portfolio_EF.weights

~\anaconda3\envs\GCPortfolio\Lib\site-packages\empyrial\main.py in ?(my_portfolio, rf, sigma_value, confidence_value, report, filename) 228 end_date=dates[i + 1], 229 ) 230 231 # then append those returns --> 232 returns = returns.append(add_returns) 233 else: 234 if not my_portfolio.data.empty: 235 returns = get_returns_from_data(my_portfolio.data, my_portfolio.weights, my_portfolio.portfolio)

~\anaconda3\envs\GCPortfolio\Lib\site-packages\pandas\core\generic.py in ?(self, name) 6200 and name not in self._accessors 6201 and self._info_axis._can_hold_identifiers_and_holds_name(name) 6202 ): 6203 return self[name] -> 6204 return object.getattribute(self, name)

AttributeError: 'Series' object has no attribute 'append'

pabloatb commented 5 months ago

Nevermind, with python 3.10 and this packages works great. Thanks again

bta-lib==1.0.0
empyrial==2.1.4
pandas==1.5.3
numpy==1.25.2
matplotlib==3.7.1
scipy==1.11.4
yfinance==0.2.37
quantstats==0.0.62
python-dateutil==2.8.2
pytz==2023.4
kiwisolver==1.4.5
pyparsing==3.1.2
sklearn-pandas==2.2.0