ํฐ์คํ ๋ฆฌ ๋ทฐ
๐ Streamlit + Flask๋ก ๋ง๋๋ ์ค์๊ฐ ํํธ ํฌ์ ๋์๋ณด๋ (์ค์ ์ด์ UI ์์ฑํธ)
octo54 2025. 10. 27. 11:38๐ Streamlit + Flask๋ก ๋ง๋๋ ์ค์๊ฐ ํํธ ํฌ์ ๋์๋ณด๋ (์ค์ ์ด์ UI ์์ฑํธ)
์ง๊ธ๊น์ง ์ฐ๋ฆฌ๋ ์๋ฒฝํ ์๋ํ๋ ๋ฐฑ์๋ ํํธ ๋งค๋งค ์์ง์ ์์ฑํ์ต๋๋ค.
๋ฐ์ดํฐ ์์ง, ๋ฆฌ๋ฐธ๋ฐ์ฑ, ๋งค๋งค, ๋ฆฌํฌํธ, ๋ฐฑ์
—all done.
์ด์ ๋จ์ ๊ฒ์ ํ๋, **์ฌ๋์ด ๋ณผ ์ ์๋ ์ธํฐํ์ด์ค(UI)**์
๋๋ค.
์ด๋ฒ ๊ธ์์๋ Streamlit + Flask๋ฅผ ์ด์ฉํด
“์ค์๊ฐ์ผ๋ก ์์ต๋ฅ ·ํฌํธ ๊ตฌ์ฑ·ํฉํฐ ๋ณํ”๋ฅผ ๋ชจ๋ํฐ๋งํ๋
ํํธ ์ด์ฉ ๋์๋ณด๋๋ฅผ ๊ตฌ์ถํฉ๋๋ค.
๐ฏ ๋ชฉํ
- PostgreSQL์ ์ ์ฅ๋ ๋ฐ์ดํฐ๋ฅผ ์ค์๊ฐ์ผ๋ก ์๊ฐํ
- ์์ต๋ฅ , ๋ณ๋์ฑ, ๋์ ์ฑ๊ณผ๋ฅผ ์ฐจํธ๋ก ํ์
- Flask REST API → Streamlit ํ๋ก ํธ์๋ ์ฐ๋
- Slack ์๋ฆผ๊ณผ ๋์ผํ ๋ฐ์ดํฐ๋ฅผ ์น์์ ํ์ธ
๐งฑ 1๏ธโฃ ์ ์ฒด ๊ตฌ์กฐ
[ PostgreSQL ]
โฒ
โ SQLAlchemy
โผ
[ Flask API ์๋ฒ ] ← /report, /performance
โฒ
โ REST JSON
โผ
[ Streamlit Dashboard ]
โโ ๋์ ์์ต๋ฅ ์ฐจํธ
โโ ํ์ฌ ํฌํธํด๋ฆฌ์ค
โโ ํฉํฐ ๋ณํ ํธ๋ ๋
โ๏ธ 2๏ธโฃ Flask API ์๋ฒ (๋ฐฑ์๋)
# api_server.py
from flask import Flask, jsonify
from sqlalchemy import create_engine
import pandas as pd, os
app = Flask(__name__)
engine = create_engine(os.getenv("DB_URL", "postgresql+psycopg2://quant_user:quant_pass@localhost:5432/quantdb"))
@app.route("/report")
def report():
df = pd.read_sql("SELECT * FROM factors ORDER BY updated DESC LIMIT 100", engine)
return jsonify(df.to_dict(orient="records"))
@app.route("/performance")
def performance():
df = pd.read_sql("""
SELECT date_trunc('day', updated) AS date,
AVG(return_6m) AS avg_ret,
AVG(vol_60) AS avg_vol
FROM factors
GROUP BY date
ORDER BY date
""", engine)
return jsonify(df.to_dict(orient="records"))
if __name__ == "__main__":
app.run(host="0.0.0.0", port=5050)
โ
/report : ์ต๊ทผ ํฉํฐ ๋ฐ์ดํฐ 100๊ฐ
โ
/performance : ์ผ๋ณ ํ๊ท ์์ต๋ฅ & ๋ณ๋์ฑ
๐ 3๏ธโฃ Streamlit ํ๋ก ํธ์๋
# dashboard.py
import streamlit as st
import pandas as pd
import requests, datetime as dt
import plotly.express as px
API_URL = "http://localhost:5050"
st.set_page_config(page_title="Quant Dashboard", layout="wide")
st.title("๐ Quant Portfolio Live Dashboard")
st.markdown(f"๐ Last update: {dt.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
# ์ต๊ทผ ํฉํฐ ๋ฆฌํฌํธ
st.header("๐ Latest Factor Data")
data = requests.get(f"{API_URL}/report").json()
df = pd.DataFrame(data)
st.dataframe(df)
# ์ผ๋ณ ์ฑ๊ณผ
st.header("๐ Performance Overview")
perf = pd.DataFrame(requests.get(f"{API_URL}/performance").json())
col1, col2 = st.columns(2)
with col1:
fig1 = px.line(perf, x="date", y="avg_ret", title="Average 6M Return")
st.plotly_chart(fig1, use_container_width=True)
with col2:
fig2 = px.line(perf, x="date", y="avg_vol", title="Average Volatility (60D)")
st.plotly_chart(fig2, use_container_width=True)
# ํฌํธํด๋ฆฌ์ค ์์ฝ
st.header("๐ผ Portfolio Summary")
top_df = df.sort_values("return_6m", ascending=False).head(5)
st.bar_chart(top_df.set_index("ticker")["return_6m"])
๐ฅ๏ธ ์คํ ๋ฐฉ๋ฒ
1. Flask ์๋ฒ ์คํ
python api_server.py
2. Streamlit ์คํ
streamlit run dashboard.py
3. ์ ์
๋ธ๋ผ์ฐ์ ์์ http://localhost:8501 →
๐ ํํธ ํฌ์ ์ค์๊ฐ ๋์๋ณด๋ ์คํ!
๐ 4๏ธโฃ ์ค์๊ฐ ์ ๋ฐ์ดํธ
Streamlit์ ์๋ ์๋ก๊ณ ์นจ(interval) ๊ธฐ๋ฅ์ด ์์ด
๊ฐ๋จํ ์๋ ์ฝ๋ ์ถ๊ฐ๋ก 1๋ถ๋ง๋ค ๋ฆฌํ๋ ์ํ ์ ์์ต๋๋ค.
import time
st_autorefresh = st.experimental_rerun # Streamlit 1.36+ ๋ฒ์
st.button("๐ ์๋ก๊ณ ์นจ", on_click=lambda: st_autorefresh())
๋๋ Linux ์๋ฒ์์๋ watch curl http://127.0.0.1:5050/health
๋ช
๋ น์ผ๋ก ๋ฐฑ์๋ ์ํ๋ฅผ ๋ชจ๋ํฐ๋งํ ์๋ ์์ต๋๋ค.
๐งฉ 5๏ธโฃ ํ์ฅ ์์ด๋์ด
๊ธฐ๋ฅ ์ค๋ช
| ๐ Slack Alert ์ฐ๋ | ๋์๋ณด๋ ์ด๋ฒคํธ ํธ๋ฆฌ๊ฑฐ ์ ์ฌ๋ ๋ฉ์์ง ์ ์ก |
| ๐ง ํฉํฐ๋ณ ์ฑ๊ณผ Heatmap | Plotly Heatmap์ผ๋ก ํฉํฐ๋ณ ์๋์ฑ๊ณผ ์๊ฐํ |
| ๐ Drawdown ๊ทธ๋ํ | MDD ๊ณ์ฐ ํ ๋์ ์์ต๋ฅ ๋๋น ํ๋ฝ ๊ตฌ๊ฐ ํ์ |
| ๐ PDF Export | Streamlit → Reportlab์ผ๋ก ์๊ฐ ๋ฆฌํฌํธ ์๋ ์์ฑ |
| ๐ฌ Email ๋ฐ์ก | ๋งค์ฃผ ์์์ผ ์์นจ PDF + ์์ฝ ๋ฆฌํฌํธ ์ ์ก |
๐งฐ 6๏ธโฃ Docker๋ก ํตํฉ ๋ฐฐํฌ
version: "3.9"
services:
flask-api:
build: ./api
ports:
- "5050:5050"
env_file: .env
streamlit-dashboard:
build: ./dashboard
ports:
- "8501:8501"
depends_on:
- flask-api
restart: unless-stopped
๐ก ์ด๋ ๊ฒ ๊ตฌ์ฑํ๋ฉด Flask์ Streamlit์ด ํจ๊ป ์คํ๋์ด
์๋๋งค๋งค ๋ฐฑ์๋ + ์ค์๊ฐ ๋ชจ๋ํฐ๋ง UI๊ฐ ์์ ํ ํตํฉ๋ฉ๋๋ค.
๐ ์ ๋ฆฌ
๊ตฌ์ฑ ์์ ์ญํ
| Flask | REST API (๋ฐ์ดํฐ ์ ๊ณต) |
| PostgreSQL | ํฉํฐ ๋ฐ ์ฑ๊ณผ ๋ฐ์ดํฐ ์ ์ฅ |
| Streamlit | ์ค์๊ฐ UI ๋์๋ณด๋ |
| Plotly | ์ฐจํธ ์๊ฐํ |
| Docker | ๋ฐฐํฌ ์๋ํ |
์ด์ ์๋ฒ๋ ์ค์ค๋ก ํฌ์ํ๊ณ ,
๋น์ ์ ์น์์ ์ค์๊ฐ์ผ๋ก ๊ทธ ๊ฒฐ๊ณผ๋ฅผ ๋ชจ๋ํฐ๋งํ ์ ์์ต๋๋ค.
์ง์ง **‘ํ๋ฃจ 24์๊ฐ ์ผํ๋ ํํธ ๋งค๋์ ’**๊ฐ ์๊ธด ๊ฑฐ์ฃ .
๐ ๋ค์ ๊ธ ์๊ณ
๋ค์ ํธ์์๋ **“AI ํฉํฐ ์์ธก ๋ชจ๋ธ ๋์
– Transformer๋ก ๋ค์ ๋ถ๊ธฐ ์์ต๋ฅ ์์ธกํ๊ธฐ”**๋ฅผ ๋ค๋ฃน๋๋ค.
์ค์ ํฌ์๋ฐ์ดํฐ๋ฅผ ํ์ตํ ๋ฅ๋ฌ๋ ๊ธฐ๋ฐ ํํธ ์์ธก ๋ชจ๋ธ(Transformer + PyTorch) ์ ๊ตฌ์ถํด๋ณผ ์์ ์
๋๋ค.
Streamlit,Flask,ํํธ๋์๋ณด๋,ํ์ด์ฌ์๊ฐํ,PostgreSQL,๋ฐ์ดํฐํฌ์,์ค์๊ฐํฌ์๋ชจ๋ํฐ๋ง,Plotly,ํํธ์๋ํ,ํ์ด์ฌ๋ฐฑ์๋
'์ฃผ์' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
- Total
- Today
- Yesterday
- JWT
- CI/CD
- fastapi
- Python
- ์น๊ฐ๋ฐ
- flax
- seo ์ต์ ํ 10๊ฐ
- ์ฟ ๋ฒ๋คํฐ์ค
- ai์ฒ ํ
- llm
- Next.js
- ์๋ฐ๋ฉด์
- Redis
- ๊ฐ๋ฐ๋ธ๋ก๊ทธ
- Express
- node.js
- DevOps
- Docker
- JAX
- ๋ฅ๋ฌ๋
- NestJS
- rag
- SEO์ต์ ํ
- kotlin
- REACT
- nextJS
- ํ๋ก ํธ์๋๊ฐ๋ฐ
- Prisma
- PostgreSQL
- ๋ฐฑ์๋๊ฐ๋ฐ
| ์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | 7 |
| 8 | 9 | 10 | 11 | 12 | 13 | 14 |
| 15 | 16 | 17 | 18 | 19 | 20 | 21 |
| 22 | 23 | 24 | 25 | 26 | 27 | 28 |

