Portfolio Performance

Measuring portfolio performance is a difficult task. Let's see how it's done!

Measuring portfolio performance is a difficult task. There are different ways of calculating portfolio performance, each of which represents a different way of looking at the performance. Therefore it is very important to analyze each of a product’s specific use cases and decide which way of calculating portfolio performance fits best.


In this document, we will outline different views on portfolio performance and highlight specific solutions for specific problems in this space.


We frequently see the below terms used for multiple, different things. In this document, we'll apply these meanings to achieve consistency:

  • Value: When we use the term “value” in this document, we refer to an absolute value measured using a currency. The cash balance is a value, so is each instrument's result for the formula quantity * latest_bid.
  • Profit/Loss: The terms profit and/or loss refer to absolute change of value on a portfolio or an instrument; also measured using a currency. The formula quantity * (latest_bid - buy_in) can be used to express the profit/loss on an open position.
  • Returns: The term “returns” is used when we want to discuss relative changes in portfolio value. E.g. an instrument's rate of returns can be calculated using latest_bid / buy_in - 1.
  • Rate of Returns: The term “rate of returns” is used to express annualized returns. When someone says “My portfolio gained 60% in value” it makes a huge difference if the portfolio is five months old or five years.
  • Portfolio: The term “portfolio” is used to represent both open positions and the cash balance on the brokerage account.


Total Value

The total value of the portfolio is used to provide the user with information about today's market value of a portfolio.

If a user pays in money every month, the graph will eventually go from the bottom-left corner to the top-right corner and it will be hard to see if this is primarily caused by the deposits or by investment returns.

In order to determine the total value, add the portfolio's cash position to the current value of all open positions. To approximate the current value, we recommend to use the bid price of the most recent quote.


const total_value = positions
    // Convert position into it's current market value
    .map(p => p.quantity * p.latest_bid)
    // Create total sum of everything, starting with `balance`
    .reduce((a, b) => (a + b), financials.balance)


Balance:      1,000.00 EUR
Instrument A: 1,000.00 EUR (`quantity=100`, `latest_bid=10.00`)
Instrument B:   250.00 EUR (`quantity=50`, `latest_bid=5.00`)
Total Value:  2,250.00 EUR

Recommended Use-Cases

We recommend to use the total value in a portfolio overview screen. A user reading this number will understand the total value of his investments.

Total Profit/Loss

In order to determine the total returns of a portfolio, you subtract the net deposits (total deposits – total withdrawals) from the total value.

Compared to the total value earlier, this indicator is not skewed by deposits. If a user pays in more money every month, the graph will only indicate the absolute returns.

Note: A complete solution will also include security transfers between brokerage accounts (skipped for simplicity). It will be important to consider the present-day value of the securities as of the transfer date. Considering the buy_in will skew the performance just as the transfer will change the total value.


const total_deposits = transactions
    // Filter all cash transfers
    .filter((t) => ['deposit', 'withdrawal'].contains(t.type))
    // Inspect transactions' components
    .flatMap((t) => t.components)
    // Filter for gross cash components
    .filter((c) => c.type == 'cash' && c.cash.type == 'gross')
    // Apply +/- sign
    .map((c) => c.direction == 'credit' ?
	      c.cash.amount :
    // Create the total sum of everything
    .reduce((a, b) => a + b, 0)


Cash Transfers: 1,000.00 EUR deposited
                  500.00 EUR deposited
                  300.00 EUR withdrawn
Net Deposits:   1,200.00 EUR
Balance:        1,000.00 EUR
Instrument A:     250.00 EUR (`quantity=50`, `latest_bid=5.00`)
Total Value:    1,250.00 EUR
Total Value:    1,250.00 EUR
Net Deposits:   1,200.00 EUR
Total P/L:         50.00 EUR (positive => profit)

Recommended Use-Cases

When plotting the total value of a portfolio, the total profit/loss is a good indicator for the chart's line. You can add an indicator line at the break-even point (where profit/loss would be zero). As long as the line is above the zero-level, the user made a profit, when it's below, the user took some losses.

Time-Weighted Returns (TWR)

When it comes to relative portfolio performance, time-weighted returns have become the established standard to indicate a portfolio's performance. This is mostly due to the fact that the TWR provides a good indicator, even when facing deposits and withdrawals.

The TWR is the so-called geometric mean of the returns of different time periods, where each time period is considered from one cash flow event to another; the last period is from the most recent cash flow until today:

// Time-Weighted Returns over `n` periods

TWR := [(1 + PR_1) × (1 + PR_2) × ⋯ × (1 + PR_n)] - 1

// Returns for Period `x`

        end_value - (initial_value + cash_flow)
PR_x := ———————————————————————————————————————
               initial_value + cash_flow


  • Day 1:

    • 1,000 EUR deposited
    • Buy 30 shares in instrument A for 25 EUR each (250 EUR cash remaining).
  • Day X:

    • 500 EUR deposited
    • Buy 25 shares in instrument A for 30 EUR each (no cash remaining).
  • Day Y (today):

    • Instrument A is worth 27.50 EUR now (via latest_bid)
  • Period 0 (Account Opening…Day 1):

    • Initial Value: 0 EUR
    • Cash Flow: 1,000 EUR
    • Final Value: 1,000 EUR
    • Return: 0% (= (1,000 - (0 + 1,000)) / (0 + 1,000)))
  • Period 1 (Days 1…X):

    • Initial Value: 1,000 EUR (1,000 EUR cash)
    • Cash Flow: 500 EUR
    • Final Value: 1,650 EUR: 750 EUR cash + 900 EUR shares (30 shares bought on Day 1 at 30 EUR price on day X)
    • Return: 10% (= (1,650 - (1,000 + 500)) / (1,000 + 500))
  • Period 2 (Days X…Y):

    • Initial Value: 1,650.00 EUR: 750 EUR cash + 900 EUR shares (30 shares bought on Day 1 at 30 EUR price on day X)
    • Final Value: 1,512.50 EUR: 0 EUR cash + 1,512.50 EUR shares (30 shares bought on Day 1, 25 shares bought on Day X at a 27.50 EUR price on Day Y)
    • Relative Value: -8,33% (= (1,512.5 - (1,650 + 0)) / (1,650 + 0))

TWR: 0,83% (= (1 + 10%) × (1 - 8,33%) - 1)

Metrics to Avoid

The following metrics might make sense intuitively, and are also easy to calculate, though they will become misleading over time. We strongly advise against using these metrics.

Total Returns (Avoid‼️)

You can calculate the total returns as the total profit/loss over the total deposits. However, this indicator has one significant disadvantage: It is heavily skewed by cash transactions:

  1. If a user has recurring deposits, the investment profits from early months will diminish over time.
  2. If a user eventually withdraws a large amount of money, the indicator will show unreasonably high returns.

Think of this example (without fees, to keep things simple):

  • Deposit 1000 EUR.
  • Buy 100 shares for 10 EUR each.
  • Sell 100 shares for 12 EUR each.

This will result in a cash balance of 1,200 EUR for deposits of 1,000 EUR. Total returns of 20% make sense intuitively (20% = 1,200 / 1,000 - 1). However, if we perform one of these two actions, the returns will be very skewed:

  1. Deposit 9,000 EUR: We'd have total returns of 2% (= 10,200 / 10,000 - 1). We don't think it makes sense that the portfolio performance gets worse when money is deposited. People may realize that adding money hurts this metric and stop depositing money in order to keep a metric “nice” that doesn't really provide much information.
  2. Withdraw 999.99 EUR: We'd have total returns of 2,000,000% (= 200.01 / 0.01 - 1 = 20,001 - 1 = 20,000). Again, we don't think it makes sense to calculate performance like this.