In einem früheren Artikel habe ich gezeigt, wie ich die 200-Tageslinie mit einem Python-Script und der Stooq-API berechne. Das Script funktionierte – aber es lief lokal, die Daten mussten manuell aktualisiert werden, und die Ergebnisse verschwanden, sobald das Terminal geschlossen wurde. Der nächste logische Schritt war klar: eine vollwertige Web-App.
Entstanden ist ein Django-Dashboard für Aktienanalyse mit OHLC-Charts, automatischer täglicher Datenpflege und Portfolio-Tracking – selbst gehostet, ohne Cloud-Abhängigkeiten.
Architektur im Überblick
- Datenmodell:
Stock(Symbol, Name),StockDailyMetrics(OHLC-Daten pro Tag),AccountundTransactionfür Portfolio-Tracking - Datenpflege: APScheduler läuft täglich früh morgens und aktualisiert alle Aktien automatisch
- Frontend: Django-Templates mit Chart.js für OHLC-Visualisierung
Datenabruf mit yfinance und curl_cffi
yfinance ist die einfachste Möglichkeit, historische Kursdaten kostenlos zu beziehen. Das Problem: Yahoo Finance blockiert reguläre Requests mit 429-Fehlern. Die Lösung ist Browser-Impersonation über curl_cffi:
import yfinance as yf
from curl_cffi import requests as cffi_requests
session = cffi_requests.Session(impersonate="chrome")
ticker = yf.Ticker(symbol, session=session)
hist = ticker.history(period="2y")
for date, row in hist.iterrows():
StockDailyMetrics.objects.update_or_create(
stock=stock,
date=date.date(),
defaults={
"open": row["Open"],
"high": row["High"],
"low": row["Low"],
"close": row["Close"],
"volume": row["Volume"],
}
)APScheduler: Automatische Updates ohne Celery
Für wiederkehrende Hintergrundaufgaben in Django gibt es zwei verbreitete Ansätze: Celery (mächtig, aber komplex) und APScheduler (einfach, kein Redis nötig). Für diesen Anwendungsfall reicht APScheduler vollständig:
from apscheduler.schedulers.background import BackgroundScheduler
from django.apps import AppConfig
import os
class StockAnalysisConfig(AppConfig):
def ready(self):
# Verhindert Doppelstart im Django Dev-Server
if os.environ.get("RUN_MAIN") != "true":
return
scheduler = BackgroundScheduler(timezone="Europe/Berlin")
scheduler.add_job(
refresh_all_stocks,
"cron",
hour=3, minute=10,
id="daily_stock_refresh",
replace_existing=True,
)
scheduler.start()Der RUN_MAIN-Check ist wichtig: Django startet ready() zweimal im Development-Server – ohne diese Prüfung würde der Scheduler doppelt starten.
Die 200-Tageslinie im Dashboard
Die 200-Tageslinie wird dynamisch aus den vorhandenen Schlusskursen berechnet:
def calculate_sma200(stock):
closes = list(
StockDailyMetrics.objects
.filter(stock=stock)
.order_by("date")
.values_list("close", flat=True)
)
if len(closes) < 200:
return None
return sum(closes[-200:]) / 200Im Chart wird die SMA-200-Linie als horizontale Referenzlinie eingezeichnet. Liegt der aktuelle Kurs darunter, ist die Aktie laut dieser Metrik im Abwärtstrend.
Portfolio-Tracking
Das Account-Modell repräsentiert ein Broker-Konto, Transaction speichert Käufe und Verkäufe. Daraus wird der aktuelle Depotwert gegen den Einstandspreis berechnet und als Performance-Chart dargestellt.
Fazit
Das Dashboard hat mein Python-Script vollständig ersetzt. Die tägliche Automatisierung bedeutet, dass ich morgens aktuelle Daten vorfinde, ohne etwas tun zu müssen. Alle Daten liegen lokal in SQLite – keine API-Kosten, keine Datenschutzbedenken, vollständige Kontrolle.
Das Dashboard ist Teil dieser Website und unter Aktienanalyse einsehbar. Fragen zur Umsetzung gerne über das Kontaktformular.