Skip to content

Commit d7f2fc6

Browse files
authored
[ENH] Convert all docstrings to numpydoc format (#712)
Converts all docstrings across the `pypfopt` module from Sphinx/reStructuredText style to NumPy docstring format, with no content changes (content-only fixes are typos/formatting). Fixes #688 ## Changes - **Format conversion** across 13 source files: `:param`/`:type`/`:return:`/`:rtype:`/`:raises` → structured `Parameters`, `Returns`, `Raises` sections ### Before ```python def mean_historical_return(prices, returns_data=False, ...): """ :param prices: adjusted closing prices :type prices: pd.DataFrame :param returns_data: if true, first arg is returns :type returns_data: bool, defaults to False. :return: annualised mean return for each asset :rtype: pd.Series """ ``` ### After ```python def mean_historical_return(prices, returns_data=False, ...): """ Parameters ---------- prices : pd.DataFrame adjusted closing prices returns_data : bool, optional if true, first arg is returns. Defaults to False. Returns ------- pd.Series annualised mean return for each asset """ ```
1 parent 0186e70 commit d7f2fc6

13 files changed

Lines changed: 1394 additions & 834 deletions

pypfopt/base_optimizer.py

Lines changed: 163 additions & 105 deletions
Large diffs are not rendered by default.

pypfopt/black_litterman.py

Lines changed: 125 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,23 @@ def market_implied_prior_returns(
2828
2929
\Pi = \delta \Sigma w_{mkt}
3030
31-
:param market_caps: market capitalisations of all assets
32-
:type market_caps: {ticker: cap} dict or pd.Series
33-
:param risk_aversion: risk aversion parameter
34-
:type risk_aversion: positive float
35-
:param cov_matrix: covariance matrix of asset returns
36-
:type cov_matrix: pd.DataFrame
37-
:param risk_free_rate: risk-free rate of borrowing/lending, defaults to 0.0.
38-
You should use the appropriate time period, corresponding
39-
to the covariance matrix.
40-
:type risk_free_rate: float, optional
41-
:return: prior estimate of returns as implied by the market caps
42-
:rtype: pd.Series
31+
Parameters
32+
----------
33+
market_caps : {ticker: cap} dict or pd.Series
34+
market capitalisations of all assets
35+
risk_aversion : positive float
36+
risk aversion parameter
37+
cov_matrix : pd.DataFrame
38+
covariance matrix of asset returns
39+
risk_free_rate : float, optional
40+
risk-free rate of borrowing/lending, defaults to 0.0.
41+
You should use the appropriate time period, corresponding
42+
to the covariance matrix.
43+
44+
Returns
45+
-------
46+
pd.Series
47+
prior estimate of returns as implied by the market caps
4348
"""
4449
if not isinstance(cov_matrix, pd.DataFrame):
4550
warnings.warn(
@@ -63,16 +68,25 @@ def market_implied_risk_aversion(market_prices, frequency=252, risk_free_rate=0.
6368
6469
\delta = \frac{R - R_f}{\sigma^2}
6570
66-
:param market_prices: the (daily) prices of the market portfolio, e.g SPY.
67-
:type market_prices: pd.Series with DatetimeIndex.
68-
:param frequency: number of time periods in a year, defaults to 252 (the number
69-
of trading days in a year)
70-
:type frequency: int, optional
71-
:param risk_free_rate: annualised risk-free rate of borrowing/lending, defaults to 0.0.
72-
:type risk_free_rate: float, optional
73-
:raises TypeError: if market_prices cannot be parsed
74-
:return: market-implied risk aversion
75-
:rtype: float
71+
Parameters
72+
----------
73+
market_prices : pd.Series with DatetimeIndex.
74+
the (daily) prices of the market portfolio, e.g SPY.
75+
frequency : int, optional
76+
number of time periods in a year, defaults to 252 (the number
77+
of trading days in a year)
78+
risk_free_rate : float, optional
79+
annualised risk-free rate of borrowing/lending, defaults to 0.0.
80+
81+
Raises
82+
------
83+
TypeError
84+
if market_prices cannot be parsed
85+
86+
Returns
87+
-------
88+
float
89+
market-implied risk aversion
7690
"""
7791
if not isinstance(market_prices, (pd.Series, pd.DataFrame)):
7892
raise TypeError("Please format market_prices as a pd.Series")
@@ -138,36 +152,38 @@ def __init__(
138152
**kwargs,
139153
):
140154
"""
141-
:param cov_matrix: NxN covariance matrix of returns
142-
:type cov_matrix: pd.DataFrame or np.ndarray
143-
:param pi: Nx1 prior estimate of returns, defaults to None.
144-
If pi="market", calculate a market-implied prior (requires market_caps
145-
to be passed).
146-
If pi="equal", use an equal-weighted prior.
147-
:type pi: np.ndarray, pd.Series, optional
148-
:param absolute_views: a collection of K absolute views on a subset of assets,
149-
defaults to None. If this is provided, we do not need P, Q.
150-
:type absolute_views: pd.Series or dict, optional
151-
:param Q: Kx1 views vector, defaults to None
152-
:type Q: np.ndarray or pd.DataFrame, optional
153-
:param P: KxN picking matrix, defaults to None
154-
:type P: np.ndarray or pd.DataFrame, optional
155-
:param omega: KxK view uncertainty matrix (diagonal), defaults to None
156-
Can instead pass "idzorek" to use Idzorek's method (requires
157-
you to pass view_confidences). If omega="default" or None,
158-
we set the uncertainty proportional to the variance.
159-
:type omega: np.ndarray or Pd.DataFrame, or string, optional
160-
:param view_confidences: Kx1 vector of percentage view confidences (between 0 and 1),
161-
required to compute omega via Idzorek's method.
162-
:type view_confidences: np.ndarray, pd.Series, list, optional
163-
:param tau: the weight-on-views scalar (default is 0.05)
164-
:type tau: float, optional
165-
:param risk_aversion: risk aversion parameter, defaults to 1
166-
:type risk_aversion: positive float, optional
167-
:param market_caps: (kwarg) market caps for the assets, required if pi="market"
168-
:type market_caps: np.ndarray, pd.Series, optional
169-
:param risk_free_rate: (kwarg) risk_free_rate is needed in some methods
170-
:type risk_free_rate: float, defaults to 0.0
155+
Parameters
156+
----------
157+
cov_matrix : pd.DataFrame or np.ndarray
158+
NxN covariance matrix of returns
159+
pi : np.ndarray or pd.Series, optional
160+
Nx1 prior estimate of returns, defaults to None.
161+
If pi="market", calculate a market-implied prior (requires market_caps
162+
to be passed).
163+
If pi="equal", use an equal-weighted prior.
164+
absolute_views : pd.Series or dict, optional
165+
a collection of K absolute views on a subset of assets,
166+
defaults to None. If this is provided, we do not need P, Q.
167+
Q : np.ndarray or pd.DataFrame, optional
168+
Kx1 views vector, defaults to None
169+
P : np.ndarray or pd.DataFrame, optional
170+
KxN picking matrix, defaults to None
171+
omega : np.ndarray or pd.DataFrame, or string, optional
172+
KxK view uncertainty matrix (diagonal), defaults to None
173+
Can instead pass "idzorek" to use Idzorek's method (requires
174+
you to pass view_confidences). If omega="default" or None,
175+
we set the uncertainty proportional to the variance.
176+
view_confidences : np.ndarray, pd.Series, list, optional
177+
Kx1 vector of percentage view confidences (between 0 and 1),
178+
required to compute omega via Idzorek's method.
179+
tau : float, optional
180+
the weight-on-views scalar (default is 0.05)
181+
risk_aversion : positive float, optional
182+
risk aversion parameter, defaults to 1
183+
market_caps : np.ndarray or pd.Series, optional
184+
(kwarg) market caps for the assets, required if pi="market"
185+
risk_free_rate : float, optional
186+
(kwarg) risk_free_rate is needed in some methods. Defaults to 0.0.
171187
"""
172188
if sys.version_info[1] == 5: # pragma: no cover
173189
warnings.warn(
@@ -213,8 +229,10 @@ def _parse_views(self, absolute_views):
213229
214230
{"AAPL": 0.20, "GOOG": 0.12, "XOM": -0.30}
215231
216-
:param absolute_views: absolute views on asset performances
217-
:type absolute_views: dict, pd.Series
232+
Parameters
233+
----------
234+
absolute_views : dict or pd.Series
235+
absolute views on asset performances
218236
"""
219237
if not isinstance(absolute_views, (dict, pd.Series)):
220238
raise TypeError("views should be a dict or pd.Series")
@@ -333,7 +351,10 @@ def _check_attribute_dimensions(self):
333351
Helper method to ensure that all of the attributes created by the initialiser
334352
have the correct dimensions, to avoid linear algebra errors later on.
335353
336-
:raises ValueError: if there are incorrect dimensions.
354+
Raises
355+
------
356+
ValueError
357+
if there are incorrect dimensions.
337358
"""
338359
N = self.n_assets
339360
K = len(self.Q)
@@ -348,8 +369,10 @@ def default_omega(cov_matrix, P, tau):
348369
He and Litterman (1999), such that the ratio omega/tau is proportional to the
349370
variance of the view portfolio.
350371
351-
:return: KxK diagonal uncertainty matrix
352-
:rtype: np.ndarray
372+
Returns
373+
-------
374+
np.ndarray
375+
KxK diagonal uncertainty matrix
353376
"""
354377
return np.diag(np.diag(tau * P @ cov_matrix @ P.T))
355378

@@ -360,11 +383,16 @@ def idzorek_method(view_confidences, cov_matrix, pi, Q, P, tau, risk_aversion=1)
360383
percentage confidences. We use the closed-form solution described by
361384
Jay Walters in The Black-Litterman Model in Detail (2014).
362385
363-
:param view_confidences: Kx1 vector of percentage view confidences (between 0 and 1),
364-
required to compute omega via Idzorek's method.
365-
:type view_confidences: np.ndarray, pd.Series, list,, optional
366-
:return: KxK diagonal uncertainty matrix
367-
:rtype: np.ndarray
386+
Parameters
387+
----------
388+
view_confidences : np.ndarray, pd.Series, or list, optional
389+
Kx1 vector of percentage view confidences (between 0 and 1),
390+
required to compute omega via Idzorek's method.
391+
392+
Returns
393+
-------
394+
np.ndarray
395+
KxK diagonal uncertainty matrix
368396
"""
369397
view_omegas = []
370398
for view_idx in range(len(Q)):
@@ -391,8 +419,10 @@ def bl_returns(self):
391419
Calculate the posterior estimate of the returns vector,
392420
given views on some assets.
393421
394-
:return: posterior returns vector
395-
:rtype: pd.Series
422+
Returns
423+
-------
424+
pd.Series
425+
posterior returns vector
396426
"""
397427

398428
if self._tau_sigma_P is None:
@@ -419,8 +449,10 @@ def bl_cov(self):
419449
It is assumed that omega is diagonal. If this is not the case,
420450
please manually set omega_inv.
421451
422-
:return: posterior covariance matrix
423-
:rtype: pd.DataFrame
452+
Returns
453+
-------
454+
pd.DataFrame
455+
posterior covariance matrix
424456
"""
425457
if self._tau_sigma_P is None:
426458
self._tau_sigma_P = self.tau * self.cov_matrix @ self.P.T
@@ -450,10 +482,15 @@ def bl_weights(self, risk_aversion=None):
450482
451483
w = (\delta \Sigma)^{-1} E(R)
452484
453-
:param risk_aversion: risk aversion parameter, defaults to 1
454-
:type risk_aversion: positive float, optional
455-
:return: asset weights implied by returns
456-
:rtype: OrderedDict
485+
Parameters
486+
----------
487+
risk_aversion : positive float, optional
488+
risk aversion parameter, defaults to 1
489+
490+
Returns
491+
-------
492+
OrderedDict
493+
asset weights implied by returns
457494
"""
458495
if risk_aversion is None:
459496
risk_aversion = self.risk_aversion
@@ -484,15 +521,24 @@ def portfolio_performance(self, verbose=False, risk_free_rate=0.0):
484521
portfolio. Currently calculates expected return, volatility, and the Sharpe ratio.
485522
This method uses the BL posterior returns and covariance matrix.
486523
487-
:param verbose: whether performance should be printed, defaults to False
488-
:type verbose: bool, optional
489-
:param risk_free_rate: risk-free rate of borrowing/lending, defaults to 0.0.
490-
The period of the risk-free rate should correspond to the
491-
frequency of expected returns.
492-
:type risk_free_rate: float, optional
493-
:raises ValueError: if weights have not been calculated yet
494-
:return: expected return, volatility, Sharpe ratio.
495-
:rtype: (float, float, float)
524+
Parameters
525+
----------
526+
verbose : bool, optional
527+
whether performance should be printed, defaults to False
528+
risk_free_rate : float, optional
529+
risk-free rate of borrowing/lending, defaults to 0.0.
530+
The period of the risk-free rate should correspond to the
531+
frequency of expected returns.
532+
533+
Raises
534+
------
535+
ValueError
536+
if weights have not been calculated yet
537+
538+
Returns
539+
-------
540+
(float, float, float)
541+
expected return, volatility, Sharpe ratio.
496542
"""
497543
if self.posterior_cov is None:
498544
self.posterior_cov = self.bl_cov()

0 commit comments

Comments
 (0)