Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 67 additions & 21 deletions cookbook/1-RiskReturnModels.ipynb

Large diffs are not rendered by default.

6,337 changes: 3,085 additions & 3,252 deletions cookbook/2-Mean-Variance-Optimisation.ipynb

Large diffs are not rendered by default.

855 changes: 323 additions & 532 deletions cookbook/3-Advanced-Mean-Variance-Optimisation.ipynb

Large diffs are not rendered by default.

1,165 changes: 604 additions & 561 deletions cookbook/4-Black-Litterman-Allocation.ipynb

Large diffs are not rendered by default.

947 changes: 526 additions & 421 deletions cookbook/5-Hierarchical-Risk-Parity.ipynb

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions pypfopt/data/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
from .data_loader import load_stockdata, available_tickers, load_marketcaps

__all__ = ["load_stockdata", "available_tickers", "load_marketcaps"]
47 changes: 47 additions & 0 deletions pypfopt/data/data_loader.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import pandas as pd
from importlib import resources


def _load_raw_data(filename: str, **read_csv_kwargs):
with resources.files(__package__).joinpath(filename).open("r") as f:
return pd.read_csv(f, **read_csv_kwargs)


def load_stockdata(tickers: list = None, start: str = None, end: str = None):

df = _load_raw_data("stock_prices.csv", parse_dates=["date"])

if start is not None:
df = df[df["date"] >= pd.to_datetime(start)]
if end is not None:
df = df[df["date"] <= pd.to_datetime(end)]

if tickers is not None:
cols = ["date"] + tickers
df = df[cols]

return df.set_index("date")


def load_marketcaps(tickers: list = None):

df = _load_raw_data("market_caps.csv")

if tickers is not None:
available = set(df["ticker"])
invalid = set(tickers) - available
if invalid:
raise ValueError(f"Invalid tickers: {invalid}")

df = df[df["ticker"].isin(tickers)]

return dict(zip(df["ticker"], df["market_cap"]))


def available_tickers():

df = _load_raw_data("stock_prices.csv", parse_dates=["date"])
cols = [c for c in df.columns if c != "date"]
cols.sort()

return cols
34 changes: 34 additions & 0 deletions pypfopt/data/market_caps.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
ticker,market_cap
AAPL,752207537100
ACN,1901675041287
AMD,1465327913913
AMZN,1199323675973
BAC,316257187682
BLK,316209068070
COST,120876806275
CVS,1733021410820
DIS,1204224448427
DPZ,1417604792703
F,46066066120
GILD,1939970155063
INTU,1665723068396
JD,428616525803
JPM,367740809578
KO,370891997157
LUV,611963274704
MA,1051889081106
MCD,866730312191
MSFT,586002134695
NAT,1225646524971
NVDA,283290252000
PBI,587828573827
PFE,735891877370
SBUX,914859618512
SPY,1571426042979
TGT,403349195405
TM,1030897704635
TSLA,1186867064879
UL,97668573376
UNH,1217051979543
WMT,345195626756
XOM,134777928005
757 changes: 757 additions & 0 deletions pypfopt/data/stock_prices.csv

Large diffs are not rendered by default.

4 changes: 3 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ all_extras = [
dev = [
"pytest>=9.0.0",
"pytest-cov>=7.0.0",
"yfinance>=0.2.66",
]

# notebook tests
Expand All @@ -87,6 +86,9 @@ requires = [
[tool.setuptools.packages.find]
exclude = ["example", "example.*", "tests", "tests.*"]

[tool.setuptools.package-data]
pypfopt = ["data/*.csv"]

[tool.ruff]
line-length = 88
# Keep Ruff aligned with project target version
Expand Down