skfolio.portfolio.Portfolio#

class skfolio.portfolio.Portfolio(X, weights, previous_weights=None, transaction_costs=None, management_fees=None, risk_free_rate=0, name=None, tag=None, annualization_factor=None, fitness_measures=None, compounded=False, weight_drift=False, sample_weight=None, min_acceptable_return=None, value_at_risk_beta=0.95, entropic_risk_measure_theta=1, entropic_risk_measure_beta=0.95, cvar_beta=0.95, evar_beta=0.95, drawdown_at_risk_beta=0.95, cdar_beta=0.95, edar_beta=0.95, fallback_chain=None, **kwargs)[source]#

Portfolio class.

Portfolio is returned by the predict method of Optimization estimators.

By default, each observation is evaluated at the target weights. Portfolio returns are the dot product of those weights and the asset returns, minus transaction costs and management fees. This constant-weight convention (weight_drift=False) is consistent with the optimizer’s linear portfolio return definition and evaluates allocation skill independently of subsequent changes in weights caused by relative asset returns.

With weight_drift=True, the portfolio starts at the target weights and holds the resulting positions throughout the observation window of X. Position values change with asset returns, so portfolio weights evolve with the relative performance of the assets. Combined with compounded=True, this produces a compounded wealth path for evaluating realized capital growth and other path-dependent quantities.

weight_drift changes the observation-level portfolio return series, while compounded changes how that series is accumulated. See Backtesting and Evaluation.

Parameters:
Xarray-like of shape (n_observations, n_assets)

Price returns of the assets. If X is a DataFrame or another array containers that implements ‘columns’ and ‘index’, the columns will be considered as assets names and the indices will be considered as observations. Otherwise, we use ["x0", "x1", ..., "x(n_assets - 1)"] as asset names and [0, 1, ..., n_observations] as observations. NaN values are treated as zero returns for the portfolio return computation (e.g. non-investable assets, delisted assets or trading holidays), while the original X is preserved.

weightsarray-like of shape (n_assets,) | dict[str, float]

Portfolio weights. If a dictionary is provided, its (key/value) pair must be the (asset name/asset weight) and X must be a DataFrame with assets names in columns.

transaction_costsfloat | dict[str, float] | array-like of shape (n_assets, ), optional

Linear transaction costs of the assets. The Portfolio total transaction cost is:

\[total\_cost = \sum_{i=1}^{N} c_{i} \times |w_{i} - w\_prev_{i}|\]

with \(c_{i}\) the transaction cost of asset i, \(w_{i}\) its weight and \(w\_prev_{i}\) its previous weight (defined in previous_weights). The float \(total\_cost\) is used in the portfolio returns:

\[ptf\_returns = R \cdot w - total\_cost\]

with \(R\) the matrix of assets returns and \(w\) the vector of assets weights.

If a float is provided, it is applied to each asset. If a dictionary is provided, its (key/value) pair must be the (asset name/asset weight) and X must be a DataFrame with assets names in columns. The default (None) means no transaction costs.

Warning

To be consistent with the optimization problems, the periodicity of the transaction costs must match the periodicity of the returns X. For example, if X is composed of daily returns, the transaction_costs need to be expressed in daily transaction costs.

management_feesfloat | dict[str, float] | array-like of shape (n_assets, ), optional

Linear management fees of the assets. The Portfolio total management cost is:

\[total\_fee = \sum_{i=1}^{N} f_{i} \times w_{i}\]

with \(f_{i}\) the management fee of asset i and \(w_{i}\) its weight. The float \(total\_fee\) is used in the portfolio returns:

\[ptf\_returns = R \cdot w - total\_fee\]

with \(R\) the matrix of assets returns and \(w\) the vector of assets weights.

If a float is provided, it is applied to each asset. If a dictionary is provided, its (key/value) pair must be the (asset name/asset weight) and X must be a DataFrame with assets names in columns. The default (None) means no management fees.

Warning

To be consistent with the optimization problems, the periodicity of the management fees must match the periodicity of the returns X. For example, if X is composed of daily returns, the management_fees need to be expressed in daily fees.

previous_weightsfloat | dict[str, float] | array-like of shape (n_assets, ), optional

Previous portfolio weights. Previous weights are used to compute turnover and transaction costs. For named positions in assets absent from X, these calculations assume full liquidation. To specify their transaction costs, transaction_costs must be a single rate applied to all assets or a dictionary keyed by asset name. If a float is provided, it is applied to each asset. If a dictionary is provided, its (key/value) pair must be the (asset name/asset previous weight) and X must be a DataFrame with assets names in columns. The default (None) means no previous weights.

namestr, optional

Name of the portfolio. The default (None) is to use the object id.

tagstr, optional

Tag given to the portfolio. Tags are used to manipulate groups of Portfolios from a Population.

fitness_measureslist[measures], optional

List of fitness measures. Fitness measures are used to compute the portfolio fitness which is used to compute domination. The default (None) is to use the list [PerfMeasure.MEAN, RiskMeasure.VARIANCE]

annualization_factorfloat, default=252.0

Factor used to annualize the below measures using the square-root rule:

  • Annualized Mean = Mean * factor

  • Annualized Variance = Variance * factor

  • Annualized Semi-Variance = Semi-Variance * factor

  • Annualized Standard-Deviation = Standard-Deviation * sqrt(factor)

  • Annualized Semi-Deviation = Semi-Deviation * sqrt(factor)

  • Annualized Sharpe Ratio = Sharpe Ratio * sqrt(factor)

  • Annualized Sortino Ratio = Sortino Ratio * sqrt(factor)

risk_free_ratefloat, default=0.0

Risk-free rate. The default value is 0.0.

compoundedbool, default=False

If True, cumulative returns are compounded. The default is False.

weight_driftbool, default=False

If True, the portfolio starts at the target weights and the weights used for subsequent observations evolve with asset returns following the self-financing identity \(u_{t+1} = u_t \circ (1 + r_t) / (1 + u_t \cdot r_t)\). Drift accumulates over the entire window of X, and the implicit cash position \(1 - \sum_i w_i\) earns zero. The same transaction-cost and management-fee formulas are used with either setting. With the default (False), every observation is evaluated at the target weights. This attribute is read-only. See Backtesting and Evaluation.

sample_weightndarray of shape (n_observations,), optional

Sample weights for each observation. If None, equal weights are assumed.

min_acceptable_returnfloat, optional

The minimum acceptable return used to distinguish “downside” and “upside” returns for the computation of lower partial moments:

  • First Lower Partial Moment

  • Semi-Variance

  • Semi-Deviation

The default (None) is to use the mean.

value_at_risk_betafloat, default=0.95

The confidence level of the Portfolio VaR (Value At Risk) which represents the return on the worst (1-beta)% observations. The default value is 0.95.

entropic_risk_measure_thetafloat, default=1.0

The risk aversion level of the Portfolio Entropic Risk Measure. The default value is 1.0.

entropic_risk_measure_betafloat, default=0.95

The confidence level of the Portfolio Entropic Risk Measure. The default value is 0.95.

cvar_betafloat, default=0.95

The confidence level of the Portfolio CVaR (Conditional Value at Risk) which represents the expected VaR on the worst (1-beta)% observations. The default value is 0.95.

evar_betafloat, default=0.95

The confidence level of the Portfolio EVaR (Entropic Value at Risk). The default value is 0.95.

drawdown_at_risk_betafloat, default=0.95

The confidence level of the Portfolio Drawdown at Risk (DaR) which represents the drawdown on the worst (1-beta)% observations. The default value is 0.95.

cdar_betafloat, default=0.95

The confidence level of the Portfolio CDaR (Conditional Drawdown at Risk) which represents the expected drawdown on the worst (1-beta)% observations. The default value is 0.95.

edar_betafloat, default=0.95

The confidence level of the Portfolio EDaR (Entropic Drawdown at Risk). The default value is 0.95.

fallback_chainlist[tuple[str, str]] | None, optional

Sequence describing the optimization fallback attempts. Each element is a pair (estimator_repr, outcome) where:

  • estimator_repr is the string representation of the primary estimator or a fallback (e.g. "EqualWeighted()", "previous_weights").

  • outcome is "success" if that step produced a valid solution, otherwise the stringified error message.

For successful fits without any fallback, this is None. When fallbacks are provided and the primary fails, the chain starts with (primary_repr, primary_error) and is followed by one entry per fallback that was attempted, ending with the first "success" or the last error if all fail. This is set by the optimization estimator and propagated to the resulting portfolio.

Attributes:
n_observationsfloat

Number of observations.

meanfloat

Mean of the portfolio returns.

annualized_meanfloat

Mean annualized by \(mean \times annualization\_factor\)

mean_absolute_deviationfloat

Mean Absolute Deviation. The deviation is the difference between the return and a minimum acceptable return (min_acceptable_return).

first_lower_partial_momentfloat

First Lower Partial Moment. The First Lower Partial Moment is the mean of the returns below a minimum acceptable return (min_acceptable_return).

variancefloat

Variance (Second Moment)

annualized_variancefloat

Variance annualized by \(variance \times annualization\_factor\)

semi_variancefloat

Semi-variance (Second Lower Partial Moment). The semi-variance is the variance of the returns below a minimum acceptable return (min_acceptable_return).

annualized_semi_variancefloat

Semi-variance annualized by \(semi\_variance \times annualization\_factor\)

standard_deviationfloat

Standard Deviation (Square Root of the Second Moment).

annualized_standard_deviationfloat

Standard Deviation annualized by \(standard\_deviation \times \sqrt{annualization\_factor}\)

semi_deviationfloat

Semi-deviation (Square Root of the Second Lower Partial Moment). The Semi Standard Deviation is the Standard Deviation of the returns below a minimum acceptable return (min_acceptable_return).

annualized_semi_deviationfloat

Semi-deviation annualized by \(semi\_deviation \times \sqrt{annualization\_factor}\)

skewfloat

Skew. The Skew is a measure of the lopsidedness of the distribution. A symmetric distribution have a Skew of zero. Higher Skew corresponds to longer right tail.

kurtosisfloat

Kurtosis. It is a measure of the heaviness of the tail of the distribution. Higher Kurtosis corresponds to greater extremity of deviations (fat tails).

fourth_central_momentfloat

Fourth Central Moment.

fourth_lower_partial_momentfloat

Fourth Lower Partial Moment. It is a measure of the heaviness of the downside tail of the returns below a minimum acceptable return (min_acceptable_return). Higher Fourth Lower Partial Moment corresponds to greater extremity of downside deviations (downside fat tail).

worst_realizationfloat

Worst Realization which is the worst return.

value_at_riskfloat

Historical VaR (Value at Risk). The VaR is the maximum loss at a given confidence level (value_at_risk_beta).

cvarfloat

Historical CVaR (Conditional Value at Risk). The CVaR (or Tail VaR) represents the mean shortfall at a specified confidence level (cvar_beta).

entropic_risk_measurefloat

Historical Entropic Risk Measure. It is a risk measure which depends on the risk aversion defined by the investor (entropic_risk_measure_theta) through the exponential utility function at a given confidence level (entropic_risk_measure_beta).

evarfloat

Historical EVaR (Entropic Value at Risk). It is a coherent risk measure which is an upper bound for the VaR and the CVaR, obtained from the Chernoff inequality at a given confidence level (evar_beta). The EVaR can be represented by using the concept of relative entropy.

drawdown_at_riskfloat

Historical Drawdown at Risk. It is the maximum drawdown at a given confidence level (drawdown_at_risk_beta).

cdarfloat

Historical CDaR (Conditional Drawdown at Risk) at a given confidence level (cdar_beta).

max_drawdownfloat

Maximum Drawdown.

average_drawdownfloat

Average Drawdown.

edarfloat

EDaR (Entropic Drawdown at Risk). It is a coherent risk measure which is an upper bound for the Drawdown at Risk and the CDaR, obtained from the Chernoff inequality at a given confidence level (edar_beta). The EDaR can be represented by using the concept of relative entropy.

ulcer_indexfloat

Ulcer Index

gini_mean_differencefloat

Gini Mean Difference (GMD). It is the expected absolute difference between two realizations. The GMD is a superior measure of variability for non-normal distribution than the variance. It can be used to form necessary conditions for second-degree stochastic dominance, while the variance cannot.

mean_absolute_deviation_ratiofloat

Mean Absolute Deviation ratio. It is the excess mean (mean - risk_free_rate) divided by the MaD.

first_lower_partial_moment_ratiofloat

First Lower Partial Moment ratio. It is the excess mean (mean - risk_free_rate) divided by the First Lower Partial Moment.

sharpe_ratiofloat

Sharpe ratio. It is the excess mean (mean - risk_free_rate) divided by the standard-deviation.

annualized_sharpe_ratiofloat

Sharpe ratio annualized by \(sharpe\_ratio \times \sqrt{annualization\_factor}\).

sortino_ratiofloat

Sortino ratio. It is the excess mean (mean - risk_free_rate) divided by the semi standard-deviation.

annualized_sortino_ratiofloat

Sortino ratio annualized by \(sortino\_ratio \times \sqrt{annualization\_factor}\).

value_at_risk_ratiofloat

VaR ratio. It is the excess mean (mean - risk_free_rate) divided by the Value at Risk (VaR).

cvar_ratiofloat

CVaR ratio. It is the excess mean (mean - risk_free_rate) divided by the Conditional Value at Risk (CVaR).

entropic_risk_measure_ratiofloat

Entropic risk measure ratio. It is the excess mean (mean - risk_free_rate) divided by the Entropic risk measure.

evar_ratiofloat

EVaR ratio. It is the excess mean (mean - risk_free_rate) divided by the EVaR (Entropic Value at Risk).

worst_realization_ratiofloat

Worst Realization ratio. It is the excess mean (mean - risk_free_rate) divided by the Worst Realization (worst return).

drawdown_at_risk_ratiofloat

Drawdown at Risk ratio. It is the excess mean (mean - risk_free_rate) divided by the drawdown at risk.

cdar_ratiofloat

CDaR ratio. It is the excess mean (mean - risk_free_rate) divided by the CDaR (conditional drawdown at risk).

calmar_ratiofloat

Calmar ratio. It is the excess mean (mean - risk_free_rate) divided by the Maximum Drawdown.

average_drawdown_ratiofloat

Average Drawdown ratio. It is the excess mean (mean - risk_free_rate) divided by the Average Drawdown.

edar_ratiofloat

EDaR ratio. It is the excess mean (mean - risk_free_rate) divided by the EDaR (Entropic Drawdown at Risk).

ulcer_index_ratiofloat

Ulcer Index ratio. It is the excess mean (mean - risk_free_rate) divided by the Ulcer Index.

gini_mean_difference_ratiofloat

Gini Mean Difference ratio. It is the excess mean (mean - risk_free_rate) divided by the Gini Mean Difference.

ending_weightsndarray of shape (n_assets,)

Asset weights immediately after the final observation. With weight_drift=False, they equal the target weights. With weight_drift=True, they reflect the effect of asset returns through the final observation. They are calculated before transaction costs and management fees. In a sequential evaluation, the ending_weights of a successful Portfolio are used as previous_weights for the next optimization. A FailedPortfolio contains only NaN ending weights.

turnoverfloat

Total absolute weight traded at the start of the period.

Methods

clear()

Clear all measures, fitness, cumulative returns and drawdowns in slots.

contribution(measure[, spacing, to_df])

Compute the contribution of each asset to a given measure.

copy()

Copy the Portfolio attributes without its measures values.

dominates(other[, idx])

Portfolio domination.

expected_returns_from_assets(...)

Compute the portfolio expected return from expected asset returns, weights, management costs and transaction fees.

get_measure(measure)

Returns the value of a given measure.

get_weight(asset)

Get the weight of a given asset.

plot_composition()

Plot the Portfolio composition.

plot_composition_treemap([groups])

Plot the Portfolio composition as a treemap nested by asset groups.

plot_contribution(measure[, spacing])

Plot the contribution of each asset to a given measure.

plot_cumulative_returns([log_scale, idx])

Plot the Portfolio cumulative returns.

plot_drawdowns([idx])

Plot the Portfolio drawdowns.

plot_returns([idx])

Plot the Portfolio returns.

plot_returns_distribution([percentile_cutoff])

Plot the Portfolio returns distribution using Gaussian KDE.

plot_rolling_measure([measure, window])

Plot the measure over a rolling window.

predicted_attribution(factor_model[, ...])

Ex-ante (predicted) factor risk and performance attribution.

realized_attribution(factor_model[, ...])

Realized (ex-post) factor risk and performance attribution.

rolling_measure([measure, window])

Compute the measure over a rolling window.

rolling_realized_attribution(factor_model[, ...])

Rolling realized (ex-post) factor risk and performance attribution.

summary([formatted])

Portfolio summary of all its measures.

variance_from_assets(assets_covariance)

Compute the Portfolio variance expectation from the assets covariance and weights.

property annualization_factor#

Portfolio annualization factor.

property annualized_factor#

Deprecated alias for annualization_factor.

clear()#

Clear all measures, fitness, cumulative returns and drawdowns in slots.

property composition#

DataFrame of portfolio composition (weights). Rows with zero weights are filtered out. Use weights_dict to access all weights, including zeros.

contribution(measure, spacing=None, to_df=False)[source]#

Compute the contribution of each asset to a given measure.

With weight_drift=True, the contributions are finite-difference sensitivities to the target weights. Because drifted returns are nonlinear in the target weights, the contributions are not guaranteed to sum exactly to the measure.

Parameters:
measureMeasure

The measure used for the contribution computation.

spacingfloat, optional

Spacing “h” of the finite difference: \(contribution(wi)= \frac{measure(wi-h) - measure(wi+h)}{2h}\)

to_dfbool, default=False

If set to True, a DataFrame with asset names in index is returned, otherwise a numpy array is returned. When a DataFrame is returned, the values are sorted in descending order and assets with zero weights are removed.

Returns:
valuesnumpy array of shape (n_assets,) or DataFrame

The measure contribution of each asset.

copy()#

Copy the Portfolio attributes without its measures values.

cumulative_returns#

Portfolio cumulative returns array. Non-compounded (arithmetic) cumulative returns start at 0. Compounded (geometric) cumulative returns are expressed as a wealth index, starting at 1.0 (i.e., the value of $1 invested).

property cumulative_returns_df#

Portfolio cumulative returns Series. Non-compounded (arithmetic) cumulative returns start at 0. Compounded (geometric) cumulative returns are expressed as a wealth index, starting at 1.0 (i.e., the value of $1 invested).

property diversification#

Weighted average of volatility divided by the portfolio volatility.

dominates(other, idx=None)#

Portfolio domination.

Returns true if each objective of the current portfolio fitness is not strictly worse than the corresponding objective of the other portfolio fitness and at least one objective is strictly better.

Parameters:
otherBasePortfolio

The other portfolio.

idxslice | array, optional

Indexes or slice indicating on which objectives the domination is performed. The default (None) is to use all objectives.

Returns:
valuebool

Returns True if the Portfolio dominates the other one.

drawdowns#

Portfolio drawdowns array.

property drawdowns_df#

Portfolio drawdowns Series.

property effective_number_assets#

Computes the effective number of assets, defined as the inverse of the Herfindahl index.

\[N_{eff} = \frac{1}{\Vert w \Vert_{2}^{2}}\]

It quantifies portfolio concentration, with a higher value indicating a more diversified portfolio.

Returns:
valuefloat

Effective number of assets.

References

[1]

“Banking and Financial Institutions Law in a Nutshell”. Lovett, William Anthony (1988)

property ending_weights_dict#

Dict mapping asset name to ending weight; includes zeros.

expected_returns_from_assets(assets_expected_returns)[source]#

Compute the portfolio expected return from expected asset returns, weights, management costs and transaction fees.

Parameters:
assets_expected_returnsndarray of shape (n_assets,)

The vector of expected asset returns.

Returns:
valuefloat

The portfolio expected return.

fitness#

Portfolio fitness.

property fitness_measures#

Portfolio fitness measures.

get_measure(measure)#

Returns the value of a given measure.

Parameters:
measurePerfMeasure | RiskMeasure | ExtraRiskMeasure | RatioMeasure

The input measure.

Returns:
valuefloat

The measure value.

get_weight(asset)[source]#

Get the weight of a given asset.

Parameters:
assetstr

Name of the asset.

Returns:
weightfloat

Weight of the asset.

property measures_df#

DataFrame of all measures.

property n_observations#

Number of observations.

nonzero_assets#

Invested asset \(abs(weights) > 0.001%\).

nonzero_assets_index#

Indices of invested asset \(abs(weights) > 0.001%\).

plot_composition()#

Plot the Portfolio composition.

Returns:
plotFigure

Returns the plot Figure object.

plot_composition_treemap(groups=None)[source]#

Plot the Portfolio composition as a treemap nested by asset groups.

Each asset is a tile with an area proportional to its absolute weight \(|w_i|\), so that long and short positions are both sized by their gross exposure. Long positions are shown in blue and short positions in red, with a color intensity increasing with \(|w_i|\). Each group is sized by the sum of the absolute weights of its assets and its header shows the net weight of the group. When the Portfolio has short positions, the subtitle reports the long, short, net and gross exposures.

Parameters:
groupsdict[str, list[str]] or array-like of shape (n_groups, n_assets), optional

Asset groups defining the treemap hierarchy, in the same format as the groups parameter of the optimization estimators. The first group level is the top of the hierarchy. If a dictionary is provided, its (key/value) pair must be the (asset name/asset groups) and keys that are not assets of the Portfolio are ignored. Each asset with a non-zero weight must have one label per group level. The default (None) is to place all assets directly under the Portfolio root.

For example:

  • groups = {"SX5E": ["Equity", "Europe"], "SPX": ["Equity", "US"], "TLT": ["Bond", "US"]}

  • groups = [["Equity", "Equity", "Bond"], ["Europe", "US", "US"]]

Returns:
plotFigure

Returns the plot Figure object.

plot_contribution(measure, spacing=None)#

Plot the contribution of each asset to a given measure.

Parameters:
measureMeasure

The measure used for the contribution computation.

spacingfloat, optional

Spacing “h” of the finite difference: \(contribution(wi)= \frac{measure(wi-h) - measure(wi+h)}{2h}\)

Returns:
plotFigure

The plotly Figure of assets contribution to the measure.

plot_cumulative_returns(log_scale=False, idx=None)#

Plot the Portfolio cumulative returns. Non-compounded (arithmetic) cumulative returns start at 0. Compounded (geometric) cumulative returns are expressed as a wealth index, starting at 1.0 (i.e., the value of $1 invested).

Parameters:
log_scalebool, default=False

If this is set to True, the cumulative returns are displayed with a logarithm scale on the y-axis. The cumulative returns must be compounded otherwise an exception is raised.

idxslice | array, optional

Indexes or slice of the observations to plot. The default (None) is to plot all observations.

Returns:
plotFigure

Returns the plot Figure object.

plot_drawdowns(idx=None)#

Plot the Portfolio drawdowns.

Parameters:
idxslice | array, optional

Indexes or slice of the observations to plot. The default (None) is to plot all observations.

Returns:
plotFigure

Returns the plot Figure object.

plot_returns(idx=None)#

Plot the Portfolio returns.

Parameters:
idxslice | array, optional

Indexes or slice of the observations to plot. The default (None) is to plot all observations.

Returns:
plotFigure

Returns the plot Figure object

plot_returns_distribution(percentile_cutoff=None)#

Plot the Portfolio returns distribution using Gaussian KDE.

Parameters:
percentile_cutofffloat, default=None

Percentile cutoff for tail truncation (percentile), in percent. If a float p is provided, the distribution support is truncated at the p-th and (100 - p)-th percentiles. If None, no truncation is applied (uses full min/max of returns).

Returns:
plotFigure

Returns the plot Figure object

plot_rolling_measure(measure=Sharpe Ratio, window=30)#

Plot the measure over a rolling window.

Parameters:
measureMeasure, default = RatioMeasure.SHARPE_RATIO

The measure.

windowint, default=30

The window size.

Returns:
plotFigure

Returns the plot Figure object

predicted_attribution(factor_model, compute_asset_breakdowns=True)[source]#

Ex-ante (predicted) factor risk and performance attribution.

Decomposes the portfolio’s predicted risk and expected return into contributions from individual factors and an idiosyncratic component using the factor model’s latest forecast estimates (loading_matrix, factor_covariance, idio_covariance, factor_mu, idio_mu).

The annualization scaling uses self.annualization_factor.

Predicted attribution uses only these latest forecast estimates, so no observation alignment is required. The factor_model may therefore cover a different observation window than the portfolio.

The portfolio may hold a subset of the assets covered by the factor model and weights are zero-filled for missing assets.

See predicted_factor_attribution for the full mathematical description.

Parameters:
factor_modelFactorModel

Factor model whose latest forecast estimates are used. Every asset in self.assets must appear in factor_model.asset_names.

compute_asset_breakdownsbool, default=True

If True, compute per-asset systematic/idiosyncratic decomposition. Set to False for faster computation when only portfolio-level results are needed.

Returns:
attributionAttribution

Component-level, factor-level, and optionally asset-level attribution results.

Raises:
ValueError

If the portfolio is a failed portfolio or if it holds assets not covered by the factor model.

property previous_weights_dict#

Dict mapping asset name to previous weight; includes zeros.

realized_attribution(factor_model, compute_asset_breakdowns=True, compute_uncertainty=True)[source]#

Realized (ex-post) factor risk and performance attribution.

Decomposes the portfolio’s realized risk and return into contributions from individual factors and an idiosyncratic component using actual historical factor returns, exposures, and residuals.

The annualization scaling uses self.annualization_factor.

Realized attribution uses the target weights when weight_drift=False and the weights held during each observation when weight_drift=True.

Realized attribution is computed on the overlapping observation window between the portfolio and the factor model. Portfolio observations outside the factor model window, commonly caused by factor-model warmup or exposure lag, are excluded. Missing portfolio observations inside the overlapping window raise ValueError. Time-varying exposures follow the as-of indexing convention described in realized_factor_attribution: when exposure_lag > 0, exposures known at observation \(t-\ell\) are aligned with returns at observation \(t\).

The portfolio may hold a subset of the assets covered by the factor model and weights are zero-filled for missing assets.

See realized_factor_attribution for the full mathematical description.

Parameters:
factor_modelFactorModel

Factor model containing time-varying fields (factor_returns, exposures, idio_returns) that overlap with the portfolio’s observation period. Every asset in self.assets must appear in factor_model.asset_names.

compute_asset_breakdownsbool, default=True

If True, compute per-asset systematic/idiosyncratic attribution. Set to False for faster computation when only portfolio-level results are needed.

compute_uncertaintybool, default=True

If True, compute attribution uncertainty (standard errors on the factor and idiosyncratic mean-return split).

Returns:
attributionAttribution

Component-level, factor-level, and optionally asset-level attribution results.

Raises:
ValueError

If the portfolio is a failed portfolio, if it holds assets not covered by the factor model, if no portfolio observations overlap with the factor model or if portfolio observations are missing inside the overlapping window.

property returns_df#

Portfolio returns DataFrame.

rolling_measure(measure=Sharpe Ratio, window=30)#

Compute the measure over a rolling window.

Parameters:
measureMeasure, default=RatioMeasure.SHARPE_RATIO

The measure. The default measure is the Sharpe Ratio.

windowint, default=30

The window size. The default value is 30 observations.

Returns:
seriespandas Series

The rolling measure Series.

rolling_realized_attribution(factor_model, window_size=60, step=21, compute_asset_breakdowns=True, compute_asset_factor_contribs=False, compute_uncertainty=True)[source]#

Rolling realized (ex-post) factor risk and performance attribution.

Computes realized_factor_attribution over rolling windows, returning an Attribution where all numeric fields carry an additional leading dimension for the number of windows.

Rolling realized attribution is computed on the overlapping observation window between the portfolio and the factor model. Portfolio observations outside the factor model window, commonly caused by factor-model warmup or exposure lag, are excluded. Missing portfolio observations inside the overlapping window raise ValueError. Time-varying exposures follow the as-of indexing convention described in rolling_realized_factor_attribution.

Each rolling window uses the target weights when weight_drift=False and the weights held during its observations when weight_drift=True.

The portfolio may hold a subset of the assets covered by the factor model and weights are zero-filled for missing assets.

See rolling_realized_factor_attribution for the full mathematical description.

Parameters:
factor_modelFactorModel

Factor model containing time-varying fields that overlap with the portfolio’s observation period.

window_sizeint, default=60

Number of effective return periods in each rolling window.

stepint, default=21

Number of observations to advance between consecutive windows. The default of 21 produces approximately monthly output for daily data.

compute_asset_breakdownsbool, default=True

If True, compute per-asset attribution for each window.

compute_asset_factor_contribsbool, default=False

If True, compute asset-factor matrix for each window.

compute_uncertaintybool, default=True

If True, compute per-window attribution uncertainty.

Returns:
attributionAttribution

Rolling attribution results.

Raises:
ValueError

If the portfolio is a failed portfolio, if it holds assets not covered by the factor model, if no portfolio observations overlap with the factor model or if window_size exceeds the number of overlapping observations.

property sample_weight#

Observations sample weights.

property sric#

Sharpe Ratio Information Criterion (SRIC).

It is an unbiased estimator of the Sharpe Ratio adjusting for both sources of bias which are noise fit and estimation error [1].

References

[1]

“Noise Fit, Estimation Error and a Sharpe Information Criterion”, Dirk Paulsen (2019)

summary(formatted=True)[source]#

Portfolio summary of all its measures.

Parameters:
formattedbool, default=True

If this is set to True, the measures are formatted into rounded string with units.

Returns:
summaryseries

Portfolio summary.

property turnover#

Total absolute weight traded at the start of the period.

In a sequential evaluation, previous_weights come from the last successful Portfolio. With weight_drift=False, target turnover compares successive target allocations. With weight_drift=True, executed turnover compares the previous period’s ending weights with the new target allocation. When previous_weights is None, it defaults to zero. Turnover includes the full absolute weight of positions in assets absent from X.

variance_from_assets(assets_covariance)[source]#

Compute the Portfolio variance expectation from the assets covariance and weights.

Parameters:
assets_covariancendarray of shape (n_assets,n_assets)

The matrix of assets covariance expectation.

Returns:
valuefloat

The Portfolio variance from the assets covariance.

property weights_dict#

Dict mapping asset name to weight; includes zeros.

property weights_per_observation#

DataFrame of asset weights at the start of each observation.

With weight_drift=False, every row contains the target weights. With weight_drift=True, each row incorporates the effect of preceding asset returns. ending_weights contains the weights immediately after the final observation.