Example 12: Portfolio Optimization Problem
Problem Description
There are
When purchasing
Design an investment portfolio strategy with given funds of
Mathematical Model
Variables
Intermediate Values
1. Whether Purchased
2. Transaction Fee
3. Return
4. Risk
Objective Function
1. Maximize Return
Constraints
1. Sum of Funds Equals
2. Risk Limit
Expected Results
Invest
Code Implementation
import fuookami.ospf.kotlin.utils.math.*
import fuookami.ospf.kotlin.utils.concept.*
import fuookami.ospf.kotlin.utils.functional.*
import fuookami.ospf.kotlin.utils.multi_array.*
import fuookami.ospf.kotlin.core.frontend.variable.*
import fuookami.ospf.kotlin.core.frontend.expression.polynomial.*
import fuookami.ospf.kotlin.core.frontend.expression.symbol.*
import fuookami.ospf.kotlin.core.frontend.inequality.*
import fuookami.ospf.kotlin.core.frontend.model.mechanism.*
import fuookami.ospf.kotlin.core.backend.plugins.scip.*
data class Product(
val yield: Flt64,
val risk: Flt64,
val premium: Flt64,
val minPremium: Flt64
) : AutoIndexed(Product::class)
val products: List<Product> = ... // Product list
val funds = Flt64(1000000.0)
val maxRisk = Flt64(0.02)
// Create model instance
val metaModel = LinearMetaModel("demo12")
// Define variables
val x = UIntVariable1("x", Shape1(products.size))
metaModel.add(x)
// Define intermediate values
val assignment = LinearIntermediateSymbols1(
"assignment",
Shape1(products.size)
) { i, _ ->
BinaryzationFunction(
x = LinearPolynomial(x[i]),
name = "assignment_$i"
)
}
metaModel.add(assignment)
val premium = LinearIntermediateSymbols1(
"premium",
Shape1(products.size)
) { i, _ ->
val product = products[i]
MaxFunction(
listOf(
LinearPolynomial(product.premium * x[i]),
LinearPolynomial(product.minPremium * assignment[i])
),
"premium_$i"
)
}
metaModel.add(premium)
val risk = LinearExpressionSymbol(
sum(products.map { p -> p.risk * x[p] / funds }),
"risk"
)
metaModel.add(risk)
val yield = LinearExpressionSymbol(
sum(products.map { p -> p.yield * x[p] - premium[p] }),
"yield"
)
metaModel.add(yield)
// Define objective function
metaModel.maximize(yield, "yield")
// Define constraints
metaModel.addConstraint(
sum(products.map { p -> x[p] + premium[p] }) eq funds,
"funs"
)
metaModel.addConstraint(
risk leq maxRisk,
"risk"
)
// Call solver to solve
val solver = ScipLinearSolver()
when (val ret = solver(metaModel)) {
is Ok -> {
metaModel.tokens.setSolution(ret.value.solution)
}
is Failed -> {}
}
// Parse results
val solution = HashMap<Product, UInt64>()
for (token in metaModel.tokens.tokens) {
if (token.result!! geq Flt64.one && token.variable.belongsTo(x)) {
val vector = token.variable.vectorView
val product = products[vector[0]]
solution[product] = token.result!!.round().toUInt64()
}
}Complete Implementation Reference: