Optimization Tool for Portfolio Liquidation

Optimization tool for portfolio withdrawals under FIFO constraints, designed to optimize realized capital gains and losses.

The Problem

During my internship at Indexa Capital Group, I worked on an optimization tool for a common portfolio-management problem: how should an investor withdraw money from a portfolio containing several investment funds?

A client’s portfolio may contain several funds, and each fund may have been purchased multiple times at different dates and prices. Throughout this project:

  • a fund is one investment fund in the client’s portfolio;
  • a participation is one unit or share of that fund;
  • a purchase lot is a group of participations bought together on the same date and at the same price.

For example, a portfolio could look like this:

Fund Purchase lot Participations Purchase date Buying price Current price
Fund A Lot 1 100 Jan 2021 €10 €16
Fund A Lot 2 50 Jun 2023 €14 €16
Fund B Lot 1 80 Mar 2022 €20 €24
Fund B Lot 2 40 Feb 2024 €18 €24

If the client wants to withdraw money, Indexa has to decide how many participations to redeem from each fund, since there may be many possible combinations of withdrawal. This matters because different purchase lots have different buying prices. Redeeming them can therefore realize different amounts of gains or losses, producing a different fiscal impact.

We wanted the tool to address two main client needs.

1. Withdraw a specific amount of money

The first case is a client who actually needs liquidity.

For example:

“I need to withdraw €10,000. Among the possible ways of obtaining it, show me the withdrawal that realizes the most gains or the most losses.”

The required cash amount is fixed, but there may be several ways of obtaining it by redeeming participations from different funds. The client may prefer to maximize realized gains or maximize realized losses depending on their personal tax situation. The optimization tool finds the combination of fund redemptions that generates the required withdrawal while respecting the portfolio and tax constraints.

2. Generate a specific fiscal impact

The second case is different: the client does not necessarily need cash. Instead, they may want to deliberately realize a given amount of gains or losses for tax-planning purposes.

For example:

“I want to realize €3,000 of losses. What is the minimum amount of my portfolio that needs to be redeemed?”

Those realized losses could, subject to the applicable tax rules, be used to offset gains generated elsewhere in the investor’s portfolio.

In this case, the cash obtained from the redemption can be reinvested afterwards. The objective is therefore not liquidity itself, but generating a desired fiscal impact while liquidating as little of the portfolio as possible.


What Is Fiscal Impact?

In this project, fiscal impact means the capital gain or loss realized when fund participations are redeemed.

Suppose a client owns the following purchase lot:

Participations Purchase date Buying price Current price
100 Jan 2021 €10 €16

Each participation was bought for €10 and is now worth €16. If one participation is redeemed, its fiscal impact is: \(\text{Fiscal Impact} = P - C\) where P is the current redemption price and C is the original buying price.

In this example \(16 - 10 = 6\) so each redeemed participation realizes a €6 gain. If X participations are redeemed: \(F = X(P-C)\) where F is the resulting fiscal impact. For example, redeeming 50 participations would generate: \(F = 50(16-10)=300\) or a €300 realized gain.

Similarly:

  • if P>C, the investor realizes a gain;
  • if P<C, the investor realizes a loss;
  • if P=C, there is no realized gain or loss.

A positive fiscal impact does not mean that the entire redeemed amount is taxed. Only the realized gain is relevant for capital-gains taxation. For example, selling €5,000 worth of fund participations does not mean paying tax on €5,000. If those participations originally cost €4,500, the realized gain is €500. The final tax situation also depends on the investor’s other gains, losses and savings income. For the purpose of this optimization problem, however, the relevant quantity is the gain or loss generated by the redemption.


Why FIFO Matters

There is another important restriction: Spanish investment funds follow the FIFO — First In, First Out — rule. Within each fund, the oldest participations are considered to be redeemed first.

Consider Fund A:

Purchase lot Participations Purchase date Buying price Current price
Lot 1 100 Jan 2021 €10 €16
Lot 2 50 Jun 2023 €14 €16
Lot 3 75 Feb 2025 €12 €16

Suppose the client wants to redeem 120 participations from Fund A. We cannot choose whichever participations generate the most convenient tax outcome. FIFO requires all 100 participations from Lot 1 to be redeemed first; followed by 20 participations from Lot 2. Lot 3 cannot be touched while older participations remain.

Conceptually:

Fund A

Oldest                                                Newest
   ↓                                                     ↓

┌────────────────────────┬───────────────┬────────────────────┐
│ Lot 1                  │ Lot 2         │ Lot 3              │
│ 100 participations     │ 50            │ 75                 │
│ Jan 2021               │ Jun 2023      │ Feb 2025           │
│ Bought: €10            │ Bought: €14   │ Bought: €12        │
│ Current: €16           │ Current: €16  │ Current: €16       │
└────────────────────────┴───────────────┴────────────────────┘

        ████████████████████████ █████
        100 redeemed              20 redeemed

This sequential restriction is one of the main reasons why the problem is well suited to mathematical optimization.


Withdrawal Example

Now consider a portfolio containing two funds:

Fund Purchase lot Participations Purchase date Buying price Current price
Fund A Lot 1 100 Jan 2021 €10 €16
Fund A Lot 2 50 Jun 2023 €14 €16
Fund B Lot 1 80 Mar 2022 €20 €24
Fund B Lot 2 40 Feb 2024 €18 €24

Suppose the client requests a €2,000 withdrawal.

There may be several ways to obtain that money:

  • redeem mainly from Fund A;
  • redeem mainly from Fund B;
  • or combine participations from both funds.

Although each solution can provide the same €2,000, they do not necessarily generate the same realized gain or loss.

The problem is therefore not simply:

“How can we obtain €2,000?”

It becomes:

“Which fund participations should be redeemed, while respecting FIFO, to obtain €2,000 and achieve the client’s desired fiscal outcome?”

A portfolio contains several funds, each composed of purchase lots acquired at different dates and prices. FIFO determines which participations can be redeemed first, while the optimization model determines how much to redeem from each fund.

Optimization Approach

I formulated both problems as Mixed-Integer Programming (MIP) models.

Let:

  • $j$ identifies a fund;
  • $i$ identifies a purchase lot within that fund;
  • $N_{ij}$ is the number of participations available in that lot;
  • $C_{ij}$ is their buying price;
  • $P_j$ is the current price of fund $j$;
  • $X_{ij}$ is the number of participations redeemed from the lot.

The main decision variable is therefore \(X_{ij}\) with \(0 \leq X_{ij} \leq N_{ij}.\)

Fiscal impact

The gain or loss generated by redeeming \(X_{ij}\) participations is \(X_{ij}(P_j-C_{ij}).\) Across the complete portfolio, the fiscal impact is:

\[F = \sum_{j} \sum_{i} X_{ij}(P_j-C_{ij}).\]

Liquidated value

The total amount redeemed from the portfolio is:

\[L = \sum_{j} \sum_{i} X_{ij}P_j.\]

These two quantities — cash generated and fiscal impact generated — form the core of the two optimization problems.


Enforcing FIFO

The model also needs to guarantee that a newer purchase lot cannot be redeemed while an older lot of the same fund remains available.

If \(X_{ij}>0,\) then every previous purchase lot of fund \(j\) must have been completely redeemed \(X_{1j}=N_{1j},\quad X_{2j}=N_{2j},\quad \ldots,\quad X_{i-1,j}=N_{i-1,j}.\) Binary decision variables are used in the complete MIP formulation to represent which FIFO boundary is active for each fund. This allows the optimization model to choose how much to redeem from each fund, while the FIFO constraints determine which purchase lots those redemptions must come from.


Model 1 — Withdraw a Target Amount

The first model starts from a requested cash withdrawal D.

Ignoring withholding for a moment, the basic cash requirement is:

\[\sum_j \sum_i X_{ij}P_j = D.\]

The corresponding fiscal impact is:

\[F = \sum_j \sum_i X_{ij}(P_j-C_{ij}).\]

The client can then choose which fiscal direction they prefer. To generate as much realized gain as possible \(\max F\) or, alternatively, to generate as much realized loss as possible \(\min F.\) So the question solved by this model is:

Given that the client needs (D) euros, which participations should be redeemed to maximize or minimize the resulting fiscal impact?

In the complete implementation, the cash constraint also accounts for applicable withholding when positive taxable gains are generated, so that the model targets the amount of net cash actually received by the client.


Model 2 — Generate a Target Fiscal Impact

The second model reverses the problem.

Here, the investor specifies a desired fiscal impact F:

\[\sum_j \sum_i X_{ij}(P_j-C_{ij}) = F^*.\]

The objective is then to minimize the amount of the portfolio that needs to be redeemed:

\[\min \sum_j \sum_i X_{ij}P_j.\]

In plain language:

What is the smallest amount of the portfolio that must be redeemed to realize the desired amount of gains or losses?

This is intended for situations in which the client is primarily interested in generating a specific tax outcome rather than obtaining liquidity. The resulting cash can subsequently be reinvested according to the client’s investment strategy.


Implementation

The optimization model also had to fit into Indexa Capital’s existing technology stack. Indexa’s client data and web infrastructure used PHP, while the optimization work itself was developed in Python. I implemented the optimization logic in Python using:

  • PuLP to formulate the mathematical optimization models;
  • Gurobi to solve the resulting Mixed-Integer Programs;
  • FastAPI to expose the Python optimization functionality through an API that could communicate with the existing application environment.

Conceptually, the architecture was:

Existing Indexa application / client data
                 │
                 │
                PHP
                 │
                 ▼
          FastAPI endpoint
                 │
                 ▼
       Python optimization layer
                 │
          ┌──────┴──────┐
          │             │
        PuLP          Gurobi
     formulation       solver
          │             │
          └──────┬──────┘
                 │
                 ▼
       Optimized withdrawal
                 │
                 ▼
   Funds + participations to redeem
   Cash generated
   Fiscal impact generated

The Python service received the relevant client portfolio information, including:

  • the funds held by the client;
  • the purchase lots associated with each fund;
  • the number of participations in each lot;
  • each lot’s purchase date;
  • each lot’s buying price;
  • the current fund price;
  • and either the desired withdrawal or the desired fiscal impact.

The optimization model then returned:

  • which funds should be used;
  • how many participations should be redeemed from each fund;
  • which purchase lots are reached under FIFO;
  • the gross amount liquidated;
  • the resulting realized gain or loss;
  • and the withdrawal solution satisfying the selected objective.

This turned the mathematical model into a practical decision-support tool that could be connected to the company’s existing infrastructure.