Portfolio#
Portfolio
classes implement a large set of attributes and methods intended for
portfolio analysis. They are returned by the predict
method of
portfolio optimizations.
They are also data-containers (calling
np.asarray(portfolio)
returns the portfolio returns) making them compatible
with sklearn.model_selection
tools.
They use slots
for improved performance.
Base Portfolio#
BasePortfolio
directly takes a portfolio returns array as input and implements
a large set of attributes and methods.
Example:
import datetime as dt
from skfolio import BasePortfolio
portfolio = BasePortfolio(
returns=[0.002, -0.001, 0.0015],
observations=[dt.date(2022, 1, 1), dt.date(2022, 1, 2), dt.date(2022, 1, 3)],
)
Attributes and Methods#
More than 40 attributes and methods are available, including all the
measures (Mean, Variance, Sharpe Ration, CVaR, CDaR, Drawdowns,
etc.). The attributes are computed only when requested then cached in slots
for
enhanced performance.
Example:
from skfolio import RatioMeasure
# attributes
portfolio.mean
portfolio.variance
portfolio.sharpe_ratio
portfolio.sortino_ratio
portfolio.cdar
portfolio.max_drawdown
portfolio.cumulative_returns
portfolio.drawdowns
portfolio.returns_df
portfolio.cumulative_returns_df
# methods
portfolio.summary()
portfolio.dominates(other_portfolio)
portfolio.rolling_measure(measure=RatioMeasure.SHARPE_RATIO)
# plots
portfolio.plot_cumulative_returns()
portfolio.plot_rolling_measure(measure=RatioMeasure.SHARPE_RATIO)
It’s also an array-container:
np.asarray(portfolio)
>>> array([ 0.002 , -0.001 , 0.0015])
Finally, portfolios can be compared together using domination:
portfolio == other_portfolio
portfolio >= other_portfolio
portfolio > other_portfolio
The measures used in the domination are controlled using fitness_measures
. The default
is to use the list [PerfMeasure.MEAN, RiskMeasure.VARIANCE]
.
Portfolio#
Portfolio
inherits from BasePortfolio
. The portfolio returns are the
dot product of the assets weights with the assets returns minus costs:
\[r_p = R \cdot w^{T} - c^{T} \cdot | w - w_{prev} | - f^{T} \cdot w\]
with \(r_p\) the vector of portfolio returns , \(R\) the matrix of assets returns, \(w\) the vector of assets weights, \(c\) the vector of assets transaction costs, \(f\) the vector of assets management fees and \(w_{prev}\) the assets previous weights.
Warning
The Portfolio
formulation is homogenous to the convex optimization
problems for coherent analysis. It’s important to note that this portfolio
formulation is not perfectly replicable due to weight drift when asset prices
move. The only case where it would be perfectly replicable is with periodic
rebalancing with zero costs. In practice, portfolios are
rebalanced frequently enough, so this weight drift becomes negligible in regards to
model analysis and selection. Before trading, a full replicability analysis should
be performed, which is another topic left to the investor.
Example:
from skfolio import Portfolio
X = [
[0.003, -0.001],
[-0.001, 0.002],
[0.0015, 0.004],
]
weights = [0.6, 0.4]
portfolio = Portfolio(X=X, weights=weights)
print(portfolio.returns)
>>> array([0.0014, 0.0002, 0.0025])
X
can be any data-container including numpy array and pandas DataFrame:
import datetime as dt
import pandas as pd
X = pd.DataFrame(
data=[[0.003, -0.001], [-0.001, 0.002], [0.0015, 0.004]],
columns=["Asset A", "Asset B"],
index=[dt.date(2022, 1, 1), dt.date(2022, 1, 2), dt.date(2022, 1, 3)],
)
print(X)
>>>
Asset A Asset B
2022-01-01 0.0030 -0.001
2022-01-02 -0.0010 0.002
2022-01-03 0.0015 0.004
weights = [0.6, 0.4]
portfolio = Portfolio(X=X, weights=weights, name="my_portfolio")
print(portfolio.returns)
>>> array([0.0014, 0.0002, 0.0025])
Attributes and Methods#
Portfolio
inherits all the attributes and methods from BasePortfolio
.
In addition, it also implements weights related methods:
from skfolio import RatioMeasure
portfolio.contribution(measure=RatioMeasure.ANNUALIZED_SHARPE_RATIO)
>>> array([-3.04203502, 3.04203503])
portfolio.composition
>>>
my_portfolio
asset
Asset A 0.6
Asset B 0.4
portfolio.get_weight("Asset A")
>>> 0.6
# Plots
portfolio.plot_contribution()
portfolio.plot_composition()
Multi Period Portfolio#
MultiPeriodPortfolio
inherits from BasePortfolio
and is composed of a
list of Portfolio
. The multi-period portfolio returns are the sum of all its
underlying Portfolio
returns.
A MultiPeriodPortfolio
is returned by cross_val_predict
.
For example, calling cross_val_predict
with WalkForward
will return a MultiPeriodPortfolio
composed of multiple test Portfolio
, each
corresponding to a train/test fold.
from skfolio import MultiPeriodPortfolio
portfolio = MultiPeriodPortfolio(portfolios=[ptf1, ptf2, ptf3])