Aziz30's picture
Update Interface_Graphique/app.py
f6ce511 verified
import dash
from dash import html, dcc, Input, Output
import yfinance as yf
import os
# =========================
# PATH
# =========================
BASE_DIR = os.path.dirname(__file__)
# =========================
# INIT APP
# =========================
app = dash.Dash(
__name__,
use_pages=True,
pages_folder=os.path.join(BASE_DIR, "pages"),
suppress_callback_exceptions=True,
external_stylesheets=[
"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.0/css/all.min.css"
]
)
server = app.server # 🔥 IMPORTANT pour Hugging Face
app.title = "TradeLux - Plateforme de Trading"
# =========================
# TICKERS
# =========================
TICKERS = {
"BTC-USD": "BTC/USD",
"ETH-USD": "ETH/USD",
"^IXIC": "NASDAQ",
"AAPL": "AAPL",
"GOOGL": "GOOGL"
}
# =========================
# FETCH DATA
# =========================
def fetch_ticker_data():
data = []
for symbol, label in TICKERS.items():
try:
stock = yf.Ticker(symbol)
hist = stock.history(period="1d", interval="1m")
if len(hist) >= 2:
current = hist['Close'].iloc[-1]
prev = hist['Close'].iloc[-2]
change = (current - prev) / prev * 100
change_class = "up" if change > 0 else "down"
data.append({
"label": label,
"value": f"{current:,.2f}",
"change": f"{change:+.2f}%",
"class": change_class
})
else:
data.append({
"label": label,
"value": "N/A",
"change": "0.00%",
"class": "down"
})
except Exception as e:
print("Ticker error:", e)
data.append({
"label": label,
"value": "ERR",
"change": "0.00%",
"class": "down"
})
return data
# =========================
# BACKGROUND SAFE (IMPORTANT)
# =========================
background = html.Div(
[
html.Div(className="trade-bg"),
html.Div(className="grid-lines"),
html.Div(
[html.Div(className="particle") for _ in range(40)],
style={
"position": "fixed",
"zIndex": -10,
"pointerEvents": "none"
}
)
]
)
# =========================
# NAVBAR
# =========================
navbar = html.Div(
className="navbar",
children=[
html.Div(
className="navbar-left",
children=[
html.Img(src="/assets/logo.png", className="logo")
]
),
html.Div(
className="nav-links",
children=[
dcc.Link("Accueil", href="/", className="nav-link"),
dcc.Link("Marchés", href="/actions", className="nav-link"),
dcc.Link("Analyse", href="/data", className="nav-link"),
]
),
]
)
# =========================
# LAYOUT
# =========================
app.layout = html.Div([
# Background FIXED (non bloquant)
background,
# Ticker dynamique
html.Div(id="ticker-container"),
# Navbar
navbar,
# Content
html.Div(
className="page-content",
children=[
dash.page_container
],
style={"zIndex": 1} # 🔥 FIX CLICK
),
# Interval
dcc.Interval(id="interval", interval=60000, n_intervals=0)
])
# =========================
# CALLBACK TICKER (FIX STRUCTURE)
# =========================
@app.callback(
Output("ticker-container", "children"),
Input("interval", "n_intervals")
)
def update_ticker(n):
data = fetch_ticker_data()
items = [
html.Div(className="ticker-item", children=[
html.Span(d["label"]),
html.Span(d["value"], className="ticker-value"),
html.Span(d["change"], className=f"ticker-change {d['class']}")
])
for d in data
]
return html.Div(
className="ticker-wrap",
children=[
html.Div(
className="ticker-inner",
children=[
html.Div(className="ticker-set", children=items),
html.Div(className="ticker-set", children=items) # duplication scroll
]
)
]
)
# =========================
# RUN
# =========================
if __name__ == "__main__":
app.run(host="0.0.0.0", port=7860, debug=True)