Aktien nach Fundamentaldaten bewerten | Schritt für Schritt mit Python

Für eine Kaufentscheidung ist es wichtig Aktien zu bewerten.
In dem Artikel soll es genau darum gehen.
Du wirst dir deine eigenen Bewertungskriterien und Gewichtungen festlegen.

Am Ende erhältst du eine Excel Datei mit deinen Daten zu deinen Aktien.
Sortiert nach deiner Bewertung.

Du weißt nicht, was du mit den Dateien machen sollst?
Hier findest du Hilfe.

Vorbereitung

Hier findest du den Einstieg in die Serie:

Den Teil mit Listen habe ich aus dem Code entfernt.
Mit Dictionaries lässt sich einfach besser arbeiten.

%pip install yfinance openpyxl

import yfinance, json, openpyxl

# Microsoft, AMD, Apple, RWE
symbols = ['MSF.DE', 'AMD.DE', 'APC.DE', 'RWE.DE']
stock_data = {}


for symbol in symbols:
  print(f'Daten für {symbol} werden abgefragt...')
  stock = yfinance.Ticker(symbol)
  info = stock.info

  # Aktieninformationen als Dictionary
  data = {
      'Aktueller Preis': info['regularMarketPrice'],
      '52-Wochen-Hoch': info['fiftyTwoWeekHigh'],
      '52-Wochen-Tief': info['fiftyTwoWeekLow'],
      'Unternehmenswert / EBITDA': info['enterpriseToEbitda'],
      'Durchschnittliche Dividendenrendite über 5 Jahre': info['fiveYearAvgDividendYield'],
      'Eigenkapitalrendite': info['returnOnEquity'],
      'Schulden / Equity (gesamt) (mrq)': info['debtToEquity']
  }
  stock_data[symbol] = data

print(json.dumps(stock_data, indent=4, ensure_ascii=False))
print('Daten in Excel Datei schreiben...')

workbook = openpyxl.Workbook()
sheet_dictionary = workbook.active
sheet_dictionary.title = 'Daten als Dictionary'

header = ['Symbol',	'Aktueller Preis',	'52-Wochen-Hoch', '52-Wochen-Tief',	'Unternehmenswert / EBITDA',	'Durchschnittliche Dividendenrendite über 5 Jahre',	'Eigenkapitalrendite',	'Schulden / Equity (gesamt) (mrq)']
sheet_dictionary.append(header)

for key, value in stock_data.items():
  line = []
  line.append(key)
  line.extend(list(value.values()))
  sheet_dictionary.append(line)

workbook.save('test.xlsx')

print('Fertig!')

Code Strukturieren

Je mehr Logik in den Code kommt, desto unübersichtlicher wird alles.
Es ist also an der Zeit die ersten Umstrukturierungen vorzunehmen.

Logisch sind hier zwei Blöcke im Code:

  • Daten sammeln
  • Daten in Excel schreiben

Genau die zwei wollen wir jetzt auch in Blöcken – also in Funktionen – zusammenfassen.

Zwei Namen definiert und einmal eingerückt, schon ist mehr Ordnung da.
Jetzt nur noch in der richtigen Reihenfolge aufrufen.

Mit der Abfrage nach __main__ markierst du den Startpunkt für dein Programm.

%pip install yfinance openpyxl

import yfinance, json, openpyxl

# Microsoft, AMD, Apple, RWE
symbols = ['MSF.DE', 'AMD.DE', 'APC.DE', 'RWE.DE']
stock_data = {}


def aktiendaten_sammeln():
  for symbol in symbols:
    print(f'Daten für {symbol} werden abgefragt...')
    stock = yfinance.Ticker(symbol)
    info = stock.info

    # Aktieninformationen als Dictionary
    data = {
        'Aktueller Preis': info['regularMarketPrice'],
        '52-Wochen-Hoch': info['fiftyTwoWeekHigh'],
        '52-Wochen-Tief': info['fiftyTwoWeekLow'],
        'Unternehmenswert / EBITDA': info['enterpriseToEbitda'],
        'Durchschnittliche Dividendenrendite über 5 Jahre': info['fiveYearAvgDividendYield'],
        'Eigenkapitalrendite': info['returnOnEquity'],
        'Schulden / Equity (gesamt) (mrq)': info['debtToEquity']
    }
    stock_data[symbol] = data


def daten_in_excel_schreiben():
  print('Daten in Excel Datei schreiben...')

  workbook = openpyxl.Workbook()
  sheet_dictionary = workbook.active
  sheet_dictionary.title = 'Daten als Dictionary'

  header = ['Symbol',	'Aktueller Preis',	'52-Wochen-Hoch', '52-Wochen-Tief',	'Unternehmenswert / EBITDA',	'Durchschnittliche Dividendenrendite über 5 Jahre',	'Eigenkapitalrendite',	'Schulden / Equity (gesamt) (mrq)', 'Punkte']
  sheet_dictionary.append(header)

  for key, value in stock_data.items():
    line = []
    line.append(key)
    line.extend(list(value.values()))
    sheet_dictionary.append(line)

  workbook.save('test.xlsx')

  print('Fertig!')


if __name__ == '__main__':
  aktiendaten_sammeln()
  daten_in_excel_schreiben()

Wunderbar.
Weiter gehts mit der Bewertung.

Bewertungskriterien definieren

Du hast jetzt ein paar Informationen über die Aktie gesammelt.
Aber nicht alle Informationen sind dir gleichermaßen wichtig.

Du musst also erstmal festlegen wie wichtig welche Information ist.
Dafür überlegen wir uns ein einfaches Regelwerk nach Punkten.

Mir sind ein paar Punkte wichtig:

  • Hohe Eigenkapitalrendite (>= 50%)
  • Niedrige Schulden (<= 50%)
  • Niedrige Bewertung (<= 25) – Unternehmenswert / EBITDA
  • Dividende (>= 1%)

Für jedes erfüllte Kriterium bekommt das Unternehmen einen Punkt.
Manche Punkte sind allerdings wichtiger als andere.

Deshalb vergebe ich die Punkte gewichtet.

  • Hohe Eigenkapitalrendite = 3 Punkte
  • Niedrige Schulden = 2 Punkte
  • Niedrige Bewertung = 1 Punkt
  • Dividende = 1 Punkt

Diese Regeln kann ich ganz einfach in Code fließen lassen.
Dafür baue ich eine neue Funktion und lass mir die Punkte einfach ermitteln.

Aktien bewerten

Am Ende kommen die Punkte als zusätzlicher Eintrag in das Dictionary.
Damit werden sie dann auch automatisch mit in die Datei geschrieben.
Du musst lediglich die Variable header erweitern. Dann wird auch die Kopfzeile korrekt dazu geschrieben.

def punkte_ermitteln():
  for stock, info in stock_data.items():
    points = 0
    if info['Eigenkapitalrendite'] is not None and info['Eigenkapitalrendite'] >= 0.5:
      points += 3
    if info['Schulden / Equity (gesamt) (mrq)'] is not None and info['Schulden / Equity (gesamt) (mrq)'] <= 50:
      points += 2
    if info['Unternehmenswert / EBITDA']is not None and info['Unternehmenswert / EBITDA'] <= 25:
      points += 1
    if info['Durchschnittliche Dividendenrendite über 5 Jahre'] is not None and info['Durchschnittliche Dividendenrendite über 5 Jahre'] >= 1:
      points += 1

    info['Punkte'] = points

if __name__ == '__main__':
  aktiendaten_sammeln()
  punkte_ermitteln()
  daten_in_excel_schreiben()

Mit jeder neuen Auswertung die Kopfzeile anpassen?
Das ist auch nicht so schön.

Dann lass uns das doch als nächstes gleich automatisieren.
Immerhin sind die Namen im Dictionary schon schön sprechend.

Dafür nimmst du beim Sammeln der Aktien direkt das Symbol mit in die Daten auf:

def aktiendaten_sammeln():
  for symbol in symbols:
    print(f'Daten für {symbol} werden abgefragt...')
    stock = yfinance.Ticker(symbol)
    info = stock.info

    # Aktieninformationen als Dictionary
    data = {
        'Symbol': symbol,
        'Aktueller Preis': info['regularMarketPrice'],
        '52-Wochen-Hoch': info['fiftyTwoWeekHigh'],
        '52-Wochen-Tief': info['fiftyTwoWeekLow'],
        'Unternehmenswert / EBITDA': info['enterpriseToEbitda'],
        'Durchschnittliche Dividendenrendite über 5 Jahre': info['fiveYearAvgDividendYield'],
        'Eigenkapitalrendite': info['returnOnEquity'],
        'Schulden / Equity (gesamt) (mrq)': info['debtToEquity']
    }
    stock_data[symbol] = data

if __name__ == '__main__':
  aktiendaten_sammeln()
  punkte_ermitteln()
  daten_in_excel_schreiben()

Dann musst du nur noch den header aus dem Dictionary entnehmen:

def daten_in_excel_schreiben():
  print('Daten in Excel Datei schreiben...')

  workbook = openpyxl.Workbook()
  sheet_dictionary = workbook.active
  sheet_dictionary.title = 'Daten als Dictionary'

  header = list(list(stock_data.values())[0].keys())
  sheet_dictionary.append(header)

  for key, value in stock_data.items():
    sheet_dictionary.append(list(value.values()))

  workbook.save('test.xlsx')

  print('Fertig!')

if __name__ == '__main__':
  aktiendaten_sammeln()
  punkte_ermitteln()
  daten_in_excel_schreiben()

Das sollte ich vielleicht ein wenig erklären: Bei einem Dictionary hast du im Grunde 3 Möglichkeiten.
Du kannst mit items() immer ein Paar aus Schlüssel (key) und Wert (value) bekommen.
Oder du fragst mit keys() bzw. values() direkt nur die Schlüssel oder die Werte ab.

Diese Werte kommen allerdings immer als Dictionary Eintrag / Schlüssel / Wert Objekt.
Nicht als Liste.
Deswegen brauchst du hier das Python BuiltIn list().
Damit wandelst du das Objekt einmal in eine Liste um.
Und schon kannst du auf die einzelnen Einträge zugreifen.

Unser stock_data ist ein Dictionary mit dem Symbol als Schlüssel. Als Wert hat es wieder ein Dictionary für jede einzelne Aktie.

Die Kopfzeile für die Excel Datei bekommst du aus den Schlüsseln der einzelnen Aktien Einträge.

Deshalb zuerst mit stock_data.values() auf ein einzelnes Aktien-Dictionary zugreifen.
Bzw. mit list(stock_data_values()) in eine Liste umwandeln.
Anschließend über den Index auf das erste Einzel-Aktien-Dictionary zugreifen.

An diesem Aktien-Dictionary rufst du keys() auf.
Immhin willst du ja die Schlüssel aus genau diesem Dictionary als header.
Das noch einmal mit list() umgewandelt und schon hast du deinen header.

Abschließend nur nicht vergessen den ersten Eintrag aus der Schleife zu entfernen.
Wir hatten in der for-Schleife manuell das Symbol als erste Spalte gesetzt.
Das Symbol ist jetzt Teil der Daten.
Damit kannst du den Schritt entfernen und die Zeile direkt schreiben.

Aktien nach Bewertung sortieren

Damit haben wir jetzt eine schöne Bewertung und Priorisierung geschaffen.
Die möchte natürlich auch genutzt werden!

Manuell alle Zeilen durchsehen und die höchste Punktzahl auslesen ist zu anstrengend.
Dafür gibt es doch Sortierungen.

Sortieren mit openpyxl

Die Bibliothek openpyxl ist nur eine Hilfe, um mit Excel zu reden.
Das heißt, du kannst damit zwar sortieren, allerdings nicht direkt.
Du kannst lediglich eine Excel-Sortierung erstellen.

Besser als nichts!
Wollen wir das jetzt trotzdem einmal machen?

Da es sich um eine Excel Funktion handelt, wird die natürlich auch an dem Excel Objekt erstellt.
Du sagst dem Arbeitsblatt also, dass du eine Sortierung zufügen möchtest.

Sortierung ist Teil der Excel Filterung.
Du musst also nur einen Autofilter erzeugen und ihm einen Bereich geben.

Bereiche definierst du genauso wie du es aus Excel gewohnt bist.
Die erste Spalte ist A.
Die zweite Spalte ist B.
Die erste Zeile ist 1.
Die zweite Zeile ist 2.
Und so weiter.

Unser Bereich geht also von A1 bis I5.
Oder auch A1:I5 in Excel Schreibweise.

def daten_in_excel_schreiben():
  print('Daten in Excel Datei schreiben...')

  workbook = openpyxl.Workbook()
  sheet_dictionary = workbook.active
  sheet_dictionary.title = 'Daten als Dictionary'

  header = list(list(stock_data.values())[0].keys())
  sheet_dictionary.append(header)

  for key, value in stock_data.items():
    sheet_dictionary.append(list(value.values()))

  sheet_dictionary.auto_filter.ref = 'A1:I5'

  workbook.save('test.xlsx')

  print('Fertig!')

if __name__ == '__main__':
  aktiendaten_sammeln()
  punkte_ermitteln()
  daten_in_excel_schreiben()

Wenn du eine Aktie hinzufügst, musst du allerdings den Filter anpassen.
Genauso, wenn du eine Spalte zufügst – also weitere Daten aufnimmst.

Das ist auch dämlich…

Zum Glück liefert openpyxl die openpyxl.utils mit.
Eine Funktion ist get_column_letter().
Du übergibst eine Spaltennummer und bekommst dafür den Buchstaben zurück:
1 = A
50 = AX
etc.

Die Anzahl der Spalten kannst du einfach aus dem header entnehmen.

Wie viele Zeilen dein Excel haben wird, weißt du auch.
Das ist die Anzahl der Einträge in deiner symbols Liste plus Kopfzeile.

Damit lässt sich doch was anfangen!

def daten_in_excel_schreiben():
  print('Daten in Excel Datei schreiben...')

  workbook = openpyxl.Workbook()
  sheet_dictionary = workbook.active
  sheet_dictionary.title = 'Daten als Dictionary'

  header = list(list(stock_data.values())[0].keys())
  sheet_dictionary.append(header)

  for key, value in stock_data.items():
    sheet_dictionary.append(list(value.values()))

  # Spalten Buchstabe über die Länge von *header*
  column_letter = openpyxl.utils.get_column_letter(len(header))

  # Länge von *symbols* plus 1x Kopfzeile
  row_number = len(symbols) + 1

  # Bereich mit f-String zusammensetzen
  sheet_dictionary.auto_filter.ref = f'A1:{column_letter}{row_number}'

  workbook.save('test.xlsx')

  print('Fertig!')

if __name__ == '__main__':
  aktiendaten_sammeln()
  punkte_ermitteln()
  daten_in_excel_schreiben()

Heraus kommt ein Excel mit Sortierung über deine Spalten und Zeilen.
Allerdings noch nichts sortiert.
Das musst du in deinem Excel dann selbst machen.

Sortieren mit Python

Schöner wäre doch, wenn die Aktien direkt sortiert, in der Excel landen.

Dafür machst du doch die Bewertung und Priorisierung.
Warum also nochmal händisch sortieren?

def daten_in_excel_schreiben():
  print('Daten in Excel Datei schreiben...')

  workbook = openpyxl.Workbook()
  sheet_dictionary = workbook.active
  sheet_dictionary.title = 'Daten als Dictionary'

  # Aktiendaten sortieren
  sorted_stock_data = sorted(stock_data.items(), reverse=True, key=lambda item: item[1]['Punkte'])

  header = list(list(stock_data.values())[0].keys())  # list(sorted_stock_data[0][1].keys())
  sheet_dictionary.append(header)

  for symbol, stock in sorted_stock_data:
    sheet_dictionary.append(list(stock.values()))

  # Filterung zufügen
  column_letter = openpyxl.utils.get_column_letter(len(header))
  row_number = len(symbols) + 1
  sheet_dictionary.auto_filter.ref = f'A1:{column_letter}{row_number}'

  workbook.save('test.xlsx')

  print('Fertig!')

if __name__ == '__main__':
  aktiendaten_sammeln()
  punkte_ermitteln()
  daten_in_excel_schreiben()

Zum Sortieren steht in Python das BuiltIn sorted() zur Verfügung.

Zuerst gibst du an, was sortiert werden soll.
Die stock_data.items(), also deine Einträge im Dictionary.

Regulär sortiert sorted() alphabetisch.
Also von klein nach groß.
In unserem Fall wollen wir aber die größte Punktzahl ganz oben stehen haben.
Deshalb kommt das Attribut reverse=True mit dazu.
Damit sortieren wir von groß nach klein.

Sorted muss natürlich auch wissen, was es sortieren soll.
Einfach alphabetisch geht natürlich nicht.
Immerhin geben wir mit stock_data.items() ganze Objekte in die Sortierung.

Deshalb brauchst du noch das Attribut key.
Damit kannst du eine Funktion angeben.
Die Funktion muss immer den Wert zurückliefern, nach dem sortiert werden soll.

Da wir die Funktion nur ein einziges Mal brauchen eignet sich lambda perfekt dafür.

Die Funktion in key bekommt also immer ein Item aus dem Dictionary übergeben.
Ein Item im Dictionary besteht aus Schlüssel und Wert.
Schlüssel ist das Aktiensymbol, Wert sind die Aktiendaten.

Mit item[1] greifst du auf den Wert zu. Also die Aktiendaten.
Innerhalb der Aktiendaten möchtest du jetzt die Punkte. Also item[1][‚Punkte‘].
Und schon hast du das Punkteattribut für die Sortierung gewählt.

Abschließend fehlt nur noch die for-Schleife.
Du musst natürlich auch aus der sortierten Liste auslesen.

Tupel werden dir beim iterieren automatisch entpackt. So wie es bei den Dictionary Items auch der Fall ist.
Deshalb musst du eigentlich nur stock_data.items() durch sorted_stock_data ersetzen.

Ich habe zusätzlich noch key und value auf symbol und stock umbenannt.
Einfach um es übersichtlicher zu haben.
Kannst du machen, musst du aber nicht.

Zusammenfassung

Fertig!
Du kannst jetzt deine eigenen Kriterien und Gewichtungen angeben.
Damit Aktien bewerten und entsprechend sortiert in eine Excel Datei schreiben.

Wie viele Aktien du bewertest, liegt an dir.

Viel Erfolg!

Scroll to Top