Skip to content

Portfolio API Reference

Portfolio Module

This module provides a class for calculating various portfolio metrics including returns, risk-adjusted performance, and risk measurements.

Portfolio

A class for calculating various portfolio metrics and assessing portfolio health.

This class provides methods for calculating portfolio returns, risk-adjusted performance metrics, and risk measurements, while maintaining state to assess overall portfolio health.

Examples:

>>> from pypulate.dtypes import Portfolio
>>> portfolio = Portfolio()
>>> returns = portfolio.simple_return(105, 100)
>>> sharpe = portfolio.sharpe_ratio([0.01, 0.02, -0.01, 0.03, 0.01])
>>> health = portfolio.health

health property

Calculate and return the overall health of the portfolio based on stored metrics.

Returns:

Type Description
dict

Dictionary containing: - overall_score: Float between 0 and 100 - status: String indicating health status - components: Dictionary of component scores and metrics - returns: Return metrics and score - risk_adjusted: Risk-adjusted performance metrics and score - risk: Risk metrics and score

__init__()

Initialize the Portfolio class with empty state.

annualized_return(total_return, years)

Calculate the annualized return from a total return over a period of years.

Parameters:

Name Type Description Default
total_return float or array - like

The total return over the entire period as a decimal

required
years float or array - like

The number of years in the period

required

Returns:

Type Description
float or ndarray

The annualized return as a decimal If array inputs are provided, returns an array of annualized returns

Examples:

>>> annualized_return(0.2, 2)
0.09544511501033215
>>> annualized_return([0.2, 0.3, 0.15], [2, 3, 1.5])
[0.09544512, 0.09139288, 0.0976534 ]
>>> annualized_return(np.array([0.4, 0.5]), 2)
[0.18321596, 0.22474487]

arithmetic_return(prices)

Calculate the arithmetic average return from a series of prices.

Parameters:

Name Type Description Default
prices array - like

Array or list of prices

required

Returns:

Type Description
float

The arithmetic average return as a decimal

Examples:

>>> arithmetic_return([100, 105, 103, 108, 110])
0.024503647197821957

benchmark_alpha(returns, benchmark_returns)

Calculate the benchmark alpha, which is the difference between portfolio return and benchmark return.

Parameters:

Name Type Description Default
returns array - like

Array of portfolio returns

required
benchmark_returns array - like

Array of benchmark returns for the same periods

required

Returns:

Type Description
float

The benchmark alpha (difference in mean returns)

Examples:

>>> benchmark_alpha([0.01, 0.02, -0.01, 0.03, 0.01], [0.005, 0.01, -0.005, 0.02, 0.005])
0.005

beta_adjusted_return(portfolio_return, benchmark_return, portfolio_beta)

Calculate the beta-adjusted return (alpha) of a portfolio.

Parameters:

Name Type Description Default
portfolio_return float or array - like

The return of the portfolio as a decimal

required
benchmark_return float or array - like

The return of the benchmark as a decimal

required
portfolio_beta float or array - like

The beta of the portfolio relative to the benchmark

required

Returns:

Type Description
float or ndarray

The beta-adjusted return (alpha) as a decimal If array inputs are provided, returns an array of beta-adjusted returns

Examples:

>>> beta_adjusted_return(0.12, 0.10, 1.2)
0.0
>>> beta_adjusted_return([0.12, 0.15], [0.10, 0.08], 1.2)
[0.   , 0.054]
>>> beta_adjusted_return(0.12, 0.10, [1.2, 1.5])
[ 0.  , -0.03]

calmar_ratio(returns, max_drawdown=None, annualization_factor=1.0)

Calculate the Calmar ratio, which measures return relative to maximum drawdown.

Parameters:

Name Type Description Default
returns array - like

Array of portfolio returns

required
max_drawdown float

Maximum drawdown as a positive decimal. If None, it will be calculated from returns.

None
annualization_factor float

Factor to annualize returns

1.0

Returns:

Type Description
float

The Calmar ratio

Examples:

>>> calmar_ratio([0.01, 0.02, -0.01, 0.03, 0.01], 0.15, 252)
0.8

capm_alpha(returns, benchmark_returns, risk_free_rate=0.0)

Calculate the CAPM alpha (Jensen's alpha) and related statistics.

Parameters:

Name Type Description Default
returns array - like

Array of portfolio returns

required
benchmark_returns array - like

Array of benchmark returns for the same periods

required
risk_free_rate float or array - like

Risk-free rate for the same period as returns

0.0

Returns:

Type Description
tuple

(alpha, beta, r_squared, p_value, std_err) - alpha: The CAPM alpha (intercept) - beta: The CAPM beta (slope) - r_squared: The R-squared of the regression - p_value: The p-value for alpha - std_err: The standard error of alpha

capm_beta(portfolio_returns, market_returns)

Calculate the CAPM beta of a portfolio.

Parameters:

Name Type Description Default
portfolio_returns list or ndarray

Array or list of portfolio returns

required
market_returns list or ndarray

Array or list of market returns

required

Returns:

Type Description
float

CAPM beta

Notes

Beta measures the sensitivity of portfolio returns to market returns. It is the covariance of portfolio returns and market returns divided by the variance of market returns.

conditional_value_at_risk(returns, confidence_level=0.95, method='historical', current_value=1.0)

Calculate the Conditional Value-at-Risk (CVaR) of a portfolio.

Parameters:

Name Type Description Default
returns list or ndarray

Array or list of returns

required
confidence_level float

Confidence level for CVaR calculation (e.g., 0.95 for 95% confidence)

0.95
method str

Method for calculating CVaR ('historical' or 'parametric')

'historical'
current_value float

Current value of the portfolio

1.0

Returns:

Type Description
float

Conditional Value-at-Risk (CVaR) as a positive number representing the potential loss

Notes

CVaR, also known as Expected Shortfall, measures the expected loss given that the loss exceeds the VaR threshold. It provides a more conservative risk measure than VaR.

correlation_matrix(returns_matrix)

Calculate the correlation matrix of returns.

Parameters:

Name Type Description Default
returns_matrix list of lists or np.ndarray

Matrix of returns where each column represents an asset

required

Returns:

Type Description
np.ndarray or list of lists

Correlation matrix

Notes

The correlation matrix measures the strength of the relationship between returns of different assets, normalized to be between -1 and 1.

covariance_matrix(returns_matrix)

Calculate the covariance matrix of returns.

Parameters:

Name Type Description Default
returns_matrix list of lists or np.ndarray

Matrix of returns where each column represents an asset

required

Returns:

Type Description
np.ndarray or list of lists

Covariance matrix

Notes

The covariance matrix measures how returns of different assets move together.

dollar_weighted_return(cash_flows, cash_flow_dates, end_value)

Calculate the dollar-weighted return (internal rate of return) for a series of cash flows.

Parameters:

Name Type Description Default
cash_flows array - like

Array or list of cash flows (positive for inflows, negative for outflows)

required
cash_flow_dates array - like

Array or list of dates (in days) when each cash flow occurs

required
end_value float

The final value of the investment

required

Returns:

Type Description
float

The dollar-weighted return as a decimal

Examples:

>>> dollar_weighted_return([-1000, -500, 200], [0, 30, 60], 1400)
0.36174448410245186

drawdown(returns, as_list=False)

Calculate drawdown metrics.

geometric_return(prices)

Calculate the geometric average return from a series of prices.

Parameters:

Name Type Description Default
prices array - like

Array or list of prices

required

Returns:

Type Description
float

The geometric average return as a decimal

Examples:

>>> geometric_return([100, 105, 103, 108, 110])
0.02411368908444511

holding_period_return(prices, dividends=None)

Calculate the holding period return for a series of prices and optional dividends.

Parameters:

Name Type Description Default
prices array - like

Array or list of prices over the holding period

required
dividends array - like

Array or list of dividends paid during the holding period

None

Returns:

Type Description
float

The holding period return as a decimal

Examples:

>>> holding_period_return([100, 102, 105, 103, 106])
0.06
>>> holding_period_return([100, 102, 105, 103, 106], [0, 1, 0, 2, 0])
0.09

information_ratio(returns, benchmark_returns, annualization_factor=1.0)

Calculate the Information ratio, which measures excess return per unit of tracking error.

Parameters:

Name Type Description Default
returns array - like

Array of portfolio returns

required
benchmark_returns array - like

Array of benchmark returns for the same periods

required
annualization_factor float

Factor to annualize the Information ratio (e.g., 252 for daily returns to annual)

1.0

Returns:

Type Description
float

The Information ratio

leveraged_return(unleveraged_return, leverage_ratio, borrowing_rate)

Calculate the return of a leveraged portfolio.

Parameters:

Name Type Description Default
unleveraged_return float or array - like

The return of the unleveraged portfolio as a decimal

required
leverage_ratio float or array - like

The leverage ratio (e.g., 2.0 for 2:1 leverage)

required
borrowing_rate float or array - like

The borrowing rate as a decimal

required

Returns:

Type Description
float or ndarray

The leveraged return as a decimal If array inputs are provided, returns an array of leveraged returns

Examples:

>>> leveraged_return(0.10, 2.0, 0.05)
0.15
>>> leveraged_return([0.10, 0.15], [2.0, 1.5], 0.05)
[0.15, 0.2 ]
>>> leveraged_return(0.10, [2.0, 3.0], [0.05, 0.06])
[0.15, 0.18]

linked_modified_dietz_return(period_returns)

Calculate the linked Modified Dietz return over multiple periods.

Parameters:

Name Type Description Default
period_returns array - like

Array or list of Modified Dietz returns for each period

required

Returns:

Type Description
float

The linked Modified Dietz return as a decimal

Examples:

>>> linked_modified_dietz_return([0.05, -0.02, 0.03, 0.04])
0.10226479999999993

log_return(end_value, start_value)

Calculate the logarithmic (continuously compounded) return between two values.

Parameters:

Name Type Description Default
end_value float or array - like

The ending value(s) of the investment

required
start_value float or array - like

The starting value(s) of the investment

required

Returns:

Type Description
float or ndarray

The logarithmic return If array inputs are provided, returns an array of logarithmic returns

Examples:

>>> log_return(105, 100)
0.04879016416929972
>>> log_return([105, 110, 108], [100, 100, 100])
array([0.04879016, 0.09531018, 0.07696104])
>>> log_return(np.array([105, 110]), np.array([100, 100]))
array([0.04879016, 0.09531018])

long_short_equity_return(long_portfolio_return, short_portfolio_return, long_exposure, short_exposure, risk_free_rate=0.0, short_rebate=0.0)

Calculate the return of a long-short equity portfolio.

Parameters:

Name Type Description Default
long_portfolio_return float or array - like

The return of the long portfolio as a decimal

required
short_portfolio_return float or array - like

The return of the short portfolio as a decimal

required
long_exposure float or array - like

The exposure of the long portfolio as a decimal of NAV

required
short_exposure float or array - like

The exposure of the short portfolio as a decimal of NAV

required
risk_free_rate float or array - like

The risk-free rate as a decimal

0.0
short_rebate float or array - like

The rebate received on short proceeds as a decimal

0.0

Returns:

Type Description
float or ndarray

The return of the long-short equity portfolio as a decimal If array inputs are provided, returns an array of long-short equity returns

Examples:

>>> long_short_equity_return(0.10, -0.05, 1.0, 0.5, 0.02, 0.01)
0.14
>>> long_short_equity_return([0.10, 0.12], [-0.05, -0.03], 1.0, 0.5, 0.02, 0.01)
[0.14, 0.15]
>>> long_short_equity_return(0.10, -0.05, [1.0, 0.8], [0.5, 0.4], [0.02, 0.03], 0.01)
[0.14 , 0.122]

market_neutral_return(long_return, short_return, long_weight=0.5, short_weight=0.5, short_borrowing_cost=0.0)

Calculate the return of a market-neutral portfolio with long and short positions.

Parameters:

Name Type Description Default
long_return float or array - like

The return of the long portfolio as a decimal

required
short_return float or array - like

The return of the short portfolio as a decimal

required
long_weight float or array - like

The weight of the long portfolio

0.5
short_weight float or array - like

The weight of the short portfolio

0.5
short_borrowing_cost float or array - like

The cost of borrowing for the short position as a decimal

0.0

Returns:

Type Description
float or ndarray

The market-neutral return as a decimal If array inputs are provided, returns an array of market-neutral returns

Examples:

>>> market_neutral_return(0.08, -0.05, 0.6, 0.4, 0.01)
0.064
>>> market_neutral_return([0.08, 0.10], [-0.05, -0.03], 0.6, 0.4, 0.01)
[0.064, 0.068]
>>> market_neutral_return(0.08, -0.05, [0.6, 0.7], [0.4, 0.3], [0.01, 0.02])
[0.064, 0.065]

modified_dietz_return(start_value, end_value, cash_flows, cash_flow_days, total_days)

Calculate the Modified Dietz return, which approximates the money-weighted return.

Parameters:

Name Type Description Default
start_value float

The starting value of the investment

required
end_value float

The ending value of the investment

required
cash_flows array - like

Array or list of cash flows (positive for inflows, negative for outflows)

required
cash_flow_days array - like

Array or list of days when each cash flow occurs (day 0 is the start)

required
total_days int

Total number of days in the period

required

Returns:

Type Description
float

The Modified Dietz return as a decimal

Examples:

>>> modified_dietz_return(1000, 1200, [100, -50], [10, 20], 30)
0.14285714285714285

money_weighted_return(cash_flows, cash_flow_times, final_value, initial_value=0, max_iterations=100, tolerance=1e-06)

Calculate the money-weighted return (internal rate of return) for a series of cash flows.

Parameters:

Name Type Description Default
cash_flows array - like

Array or list of cash flows (positive for inflows, negative for outflows)

required
cash_flow_times array - like

Array or list of times (in years) when each cash flow occurs

required
final_value float

The final value of the investment

required
initial_value float

The initial value of the investment

0
max_iterations int

Maximum number of iterations for the numerical solver

100
tolerance float

Convergence tolerance for the numerical solver

1e-6

Returns:

Type Description
float

The money-weighted return (IRR) as a decimal

Examples:

>>> money_weighted_return([-1000, -500, 1700], [0, 0.5, 1], 0)
0.16120409753798307

multifactor_alpha(returns, factor_returns, risk_free_rate=0.0)

Calculate the alpha from a multifactor model (e.g., Fama-French).

Parameters:

Name Type Description Default
returns array - like

Array of portfolio returns

required
factor_returns array - like

2D array where each column represents returns for a factor

required
risk_free_rate float or array - like

Risk-free rate for the same period as returns

0.0

Returns:

Type Description
tuple

(alpha, betas, r_squared, p_value, std_err) - alpha: The multifactor alpha (intercept) - betas: Array of factor betas (coefficients) - r_squared: The R-squared of the regression - p_value: The p-value for alpha - std_err: The standard error of alpha

Examples:

>>> # Example with market, size, and value factors
>>> portfolio_returns = [0.01, 0.02, -0.01, 0.03, 0.01]
>>> factor_returns = [
...     [0.005, 0.01, -0.005, 0.02, 0.005],  # Market
...     [0.002, 0.003, -0.001, 0.004, 0.001],  # Size
...     [0.001, 0.002, -0.002, 0.003, 0.002]   # Value
... ]
>>> multifactor_alpha(portfolio_returns, factor_returns, 0.001)
(0.0032, array([0.9, 0.5, 0.3]), 0.92, 0.04, 0.0015)  # Example values

omega_ratio(returns, threshold=0.0, annualization_factor=1.0)

Calculate the Omega ratio, which measures the probability-weighted ratio of gains versus losses.

Parameters:

Name Type Description Default
returns array - like

Array of portfolio returns

required
threshold float

The threshold return

0.0
annualization_factor float

Factor to annualize the threshold

1.0

Returns:

Type Description
float

The Omega ratio

Examples:

>>> omega_ratio([0.01, 0.02, -0.01, 0.03, 0.01], 0.005)
2.0

semi_standard_deviation(returns, threshold=0.0, annualize=False, periods_per_year=252)

Calculate the semi-standard deviation of returns below a threshold.

Parameters:

Name Type Description Default
returns list or ndarray

Array or list of returns

required
threshold float

Threshold below which to calculate semi-standard deviation

0.0
annualize bool

Whether to annualize the semi-standard deviation

False
periods_per_year int

Number of periods in a year (252 for daily returns, 12 for monthly, 4 for quarterly)

252

Returns:

Type Description
float

Semi-standard deviation of returns

Notes

Semi-standard deviation only considers returns below the threshold (typically 0), making it a measure of downside risk.

sharpe_ratio(returns, risk_free_rate=0.0, annualization_factor=1.0)

Calculate the Sharpe ratio, which measures excess return per unit of risk.

Parameters:

Name Type Description Default
returns array - like

Array of portfolio returns

required
risk_free_rate float or array - like

Risk-free rate for the same period as returns

0.0
annualization_factor float

Factor to annualize the Sharpe ratio (e.g., 252 for daily returns to annual)

1.0

Returns:

Type Description
float or ndarray

The Sharpe ratio

simple_return(end_value, start_value)

Calculate the simple return (percentage change) between two values.

Parameters:

Name Type Description Default
end_value float or array - like

The ending value(s) of the investment

required
start_value float or array - like

The starting value(s) of the investment

required

Returns:

Type Description
float or ndarray

The simple return as a decimal (e.g., 0.05 for 5%) If array inputs are provided, returns an array of simple returns

Examples:

>>> simple_return(105, 100)
0.05
>>> simple_return([105, 110, 108], [100, 100, 100])
array([0.05, 0.1 , 0.08])
>>> simple_return(np.array([105, 110]), np.array([100, 100]))
array([0.05, 0.1 ])

sortino_ratio(returns, risk_free_rate=0.0, target_return=0.0, annualization_factor=1.0)

Calculate the Sortino ratio, which measures excess return per unit of downside risk.

Parameters:

Name Type Description Default
returns array - like

Array of portfolio returns

required
risk_free_rate float or array - like

Risk-free rate for the same period as returns

0.0
target_return float

Minimum acceptable return

0.0
annualization_factor float

Factor to annualize the Sortino ratio

1.0

Returns:

Type Description
float

The Sortino ratio

Examples:

>>> sortino_ratio([0.01, 0.02, -0.01, 0.03, 0.01], 0.001, 0.0, 252)
3.7947331922020545

standard_deviation(returns, annualize=False, periods_per_year=252)

Calculate the standard deviation of returns.

Parameters:

Name Type Description Default
returns list or ndarray

Array or list of returns

required
annualize bool

Whether to annualize the standard deviation

False
periods_per_year int

Number of periods in a year (252 for daily returns, 12 for monthly, 4 for quarterly)

252

Returns:

Type Description
float

Standard deviation of returns

Notes

Standard deviation measures the dispersion of returns around the mean. It is the square root of the variance.

time_weighted_return(period_returns)

Calculate the time-weighted return from a series of period returns.

Parameters:

Name Type Description Default
period_returns array - like

Array or list of returns for each period

required

Returns:

Type Description
float

The time-weighted return as a decimal

Examples:

>>> time_weighted_return([0.05, -0.02, 0.03, 0.04])
0.10226479999999993

total_return_index(prices, dividends=None)

Calculate the total return index from a series of prices and optional dividends.

Parameters:

Name Type Description Default
prices array - like

Array or list of prices

required
dividends array - like

Array or list of dividends paid

None

Returns:

Type Description
ndarray

The total return index

Examples:

>>> total_return_index([100, 102, 105, 103, 106])
[100., 102., 105., 103., 106.]
>>> total_return_index([100, 102, 105, 103, 106], [0, 1, 0, 2, 0])
[100.        , 103.        , 106.02941176, 106.02941176,
109.11764706]

tracking_error(portfolio_returns, benchmark_returns, annualize=False, periods_per_year=252)

Calculate the tracking error between portfolio returns and benchmark returns.

Parameters:

Name Type Description Default
portfolio_returns list or ndarray

Array or list of portfolio returns

required
benchmark_returns list or ndarray

Array or list of benchmark returns

required
annualize bool

Whether to annualize the tracking error

False
periods_per_year int

Number of periods in a year (252 for daily returns, 12 for monthly, 4 for quarterly)

252

Returns:

Type Description
float

Tracking error

Notes

Tracking error measures how closely a portfolio follows its benchmark. It is the standard deviation of the difference between portfolio and benchmark returns.

treynor_ratio(returns, benchmark_returns, risk_free_rate=0.0, annualization_factor=1.0)

Calculate the Treynor ratio, which measures excess return per unit of systematic risk.

Parameters:

Name Type Description Default
returns array - like

Array of portfolio returns

required
benchmark_returns array - like

Array of benchmark returns for the same periods

required
risk_free_rate float or array - like

Risk-free rate for the same period as returns

0.0
annualization_factor float

Factor to annualize the Treynor ratio

1.0

Returns:

Type Description
float

The Treynor ratio

Examples:

>>> treynor_ratio([0.01, 0.02, -0.01, 0.03, 0.01], [0.005, 0.01, -0.005, 0.02, 0.005], 0.001, 252)
0.0378

value_at_risk(returns, confidence_level=0.95, method='historical', parametric_mean=None, parametric_std=None, current_value=1.0)

Calculate the Value-at-Risk (VaR) of a portfolio.

Parameters:

Name Type Description Default
returns list or ndarray

Array or list of returns

required
confidence_level float

Confidence level for VaR calculation (e.g., 0.95 for 95% confidence)

0.95
method str

Method for calculating VaR ('historical', 'parametric', or 'monte_carlo')

'historical'
parametric_mean float

Mean for parametric VaR calculation (if None, calculated from returns)

None
parametric_std float

Standard deviation for parametric VaR calculation (if None, calculated from returns)

None
current_value float

Current value of the portfolio

1.0

Returns:

Type Description
float

Value-at-Risk (VaR) as a positive number representing the potential loss

Notes

VaR measures the potential loss in value of a portfolio over a defined period for a given confidence interval.