Liiketoiminnan tunnusluvuista#
Tämä kirjanen esittelee hieman miten pörssiyhtiöiden tietoja pystyy tarkastelemaan ohjelmoinnin avulla.
1. Työkalut#
# Tuodaan tarvittavat kirjastot
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
# Jotkut Pythonin versiot eivät oletusarvoisesti tue pandaksen kautta Excel-tiedostojen lukemista. Alla oleva käsky auttaa virheilmoituksiin.
%pip install openpyxl
Requirement already satisfied: openpyxl in /opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/site-packages (3.1.5)
Requirement already satisfied: et-xmlfile in /opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/site-packages (from openpyxl) (2.0.0)
Note: you may need to restart the kernel to use updated packages.
2. Aineistot#
# Haetaan tarkasteltavia tietoja.
# Tässä on käytetty Kauppalehden listaa Helsingin pörssistä, jonka on tuottanut Alma Talent Tietopalvelut.
# Esimerkkiaineisto on haettu 21.4.2025.
# https://www.kauppalehti.fi/porssi/indeksit/omxhpi
data = pd.read_excel("https://github.com/opendata-education/Tyopajat/raw/refs/heads/main/materiaali/data/AFAGR_financialstmt.xlsx", header=1)
/opt/hostedtoolcache/Python/3.13.3/x64/lib/python3.13/site-packages/openpyxl/styles/stylesheet.py:237: UserWarning: Workbook contains no default style, apply openpyxl's default
warn("Workbook contains no default style, apply openpyxl's default")
# Vilkaistaan aineistoon.
data
Afarak Group Oyj | 12/2015 | 12/2016 | 12/2017 | 12/2018 | 12/2019 | 12/2020 | 12/2021 | 12/2022 | 12/2023 | 12/2024 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | Sijoittajan tunnuslukuja | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1 | Markkina-arvo (P) | 103.52 | 202.25 | 220.73 | 189.94 | 126.33 | 54.94 | 34.49 | 91.00 | 104.20 | 80.34 |
2 | Tasesubstanssi ilman väh.os. (B) | 167.36 | 172.04 | 171.40 | 150.48 | 67.31 | 27.54 | 44.24 | 105.71 | 106.05 | 112.05 |
3 | Yritysarvo (EV) | 98.98 | 196.39 | 221.97 | 202.24 | 181.45 | 103.16 | 66.72 | 80.78 | 89.25 | 79.00 |
4 | Tulos (E) | 8.07 | -2.48 | 4.74 | -11.51 | -4.76 | -2.23 | -2.20 | 44.83 | 9.45 | -7.57 |
5 | P/B-luku | 0.62 | 1.18 | 1.29 | 1.26 | 1.88 | 2.00 | 0.78 | 0.86 | 0.98 | 0.72 |
6 | P/S-luku | 0.55 | 1.32 | 1.11 | 0.98 | 1.29 | 0.92 | 0.43 | 0.46 | 0.68 | 0.63 |
7 | P/E-luku | 12.83 | -81.69 | 46.55 | -16.50 | -26.52 | -24.64 | -15.66 | 2.03 | 11.03 | -10.61 |
8 | EV/EBIT-luku | 10.01 | -194.45 | 19.47 | -26.79 | -20.05 | -15.45 | 17.31 | 1.55 | 5.94 | -541.12 |
9 | Tulos/osake (EPS), euroa | 0.03 | -0.01 | 0.02 | -0.04 | -0.02 | -0.01 | -0.01 | 0.18 | 0.36 | -0.03 |
10 | Tulorahoitus/osake (CPS), euroa | 0.06 | 0.01 | 0.05 | -0.02 | -0.01 | -0.01 | 0.00 | 0.18 | 0.44 | -0.02 |
11 | Oma pääoma/osake, euroa | 0.65 | 0.66 | 0.66 | 0.58 | 0.28 | 0.12 | 0.18 | 0.41 | 0.41 | 0.43 |
12 | Osinko/kokonaistulos, % | 58.46 | 999.90 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 |
13 | Maksuvalmius | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
14 | Quick Ratio | 1.80 | 1.72 | 1.74 | 1.12 | 0.46 | 0.50 | 0.94 | 1.91 | 1.73 | 1.62 |
15 | Current Ratio | 3.14 | 3.50 | 3.19 | 2.18 | 0.88 | 0.92 | 1.25 | 3.07 | 2.96 | 3.24 |
16 | Likvidit varat | 19.64 | 9.65 | 10.70 | 12.13 | 5.39 | 1.10 | 6.29 | 12.42 | 18.03 | 3.95 |
17 | Toiminnan laajuus | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
18 | Liikevaihto | 187.71 | 153.57 | 198.81 | 194.01 | 97.89 | 59.81 | 80.26 | 198.69 | 153.66 | 128.64 |
19 | Liikevaihdon muutos, % | 8.71 | -18.19 | 29.46 | -2.41 | -49.54 | -38.91 | 34.20 | 147.57 | -22.67 | -16.28 |
20 | Ulkomaantoiminta, % | 96.96 | 97.01 | 96.80 | 96.94 | 100.00 | 99.17 | 99.85 | 100.00 | 100.00 | 0.00 |
21 | Oikaistun taseen loppusumma | 267.00 | 260.24 | 259.94 | 258.61 | 231.12 | 142.59 | 146.35 | 159.76 | 162.34 | 161.60 |
22 | Investoinnit | 7.99 | 2.80 | 7.70 | 7.70 | 4.62 | 1.16 | 0.84 | 2.12 | 2.97 | 5.80 |
23 | Investointiaste, % | 4.26 | 1.82 | 3.87 | 3.97 | 4.71 | 1.93 | 1.04 | 1.07 | 1.93 | 4.51 |
24 | Henkilöstö keskimäärin | 742.00 | 779.00 | 915.00 | 932.00 | 1022.00 | 747.00 | 567.00 | 545.00 | 599.00 | 594.00 |
25 | Kannattavuus | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
26 | Käyttökate | 17.19 | 5.48 | 17.97 | -1.02 | -5.43 | -4.05 | 5.94 | 53.75 | 16.59 | 2.61 |
27 | Liiketulos | 9.89 | -1.01 | 11.40 | -7.55 | -9.05 | -6.68 | 3.85 | 52.29 | 15.03 | -0.15 |
28 | Nettotulos | 7.76 | -2.80 | 5.19 | -12.04 | -6.07 | -6.13 | -2.36 | 44.71 | 10.00 | -7.22 |
29 | Kokonaistulos | 8.54 | -0.94 | 6.71 | -18.58 | -58.88 | -21.57 | 9.01 | 47.60 | 10.00 | -7.22 |
30 | Sijoitetun pääoman tuotto, % | 5.92 | -0.02 | 6.85 | -3.76 | -1.11 | -6.16 | 13.14 | 59.84 | 14.66 | -0.13 |
31 | Oman pääoman tuotto, % | 4.39 | -1.61 | 2.98 | -7.45 | -5.38 | -11.75 | -6.44 | 60.33 | 9.50 | -6.63 |
32 | Kokonaispääoman tuotto, % | 4.04 | -0.01 | 4.79 | -2.61 | -0.70 | -3.53 | 7.32 | 36.94 | 9.82 | -0.09 |
33 | Vakavaraisuus | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
34 | Omavaraisuusaste, % | 64.15 | 67.75 | 66.31 | 58.33 | 32.25 | 20.90 | 29.68 | 65.59 | 65.14 | 69.35 |
35 | Nettovelkaantumisaste, % | -2.65 | -3.32 | 0.72 | 8.15 | 73.95 | 161.77 | 74.18 | -9.76 | -14.13 | -1.19 |
36 | Korollinen nettovelka | -4.54 | -5.86 | 1.24 | 12.30 | 55.12 | 48.22 | 32.22 | -10.22 | -14.95 | -1.34 |
37 | Nettorah.kulut/liikevaihto, % | 1.79 | 1.39 | 3.60 | 2.29 | 3.86 | 7.12 | 4.91 | 1.56 | 2.00 | 4.00 |
38 | Nettorah.kulut/käyttökate, % | 19.59 | 38.83 | 39.83 | 999.90 | 999.90 | 999.90 | 66.40 | 5.78 | 18.48 | 197.58 |
39 | Vieraan pääoman tak.maksuaika | -0.30 | -1.59 | 0.11 | 999.90 | 999.90 | 999.90 | 999.90 | -0.22 | -1.29 | -999.90 |
40 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
41 | © Alma Talent Tietopalvelut | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
42 | Tiedot on tarkoitettu käytettäväksi vain asiak... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
43 | Tietojen osittainenkin jälleenlevittäminen ja ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
44 | Tietojen käytöstä mahdollisissa tutkimusprojek... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
# Huomataan, että tiedoston lopussa on turhia osasia. Poistetaan ne rivi-indeksien avulla.
data = data.drop([40, 41, 42, 43, 44])
# Siistitään samalla nimisaraketta hieman
data = data.rename(columns = {"Afarak Group Oyj": "Afarak_Group_Oyj"})
# Tarkastetaan, että tulos näyttää oikealta.
data
Afarak_Group_Oyj | 12/2015 | 12/2016 | 12/2017 | 12/2018 | 12/2019 | 12/2020 | 12/2021 | 12/2022 | 12/2023 | 12/2024 | |
---|---|---|---|---|---|---|---|---|---|---|---|
0 | Sijoittajan tunnuslukuja | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
1 | Markkina-arvo (P) | 103.52 | 202.25 | 220.73 | 189.94 | 126.33 | 54.94 | 34.49 | 91.00 | 104.20 | 80.34 |
2 | Tasesubstanssi ilman väh.os. (B) | 167.36 | 172.04 | 171.40 | 150.48 | 67.31 | 27.54 | 44.24 | 105.71 | 106.05 | 112.05 |
3 | Yritysarvo (EV) | 98.98 | 196.39 | 221.97 | 202.24 | 181.45 | 103.16 | 66.72 | 80.78 | 89.25 | 79.00 |
4 | Tulos (E) | 8.07 | -2.48 | 4.74 | -11.51 | -4.76 | -2.23 | -2.20 | 44.83 | 9.45 | -7.57 |
5 | P/B-luku | 0.62 | 1.18 | 1.29 | 1.26 | 1.88 | 2.00 | 0.78 | 0.86 | 0.98 | 0.72 |
6 | P/S-luku | 0.55 | 1.32 | 1.11 | 0.98 | 1.29 | 0.92 | 0.43 | 0.46 | 0.68 | 0.63 |
7 | P/E-luku | 12.83 | -81.69 | 46.55 | -16.50 | -26.52 | -24.64 | -15.66 | 2.03 | 11.03 | -10.61 |
8 | EV/EBIT-luku | 10.01 | -194.45 | 19.47 | -26.79 | -20.05 | -15.45 | 17.31 | 1.55 | 5.94 | -541.12 |
9 | Tulos/osake (EPS), euroa | 0.03 | -0.01 | 0.02 | -0.04 | -0.02 | -0.01 | -0.01 | 0.18 | 0.36 | -0.03 |
10 | Tulorahoitus/osake (CPS), euroa | 0.06 | 0.01 | 0.05 | -0.02 | -0.01 | -0.01 | 0.00 | 0.18 | 0.44 | -0.02 |
11 | Oma pääoma/osake, euroa | 0.65 | 0.66 | 0.66 | 0.58 | 0.28 | 0.12 | 0.18 | 0.41 | 0.41 | 0.43 |
12 | Osinko/kokonaistulos, % | 58.46 | 999.90 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 | 0.00 |
13 | Maksuvalmius | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
14 | Quick Ratio | 1.80 | 1.72 | 1.74 | 1.12 | 0.46 | 0.50 | 0.94 | 1.91 | 1.73 | 1.62 |
15 | Current Ratio | 3.14 | 3.50 | 3.19 | 2.18 | 0.88 | 0.92 | 1.25 | 3.07 | 2.96 | 3.24 |
16 | Likvidit varat | 19.64 | 9.65 | 10.70 | 12.13 | 5.39 | 1.10 | 6.29 | 12.42 | 18.03 | 3.95 |
17 | Toiminnan laajuus | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
18 | Liikevaihto | 187.71 | 153.57 | 198.81 | 194.01 | 97.89 | 59.81 | 80.26 | 198.69 | 153.66 | 128.64 |
19 | Liikevaihdon muutos, % | 8.71 | -18.19 | 29.46 | -2.41 | -49.54 | -38.91 | 34.20 | 147.57 | -22.67 | -16.28 |
20 | Ulkomaantoiminta, % | 96.96 | 97.01 | 96.80 | 96.94 | 100.00 | 99.17 | 99.85 | 100.00 | 100.00 | 0.00 |
21 | Oikaistun taseen loppusumma | 267.00 | 260.24 | 259.94 | 258.61 | 231.12 | 142.59 | 146.35 | 159.76 | 162.34 | 161.60 |
22 | Investoinnit | 7.99 | 2.80 | 7.70 | 7.70 | 4.62 | 1.16 | 0.84 | 2.12 | 2.97 | 5.80 |
23 | Investointiaste, % | 4.26 | 1.82 | 3.87 | 3.97 | 4.71 | 1.93 | 1.04 | 1.07 | 1.93 | 4.51 |
24 | Henkilöstö keskimäärin | 742.00 | 779.00 | 915.00 | 932.00 | 1022.00 | 747.00 | 567.00 | 545.00 | 599.00 | 594.00 |
25 | Kannattavuus | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
26 | Käyttökate | 17.19 | 5.48 | 17.97 | -1.02 | -5.43 | -4.05 | 5.94 | 53.75 | 16.59 | 2.61 |
27 | Liiketulos | 9.89 | -1.01 | 11.40 | -7.55 | -9.05 | -6.68 | 3.85 | 52.29 | 15.03 | -0.15 |
28 | Nettotulos | 7.76 | -2.80 | 5.19 | -12.04 | -6.07 | -6.13 | -2.36 | 44.71 | 10.00 | -7.22 |
29 | Kokonaistulos | 8.54 | -0.94 | 6.71 | -18.58 | -58.88 | -21.57 | 9.01 | 47.60 | 10.00 | -7.22 |
30 | Sijoitetun pääoman tuotto, % | 5.92 | -0.02 | 6.85 | -3.76 | -1.11 | -6.16 | 13.14 | 59.84 | 14.66 | -0.13 |
31 | Oman pääoman tuotto, % | 4.39 | -1.61 | 2.98 | -7.45 | -5.38 | -11.75 | -6.44 | 60.33 | 9.50 | -6.63 |
32 | Kokonaispääoman tuotto, % | 4.04 | -0.01 | 4.79 | -2.61 | -0.70 | -3.53 | 7.32 | 36.94 | 9.82 | -0.09 |
33 | Vakavaraisuus | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
34 | Omavaraisuusaste, % | 64.15 | 67.75 | 66.31 | 58.33 | 32.25 | 20.90 | 29.68 | 65.59 | 65.14 | 69.35 |
35 | Nettovelkaantumisaste, % | -2.65 | -3.32 | 0.72 | 8.15 | 73.95 | 161.77 | 74.18 | -9.76 | -14.13 | -1.19 |
36 | Korollinen nettovelka | -4.54 | -5.86 | 1.24 | 12.30 | 55.12 | 48.22 | 32.22 | -10.22 | -14.95 | -1.34 |
37 | Nettorah.kulut/liikevaihto, % | 1.79 | 1.39 | 3.60 | 2.29 | 3.86 | 7.12 | 4.91 | 1.56 | 2.00 | 4.00 |
38 | Nettorah.kulut/käyttökate, % | 19.59 | 38.83 | 39.83 | 999.90 | 999.90 | 999.90 | 66.40 | 5.78 | 18.48 | 197.58 |
39 | Vieraan pääoman tak.maksuaika | -0.30 | -1.59 | 0.11 | 999.90 | 999.90 | 999.90 | 999.90 | -0.22 | -1.29 | -999.90 |
3. Analyysi#
Lähdetään tarkastelemaan ensin yhden muuttujan kohdalla miten rivistä saadaan yksinkertainen kuvaaja ulos ennen kuin alamme laskemaan niistä tarkempia lukuja.
# Määritetään mitä riviä halutaan tarkastella.
ehto = "Nettovelkaantumisaste, %"
# Kyseisen rivin aineistot halutaan y-akselille, joten tehdään niistä lista.
pysty = data.query('Afarak_Group_Oyj == @ehto')
pysty = pysty.iloc[0][1:].tolist()
# Käytetään vaaka-akselina sarakeotsikoiden päiväyksiä.
vaaka = data.columns[1:].tolist()
# Piirretään kuvaajat.
plt.figure(figsize = (10,5))
plt.plot(vaaka, pysty, c = "y")
plt.scatter(vaaka, pysty, c = "firebrick")
# Koristellaan kuvaaja soveltuvilla selitteillä.
plt.title(ehto)
plt.xticks(rotation = 30)
plt.show()

Tyypillisesti meitä kiinnostaa erilaisten keskiarvojen tai poikkeamien laskeskelu. Yksi tapa tehdä näin on käyttää numpy-kirjaston mean()-käskyä, joka soveltuu lista-tyyppisten muuttujien käsittelyyn.
print(f"Keskiarvo muuttujalle {ehto} on : " + str(np.mean(pysty)))
Keskiarvo muuttujalle Nettovelkaantumisaste, % on : 28.772000000000002
Voisimme tietysti yhdistää useamman eri muuttujan keskiarvoineen samaan kuvaajaan helpottamaan vertailutyötämme.
# Määritetään mitä riviä halutaan tarkastella.
ehto1 = "P/E-luku"
ehto2 = "EV/EBIT-luku"
# Kyseisten rivien aineistot halutaan y-akselille, joten tehdään niistä listat.
y1 = data.query('Afarak_Group_Oyj == @ehto1')
y1 = y1.iloc[0][1:].tolist()
y2 = data.query('Afarak_Group_Oyj == @ehto2')
y2 = y2.iloc[0][1:].tolist()
# Käytetään vaaka-akselina sarakeotsikoiden päiväyksiä.
vaaka = data.columns[1:].tolist()
# Lasketaan kummankin muuttujan keskiarvot.
KA1 = np.mean(y1)
KA2 = np.mean(y2)
# Piirretään kuvaajat.
plt.figure(figsize = (10,5))
plt.plot(vaaka, y1, c = "y")
plt.scatter(vaaka, y1, c = "firebrick", label = f"{ehto1}, keskiarvo {str(KA1)}")
plt.plot(vaaka, y2, c = "slateblue")
plt.scatter(vaaka, y2, c = "navy", label = f"{ehto2}, keskiarvo {str(KA2)}")
# Piirretään vielä keskiarvotkin mukaan.
plt.axhline(y = KA1, color = 'wheat', linestyle = 'dashed')
plt.axhline(y = KA2, color = 'lightsteelblue', linestyle = 'dashed')
# Koristellaan kuvaaja soveltuvilla selitteillä.
plt.title(f"Vertailussa {ehto1} ja {ehto2} \n", fontsize = 20)
plt.xticks(rotation = 30)
plt.legend()
plt.show()

Ylläolevasta kuvasta voi miettiä miten hyvä työkalu koko kymmenvuotisen kauden keskiarvo on kuvaamaan yrityksen yleistä tilaa tai muutosta. Tähän tarkoitukseen voisi käyttää jotakin sopivampaa, kuten trendiviivaa.
# Sovitetaan äskeisiin havaintoihin yleiskuvaa tasoittava trendiviiva.
plt.figure(figsize = (10, 5))
# Aineisto y2.
plt.scatter(vaaka, y2, c = "navy", label = f"{ehto2}, keskiarvo {str(KA2)}")
# Trendi.
x = np.arange(len(vaaka))
y = y2.copy()
# Tästä lukua vaihtamalla voi muuttaa sovitetun yhtälön astetta.
z = np.polyfit(x, y, 3)
p = np.poly1d(z)
plt.plot(vaaka, p(x), c = "black", linestyle = "dashed", label = f"{ehto2}", alpha = 0.7)
# Selitteet.
plt.legend(loc = "lower left")
plt.title(f"{ehto2} \n", fontsize = 20)
plt.xticks(rotation = 30)
plt.show()

Ideoita omiin testailuihin#
Kauppalehden sivuilta voit etsiä eri yrityksiä ja yhtiöitä oman mielenkiintosi mukaan. Niiden aineistoista voisi kysyä esimerkiksi seuraavia:
Liikevaihdon ja tuloksen keskimääräinen kasvuprosentti viideltä ja kymmeneltä vuodelta.
Viiden vuoden ja 10 vuoden keskiarvo P/E-luvulle sekä EV/EBIT-luvulle, niiden vertaaminen nykyisiin P/E- ja EV/EBIT-lukuihin.
Oman pääoman tuottoprosentin suhde P/B-lukuun sekä näistä viiden ja 10 vuoden keskiarvo.
Sijoitetun pääoman tuotto, viiden ja 10 vuoden keskiarvo.
Nettovelkaantumisaste yleisesti.