""" monitor/dashboard.py - Streamlit 대시보드 실행: streamlit run monitor/dashboard.py --server.port 8501 """ import streamlit as st import pandas as pd import sqlite3 import json import os from datetime import datetime, timedelta DB_PATH = os.getenv("DB_PATH", "data/stockbot.db") AI_CTX = os.getenv("AI_CONTEXT_PATH", "data/daily_context.json") st.set_page_config(page_title="단타봇 대시보드", layout="wide") st.title("📈 단타 자동매매 대시보드") st.caption(f"마지막 갱신: {datetime.now().strftime('%H:%M:%S')}") # ── AI 판단 현황 ── st.subheader("🤖 오늘의 AI 판단") try: with open(AI_CTX, encoding="utf-8") as f: ctx = json.load(f) col1, col2, col3, col4 = st.columns(4) col1.metric("시장 분위기", ctx.get("market_sentiment", "-")) col2.metric("감성 점수", f"{ctx.get('sentiment_score', 0)}점") col3.metric("리스크 레벨", ctx.get("risk_level", "-")) col4.metric("거래 허용", "✅" if ctx.get("trade_allowed") else "❌") st.info(f"💬 {ctx.get('reason', '')}") col_l, col_r = st.columns(2) col_l.write(f"**주목 섹터:** {', '.join(ctx.get('hot_sectors', []))}") col_r.write(f"**회피 섹터:** {', '.join(ctx.get('avoid_sectors', []))}") except: st.warning("AI 판단 데이터 없음 (08:00 이후 생성)") st.divider() # ── 오늘 매매 현황 ── st.subheader("📊 오늘 매매 현황") try: conn = sqlite3.connect(DB_PATH) today = datetime.now().strftime("%Y-%m-%d") df = pd.read_sql( "SELECT * FROM trades WHERE date=?", conn, params=(today,) ) conn.close() if df.empty: st.info("오늘 매매 없음") else: total = len(df) wins = (df["pnl"] > 0).sum() net = df["pnl"].sum() win_rt = wins / total * 100 if total else 0 c1, c2, c3, c4 = st.columns(4) c1.metric("총 매매", f"{total}회") c2.metric("승률", f"{win_rt:.0f}%") c3.metric("순손익", f"{net:+,.0f}원") c4.metric("승/패", f"{wins}/{total-wins}") st.dataframe(df[["entry_time","ticker","name","entry_price", "exit_price","pnl","exit_reason"]].fillna("-"), use_container_width=True) except Exception as e: st.error(f"DB 연결 실패: {e}") st.divider() # ── 주간 손익 ── st.subheader("📅 최근 7일 손익") try: conn = sqlite3.connect(DB_PATH) week_ago = (datetime.now() - timedelta(days=7)).strftime("%Y-%m-%d") df_w = pd.read_sql( "SELECT date, SUM(pnl) as net_pnl, COUNT(*) as trades " "FROM trades WHERE date >= ? GROUP BY date ORDER BY date", conn, params=(week_ago,) ) conn.close() if not df_w.empty: st.bar_chart(df_w.set_index("date")["net_pnl"]) st.dataframe(df_w, use_container_width=True) except: st.info("주간 데이터 없음") st.button("🔄 새로고침", on_click=st.rerun)