Portfolio Optimization with Investment Bands API Reference
Data
Data model for Portfolio Optimization with Investment Bands use case.
PoIbtvData
Bases: UcData
Data for the Portfolio Optimization with Investment Bands use case.
Models a Markowitz-style mean-variance portfolio optimization where each asset has a minimum and maximum investment band. Continuous allocations are discretised using binary variables so the problem is suitable for QUBO/quantum solvers.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
Literal['portfolio_optimization_with_investment_bands']
|
Identifier for this data type. |
log_returns |
list[float]
|
Expected log-return per asset. Positive values indicate expected gains, negative values indicate expected losses. |
covariance_matrix |
NumPyArray
|
Symmetric positive semi-definite covariance matrix of shape (n_assets, n_assets). Entry [i,j] is the covariance between asset i and asset j. Diagonal entries are variances. |
investment_bands |
list[tuple[float, float]]
|
(lower, upper) investment bounds per asset. Each allocation is constrained to lie within [lower, upper]. |
risk_aversion |
float
|
Risk aversion parameter lambda in the Markowitz objective: Higher values penalise variance more strongly. Default: 1.0. |
max_budget |
float
|
Maximum total budget that can be allocated across all assets: sum_i investment[i] <= max_budget. |
n_bits |
int
|
Number of binary bits used to discretise each asset's allocation within its investment band. Higher values give finer resolution but increase the number of binary variables (n_assets * n_bits). |
plot(*, ax: Axes | None = None) -> Axes
Plot investment bands and expected returns per asset.
Shows a horizontal bar for each asset's investment band, colored per asset. The expected log-return is annotated to the right of each bar.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
ax
|
Axes | None
|
Matplotlib axes to draw on. Creates a new figure if |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The axes with the plot. |
to_string() -> str
Return a human-readable description of the problem data.
Returns:
| Type | Description |
|---|---|
str
|
String representation of the data including all parameters and per-asset investment bands and expected returns. |
from_values(log_returns: list[float], covariance_matrix: np.ndarray, investment_bands: list[tuple[float, float]], max_budget: float, n_bits: int = 3, risk_aversion: float = 1.0) -> PoIbtvData
staticmethod
Create a PoIbtvData instance from explicit problem parameters.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
log_returns
|
list[float]
|
Expected log-return per asset. Positive values indicate expected gains, negative values indicate expected losses. |
required |
covariance_matrix
|
ndarray
|
Symmetric positive semi-definite covariance matrix of shape (n_assets, n_assets). Entry [i,j] represents the covariance between asset i and asset j. Diagonal entries are variances. |
required |
investment_bands
|
list[tuple[float, float]]
|
(lower, upper) investment bounds per asset. Each allocation is constrained to [lower, upper]. Must have length n_assets. |
required |
max_budget
|
float
|
Maximum total budget across all assets: sum_i investment[i] <= max_budget. |
required |
n_bits
|
int
|
Number of binary bits used to discretise each asset's allocation within its band. Higher values give finer resolution but increase the number of variables exponentially. Default: 3. |
3
|
risk_aversion
|
float
|
Risk aversion parameter lambda in the Markowitz objective: Higher values penalise variance more strongly. Default: 1.0. |
1.0
|
Returns:
| Type | Description |
|---|---|
PoIbtvData
|
A validated data instance ready for optimisation. |
Raises:
| Type | Description |
|---|---|
ValueError
|
If any of the following conditions are violated:
|
Examples:
>>> import numpy as np
>>> data = PoIbtvData.from_values(
... log_returns=[0.05, 0.08, 0.03],
... covariance_matrix=np.array(
... [
... [0.04, 0.01, 0.005],
... [0.01, 0.09, 0.02],
... [0.005, 0.02, 0.03],
... ]
... ),
... investment_bands=[(0.1, 0.5), (0.1, 0.4), (0.1, 0.6)],
... max_budget=1.0,
... n_bits=3,
... risk_aversion=1.0,
... )
generate_random(n_assets: int = 3, n_bits: int = 3, risk_aversion: float = 1.0, seed: int | None = None) -> PoIbtvData
staticmethod
Generate a random PO-IBTV instance.
Creates a random portfolio problem with plausible return and covariance structure. Investment bands are sampled uniformly, and the covariance matrix is constructed to be positive semi-definite.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
n_assets
|
int
|
Number of assets, by default 3. |
3
|
n_bits
|
int
|
Number of binary bits per asset for discretisation, by default 3. |
3
|
risk_aversion
|
float
|
Risk aversion parameter lambda controlling the trade-off between expected return and variance. Default: 1.0. |
1.0
|
seed
|
int | None
|
Random seed for reproducibility, by default None. |
None
|
Returns:
| Type | Description |
|---|---|
PoIbtvData
|
A randomly generated data instance. |
Examples:
Formulation
Formulation for Portfolio Optimization with Investment Bands use case.
PoIbtvFormulation
Bases: UcFormulation[PoIbtvData, PoIbtvSolution]
Formulation for Portfolio Optimization with Investment Bands.
Each asset's allocation is discretised within its investment band using
n_bits binary variables. The objective is the Markowitz mean-variance
formulation: maximise expected return minus risk-aversion-weighted variance.
The continuous allocation per asset is encoded as: investment[i] = lower[i] + step[i] * sum_q (2^q * x[i,q]) where step[i] = (upper[i] - lower[i]) / (2^n_bits - 1)
This allows a quantum solver to search over discretised allocations within the investment bands without requiring continuous variables.
Mathematical Formulation
Decision Variables: x[i,q] in {0,1} for asset i, bit q in 0..n_bits-1
Derived investment: investment[i] = lower[i] + step[i] * sum_q (2^q * x[i,q]) where step[i] = (upper[i] - lower[i]) / (2^n_bits - 1)
Objective (maximize): sum_i log_returns[i] * investment[i] - risk_aversion * sum_{i,j} sigma[i][j] * investment[i] * investment[j] where risk_aversion = 1 / (2 * target_volatility^2)
Constraints: 1. Budget: sum_i investment[i] <= max_budget
to_string(data: PoIbtvData) -> str
staticmethod
Format the formulation as a string.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
PoIbtvData
|
The problem data. |
required |
Returns:
| Type | Description |
|---|---|
str
|
String representation of the formulation. |
formulate(data: PoIbtvData) -> Model
staticmethod
Formulate PO-IBTV as an optimization model.
Expands the continuous Markowitz objective fully into binary variables by substituting the discretised investment expression. The resulting objective contains linear and quadratic terms in x[i,q].
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
PoIbtvData
|
The problem data containing returns, covariance, bands, and parameters. |
required |
Returns:
| Type | Description |
|---|---|
Model
|
A Luna optimization model representing the investment band portfolio problem. |
interpret(solution: Solution, data: PoIbtvData) -> PoIbtvSolution
staticmethod
Extract solution from solver result.
Reconstructs the continuous allocation per asset from the binary variables and computes portfolio return, volatility, and validity.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
solution
|
Solution
|
The solution containing variable assignments. |
required |
data
|
PoIbtvData
|
The original problem data. |
required |
Returns:
| Type | Description |
|---|---|
PoIbtvSolution
|
A structured solution object with: - allocations: continuous allocation per asset - portfolio_return: expected return of the portfolio - portfolio_volatility: standard deviation of the portfolio - is_valid: whether investment bands and budget are satisfied |
Raises:
| Type | Description |
|---|---|
NoSolutionFoundError
|
If the solver did not find a solution. |
Solution
Solution model for Portfolio Optimization with Investment Bands use case.
PoIbtvSolution
Bases: UcSolution
Solution for the Portfolio Optimization with Investment Bands use case.
Attributes:
| Name | Type | Description |
|---|---|---|
name |
Literal['portfolio_optimization_with_investment_bands']
|
Identifier for this solution type. |
allocations |
list[float]
|
Allocation fraction per asset (discretised). |
portfolio_return |
float
|
Expected portfolio return. |
portfolio_volatility |
float
|
Portfolio volatility (standard deviation). |
is_valid |
bool
|
Whether the solution satisfies all constraints (allocations within bands, budget met). |
plot(data: PoIbtvData, *, ax: Axes | None = None) -> Axes
Plot the portfolio allocation against investment bands.
Mirrors the data plot layout: horizontal bars show the investment bands (background) with the selected allocation overlaid as a marker, making it easy to see where each allocation falls within its band.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
data
|
PoIbtvData
|
The original problem data containing investment bands. |
required |
ax
|
Axes | None
|
Matplotlib axes to draw on. Creates a new figure if |
None
|
Returns:
| Type | Description |
|---|---|
Axes
|
The axes with the plot. |
to_string() -> str
Return a string describing the PO-IBTV solution.
Instance
Instance model for PoIbtv use case.
PoIbtvInstance
Bases: UcInstance[PoIbtvData, PoIbtvFormulation, PoIbtvSolution]
Instance combining data and formulation for PoIbtv.
Collection
Collection of PO Investment Bands instances.
PoIbtvCollection
Bases: UcInstanceCollection[PoIbtvInstance]
Collection of PO Investment Bands instances.
This collection provides methods to generate benchmark instances with various characteristics for testing and evaluation.
from_random(min_assets: int = 2, max_assets: int = 5, n_bits: int = 3, num_instances: int = 1, *, seed: int | None = None) -> PoIbtvCollection
classmethod
Generate random PO-IBTV instances.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
min_assets
|
int
|
Minimum number of assets per instance (default: 2). |
2
|
max_assets
|
int
|
Maximum number of assets per instance (default: 5). |
5
|
n_bits
|
int
|
Number of binary bits per asset (default: 3). |
3
|
num_instances
|
int
|
Number of instances per asset count (default: 1). |
1
|
seed
|
int | None
|
Random seed for reproducibility (default: None). |
None
|
Returns:
| Type | Description |
|---|---|
PoIbtvCollection
|
Collection containing generated instances. |