|
import streamlit as st |
|
import yfinance as yf |
|
import pandas as pd |
|
import plotly.graph_objects as go |
|
import plotly.express as px |
|
from datetime import datetime, timedelta |
|
import base64 |
|
|
|
|
|
st.set_page_config(page_title="JQuant - Marktanalyse", page_icon="📊", layout="wide") |
|
|
|
|
|
def get_base64_image(image_path): |
|
with open(image_path, "rb") as img_file: |
|
return base64.b64encode(img_file.read()).decode() |
|
|
|
|
|
image_base64 = get_base64_image("JQ.png") |
|
|
|
|
|
st.markdown( |
|
f""" |
|
<style> |
|
.fixed-logo {{ |
|
position: fixed; |
|
top: 10px; |
|
left: 50%; |
|
transform: translateX(-50%); |
|
z-index: 1000; |
|
text-align: center; |
|
}} |
|
</style> |
|
<div class="fixed-logo"> |
|
<img src="data:image/png;base64,{image_base64}" width="250"> |
|
</div> |
|
""", |
|
unsafe_allow_html=True |
|
) |
|
|
|
|
|
default_end_date = datetime.today().date() |
|
default_start_date = default_end_date - timedelta(days=365) |
|
|
|
|
|
st.markdown("<br><br><br>", unsafe_allow_html=True) |
|
|
|
|
|
st.title("📈 Interaktive Analyse von Aktienindizes") |
|
|
|
indices = { |
|
|
|
|
|
|
|
|
|
|
|
"S&P 500 (USA)": "^GSPC", |
|
"Nasdaq 100 (USA)": "^NDX", |
|
"Dow Jones Industrial Average (USA)": "^DJI", |
|
"Russell 2000 (USA)": "^RUT", |
|
|
|
|
|
"DAX (Deutschland)": "^GDAXI", |
|
"MDAX (Deutschland)": "^MDAXI", |
|
"CAC 40 (Frankreich)": "^FCHI", |
|
"FTSE 100 (UK)": "^FTSE", |
|
"EURO STOXX 50": "^STOXX50E", |
|
"AEX (Niederlande)": "^AEX", |
|
"IBEX 35 (Spanien)": "^IBEX", |
|
|
|
|
|
"SMI (Schweiz)": "^SSMI", |
|
|
|
|
|
"Shanghai Composite": "000001.SS", |
|
"Hang Seng (Hongkong)": "^HSI", |
|
|
|
|
|
"Nikkei 225": "^N225", |
|
"TOPIX": "^TOPX", |
|
|
|
|
|
"BSE Sensex": "^BSESN", |
|
"Nifty 50": "^NSEI", |
|
|
|
|
|
"ASX 200": "^AXJO", |
|
|
|
|
|
"TSX Composite": "^GSPTSE", |
|
|
|
|
|
"Bovespa": "^BVSP" |
|
} |
|
|
|
|
|
ticker1_name = st.selectbox("📈 Wähle Index 1:", list(indices.keys()), index=0) |
|
ticker2_name = st.selectbox("📈 Wähle Index 2:", list(indices.keys()), index=1) |
|
|
|
|
|
ticker1 = indices[ticker1_name] |
|
ticker2 = indices[ticker2_name] |
|
|
|
|
|
start_date = st.date_input("Startdatum", default_start_date, min_value=datetime(1900, 1, 1).date(), max_value=default_end_date) |
|
|
|
end_date = st.date_input("Enddatum", default_end_date, min_value=datetime(1900, 1, 1).date(), max_value=datetime.today().date()) |
|
|
|
|
|
color_ticker1 = "#1f77b4" |
|
color_ticker2 = "#ff7f0e" |
|
color_ticker3 = "#e377c2" |
|
|
|
|
|
if st.button("GO"): |
|
|
|
|
|
data_dict = {} |
|
|
|
for name, symbol in [(ticker1_name, ticker1), (ticker2_name, ticker2)]: |
|
ticker = yf.Ticker(symbol) |
|
df = ticker.history(start=start_date, end=end_date) |
|
|
|
|
|
df.index = pd.to_datetime(df.index).date |
|
|
|
|
|
if "Adj Close" in df.columns and not df["Adj Close"].isna().all(): |
|
selected_data = df["Adj Close"] |
|
elif "Close" in df.columns and not df["Close"].isna().all(): |
|
selected_data = df["Close"] |
|
else: |
|
st.warning(f"⚠️ Keine gültigen Daten für {name} ({symbol}) gefunden!") |
|
continue |
|
|
|
|
|
selected_data = selected_data[~selected_data.index.duplicated(keep="last")] |
|
|
|
|
|
selected_data.name = name |
|
|
|
|
|
data_dict[name] = selected_data |
|
|
|
|
|
if ticker1_name in data_dict and ticker2_name in data_dict: |
|
df1 = data_dict[ticker1_name].to_frame() |
|
df2 = data_dict[ticker2_name].to_frame() |
|
|
|
|
|
df_indices = pd.merge(df1, df2, left_index=True, right_index=True, how="outer") |
|
|
|
|
|
df_indices.ffill(inplace=True) |
|
|
|
|
|
df_indices.dropna(inplace=True) |
|
|
|
|
|
if df_indices.empty: |
|
st.error("❌ Keine gemeinsamen Daten für die gewählten Indizes gefunden!") |
|
st.stop() |
|
|
|
|
|
|
|
fig1 = go.Figure() |
|
|
|
|
|
fig1.add_trace(go.Scatter( |
|
x=df_indices.index, y=df_indices[ticker1_name], mode='lines', |
|
name=ticker1_name, yaxis='y1', line=dict(color=color_ticker1))) |
|
|
|
|
|
fig1.add_trace(go.Scatter( |
|
x=df_indices.index, y=df_indices[ticker2_name], mode='lines', |
|
name=ticker2_name, yaxis='y2', line=dict(color=color_ticker2))) |
|
|
|
|
|
fig1.update_layout( |
|
title=f"Vergleich der Close-Preise: {ticker1_name} vs. {ticker2_name}", |
|
xaxis=dict(title="Datum"), |
|
yaxis=dict(title=f"{ticker1_name} Index", side='left', showgrid=False), |
|
yaxis2=dict(title=f"{ticker2_name} Index", side='right', overlaying='y', showgrid=False), |
|
legend=dict(x=0, y=1), |
|
hovermode="x" |
|
) |
|
|
|
|
|
st.plotly_chart(fig1, use_container_width=True) |
|
|
|
|
|
df_normalized = df_indices / df_indices.iloc[0] * 100 |
|
|
|
|
|
return_ticker1 = round(((df_indices[ticker1_name].iloc[-1] - df_indices[ticker1_name].iloc[0]) / df_indices[ticker1_name].iloc[0]) * 100, 2) |
|
return_ticker2 = round(((df_indices[ticker2_name].iloc[-1] - df_indices[ticker2_name].iloc[0]) / df_indices[ticker2_name].iloc[0]) * 100, 2) |
|
|
|
|
|
legend_ticker1 = f"{ticker1_name} = {return_ticker1}%" |
|
legend_ticker2 = f"{ticker2_name} = {return_ticker2}%" |
|
|
|
|
|
fig2 = px.line(df_normalized, x=df_normalized.index, y=df_normalized.columns, |
|
title="Normierter Vergleich der Close-Preise", |
|
labels={"value": "Index (Startwert = 100)", "variable": "Index"}, |
|
template="plotly_white", |
|
color_discrete_map={ticker1_name: color_ticker1, ticker2_name: color_ticker2}) |
|
|
|
|
|
fig2.for_each_trace(lambda t: t.update(name=legend_ticker1 if t.name == ticker1_name else legend_ticker2)) |
|
|
|
|
|
fig2.update_layout(legend=dict(x=0, y=1)) |
|
|
|
|
|
st.plotly_chart(fig2, use_container_width=True) |
|
|
|
|
|
df_relative_performance = df_normalized[ticker1_name] - df_normalized[ticker2_name] |
|
|
|
|
|
relative_performance_change = round(df_relative_performance.iloc[-1], 2) |
|
|
|
|
|
legend_relative = f"{ticker1_name} - {ticker2_name} = {relative_performance_change}%" |
|
|
|
|
|
fig3 = px.line(x=df_relative_performance.index, y=df_relative_performance, |
|
title=f"Relative Performance: {ticker1_name} vs. {ticker2_name}", |
|
labels={"x": "Datum", "y": "Relative Performance (%)"}, |
|
template="plotly_white") |
|
|
|
|
|
fig3.update_traces(line=dict(color=color_ticker3), name=legend_relative) |
|
|
|
|
|
fig3.update_layout(legend=dict(x=0, y=1)) |
|
|
|
|
|
fig3.add_annotation( |
|
x=df_relative_performance.index[-1], |
|
y=df_relative_performance.iloc[-1], |
|
text=f"{df_relative_performance.iloc[-1]:.2f}%", |
|
showarrow=True, |
|
arrowhead=2, |
|
font=dict(size=14, color=color_ticker3), |
|
ax=20, ay=-40 |
|
) |
|
|
|
|
|
st.plotly_chart(fig3, use_container_width=True) |
|
|
|
|
|
|
|
|