!pip install yfinance --upgrade --no-cache-dir
Collecting yfinance
Downloading yfinance-0.2.38-py2.py3-none-any.whl (72 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 73.0/73.0 kB 52.0 MB/s eta 0:00:00
Collecting multitasking>=0.0.7
Downloading multitasking-0.0.11-py3-none-any.whl (8.5 kB)
Collecting frozendict>=2.3.4
Downloading frozendict-2.4.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (103 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 103.1/103.1 kB 101.8 MB/s eta 0:00:00
Collecting requests>=2.31
Downloading requests-2.31.0-py3-none-any.whl (62 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 62.6/62.6 kB 106.1 MB/s eta 0:00:00
Collecting pandas>=1.3.0
Downloading pandas-1.3.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (11.3 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 11.3/11.3 MB 40.5 MB/s eta 0:00:00
Collecting appdirs>=1.4.4
Downloading appdirs-1.4.4-py2.py3-none-any.whl (9.6 kB)
Requirement already satisfied: pytz>=2022.5 in /shared-libs-deprecated/python3.7/py/lib/python3.7/site-packages (from yfinance) (2022.5)
Collecting peewee>=3.16.2
Downloading peewee-3.17.3.tar.gz (3.0 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 3.0/3.0 MB 64.5 MB/s eta 0:00:00
Installing build dependencies ... done
Getting requirements to build wheel ... done
Preparing metadata (pyproject.toml) ... done
Collecting html5lib>=1.1
Downloading html5lib-1.1-py2.py3-none-any.whl (112 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 112.2/112.2 kB 224.2 MB/s eta 0:00:00
Requirement already satisfied: numpy>=1.16.5 in /shared-libs-deprecated/python3.7/py/lib/python3.7/site-packages (from yfinance) (1.21.6)
Requirement already satisfied: beautifulsoup4>=4.11.1 in /shared-libs-deprecated/python3.7/py-core/lib/python3.7/site-packages (from yfinance) (4.11.1)
Requirement already satisfied: lxml>=4.9.1 in /shared-libs-deprecated/python3.7/py/lib/python3.7/site-packages (from yfinance) (4.9.1)
Requirement already satisfied: soupsieve>1.2 in /shared-libs-deprecated/python3.7/py-core/lib/python3.7/site-packages (from beautifulsoup4>=4.11.1->yfinance) (2.3.2.post1)
Requirement already satisfied: webencodings in /shared-libs-deprecated/python3.7/py-core/lib/python3.7/site-packages (from html5lib>=1.1->yfinance) (0.5.1)
Requirement already satisfied: six>=1.9 in /shared-libs-deprecated/python3.7/py-core/lib/python3.7/site-packages (from html5lib>=1.1->yfinance) (1.16.0)
Requirement already satisfied: python-dateutil>=2.7.3 in /shared-libs-deprecated/python3.7/py-core/lib/python3.7/site-packages (from pandas>=1.3.0->yfinance) (2.8.2)
Requirement already satisfied: urllib3<3,>=1.21.1 in /shared-libs-deprecated/python3.7/py/lib/python3.7/site-packages (from requests>=2.31->yfinance) (1.26.12)
Requirement already satisfied: charset-normalizer<4,>=2 in /shared-libs-deprecated/python3.7/py-core/lib/python3.7/site-packages (from requests>=2.31->yfinance) (2.1.1)
Requirement already satisfied: certifi>=2017.4.17 in /shared-libs-deprecated/python3.7/py/lib/python3.7/site-packages (from requests>=2.31->yfinance) (2022.9.24)
Requirement already satisfied: idna<4,>=2.5 in /shared-libs-deprecated/python3.7/py-core/lib/python3.7/site-packages (from requests>=2.31->yfinance) (3.4)
Building wheels for collected packages: peewee
Building wheel for peewee (pyproject.toml) ... done
Created wheel for peewee: filename=peewee-3.17.3-py3-none-any.whl size=138405 sha256=9d1b5a0afc300d3b00b0137bc6c3d7efc2b9ede8952ef0081f0dc5ce2dea4cdf
Stored in directory: /tmp/pip-ephem-wheel-cache-s95h9rxc/wheels/52/58/ee/e76652228a2ca264efbeb1e2b1f82feb5175098caf738f861b
Successfully built peewee
Installing collected packages: peewee, multitasking, appdirs, requests, html5lib, frozendict, pandas, yfinance
Attempting uninstall: requests
Found existing installation: requests 2.28.1
Not uninstalling requests at /shared-libs-deprecated/python3.7/py/lib/python3.7/site-packages, outside environment /root/venv
Can't uninstall 'requests'. No files were found to uninstall.
Attempting uninstall: pandas
Found existing installation: pandas 1.2.5
Not uninstalling pandas at /shared-libs-deprecated/python3.7/py/lib/python3.7/site-packages, outside environment /root/venv
Can't uninstall 'pandas'. No files were found to uninstall.
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
spacy 3.4.2 requires typing-extensions<4.2.0,>=3.7.4; python_version < "3.8", but you have typing-extensions 4.4.0 which is incompatible.
snowflake-connector-python 2.7.9 requires charset-normalizer~=2.0.0, but you have charset-normalizer 2.1.1 which is incompatible.
Successfully installed appdirs-1.4.4 frozendict-2.4.2 html5lib-1.1 multitasking-0.0.11 pandas-1.3.5 peewee-3.17.3 requests-2.31.0 yfinance-0.2.38
[notice] A new release of pip is available: 23.0.1 -> 24.0
[notice] To update, run: pip install --upgrade pip
!pip install PyPortfolioOpt==1.2.1
Collecting PyPortfolioOpt==1.2.1
Downloading PyPortfolioOpt-1.2.1-py3-none-any.whl (49 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 49.0/49.0 kB 8.9 MB/s eta 0:00:00
Requirement already satisfied: numpy in /shared-libs-deprecated/python3.7/py/lib/python3.7/site-packages (from PyPortfolioOpt==1.2.1) (1.21.6)
Collecting pandas<0.26.0,>=0.25.3
Downloading pandas-0.25.3-cp37-cp37m-manylinux1_x86_64.whl (10.4 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 10.4/10.4 MB 51.8 MB/s eta 0:00:00
Requirement already satisfied: scipy in /shared-libs-deprecated/python3.7/py/lib/python3.7/site-packages (from PyPortfolioOpt==1.2.1) (1.7.3)
Collecting cvxpy<2.0.0,>=1.0.28
Downloading cvxpy-1.3.4.tar.gz (1.3 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.3/1.3 MB 31.9 MB/s eta 0:00:00
Installing build dependencies ... done
Getting requirements to build wheel ... done
Preparing metadata (pyproject.toml) ... done
Collecting setuptools>65.5.1
Using cached setuptools-68.0.0-py3-none-any.whl (804 kB)
Collecting scs>=1.1.6
Downloading scs-3.2.4.post1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (10.4 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 10.4/10.4 MB 82.6 MB/s eta 0:00:00
Collecting osqp>=0.4.1
Downloading osqp-0.6.5-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl (296 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 296.7/296.7 kB 49.3 MB/s eta 0:00:00
Collecting ecos>=2
Downloading ecos-2.0.13-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (218 kB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 218.2/218.2 kB 32.7 MB/s eta 0:00:00
Requirement already satisfied: python-dateutil>=2.6.1 in /shared-libs-deprecated/python3.7/py-core/lib/python3.7/site-packages (from pandas<0.26.0,>=0.25.3->PyPortfolioOpt==1.2.1) (2.8.2)
Requirement already satisfied: pytz>=2017.2 in /shared-libs-deprecated/python3.7/py/lib/python3.7/site-packages (from pandas<0.26.0,>=0.25.3->PyPortfolioOpt==1.2.1) (2022.5)
Collecting qdldl
Downloading qdldl-0.1.7.post2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.2 MB)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 1.2/1.2 MB 81.4 MB/s eta 0:00:00
Requirement already satisfied: six>=1.5 in /shared-libs-deprecated/python3.7/py-core/lib/python3.7/site-packages (from python-dateutil>=2.6.1->pandas<0.26.0,>=0.25.3->PyPortfolioOpt==1.2.1) (1.16.0)
Building wheels for collected packages: cvxpy
Building wheel for cvxpy (pyproject.toml) ... done
Created wheel for cvxpy: filename=cvxpy-1.3.4-cp37-cp37m-linux_x86_64.whl size=3607556 sha256=b1089025b0e0755635d195925f51a625bf516c01ece0534d862e0b1200d5ae29
Stored in directory: /root/.cache/pip/wheels/49/1b/a6/2e5d0527d953e4cbeb984aeed6bbe715f034200891df73551a
Successfully built cvxpy
Installing collected packages: setuptools, scs, qdldl, pandas, ecos, osqp, cvxpy, PyPortfolioOpt
Attempting uninstall: setuptools
Found existing installation: setuptools 47.1.0
Uninstalling setuptools-47.1.0:
Successfully uninstalled setuptools-47.1.0
Attempting uninstall: pandas
Found existing installation: pandas 1.3.5
Uninstalling pandas-1.3.5:
Successfully uninstalled pandas-1.3.5
ERROR: pip's dependency resolver does not currently take into account all the packages that are installed. This behaviour is the source of the following dependency conflicts.
yfinance 0.2.38 requires pandas>=1.3.0, but you have pandas 0.25.3 which is incompatible.
thinc 8.1.5 requires typing-extensions<4.2.0,>=3.7.4.1; python_version < "3.8", but you have typing-extensions 4.4.0 which is incompatible.
spacy 3.4.2 requires typing-extensions<4.2.0,>=3.7.4; python_version < "3.8", but you have typing-extensions 4.4.0 which is incompatible.
snowflake-connector-python 2.7.9 requires charset-normalizer~=2.0.0, but you have charset-normalizer 2.1.1 which is incompatible.
Successfully installed PyPortfolioOpt-1.2.1 cvxpy-1.3.4 ecos-2.0.13 osqp-0.6.5 pandas-0.25.3 qdldl-0.1.7.post2 scs-3.2.4.post1 setuptools-68.0.0
[notice] A new release of pip is available: 23.0.1 -> 24.0
[notice] To update, run: pip install --upgrade pip
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import datetime as dt
import yfinance as yf
symbols_list = ['SPY']
start = dt.datetime(2020,3,1)
end = dt.datetime(2021,9,1)
data = yf.download(symbols_list, start=start, end=end)
data.info()
[*********************100%%**********************] 1 of 1 completed<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 380 entries, 2020-03-02 to 2021-08-31
Data columns (total 6 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Open 380 non-null float64
1 High 380 non-null float64
2 Low 380 non-null float64
3 Close 380 non-null float64
4 Adj Close 380 non-null float64
5 Volume 380 non-null int64
dtypes: float64(5), int64(1)
memory usage: 20.8 KB
spy = data.reset_index()
spy.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 380 entries, 0 to 379
Data columns (total 7 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Date 380 non-null datetime64[ns]
1 Open 380 non-null float64
2 High 380 non-null float64
3 Low 380 non-null float64
4 Close 380 non-null float64
5 Adj Close 380 non-null float64
6 Volume 380 non-null int64
dtypes: datetime64[ns](1), float64(5), int64(1)
memory usage: 20.9 KB
# filter column adjusted close
spy = spy[['Date','Adj Close', 'Volume']]
spy.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 380 entries, 0 to 379
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Date 380 non-null datetime64[ns]
1 Adj Close 380 non-null float64
2 Volume 380 non-null int64
dtypes: datetime64[ns](1), float64(1), int64(1)
memory usage: 9.0 KB
# create variables
spy['day_of_week'] = spy['Date'].dt.dayofweek
spy['return'] = spy['Adj Close'].pct_change()
spy = spy.bfill()
from pypfopt.efficient_frontier import EfficientFrontier
from pypfopt import risk_models
from pypfopt import expected_returns
from pypfopt import cla
from pypfopt.plotting import Plotting
from pypfopt.discrete_allocation import DiscreteAllocation, get_latest_prices
from matplotlib.ticker import FuncFormatter
import seaborn as sns
from pypfopt import objective_functions
p_symbols_list = ['TSLA', 'INTC']
p_start = dt.datetime(2023,1,1)
p_end = dt.datetime(2024,4,1)
p_data = yf.download(p_symbols_list, start=p_start, end=p_end)
[*********************100%%**********************] 2 of 2 completed
p_data
Adj Close INTCfloat64
24.556591033935547 - 50.61164855957031
Adj Close TSLAfloat64
108.0999984741211 - 293.3399963378906
2024-03-28 00:00:00
44.16999817
175.7899933
p_df = p_data['Adj Close']
# Unique names (e.g., crypto trade on weekends as well but stock do not)
p_df = p_df.ffill()
p_df.head()
INTCfloat64
TSLAfloat64
2023-01-03 00:00:00
26.04400826
108.0999985
2023-01-04 00:00:00
26.96962929
113.6399994
2023-01-05 00:00:00
26.85270691
110.3399963
2023-01-06 00:00:00
27.9926815
113.0599976
2023-01-09 00:00:00
28.55779457
119.7699966
sharpe_portfolio_wt = {'TSLA': 0, 'INTC': 0.28}
latest_prices = get_latest_prices(p_df)
da = DiscreteAllocation(sharpe_portfolio_wt, latest_prices, total_portfolio_value=1000000)
allocation, leftover = da.greedy_portfolio()
print("Discrete allocation:", allocation)
print("Funds remaining: ${:.2f}".format(leftover))
Discrete allocation: {'INTC': 6339}
Funds remaining: $720006.38
sharpe_portfolio_wt_list = list(sharpe_portfolio_wt.values())
ret_data_s = p_df.pct_change()[1:]
weighted_returns_s = (sharpe_portfolio_wt_list * ret_data_s)
portfolio_ret_s = pd.DataFrame(weighted_returns_s.sum(axis=1))
ret_data_s = ret_data_s.merge(portfolio_ret_s, on="Date", how="left")
ret_data_s = ret_data_s.rename(columns={0: "portfolio_ret"})
ret_data_s=ret_data_s[["portfolio_ret"]]
ret_data_s = ret_data_s.reset_index()
ret_data_s.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 310 entries, 0 to 309
Data columns (total 2 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Date 310 non-null datetime64[ns]
1 portfolio_ret 310 non-null float64
dtypes: datetime64[ns](1), float64(1)
memory usage: 5.0 KB
ret_data_s['day_of_week'] = ret_data_s['Date'].dt.dayofweek
ret_data_s['return'] = ret_data_s['portfolio_ret']
ret_data_s.tail(10)
Datedatetime64[ns]
2024-03-15 00:00:00 - 2024-03-28 00:00:00
portfolio_retfloat64
-0.0062903986045713105 - 0.01751176056398465
300
2024-03-15 00:00:00
0.001843704928
301
2024-03-18 00:00:00
0.01751176056
302
2024-03-19 00:00:00
-0.003995390055
303
2024-03-20 00:00:00
0.007093152712
304
2024-03-21 00:00:00
-0.004526921086
305
2024-03-22 00:00:00
-0.003224172633
306
2024-03-25 00:00:00
0.00295030644
307
2024-03-26 00:00:00
0.008174697794
308
2024-03-27 00:00:00
0.00340406952
309
2024-03-28 00:00:00
-0.006290398605
ret_data_s[ret_data_s["return"]<-100]
Datedatetime64[ns]
portfolio_retfloat64
df = spy.merge(ret_data_s, how = "inner", on ="Date",suffixes=('_spy', '_sharpe'))
df.head(10)
Datedatetime64[ns]
Adj Closefloat64
df['return_spy'].hist(bins=100, color='r', alpha=0.5, figsize = (16,8) )
df['return_sharpe'].hist(bins=100, color='g', alpha=0.5)
import scipy.stats as stats
print("Difference in mean return: ")
print((df['return_sharpe'].mean() - df['return_spy'].mean())*100)
stat, p = stats.ttest_ind(df['return_sharpe'], df['return_spy'], equal_var=False, alternative='greater')
# interpret p-value
alpha = 0.05
print("p value is " + str(p))
if p <= alpha:
print('The difference in mean return is significantly different (reject H0)')
else:
print('The difference in mean return is not significantly different (fail to reject H0)')
Difference in mean return:
0.2524028442678666
p value is 0.047916505048968494
The difference in mean return is significantly different (reject H0)