window pc AI server 구축 및 NAS 중계 서버 연결 설정

This commit is contained in:
2026-01-27 01:26:23 +09:00
parent b6fd444dba
commit a8cbef75db
5 changed files with 51 additions and 262 deletions

View File

@@ -1,24 +1,23 @@
import os
from fastapi import FastAPI
import requests
from apscheduler.schedulers.background import BackgroundScheduler
from pydantic import BaseModel
from .db import init_db, save_articles, get_latest_articles
from .db import init_db, save_articles, get_latest_articles
from .scraper import fetch_market_news, fetch_major_indices, fetch_overseas_news
from .kis_api import KisApi
from .analysis import AIAnalyst
from pydantic import BaseModel
app = FastAPI()
scheduler = BackgroundScheduler(timezone=os.getenv("TZ", "Asia/Seoul"))
kis = KisApi()
analyst = AIAnalyst()
# Windows AI Server URL (NAS .env에서 설정)
WINDOWS_AI_SERVER_URL = os.getenv("WINDOWS_AI_SERVER_URL", "http://192.168.0.5:8000")
@app.on_event("startup")
def on_startup():
init_db()
# 매일 아침 8시 뉴스 스크랩
# 매일 아침 8시 뉴스 스크랩 (NAS 자체 수행)
scheduler.add_job(run_scraping_job, "cron", hour="8", minute="0")
# 앱 시작 시에도 한 번 실행 (데이터 없으면)
@@ -44,7 +43,6 @@ def run_scraping_job():
def health():
return {"ok": True}
@app.get("/api/stock/news")
@app.get("/api/stock/news")
def get_news(limit: int = 20, category: str = None):
"""최신 주식 뉴스 조회 (category: 'domestic' | 'overseas')"""
@@ -59,15 +57,22 @@ def get_indices():
def trigger_scrap():
"""수동 스크랩 트리거"""
run_scraping_job()
run_scraping_job()
return {"ok": True}
# --- Trading API ---
# --- Trading API (Windows Proxy) ---
@app.get("/api/trade/balance")
def get_balance():
"""계좌 잔고 조회 (보유주식 + 예수금)"""
return kis.get_balance()
"""계좌 잔고 조회 (Windows AI Server Proxy)"""
try:
# Windows Server로 잔고 조회 요청 (Windows가 직접 KIS 호출)
resp = requests.get(f"{WINDOWS_AI_SERVER_URL}/trade/balance", timeout=5)
# Windows Server가 500 등을 내더라도 JSON 포맷이면 그대로 전달
if resp.status_code != 200:
return {"error": "Windows AI Server returned error", "status": resp.status_code, "detail": resp.text}
return resp.json()
except Exception as e:
return {"error": "Failed to connect to Windows AI Server", "detail": str(e), "url": WINDOWS_AI_SERVER_URL}
class OrderRequest(BaseModel):
code: str
@@ -77,19 +82,36 @@ class OrderRequest(BaseModel):
@app.post("/api/trade/order")
def order_stock(req: OrderRequest):
"""주식 매수/매도 주문"""
if req.type not in ["buy", "sell"]:
return {"success": False, "message": "Invalid type (buy/sell)"}
return kis.order(req.code, req.qty, req.price, req.type)
"""주식 매수/매도 주문 (Windows AI Server Proxy)"""
try:
# Windows Server로 주문 요청
resp = requests.post(f"{WINDOWS_AI_SERVER_URL}/trade/order", json=req.dict(), timeout=10)
return resp.json()
except Exception as e:
return {"success": False, "message": f"Proxy Error: {str(e)}", "url": WINDOWS_AI_SERVER_URL}
@app.post("/api/trade/auto")
def auto_trade():
"""AI 자동 매매 트리거 (Windows AI Server Proxy)"""
try:
# Windows Server로 AI 매매 요청
resp = requests.post(f"{WINDOWS_AI_SERVER_URL}/trade/auto", timeout=120)
return resp.json()
except Exception as e:
return {"success": False, "message": f"Proxy Error: {str(e)}", "url": WINDOWS_AI_SERVER_URL}
@app.get("/api/stock/analyze")
def analyze_market():
"""최신 뉴스를 기반으로 AI 시장 요약"""
articles = get_latest_articles(20)
result = analyst.analyze_market_summary(articles)
return {"analysis": result, "model": analyst.model}
"""Windows PC를 통한 AI 시장 분석"""
try:
# Windows AI Server의 API 호출
resp = requests.post(f"{WINDOWS_AI_SERVER_URL}/analyze/portfolio", timeout=120)
return resp.json()
except Exception as e:
return {"error": "Failed to connect to Windows AI Server", "detail": str(e), "url": WINDOWS_AI_SERVER_URL}
@app.get("/api/version")
def version():
return {"version": os.getenv("APP_VERSION", "dev")}