ํฐ์คํ ๋ฆฌ ๋ทฐ
๐งญ ํํธ ์๋๋งค๋งค ์๋ฒ ๊ตฌ์ถ – Flask + Scheduler + DB๋ก ์์ ์๋ํ ์์คํ ๋ง๋ค๊ธฐ
octo54 2025. 10. 22. 13:18๐งญ ํํธ ์๋๋งค๋งค ์๋ฒ ๊ตฌ์ถ – Flask + Scheduler + DB๋ก ์์ ์๋ํ ์์คํ ๋ง๋ค๊ธฐ
์ง๋ ๊ธ์์๋ ํค์ OpenAPI๋ฅผ ์ด์ฉํ ์ค์๊ฐ ์๋ ๋งค๋งค ์ฝ๋๋ฅผ ์์ฑํ์ต๋๋ค.
์ด์ ๋ ์ด ๋ก์ง์ ๊ฐ์ธ ๋
ธํธ๋ถ์ด ์๋๋ผ, ํญ์ ์ผ์ ธ ์๋ ์๋ฒ์์ ์์ ์ ์ผ๋ก ๋๋ ค์ผ ํฉ๋๋ค.
์ค๋์ Python์ Flask ์น ์๋ฒ, ์ค์ผ์ค๋ฌ, ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ๊ฒฐํฉํด
์ค์ ํ๋ ์์คํ
์ฒ๋ผ “์๋์ผ๋ก ๋ฆฌ๋ฐธ๋ฐ์ฑ → ์ฃผ๋ฌธ → ๋ก๊ทธ ๊ธฐ๋ก → ๋์๋ณด๋ ํ์”๊ฐ ๋์๊ฐ๋
๋ฐฑ์๋ํ ํํธ ๋งค๋งค ์์ง์ ๋ง๋ค์ด๋ณด๊ฒ ์ต๋๋ค.
1๏ธโฃ ์์คํ ๊ฐ์
[ Flask ์๋ฒ ]
โโโ /trade (์ฃผ๋ฌธ ์คํ API)
โโโ /report (์ฑ๊ณผ ์กฐํ API)
โโโ /rebalance (ํฉํฐ ๊ธฐ๋ฐ ์ข
๋ชฉ ๊ฐฑ์ )
โโโ Scheduler (๋งค์ผ 09:00 ์๋ ์คํ)
↓
[ DB (SQLite or PostgreSQL) ]
↓
[ Log + Report ์๋ ์
๋ฐ์ดํธ ]
์ด ๊ตฌ์กฐ์ ํต์ฌ์,
๐ API ์๋ฒ๋ก ๋ง๋ค์ด๋๋ฉด ์น/๋ชจ๋ฐ์ผ/๋์๋ณด๋ ์ด๋์๋ ์ ์ดํ ์ ์๋ค๋ ์ ์
๋๋ค.
2๏ธโฃ ๊ธฐ๋ณธ ์ธํ
๐ฆ ํ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ค์น
pip install flask apscheduler pandas sqlalchemy yfinance
- flask: ์น API ์๋ฒ
- apscheduler: ์ฃผ๊ธฐ์ ์์ ์๋ ์คํ
- sqlalchemy: DB ORM
- yfinance: ์ฃผ๊ฐ ๋ฐ์ดํฐ ์์ง
3๏ธโฃ Flask ์๋ฒ ๊ธฐ๋ณธ ๊ตฌ์กฐ
from flask import Flask, jsonify
from apscheduler.schedulers.background import BackgroundScheduler
from sqlalchemy import create_engine
import pandas as pd, yfinance as yf, datetime
app = Flask(__name__)
engine = create_engine("sqlite:///quant.db", echo=False)
# ๋ฐ์ดํฐ ์์ง ๋ฐ ์ ์ฅ ํจ์
def collect_factor_data():
tickers = ["005930.KS", "000660.KS", "035420.KS"]
rows = []
for t in tickers:
df = yf.download(t, period="1y")
ret = (df["Close"].iloc[-1] / df["Close"].iloc[-120]) - 1
vol = df["Close"].pct_change().std()
rows.append({"ticker": t, "return": ret, "vol": vol, "updated": datetime.datetime.now()})
pd.DataFrame(rows).to_sql("factors", engine, if_exists="replace", index=False)
print("โ
ํฉํฐ ๋ฐ์ดํฐ ๊ฐฑ์ ์๋ฃ")
# ๋งค๋งค ํจ์ (๋จ์ ์์)
def execute_trade():
df = pd.read_sql("SELECT * FROM factors", engine)
top = df.sort_values("return", ascending=False).iloc[0]
print(f"๐ {top['ticker']} ๋งค์ ์คํ (return={top['return']:.2%})")
# ์ค์ผ์ค๋ฌ ๋ฑ๋ก
scheduler = BackgroundScheduler()
scheduler.add_job(collect_factor_data, "cron", hour=8, minute=55) # ๋ฐ์ดํฐ ๊ฐฑ์
scheduler.add_job(execute_trade, "cron", hour=9, minute=1) # ๋งค์ ์คํ
scheduler.start()
@app.route("/report", methods=["GET"])
def report():
df = pd.read_sql("SELECT * FROM factors", engine)
return jsonify(df.to_dict(orient="records"))
if __name__ == "__main__":
collect_factor_data()
app.run(host="0.0.0.0", port=5000)
4๏ธโฃ ์ฝ๋ ์ค๋ช
๊ธฐ๋ฅ ์ค๋ช
| collect_factor_data() | yfinance๋ก ์ข ๋ชฉ ๋ฐ์ดํฐ ์์ง ํ DB ์ ์ฅ |
| execute_trade() | ์์ ํฉํฐ ์ ์ ์ข ๋ชฉ ์๋ ๋งค์ (API ์ฐ๋ ๊ฐ๋ฅ) |
| apscheduler | ์ ํด์ง ์๊ฐ์ ํจ์ ์๋ ์คํ |
| /report | ํ์ฌ ํฌํธํด๋ฆฌ์ค ๋ฐ ํฉํฐ ์ ์ REST API๋ก ์ ๊ณต |
๐ก ์ด ์๋ฒ๋ฅผ AWS EC2, Google Cloud, ๋๋ NAS ์๋ฒ์ ์ฌ๋ ค๋๋ฉด,
๋งค์ผ ์์นจ ์๋์ผ๋ก “๋ฐ์ดํฐ ์์ง → ์ข
๋ชฉ ์ ํ → ์ฃผ๋ฌธ ์คํ”๊น์ง ๋์๊ฐ๋๋ค.
5๏ธโฃ DB ๊ตฌ์กฐ (SQLite ์์)
์ปฌ๋ผ ์ค๋ช
| ticker | ์ข ๋ชฉ ์ฝ๋ |
| return | ์ต๊ทผ 6๊ฐ์ ์์ต๋ฅ |
| vol | ๋ณ๋์ฑ |
| updated | ์ ๋ฐ์ดํธ ์๊ฐ |
์ด DB๋ ๋ฆฌํฌํธ ์์ฑ๊ธฐ(PDF)์ ์ฐ๊ฒฐ๋์ด
๋งค์ ์๋ ํฌ์ ์ฑ๊ณผ๋ฅผ ์๊ฐํํ ์ ์์ต๋๋ค.
6๏ธโฃ ๋์๋ณด๋ ์ฐ๋ (์ต์ )
Streamlit ์ฐ๋ ์์
pip install streamlit
import streamlit as st
import pandas as pd
from sqlalchemy import create_engine
engine = create_engine("sqlite:///quant.db")
df = pd.read_sql("SELECT * FROM factors", engine)
st.title("๐ Quant Trading Dashboard")
st.dataframe(df)
st.bar_chart(df.set_index("ticker")["return"])
๐ streamlit run dashboard.py
→ ์น ๋์๋ณด๋์์ ์ค์๊ฐ์ผ๋ก ํฉํฐ ์ ์์ ์ข
๋ชฉ ํํฉ์ ํ์ธํ ์ ์์ต๋๋ค.
7๏ธโฃ ์ด์ ์๋ํ ํ
ํญ๋ชฉ ์ค๋ช
| ๐ Scheduler | APScheduler๋ก ์ ๊ธฐ ์คํ (cron ํ์) |
| ๐งพ ๋ก๊ทธ ๊ด๋ฆฌ | logging ๋ชจ๋๋ก ๋ชจ๋ ์ฃผ๋ฌธ ๊ธฐ๋ก ๋จ๊ธฐ๊ธฐ |
| โ๏ธ ๋ฐฐํฌ | AWS EC2 / Railway / Docker๋ก ๋ฐฐํฌ |
| ๐ ๋ณด์ | ํค์ API ํค๋ .env์ ์ ์ฅ ํ ํ๊ฒฝ๋ณ์๋ก ๋ก๋ |
| ๐ง ์ฅ์ ๋ณต๊ตฌ | ์คํจ ์ Slack/Email ์๋ฆผ ์ถ๊ฐ ์ถ์ฒ |
๐ ์ ๋ฆฌ
๋จ๊ณ ๋ด์ฉ
| 1 | Flask ์๋ฒ๋ก ์๋๋งค๋งค API ๊ตฌ์ฑ |
| 2 | APScheduler๋ก ์๋ ์คํ ๋ฑ๋ก |
| 3 | SQLite๋ก ๋ฐ์ดํฐ ์๊ตฌ ์ ์ฅ |
| 4 | Streamlit์ผ๋ก ์๊ฐํ ๋์๋ณด๋ ๊ตฌ์ฑ |
| 5 | ํด๋ผ์ฐ๋ ๋ฐฐํฌ๋ก ์์ ์๋ํ ์์ฑ |
์ด์ ๋
ธํธ๋ถ์ ์ผ๋์ง ์์๋,
์๋ฒ๊ฐ ์ค์ค๋ก ํฌ์ํ๊ณ ๊ธฐ๋กํ๊ณ ๋ณด๊ณ ํ๋ ์์คํ
์ด ์์ฑ๋์ต๋๋ค.
๐ ๋ค์ ๊ธ ์๊ณ
๋ค์ ํธ์์๋ **“์ค์ ์ด์ ๋ชจ๋ – ์ค๋ฅ ๊ฐ์ง, ์ฌ๋ ์๋ฆผ, ๋ฐฑ์
์ ๋ต”**์ ๋ค๋ฃน๋๋ค.
์ฆ, ์ค์ ์ด์ฉ ํ๊ฒฝ์์ ์์ ์ ์ผ๋ก ๋์๊ฐ๊ฒ ๋ง๋๋ ์ด์ ์๋ํ(Ops) ๊ตฌ์กฐ ์ค๊ณ๋ฅผ ๋ณด์ฌ๋๋ฆด๊ฒ์.
ํํธ์๋ฒ,Flask์๋๋งค๋งค,ํ์ด์ฌ์ค์ผ์ค๋ฌ,apscheduler,quantAPI,๋ฐ์ดํฐํฌ์,์๋๋ฆฌ๋ฐธ๋ฐ์ฑ,ํํธ๋์๋ณด๋,streamlit,์ฃผ์์๋ํ
'์ฃผ์' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
- Total
- Today
- Yesterday
- Prisma
- llm
- ๋ฐฑ์๋๊ฐ๋ฐ
- ๋ฅ๋ฌ๋
- ํ๋ก ํธ์๋๊ฐ๋ฐ
- fastapi
- NestJS
- ์น๊ฐ๋ฐ
- REACT
- Docker
- rag
- seo ์ต์ ํ 10๊ฐ
- Redis
- CI/CD
- flax
- ์ฟ ๋ฒ๋คํฐ์ค
- kotlin
- Express
- JWT
- ๊ฐ๋ฐ๋ธ๋ก๊ทธ
- node.js
- ์๋ฐ๋ฉด์
- JAX
- Next.js
- DevOps
- ai์ฒ ํ
- Python
- nextJS
- SEO์ต์ ํ
- 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 |

