window pc AI server 구축 및 NAS 중계 서버 연결 설정
This commit is contained in:
@@ -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")}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user