stock 실계좌 예수금 정보 추가

This commit is contained in:
2026-03-02 18:44:51 +09:00
parent 136aea8aee
commit d6d2eb0787
2 changed files with 87 additions and 2 deletions

View File

@@ -46,6 +46,15 @@ def init_db():
) )
""") """)
conn.execute("""
CREATE TABLE IF NOT EXISTS broker_cash (
id INTEGER PRIMARY KEY AUTOINCREMENT,
broker TEXT UNIQUE NOT NULL,
cash INTEGER NOT NULL DEFAULT 0,
updated_at TEXT DEFAULT (datetime('now','localtime'))
)
""")
def save_articles(articles: List[Dict[str, str]]) -> int: def save_articles(articles: List[Dict[str, str]]) -> int:
count = 0 count = 0
with _conn() as conn: with _conn() as conn:
@@ -120,3 +129,33 @@ def delete_portfolio_item(item_id: int) -> bool:
with _conn() as conn: with _conn() as conn:
cur = conn.execute("DELETE FROM portfolio WHERE id = ?", (item_id,)) cur = conn.execute("DELETE FROM portfolio WHERE id = ?", (item_id,))
return cur.rowcount > 0 return cur.rowcount > 0
# --- Broker Cash CRUD ---
def upsert_broker_cash(broker: str, cash: int) -> None:
now = __import__("datetime").datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with _conn() as conn:
conn.execute("""
INSERT INTO broker_cash (broker, cash, updated_at)
VALUES (?, ?, ?)
ON CONFLICT(broker) DO UPDATE SET cash = excluded.cash, updated_at = excluded.updated_at
""", (broker, cash, now))
def get_all_broker_cash() -> List[Dict[str, Any]]:
with _conn() as conn:
rows = conn.execute("SELECT * FROM broker_cash ORDER BY broker").fetchall()
return [dict(r) for r in rows]
def get_broker_cash(broker: str) -> Dict[str, Any] | None:
with _conn() as conn:
row = conn.execute("SELECT * FROM broker_cash WHERE broker = ?", (broker,)).fetchone()
return dict(row) if row else None
def delete_broker_cash(broker: str) -> bool:
with _conn() as conn:
cur = conn.execute("DELETE FROM broker_cash WHERE broker = ?", (broker,))
return cur.rowcount > 0

View File

@@ -12,6 +12,7 @@ from .db import (
init_db, save_articles, get_latest_articles, init_db, save_articles, get_latest_articles,
add_portfolio_item, get_all_portfolio, get_portfolio_item, add_portfolio_item, get_all_portfolio, get_portfolio_item,
update_portfolio_item, delete_portfolio_item, update_portfolio_item, delete_portfolio_item,
upsert_broker_cash, get_all_broker_cash, get_broker_cash, delete_broker_cash,
) )
from .scraper import fetch_market_news, fetch_major_indices, fetch_overseas_news from .scraper import fetch_market_news, fetch_major_indices, fetch_overseas_news
from .price_fetcher import get_current_prices from .price_fetcher import get_current_prices
@@ -155,10 +156,24 @@ class PortfolioUpdateRequest(BaseModel):
@app.get("/api/portfolio") @app.get("/api/portfolio")
def get_portfolio(): def get_portfolio():
"""전체 포트폴리오 조회 (현재가 + 손익 포함)""" """전체 포트폴리오 조회 (현재가 + 손익 + 예수금 포함)"""
items = get_all_portfolio() items = get_all_portfolio()
cash_rows = get_all_broker_cash()
total_cash = sum(r["cash"] for r in cash_rows)
if not items: if not items:
return {"holdings": [], "summary": {"total_buy": 0, "total_eval": 0, "total_profit": 0, "total_profit_rate": 0.0}} return {
"holdings": [],
"cash": cash_rows,
"summary": {
"total_buy": 0,
"total_eval": 0,
"total_profit": 0,
"total_profit_rate": 0.0,
"total_cash": total_cash,
"total_assets": total_cash,
},
}
tickers = list({item["ticker"] for item in items}) tickers = list({item["ticker"] for item in items})
prices = get_current_prices(tickers) prices = get_current_prices(tickers)
@@ -196,11 +211,14 @@ def get_portfolio():
return { return {
"holdings": holdings, "holdings": holdings,
"cash": cash_rows,
"summary": { "summary": {
"total_buy": total_buy, "total_buy": total_buy,
"total_eval": total_eval, "total_eval": total_eval,
"total_profit": total_profit, "total_profit": total_profit,
"total_profit_rate": total_profit_rate, "total_profit_rate": total_profit_rate,
"total_cash": total_cash,
"total_assets": total_eval + total_cash,
}, },
} }
@@ -229,3 +247,31 @@ def delete_portfolio(item_id: int):
return {"ok": True} return {"ok": True}
# --- Broker Cash API ---
class BrokerCashRequest(BaseModel):
broker: str
cash: int
@app.get("/api/portfolio/cash")
def list_broker_cash():
"""증권사별 예수금 전체 조회"""
return get_all_broker_cash()
@app.put("/api/portfolio/cash")
def set_broker_cash(req: BrokerCashRequest):
"""증권사 예수금 등록 또는 수정 (upsert)"""
upsert_broker_cash(req.broker, req.cash)
return {"ok": True, "broker": req.broker, "cash": req.cash}
@app.delete("/api/portfolio/cash/{broker}")
def remove_broker_cash(broker: str):
"""증권사 예수금 삭제"""
if not delete_broker_cash(broker):
return JSONResponse(status_code=404, content={"error": "Broker not found"})
return {"ok": True}