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 available_tickers, load_marketcaps, load_stockdata

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

import pandas as pd


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):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please add docstrings (numpydoc format)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

added docstrings

"""
Load example stock price data.

This function loads a synthetic stock price dataset included with the
package. The data can optionally be filtered by ticker symbols and
date range.

Parameters
----------
tickers : list of str, optional
List of ticker symbols to include. If ``None``, all available
tickers are returned.
start : str, optional
Start date for filtering the dataset (inclusive). Should be
interpretable by ``pandas.to_datetime``.
end : str, optional
End date for filtering the dataset (inclusive). Should be
interpretable by ``pandas.to_datetime``.

Returns
-------
pandas.DataFrame
DataFrame of stock prices indexed by date. Columns correspond to
ticker symbols and values represent price levels.

Notes
-----
The dataset is bundled with the package and does not rely on external
data sources. It is intended for examples and tutorials.
"""
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):
"""
Load bundled example market capitalisation data.

This function loads synthetic market capitalisation values for the
example assets included in the package.

Parameters
----------
tickers : list of str, optional
List of ticker symbols to return. If ``None``, market caps for all
available tickers are returned.

Returns
-------
dict
Dictionary mapping ticker symbols to market capitalisation values.

Notes
-----
The values are synthetic and provided solely for use in examples
demonstrating portfolio optimisation methods.
"""
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():
"""
Return the list of available ticker symbols.

Returns
-------
list of str
Sorted list of ticker symbols present in the bundled example
dataset.

Notes
-----
These tickers correspond to the columns available in the example
stock price dataset returned by :func:`load_stockdata`.
"""
cols = [
"AAPL",
"ACN",
"AMD",
"AMZN",
"BAC",
"BLK",
"COST",
"CVS",
"DIS",
"DPZ",
"F",
"GILD",
"INTU",
"JD",
"JPM",
"KO",
"LUV",
"MA",
"MCD",
"MSFT",
"NAT",
"NVDA",
"PBI",
"PFE",
"SBUX",
"SPY",
"TGT",
"TM",
"TSLA",
"UL",
"UNH",
"WMT",
"XOM",
]

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.

7 changes: 5 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,8 @@ all_extras = [

# dev - the developer dependency set, for contributors and CI
dev = [
"pytest>=9.0.2",
"yfinance>=1.2.0",
"pytest>=9.0.0",
"pytest-cov>=7.0.0",
]

# notebook tests
Expand Down Expand Up @@ -93,6 +93,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