131 lines
5.8 KiB
Python
131 lines
5.8 KiB
Python
import pandas as pd
|
|
import numpy as np
|
|
|
|
class FinancialTools:
|
|
@staticmethod
|
|
def calculate_returns(prices_series, in_percent=True): # <-- NEUER PARAMETER HIER!
|
|
"""Berechnet die täglichen Renditen."""
|
|
if prices_series.empty:
|
|
return pd.Series(dtype='float64')
|
|
if isinstance(prices_series, pd.DataFrame):
|
|
if 'adj_close' in prices_series.columns:
|
|
prices_series = prices_series['adj_close']
|
|
elif 'close' in prices_series.columns:
|
|
prices_series = prices_series['close']
|
|
else:
|
|
return pd.Series(dtype='float64')
|
|
|
|
returns = prices_series.pct_change().dropna()
|
|
if in_percent:
|
|
return returns * 100 # Für die Anzeige in Prozent
|
|
return returns # Für interne Berechnungen (Dezimalwerte)
|
|
|
|
@staticmethod
|
|
def calculate_cumulative_returns(prices_series):
|
|
"""Berechnet die kumulativen Renditen."""
|
|
if prices_series.empty:
|
|
return pd.Series(dtype='float64')
|
|
# HIER: Rufe calculate_returns mit in_percent=False auf, um Dezimalwerte zu bekommen
|
|
daily_returns_raw = FinancialTools.calculate_returns(prices_series, in_percent=False)
|
|
if daily_returns_raw.empty:
|
|
return pd.Series(dtype='float64')
|
|
return (1 + daily_returns_raw).cumprod() - 1
|
|
|
|
@staticmethod
|
|
def calculate_moving_average(prices_series, window=20):
|
|
"""Berechnet den gleitenden Durchschnitt."""
|
|
if prices_series.empty:
|
|
return pd.Series(dtype='float64')
|
|
if isinstance(prices_series, pd.DataFrame):
|
|
if 'adj_close' in prices_series.columns:
|
|
prices_series = prices_series['adj_close']
|
|
elif 'close' in prices_series.columns:
|
|
prices_series = prices_series['close']
|
|
else:
|
|
return pd.Series(dtype='float64')
|
|
|
|
return prices_series.rolling(window=window).mean()
|
|
|
|
|
|
@staticmethod
|
|
def calculate_volatility(prices_series, window=20):
|
|
"""Berechnet die rollierende Volatilität (Standardabweichung der Renditen)."""
|
|
if prices_series.empty:
|
|
return pd.Series(dtype='float64')
|
|
|
|
# HIER: Rufe calculate_returns mit in_percent=False auf, um Dezimalwerte zu bekommen
|
|
daily_returns_for_vol = FinancialTools.calculate_returns(prices_series, in_percent=False)
|
|
|
|
if daily_returns_for_vol.empty:
|
|
return pd.Series(dtype='float64')
|
|
|
|
# Annualisiere die Volatilität
|
|
return daily_returns_for_vol.rolling(window=window).std() * np.sqrt(252)
|
|
|
|
|
|
@staticmethod
|
|
def calculate_beta(stock_prices, market_prices, window=60):
|
|
"""
|
|
Berechnet das rollierende Beta eines Wertpapiers relativ zu einem Marktindex.
|
|
stock_prices: Pandas Series der Aktie
|
|
market_prices: Pandas Series des Marktindex
|
|
"""
|
|
if stock_prices.empty or market_prices.empty:
|
|
return pd.Series(dtype='float64')
|
|
|
|
# Sicherstellen, dass es Series sind, falls doch DataFrames übergeben werden
|
|
if isinstance(stock_prices, pd.DataFrame):
|
|
if 'adj_close' in stock_prices.columns:
|
|
stock_prices = stock_prices['adj_close']
|
|
elif 'close' in stock_prices.columns:
|
|
stock_prices = stock_prices['close']
|
|
else:
|
|
return pd.Series(dtype='float64')
|
|
|
|
if isinstance(market_prices, pd.DataFrame):
|
|
if 'adj_close' in market_prices.columns:
|
|
market_prices = market_prices['adj_close']
|
|
elif 'close' in market_prices.columns:
|
|
market_prices = market_prices['close']
|
|
else:
|
|
return pd.Series(dtype='float64')
|
|
|
|
# HIER: Rufe calculate_returns mit in_percent=False auf, um Dezimalwerte zu bekommen
|
|
returns_stock = FinancialTools.calculate_returns(stock_prices, in_percent=False)
|
|
returns_market = FinancialTools.calculate_returns(market_prices, in_percent=False)
|
|
|
|
# Kombiniere die Renditen und richte sie an den Daten aus
|
|
combined_returns = pd.concat([returns_stock.rename('stock'), returns_market.rename('market')], axis=1).dropna()
|
|
|
|
if combined_returns.empty:
|
|
return pd.Series(dtype='float64')
|
|
|
|
# Berechne die rollierende Kovarianz und Varianz
|
|
rolling_covariance = combined_returns['stock'].rolling(window=window).cov(combined_returns['market'])
|
|
rolling_variance = combined_returns['market'].rolling(window=window).var()
|
|
|
|
# Berechne Beta
|
|
beta = rolling_covariance / rolling_variance
|
|
return beta.dropna()
|
|
|
|
# Beispielnutzung (für Tests) - Muss an die neuen Funktionssignaturen angepasst werden
|
|
if __name__ == "__main__":
|
|
# Erzeuge fiktive Daten für Tests
|
|
dates = pd.to_datetime(pd.date_range(start='2023-01-01', periods=100))
|
|
stock_prices_series = pd.Series(np.random.rand(100) * 100 + 50, index=dates) # direkt als Series
|
|
market_prices_series = pd.Series(np.random.rand(100) * 10 + 200, index=dates) # direkt als Series
|
|
|
|
print("Tägliche Renditen (in Prozent):")
|
|
print(FinancialTools.calculate_returns(stock_prices_series, in_percent=True).head()) # Für Anzeige
|
|
|
|
print("\nKumulative Renditen (Dezimal):")
|
|
print(FinancialTools.calculate_cumulative_returns(stock_prices_series).head())
|
|
|
|
print("\nGleitender 20-Tage-Durchschnitt:")
|
|
print(FinancialTools.calculate_moving_average(stock_prices_series, window=20).head())
|
|
|
|
print("\nRollierende 20-Tage-Volatilität (annualisiert, Dezimal):")
|
|
print(FinancialTools.calculate_volatility(stock_prices_series, window=20).head())
|
|
|
|
print("\nRollierendes 60-Tage-Beta (Aktie vs. Markt, Dezimal):")
|
|
print(FinancialTools.calculate_beta(stock_prices_series, market_prices_series, window=60).head()) |