---
title: "Stochastic programming"
description: "Stochastic programming chooses today's weights by planning over a tree of possible futures in which the portfolio may still rebalance, at a real trading cost."
canonical_url: "https://fincanva.com/docs/strategies/stochastic-programming"
last_updated: "2026-09-24"
md_url: "https://fincanva.com/docs/strategies/stochastic-programming.md"
---

# Stochastic programming

Stochastic programming is an [allocation method](/docs/strategies/allocation-and-allocation-method) that chooses today's weights by playing out a **tree of possible futures** in which the portfolio is allowed to react: from today, a set of scenarios for the next period; in each of them the portfolio may rebalance, paying a transaction cost; then a second set of scenarios values the result. Today's weights are chosen knowing that later adjustment is possible and costs money — something a single-period optimiser cannot take into account. It is the slowest allocation method in Fincanva. The method picker labels it **"Stochastic programming"** and describes it as "Plans over a tree of scenarios, accounting for the cost of rebalancing".

**Also seen as:** multi-stage stochastic optimisation, scenario-tree optimisation

## What does Stochastic programming optimise?

It balances the expected final value of the portfolio against how bad its worst outcomes are:

$$
\max_{w} \; \mathbb{E}\left[\,W_{\text{final}}\,\right] - \lambda \cdot \text{CVaR}\left(W_{\text{final}}\right)
$$

where: $w$ is today's set of weights, $W_{\text{final}}$ is the portfolio's value at the end of the tree, $\mathbb{E}$ averages it over every branch, $\text{CVaR}$ is the average loss of its worst outcomes (see [Minimum CVaR](/docs/strategies/minimum-cvar)), and $\lambda$ is the **Risk aversion** you set. In words: more final value is better, deep bad outcomes are worse, and risk aversion decides how much the second counts against the first.

The two preferences do different jobs, and only one of them diversifies. **Risk aversion** is what spreads the weights: at 0 the method looks only at the expected final value, and the best way to maximise an average is to put everything on the single instrument whose scenarios end highest on average — whatever the transaction cost. Raising it makes deep bad outcomes count against a mix, and a mix of instruments whose bad outcomes do not coincide has shallower ones. **Transaction cost** does not diversify by itself: it prices every later rebalance. At 0% a rebalance in any branch is free, so today's weights matter only for the first period; the higher the cost, the more each later change eats into the final value, so the plan favours today's weights that are already worth keeping through the branches and trades less afterwards.

## Which settings does Stochastic programming have?

Two preferences are always visible:

- **Risk aversion** — "0 = looks only at the expected return; higher = weighs the worst losses more." From 0 to 10; 1 by default.
- **Transaction cost** — "The method takes it into account when deciding whether to move the weights." From 0% to 1%; 0.1% by default. It shapes the plan only; the costs charged in the backtest itself are set separately — see [Transaction cost](/docs/backtesting/transaction-cost).

Three more describe the tree, under **Advanced settings**:

- **First-stage scenarios** — "How many possible futures for the first period." From 20 to 200; 50 by default.
- **Second-stage scenarios** — "For each first-stage scenario." From 5 to 40; 10 by default.
- **Length of each stage** — from 5 to 63 days; 21 by default.

The second-stage scenarios are one shared set used under every first-stage branch, so the value of planning comes from the trading cost and the shape of the risk rather than from forecasting what follows each branch. Raising the second-stage count is the lever when the tail feels thin.

## Why is Stochastic programming so slow?

Because at every [rebalance](/docs/backtesting/rebalance) it builds the scenario tree and solves one optimisation over all of it, and that optimisation grows with the number of instruments times the number of scenarios. The picker marks it "very slow to compute", the only method with that mark, and the method's card says why: "Very slow to compute: it builds a scenario tree at every rebalance."

Large baskets are where it hurts. At the default tree, a strategy that can hold more than 30 instruments pushes the work past the point the app considers reasonable, and the card shows the warning **"Large basket for this method"**, naming the basket size, the threshold, and the two ways out: reduce the instruments or the first-stage scenarios, or choose CVaR on scenarios. The threshold moves with the tree — fewer first-stage scenarios allow a larger basket — and a tree that is too large on its own, whatever the basket, gets its own message: "The scenario tree alone is too large: with this many first- and second-stage scenarios, the computation may take a very long time whatever the basket." Both are advice, not refusals: the backtest still runs.

## How does Fincanva handle it?

- Stochastic programming is offered at **both levels**: across the instruments of a strategy, and across the strategies of a [Combined](/docs/getting-started/strategy-in-a-combined). Inside a Combined the large-basket advice counts strategies instead of instruments.
- It reads the [calculation window](/docs/strategies/calculation-window) (**In-sample**, 12 months by default) and does not read the **Risk estimation** choice.
- With a single instrument there is nothing to plan: it receives the whole weight.
- How long a backtest takes also depends on your plan's compute power — see [compute time](/docs/backtesting/compute-time).

## Which plan includes Stochastic programming?

It depends on your plan, at each level where the method is offered.

**Inside a strategy**

Included from Ultimate upwards. See [what each plan includes](/docs/account-security/what-each-plan-includes).

**Inside a Combined**

Included from Ultimate upwards. See [what each plan includes](/docs/account-security/what-each-plan-includes).

## What does it look like in practice?

A strategy holds 10 instruments and keeps the default tree: 50 first-stage scenarios, each followed by the same 10 second-stage scenarios, every stage 21 trading days long.

- With **Risk aversion 0**, the plan has no reason to diversify, and all the capital goes to the instrument whose scenarios end highest on average. Raising **Transaction cost** alone does not change that: the plan still holds one instrument.
- With the defaults — **Risk aversion 1** and **Transaction cost 0.1%** — the worst outcomes now count against a concentrated bet, so the weights spread across several instruments; the cost then makes the plan prefer weights it will not need to trade away in most branches.

Let the same strategy hold up to 40 instruments at the same tree and the card warns: "This strategy can hold up to 40 instruments. The computation grows with instruments × scenarios: above 30 instruments the simulation may take a very long time. Reduce the instruments or the first-stage scenarios, or choose CVaR on scenarios." Cutting the first-stage scenarios to 20 brings the tree back under the line for 40 instruments; switching to [Scenario CVaR](/docs/strategies/minimum-cvar) removes the tree altogether.

Fincanva is for education and illustration only. It is not personalised financial advice, and past or simulated results do not predict future ones. [Read the Terms Addendum](https://fincanva.com/terms/addendum#section-3)
