Files
CrumbCharts_v0.2_OSX/server.py
Branko May Trinkwald a831ea5fb0 CO2 = ATMEN
2026-01-05 20:52:06 +01:00

154 lines
5.0 KiB
Python

from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates
from contextlib import asynccontextmanager
import uvicorn
import logging
import os
from datetime import datetime
from main import GoldMarketAnalysisSystem
from config import GOLD_TICKER_SYMBOLS
# Logging mit Rich
from rich.logging import RichHandler
logging.basicConfig(
level="INFO",
format="%(message)s",
datefmt="[%X]",
handlers=[RichHandler(rich_tracebacks=True)]
)
logger = logging.getLogger("server")
# Global System Initialisierung
system: GoldMarketAnalysisSystem = None
@asynccontextmanager
async def lifespan(app: FastAPI):
global system
logger.info("🌲 Gold Forest Watchtower wird errichtet...")
try:
system = GoldMarketAnalysisSystem()
logger.info("🦉 Eule hat Platz genommen. System bereit.")
except Exception as e:
logger.error(f"Fehler beim Starten des Systems: {e}")
yield
logger.info("Beende Watchtower...")
app = FastAPI(title="Gold Forest Watchtower", lifespan=lifespan)
# Templates setup
templates = Jinja2Templates(directory="templates")
@app.get("/", response_class=HTMLResponse)
async def read_root(request: Request):
return templates.TemplateResponse("index.html", {"request": request})
@app.get("/api/stats")
async def get_stats():
"""Liefert aktuelle Marktstatistiken"""
if not system:
return {"error": "System not initialized"}
try:
# Aktuellen Preis laden (GC=F)
ticker_key = "GC"
current_data = system.yahoo_collector.get_realtime_data(ticker_key)
# News/Sentiment
news = system.news_collector.get_all_news(hours_back=24)
sentiment = system.news_collector.aggregate_sentiment(news)
# Technische Indikatoren berechnen (Historische Daten holen und berechnen)
hist_data = system.yahoo_collector.get_historical_data(ticker_key, period="1mo", interval="1h")
indicators = system.indicator_calculator.calculate_all_indicators(hist_data)
latest_ind = indicators.iloc[-1].to_dict()
return {
"price": current_data.get("price", 0),
"change": current_data.get("change", 0),
"percent": current_data.get("percent", 0),
"timestamp": current_data.get("timestamp"),
"sentiment": {
"score": sentiment["average_score"],
"label": sentiment["sentiment_label"],
"count": sentiment["article_count"]
},
"technical": {
"rsi": float(latest_ind.get("RSI_14", 50)),
"macd": float(latest_ind.get("MACD_12_26", 0)),
"bb_upper": float(latest_ind.get("BB_upper_20", 0)),
"bb_lower": float(latest_ind.get("BB_lower_20", 0))
}
}
except Exception as e:
logger.error(f"API Error: {e}")
return {"error": str(e)}
@app.get("/api/history")
async def get_history():
"""Liefert historische Daten für Charts"""
if not system:
return {"error": "System not initialized"}
try:
hist_data = system.yahoo_collector.get_historical_data("GC", period="7d", interval="1h")
indicators = system.indicator_calculator.calculate_all_indicators(hist_data)
# Letzte 100 Punkte
df = indicators.tail(100)
return {
"dates": df.index.strftime("%Y-%m-%d %H:%M").tolist(),
"prices": df["Close"].tolist(),
"bb_upper": df["BB_upper_20"].fillna(0).tolist(),
"bb_lower": df["BB_lower_20"].fillna(0).tolist()
}
except Exception as e:
return {"error": str(e)}
@app.get("/api/news")
async def get_latest_news():
"""Liefert die letzten News"""
if not system:
return []
try:
news = system.news_collector.get_all_news(hours_back=24)
return news[:6] # Top 6
except Exception as e:
return [{"title": "Fehler beim Laden der News", "source": "System", "sentiment_label": "Neutral"}]
@app.get("/api/breath")
async def get_system_breath():
"""Liefert den ökologischen Atem des Systems"""
from CO2.breath import ForestBreath
# Singleton-like usage for demo (better: store in system)
fb = ForestBreath()
# 1. System Breath (Realtime)
sys_breath = fb.get_system_breath()
# 2. Gold Impact (Theoretical for 1 GC Contract ~ 100oz -> $200k+ but let's use current price)
price = 2500.0 # Fallback
if system:
try:
realtime = system.yahoo_collector.get_realtime_data("GC")
price = realtime.get("current_price", 2500.0)
except:
pass
# Impact for 1 oz investment
gold_impact = fb.get_gold_pricing_ecology(price)
return {
"system": sys_breath,
"gold_impact_1oz": gold_impact,
"breath_state": "Exhale" # Placeholder, could be dynamic based on volatility
}
if __name__ == "__main__":
uvicorn.run("server:app", host="0.0.0.0", port=8000, reload=True)