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

Issue loading data from FRED #157

Closed
hhenson opened this issue May 11, 2024 · 9 comments
Closed

Issue loading data from FRED #157

hhenson opened this issue May 11, 2024 · 9 comments

Comments

@hhenson
Copy link

hhenson commented May 11, 2024

Trying to run the performance example, it loads the SNP500 data, but it fails when trying to load the FRED data.
This is the output:

Updating data.......................................................YahooFinance("BBWI") has dubious total open-to-open returns for timestamps: DatetimeIndex(['1982-11-23 14:30:00+00:00', '1985-06-27 13:30:00+00:00'], dtype='datetime64[ns, UTC]', freq=None)
...YahooFinance("BEN") has dubious total open-to-open returns for timestamps: DatetimeIndex(['1984-11-12 14:30:00+00:00', '1984-11-14 14:30:00+00:00',
'1984-11-15 14:30:00+00:00', '1984-11-19 14:30:00+00:00',
'1984-12-28 14:30:00+00:00', '1985-01-02 14:30:00+00:00'],
dtype='datetime64[ns, UTC]', freq=None)
...YahooFinance("BIIB") has dubious total open-to-open returns for timestamps: DatetimeIndex(['2005-02-25 14:30:00+00:00'], dtype='datetime64[ns, UTC]', freq=None)
....................................................................YahooFinance("D") has dubious total open-to-open returns for timestamps: DatetimeIndex(['1983-05-23 13:30:00+00:00'], dtype='datetime64[ns, UTC]', freq=None)
...................................................................YahooFinance("FRT") has dubious total open-to-open returns for timestamps: DatetimeIndex(['1974-05-24 13:30:00+00:00', '1974-05-29 13:30:00+00:00',
'1974-06-04 13:30:00+00:00'],
dtype='datetime64[ns, UTC]', freq=None)
...........YahooFinance("GL") has dubious total open-to-open returns for timestamps: DatetimeIndex(['1984-06-08 13:30:00+00:00', '1985-10-10 13:30:00+00:00'], dtype='datetime64[ns, UTC]', freq=None)
...............YahooFinance("HD") has dubious total open-to-open returns for timestamps: DatetimeIndex(['1983-03-18 14:30:00+00:00'], dtype='datetime64[ns, UTC]', freq=None)
.........................................YahooFinance("JNPR") has dubious total open-to-open returns for timestamps: DatetimeIndex(['2024-01-08 14:30:00+00:00'], dtype='datetime64[ns, UTC]', freq=None)
.............YahooFinance("KR") has dubious total open-to-open returns for timestamps: DatetimeIndex(['2017-06-15 13:30:00+00:00'], dtype='datetime64[ns, UTC]', freq=None)
............YahooFinance("LOW") has dubious total open-to-open returns for timestamps: DatetimeIndex(['1983-04-29 13:30:00+00:00'], dtype='datetime64[ns, UTC]', freq=None)
............YahooFinance("MCD") has dubious total open-to-open returns for timestamps: DatetimeIndex(['1969-07-09 13:30:00+00:00'], dtype='datetime64[ns, UTC]', freq=None)
.............YahooFinance("MMC") has dubious total open-to-open returns for timestamps: DatetimeIndex(['1980-11-21 14:30:00+00:00', '2004-10-14 13:30:00+00:00'], dtype='datetime64[ns, UTC]', freq=None)
.........................................................................YahooFinance("PSA") has dubious total open-to-open returns for timestamps: DatetimeIndex(['1981-01-28 14:30:00+00:00', '1981-02-24 14:30:00+00:00'], dtype='datetime64[ns, UTC]', freq=None)
.............................................YahooFinance("SYY") has dubious total open-to-open returns for timestamps: DatetimeIndex(['1975-01-10 14:30:00+00:00', '1975-01-29 14:30:00+00:00',
'1977-05-11 13:30:00+00:00', '1977-05-12 13:30:00+00:00'],
dtype='datetime64[ns, UTC]', freq=None)
..................YahooFinance("TRV") has dubious total open-to-open returns for timestamps: DatetimeIndex(['1986-06-12 13:30:00+00:00'], dtype='datetime64[ns, UTC]', freq=None)
...YahooFinance("TSN") has dubious total open-to-open returns for timestamps: DatetimeIndex(['1983-04-18 14:30:00+00:00', '1985-04-24 14:30:00+00:00'], dtype='datetime64[ns, UTC]', freq=None)
.........YahooFinance("UHS") has dubious total open-to-open returns for timestamps: DatetimeIndex(['1986-10-21 13:30:00+00:00'], dtype='datetime64[ns, UTC]', freq=None)
.....YahooFinance("URI") has dubious total open-to-open returns for timestamps: DatetimeIndex(['2007-11-14 14:30:00+00:00'], dtype='datetime64[ns, UTC]', freq=None)
............YahooFinance("VTRS") has dubious total open-to-open returns for timestamps: DatetimeIndex(['1983-07-01 13:30:00+00:00', '1985-02-19 14:30:00+00:00'], dtype='datetime64[ns, UTC]', freq=None)
.........................
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/urllib/request.py", line 1344, in do_open
h.request(req.get_method(), req.selector, req.data, headers,
File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/http/client.py", line 1331, in request
self._send_request(method, url, body, headers, encode_chunked)
File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/http/client.py", line 1377, in _send_request
self.endheaders(body, encode_chunked=encode_chunked)
File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/http/client.py", line 1326, in endheaders
self._send_output(message_body, encode_chunked=encode_chunked)
File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/http/client.py", line 1085, in _send_output
self.send(msg)
File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/http/client.py", line 1029, in send
self.connect()
File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/http/client.py", line 1472, in connect
self.sock = self._context.wrap_socket(self.sock,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/ssl.py", line 455, in wrap_socket
return self.sslsocket_class._create(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/ssl.py", line 1042, in _create
self.do_handshake()
File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/ssl.py", line 1320, in do_handshake
self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1000)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File "/Users/hhenson/PycharmProjects/cvxportfolio_experiment/.venv/lib/python3.12/site-packages/cvxportfolio/data/symbol_data.py", line 1090, in _internal_download
return pd.to_numeric(pd.read_csv(
^^^^^^^^^^^^
File "/Users/hhenson/PycharmProjects/cvxportfolio_experiment/.venv/lib/python3.12/site-packages/pandas/io/parsers/readers.py", line 1026, in read_csv
return _read(filepath_or_buffer, kwds)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/hhenson/PycharmProjects/cvxportfolio_experiment/.venv/lib/python3.12/site-packages/pandas/io/parsers/readers.py", line 620, in _read
parser = TextFileReader(filepath_or_buffer, **kwds)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/hhenson/PycharmProjects/cvxportfolio_experiment/.venv/lib/python3.12/site-packages/pandas/io/parsers/readers.py", line 1620, in init
self._engine = self._make_engine(f, self.engine)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/hhenson/PycharmProjects/cvxportfolio_experiment/.venv/lib/python3.12/site-packages/pandas/io/parsers/readers.py", line 1880, in _make_engine
self.handles = get_handle(
^^^^^^^^^^^
File "/Users/hhenson/PycharmProjects/cvxportfolio_experiment/.venv/lib/python3.12/site-packages/pandas/io/common.py", line 728, in get_handle
ioargs = _get_filepath_or_buffer(
^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/hhenson/PycharmProjects/cvxportfolio_experiment/.venv/lib/python3.12/site-packages/pandas/io/common.py", line 384, in _get_filepath_or_buffer
with urlopen(req_info) as req:
^^^^^^^^^^^^^^^^^
File "/Users/hhenson/PycharmProjects/cvxportfolio_experiment/.venv/lib/python3.12/site-packages/pandas/io/common.py", line 289, in urlopen
return urllib.request.urlopen(*args, **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/urllib/request.py", line 215, in urlopen
return opener.open(url, data, timeout)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/urllib/request.py", line 515, in open
response = self._open(req, data)
^^^^^^^^^^^^^^^^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/urllib/request.py", line 532, in _open
result = self._call_chain(self.handle_open, protocol, protocol +
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/urllib/request.py", line 492, in _call_chain
result = func(*args)
^^^^^^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/urllib/request.py", line 1392, in https_open
return self.do_open(http.client.HTTPSConnection, req,
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/urllib/request.py", line 1347, in do_open
raise URLError(err)
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1000)>

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
File "/Users/hhenson/PycharmProjects/cvxportfolio_experiment/performance_test.py", line 50, in
simulator = cvx.StockMarketSimulator(UNIVERSE)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/hhenson/PycharmProjects/cvxportfolio_experiment/.venv/lib/python3.12/site-packages/cvxportfolio/simulator.py", line 764, in init
super().init(universe=universe,
File "/Users/hhenson/PycharmProjects/cvxportfolio_experiment/.venv/lib/python3.12/site-packages/cvxportfolio/simulator.py", line 155, in init
self.market_data = DownloadedMarketData(
^^^^^^^^^^^^^^^^^^^^^
File "/Users/hhenson/PycharmProjects/cvxportfolio_experiment/.venv/lib/python3.12/site-packages/cvxportfolio/data/market_data.py", line 714, in init
self._add_cash_column(self.cash_key, grace_period=grace_period)
File "/Users/hhenson/PycharmProjects/cvxportfolio_experiment/.venv/lib/python3.12/site-packages/cvxportfolio/data/market_data.py", line 305, in _add_cash_column
data = Fred(
^^^^^
File "/Users/hhenson/PycharmProjects/cvxportfolio_experiment/.venv/lib/python3.12/site-packages/cvxportfolio/data/symbol_data.py", line 99, in init
self.update(grace_period)
File "/Users/hhenson/PycharmProjects/cvxportfolio_experiment/.venv/lib/python3.12/site-packages/cvxportfolio/data/symbol_data.py", line 191, in update
updated = self._download(
^^^^^^^^^^^^^^^
File "/Users/hhenson/PycharmProjects/cvxportfolio_experiment/.venv/lib/python3.12/site-packages/cvxportfolio/data/symbol_data.py", line 1110, in _download
return self._internal_download(symbol)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/Users/hhenson/PycharmProjects/cvxportfolio_experiment/.venv/lib/python3.12/site-packages/cvxportfolio/data/symbol_data.py", line 1094, in _internal_download
raise DataError(f"Download of {symbol}"
cvxportfolio.errors.DataError: Download of DFF from Fred failed. Are you connected to the Internet?

I dug a bit into the code and it seems that the code tries to load data using the URL:

https://fred.stlouisfed.org/graph/fredgraph.csv

If I try and put this into a browser I get:

image

It seems like it may be a change made to the Fred Website?

May also be geographic issue?

@enzbus
Copy link
Collaborator

enzbus commented May 11, 2024

Hey Howard! Thanks, it looks like it's an SSL error on the FRED side. This is the error in your traceback:

File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/urllib/request.py", line 1347, in do_open
raise URLError(err)
urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1000)>

Or this

File "/Library/Frameworks/Python.framework/Versions/3.12/lib/python3.12/ssl.py", line 1320, in do_handshake
self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1000)

That's the first time I see it, but I did see an error with FRED on one of the GH test runners yesterday, it worked fine after re-running. FYI the endpoint is something like this https://fred.stlouisfed.org/graph/fredgraph.csv?id=DFF, it's an undocumented endpoint by FRED but it works fine. Maybe check if you're not using some proxy or vpn with cold SSL caches? Everything works on my side, and in the GH test runners.

@enzbus
Copy link
Collaborator

enzbus commented May 11, 2024

FYI @hhenson, the example you're running only uses FRED to get the USD risk free (central bank) rate, Yahoo Finance is working fine for you it seems. You can get around that by disabling that part of the the market data download. Substitute this line

simulator = cvx.StockMarketSimulator(UNIVERSE)

with this

md = cvx.DownloadedMarketData(UNIVERSE, cash_key='cash')
simulator = cvx.StockMarketSimulator(market_data = md)

that sets the risk free rate to zero...

@enzbus
Copy link
Collaborator

enzbus commented May 11, 2024

Also, this thread https://stackoverflow.com/questions/52805115/certificate-verify-failed-unable-to-get-local-issuer-certificate seems to suggest you have to run some post-installation script to enable SSL for your local Python, it looks like you're using one in the system libraries. I normally suggest using brew for installing Python on mac...

enzbus added a commit that referenced this issue May 11, 2024
see GH issue #157
now it goes through requests instead of using
pd.read_csv(endpoint) directly; should have no
effect on performance but it seems requests is
more robust in handling ssl (should use certifi)
@hhenson
Copy link
Author

hhenson commented May 11, 2024

OK, was using a pyenv setup, changed to use the brew system installation and got it working!

@hhenson
Copy link
Author

hhenson commented May 11, 2024

FYI
I have gotten the performance test to run, these are the results:

FIRST RUN
BACK-TEST TOOK: 294.0837182998657
SIMULATOR + POLICY TIMES: 294.03591322898865
AVERAGE TIME PER ITERATION: 0.23373284040460146
RESULT:

#################################################################
Universe size 501
Initial timestamp 2019-05-13 13:30:00+00:00
Final timestamp 2024-05-10 13:30:00+00:00
Number of periods 1259
Initial value (USDOLLAR) 1.000e+06
Final value (USDOLLAR) 4.394e+06
Profit (USDOLLAR) 3.394e+06

Avg. return (annualized) 60.8%
Volatility (annualized) 78.0%
Avg. excess return (annualized) 58.8%
Avg. active return (annualized) 58.8%
Excess volatility (annualized) 78.0%
Active volatility (annualized) 78.0%

Avg. growth rate (annualized) 29.7%
Avg. excess growth rate (annualized) 27.6%
Avg. active growth rate (annualized) 27.6%

Avg. StocksTransactionCost 0bp
Max. StocksTransactionCost 9bp
Avg. StocksHoldingCost 1bp
Max. StocksHoldingCost 5bp

Sharpe ratio 0.75
Information ratio 0.75

Avg. drawdown -48.1%
Min. drawdown -88.3%
Avg. leverage 299.9%
Max. leverage 399.6%
Avg. turnover 3.9%
Max. turnover 150.0%

Avg. policy time 0.152s
Avg. simulator time 0.081s
Of which: market data 0.013s
Of which: result 0.054s
Total time 294.036s
#################################################################

SECOND RUN
BACK-TEST TOOK: 216.16064381599426
SIMULATOR + POLICY TIMES: 216.1089153289795
AVERAGE TIME PER ITERATION: 0.17178769104052424
RESULT:

#################################################################
Universe size 501
Initial timestamp 2019-05-13 13:30:00+00:00
Final timestamp 2024-05-10 13:30:00+00:00
Number of periods 1259
Initial value (USDOLLAR) 1.000e+06
Final value (USDOLLAR) 4.393e+06
Profit (USDOLLAR) 3.393e+06

Avg. return (annualized) 60.8%
Volatility (annualized) 78.0%
Avg. excess return (annualized) 58.8%
Avg. active return (annualized) 58.8%
Excess volatility (annualized) 78.0%
Active volatility (annualized) 78.0%

Avg. growth rate (annualized) 29.6%
Avg. excess growth rate (annualized) 27.6%
Avg. active growth rate (annualized) 27.6%

Avg. StocksTransactionCost 0bp
Max. StocksTransactionCost 9bp
Avg. StocksHoldingCost 1bp
Max. StocksHoldingCost 5bp

Sharpe ratio 0.75
Information ratio 0.75

Avg. drawdown -48.1%
Min. drawdown -88.3%
Avg. leverage 299.9%
Max. leverage 399.6%
Avg. turnover 3.9%
Max. turnover 150.0%

Avg. policy time 0.107s
Avg. simulator time 0.065s
Of which: market data 0.010s
Of which: result 0.044s
Total time 216.109s
#################################################################

This is on an M3 MacBook Pro with the Max chipset using the brew version of Python 3.11.9

@hhenson
Copy link
Author

hhenson commented May 11, 2024

FIRST RUN
BACK-TEST TOOK: 362.78375482559204
SIMULATOR + POLICY TIMES: 362.7362184524536
AVERAGE TIME PER ITERATION: 0.28834357587635423
RESULT:

#################################################################
Universe size 501
Initial timestamp 2019-05-13 13:30:00+00:00
Final timestamp 2024-05-10 13:30:00+00:00
Number of periods 1259
Initial value (USDOLLAR) 1.000e+06
Final value (USDOLLAR) 4.394e+06
Profit (USDOLLAR) 3.394e+06

Avg. return (annualized) 60.8%
Volatility (annualized) 78.0%
Avg. excess return (annualized) 58.8%
Avg. active return (annualized) 58.8%
Excess volatility (annualized) 78.0%
Active volatility (annualized) 78.0%

Avg. growth rate (annualized) 29.7%
Avg. excess growth rate (annualized) 27.6%
Avg. active growth rate (annualized) 27.6%

Avg. StocksTransactionCost 0bp
Max. StocksTransactionCost 9bp
Avg. StocksHoldingCost 1bp
Max. StocksHoldingCost 5bp

Sharpe ratio 0.75
Information ratio 0.75

Avg. drawdown -48.1%
Min. drawdown -88.3%
Avg. leverage 299.9%
Max. leverage 399.6%
Avg. turnover 3.9%
Max. turnover 150.0%

Avg. policy time 0.198s
Avg. simulator time 0.090s
Of which: market data 0.017s
Of which: result 0.053s
Total time 362.736s
#################################################################

SECOND RUN
BACK-TEST TOOK: 248.23834991455078
SIMULATOR + POLICY TIMES: 248.17573499679565
AVERAGE TIME PER ITERATION: 0.19727800874149098
RESULT:

#################################################################
Universe size 501
Initial timestamp 2019-05-13 13:30:00+00:00
Final timestamp 2024-05-10 13:30:00+00:00
Number of periods 1259
Initial value (USDOLLAR) 1.000e+06
Final value (USDOLLAR) 4.394e+06
Profit (USDOLLAR) 3.394e+06

Avg. return (annualized) 60.8%
Volatility (annualized) 78.0%
Avg. excess return (annualized) 58.8%
Avg. active return (annualized) 58.8%
Excess volatility (annualized) 78.0%
Active volatility (annualized) 78.0%

Avg. growth rate (annualized) 29.7%
Avg. excess growth rate (annualized) 27.6%
Avg. active growth rate (annualized) 27.6%

Avg. StocksTransactionCost 0bp
Max. StocksTransactionCost 9bp
Avg. StocksHoldingCost 1bp
Max. StocksHoldingCost 5bp

Sharpe ratio 0.75
Information ratio 0.75

Avg. drawdown -48.1%
Min. drawdown -88.3%
Avg. leverage 299.9%
Max. leverage 399.6%
Avg. turnover 3.9%
Max. turnover 150.0%

Avg. policy time 0.125s
Avg. simulator time 0.072s
Of which: market data 0.013s
Of which: result 0.044s
Total time 248.176s
#################################################################

This is on the M2 ULTRA Studio

@hhenson
Copy link
Author

hhenson commented May 12, 2024

No Issue

@hhenson hhenson closed this as completed May 12, 2024
@enzbus
Copy link
Collaborator

enzbus commented May 12, 2024

Very nice, second runs are the most interesting ones. That example uses an open-source solver (ECOS), which is very similar to MOSEK. Some (~10% I guess) improvement can come from optimizing the "result time", which could be done better (but it's very tricky to make sure the accounting is correct). Otherwise it is IMO about as fast as it can be done.

*edit: ECOS, not CLARABEL

@enzbus
Copy link
Collaborator

enzbus commented May 12, 2024

@hhenson I just re-ran it myself, changing the solver to the new open-source one that is default in CVXPY 1.5; interesting to note that it gives slightly lower Sharpe, but it is a bit faster.

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

No branches or pull requests

2 participants