Some concepts for portfolio analysis

portfolio-management.png

A few days ago I decided to focus my effort in applying machine learning to the financial sector.

A first step is to be introduced to the concepts (jargon) used in finances. In this article I bring you some of them.

Performance or Return of a product

This index measures how much (in percentage) has been gained/lost when the current value of the investment is compared with the initial value.

Formula
\begin{equation*} \mathrm{Ret} = \frac{\mathrm{Val}_f - \mathrm{Val}_i}{\mathrm{Val_i}} \times 100 \end{equation*}
  • \(\mathrm{Ret}\): return or performance in percentage.
  • \(\mathrm{Val}_f\): current or final (if we are interested in a period) value of the product.
  • \(\mathrm{Val}_i\): initial value of the product.
Example

An investor purchased 1000 shares of a balanced portfolio, at a price of 125 USD the share. What is the return of the portfolio if the current value of the share is 137 USD?

The calculation of the return is independent of the number of purchased shares.

\begin{align*} \mathrm{Ret} & = \frac{137 - 125}{125} \times 100 \\ & = \frac{1200}{125} \\ & = 9.6 \% \end{align*}

Risk or Volatility

The risk or volatility measures the degree of fluctuation of the returns, giving an idea of secure would be your inversion. Despite of the name, the risk or volatility is nothing but the spread of the returns, and hence measures by the standard deviation of them.

Formula
\begin{equation*} \mathrm{Risk} = \sqrt{\frac{\sum_i (\mathrm{Ret}_i - \overline{\mathrm{Ret}})^2}{\#\mathrm{Val} - 1}} \end{equation*}
  • \(\mathrm{Risk}\): Risk or volatility, in percentage (if the returns are expressed in percentage).
  • \(i\): index running on the list of available values.
  • \(\mathrm{Ret}_i\): \(i\)-th item in the list of returns.
  • \(\overline{\mathrm{Ret}}\): average of returns.
  • \(\#\mathrm{Val}\): number of item in the list of returns.
Example

The return of a product has been evaluated, and the returns in the last four periods are shown in the following table:

5 2 -3 8

The average return is \(\overline{\mathrm{Ret}} = 3\), then the list of differences is [2, -1, -6, 5], and their square are [4, 1, 36, 25]. Summing those values we obtain 66. The number of items in the list is four, so we have to divide 66 over 4 - 1, yielding 22. Finally, the square root yields 4.69%.

We can use python or R to calculate the risk with ease. However, It is important to notice that there are two slightly different definitions of standard deviations, I recommend the article in datagy.io. In numpy the expected answer is obtained when we use the parameter ddof=1.

import numpy as np
risk = np.std(returns)
print(f"Risk: {risk:.2f}%")
Risk: 4.06%

Now, using the ddof parameter:

import numpy as np
risk = np.std(returns, ddof=1)
print(f"Risk: {risk:.2f}%")
Risk: 4.69%

Drawdown

This index indicates the worst possible scenario for a past investor. It measures the (normalized) difference between the highest and lowest value of the product.

Formula
\begin{equation*} \mathrm{DD} = \frac{\mathrm{Val}_{\mathrm{max}} - \mathrm{Val}_{\mathrm{min}}{\mathrm{Val}_{\mathrm{max}}} \times 100. \end{equation*}
Example

Consider a product whose value evolution is shown in the table below:

100
99.4
99
95
94
91.5
93.2
96.7
101
104.2
110

The maximum value is 110 and the minimum is 91.5. Hence,

\begin{align*} \mathrm{DD} & = \frac{110 - 91.5}{110} \times 100 \\ & = \frac{1850}{1109} \\ & = 16.82 \%. \end{align*}
import numpy as np
max_val, min_val = np.array(returns).max(), np.array(returns).min()
drawdown = (max_val - min_val) * 100. / max_val
print(f"Drawdown: {drawdown:.2f}%")  
Drawdown: 16.82%

It is important to note that even if the value is presented as a positive number, it represents the historical maximum lost.

Semi-deviation

Semi-deviations allows to identify stocks (or other investment product) that are less volatile during negative periods (crisis).

Formula

The semi-deviation is calculated as the risk, i.e. it is a standard deviation, but considering only the periods of negative returns.

\begin{equation*} \mathrm{sD} = \sqrt{\frac{\sum_{\mathrm{neg}} (\mathrm{Ret}_{\mathrm{neg}} - \overline{\mathrm{Ret}})^2}{\#\mathrm{NegRet}}} \times 100 \end{equation*}
Example

Let's calculate the return using the list of values above;

import numpy as np
returns = np.diff(data, axis=0)
print(returns)
[[-0.6]
 [-0.4]
 [-4. ]
 [-1. ]
 [-2.5]
 [ 1.7]
 [ 3.5]
 [ 4.3]
 [ 3.2]
 [ 5.8]]

There are five negative returns. Now, we have to calculate the standard deviation using those values.

import numpy as np
returns = np.diff(data, axis=0)
neg_returns = returns[returns < 0]
semi_dev = np.std(neg_returns)
print(f"Semi-deviation: {semi_dev:.2f}%")
Semi-deviation: 1.37%

Author: Oscar Castillo-Felisola

Created: 2026-04-02 Thu 14:59