# 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])
```