백엔드 전체 구현 완료: 내부 서비스(Auth, Client, Realtime), API 엔드포인트 및 스케줄러 구현
This commit is contained in:
8
backend/app/api/api.py
Normal file
8
backend/app/api/api.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from fastapi import APIRouter
|
||||
from app.api.endpoints import settings, kis
|
||||
|
||||
api_router = APIRouter()
|
||||
|
||||
api_router.include_router(settings.router, prefix="/settings", tags=["settings"])
|
||||
api_router.include_router(kis.router, prefix="/kis", tags=["kis"])
|
||||
# api_router.include_router(trade.router, prefix="/trade", tags=["trade"])
|
||||
41
backend/app/api/endpoints/kis.py
Normal file
41
backend/app/api/endpoints/kis.py
Normal file
@@ -0,0 +1,41 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException, Query
|
||||
from pydantic import BaseModel
|
||||
from typing import Literal
|
||||
|
||||
from app.services.kis_client import kis_client
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
class OrderRequest(BaseModel):
|
||||
market: Literal["Domestic", "Overseas"]
|
||||
side: Literal["buy", "sell"]
|
||||
code: str
|
||||
quantity: int
|
||||
price: float = 0 # 0 for Market Price (if supported)
|
||||
|
||||
@router.get("/price")
|
||||
async def get_current_price(market: Literal["Domestic", "Overseas"], code: str):
|
||||
"""
|
||||
Get Real-time Price (REST). Prefer WebSocket for streaming.
|
||||
"""
|
||||
try:
|
||||
price = await kis_client.get_current_price(market, code)
|
||||
return {"code": code, "price": price}
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@router.get("/balance")
|
||||
async def get_balance(market: Literal["Domestic", "Overseas"]):
|
||||
try:
|
||||
data = await kis_client.get_balance(market)
|
||||
return data
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
|
||||
@router.post("/order")
|
||||
async def place_order(order: OrderRequest):
|
||||
try:
|
||||
res = await kis_client.place_order(order.market, order.side, order.code, order.quantity, order.price)
|
||||
return res
|
||||
except Exception as e:
|
||||
raise HTTPException(status_code=500, detail=str(e))
|
||||
53
backend/app/api/endpoints/settings.py
Normal file
53
backend/app/api/endpoints/settings.py
Normal file
@@ -0,0 +1,53 @@
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
from sqlalchemy import select
|
||||
from pydantic import BaseModel
|
||||
|
||||
from app.db.database import get_db
|
||||
from app.db.models import ApiSettings
|
||||
from app.services.kis_auth import kis_auth
|
||||
|
||||
router = APIRouter()
|
||||
|
||||
class SettingsSchema(BaseModel):
|
||||
# Partial schema for updates
|
||||
appKey: str | None = None
|
||||
appSecret: str | None = None
|
||||
accountNumber: str | None = None
|
||||
kisApiDelayMs: int | None = None
|
||||
|
||||
class Config:
|
||||
from_attributes = True
|
||||
|
||||
@router.get("/", response_model=SettingsSchema)
|
||||
async def get_settings(db: AsyncSession = Depends(get_db)):
|
||||
stmt = select(ApiSettings).where(ApiSettings.id == 1)
|
||||
result = await db.execute(stmt)
|
||||
settings = result.scalar_one_or_none()
|
||||
if not settings:
|
||||
raise HTTPException(status_code=404, detail="Settings not initialized")
|
||||
return settings
|
||||
|
||||
@router.put("/", response_model=SettingsSchema)
|
||||
async def update_settings(payload: SettingsSchema, db: AsyncSession = Depends(get_db)):
|
||||
stmt = select(ApiSettings).where(ApiSettings.id == 1)
|
||||
result = await db.execute(stmt)
|
||||
settings = result.scalar_one_or_none()
|
||||
|
||||
if not settings:
|
||||
settings = ApiSettings(id=1)
|
||||
db.add(settings)
|
||||
|
||||
# Update fields if provided
|
||||
if payload.appKey is not None: settings.appKey = payload.appKey
|
||||
if payload.appSecret is not None: settings.appSecret = payload.appSecret
|
||||
if payload.accountNumber is not None: settings.accountNumber = payload.accountNumber
|
||||
if payload.kisApiDelayMs is not None: settings.kisApiDelayMs = payload.kisApiDelayMs
|
||||
|
||||
await db.commit()
|
||||
await db.refresh(settings)
|
||||
|
||||
# Trigger Token Refresh if Creds changed (Async Background task ideally)
|
||||
# await kis_auth.get_access_token(db)
|
||||
|
||||
return settings
|
||||
Reference in New Issue
Block a user