# πŸ“ˆ Stock Lab API Specification ν”„λ‘ νŠΈμ—”λ“œ 연동을 μœ„ν•œ 주식 μ„œλΉ„μŠ€ API λͺ…μ„Έμ„œμž…λ‹ˆλ‹€. **Base URL**: `/api` --- ## 1. πŸ’° κ³„μ’Œ μž”κ³  쑰회 ν˜„μž¬ μ—°κ²°λœ ν•œκ΅­νˆ¬μžμ¦κΆŒ κ³„μ’Œμ˜ μž”κ³ μ™€ 보유 μ’…λͺ©μ„ μ‘°νšŒν•©λ‹ˆλ‹€. - **URL**: `/trade/balance` - **Method**: `GET` - **Description**: Windows AI Serverλ₯Ό 톡해 μ‹€μ‹œκ°„ μž”κ³ λ₯Ό κ°€μ Έμ˜΅λ‹ˆλ‹€. ### Response Example ```json { "holdings": [ { "code": "005930", "name": "μ‚Όμ„±μ „μž", "qty": 10, "buy_price": 72000.0, "current_price": 74500.0, "profit_rate": 3.47 } ], "summary": { "total_eval": 15400000, "deposit": 5000000, "note": "정상 쑰회됨" } } ``` --- ## 2. πŸ€– AI μžλ™ λ§€λ§€ (뢄석/μ£Όλ¬Έ) AIμ—κ²Œ ν˜„μž¬ μž”κ³ μ™€ λ‰΄μŠ€λ₯Ό 기반으둜 λ§€λ§€ νŒλ‹¨μ„ μš”μ²­ν•©λ‹ˆλ‹€. - **URL**: `/trade/auto` - **Method**: `POST` - **Description**: λΆ„μ„μ—λŠ” 수 초~μˆ˜μ‹­ μ΄ˆκ°€ μ†Œμš”λ  수 μžˆμŠ΅λ‹ˆλ‹€. (νƒ€μž„μ•„μ›ƒ 주의) ### Response Example (성곡 - JSON νŒŒμ‹± μ™„λ£Œ) ```json { "status": "success", "decision": { "action": "BUY", "ticker": "000660", "quantity": 10, "reason": "λ°˜λ„μ²΄ μ—…ν™© κ°œμ„  λ‰΄μŠ€ λ‹€μˆ˜ 포착 및 ν˜„κΈˆ 비쀑 κ³Όλ‹€" }, "trade_result": { "success": true, "order_no": "1234567" } } ``` ### Response Example (μ‹€νŒ¨ - AIκ°€ JSON을 μ•ˆ 쀬을 λ•Œ) AIκ°€ 말둜 μ„€λͺ…ν•˜λŠλΌ JSON 포맷을 μ–΄κΈ΄ κ²½μš°μž…λ‹ˆλ‹€. `raw_response`λ₯Ό 화면에 κ·ΈλŒ€λ‘œ λ³΄μ—¬μ£ΌλŠ” 것을 ꢌμž₯ν•©λ‹ˆλ‹€. ```json { "status": "failed_parse", "raw_response": "μž”κ³  ν˜„ν™©μ„ 뢄석해 λ³΄κ² μŠ΅λ‹ˆλ‹€...\nκ²°μ •:\n```\n{\n ... \n}\n```" } ``` **Frontend 처리 ꢌμž₯사항**: `status`κ°€ `failed_parse`라면 `raw_response` ν…μŠ€νŠΈλ₯Ό `pre` νƒœκ·Έ λ“±μœΌλ‘œ κ·ΈλŒ€λ‘œ λ…ΈμΆœν•˜κ±°λ‚˜, μ •κ·œμ‹μœΌλ‘œ JSON λΆ€λΆ„λ§Œ μΆ”μΆœν•˜μ—¬ λ³΄μ—¬μ£Όμ„Έμš”. --- ## 3. πŸ“° λ‰΄μŠ€ 쑰회 DB에 μ €μž₯된 μ΅œμ‹  λ‰΄μŠ€λ₯Ό μ‘°νšŒν•©λ‹ˆλ‹€. - **URL**: `/stock/news` - **Method**: `GET` - **Params**: - `limit`: 개수 (κΈ°λ³Έ 20) - `category`: `domestic` (κ΅­λ‚΄) | `overseas` (ν•΄μ™Έ) ### Response Example ```json [ { "id": 105, "title": "μ‚Όμ„±μ „μž, 3λΆ„κΈ° μ˜μ—…μ΅ 2.4μ‘°... μ „λ…„λΉ„ 77% κ°μ†Œ", "link": "https://n.news.naver.com/...", "published_at": "2024-09-25T09:00:00", "sentiment": "negative" } ] ``` --- ## 4. πŸ“Š μ§€μˆ˜ 쑰회 KOSPI, KOSDAQ λ“± μ£Όμš” μ§€μˆ˜λ₯Ό μ‘°νšŒν•©λ‹ˆλ‹€. - **URL**: `/stock/indices` - **Method**: `GET` ### Response Example ```json { "KOSPI": { "value": "2450.55", "change": "-10.23", "percent": "-0.42%" }, "USD/KRW": { "value": "1340.50", "change": "5.00", "percent": "0.37%" } } ``` --- ## 5. πŸ“‚ 포트폴리였 (μˆ˜λ™ μž…λ ₯) KBμ¦κΆŒΒ·μ‚Όμ„±μ¦κΆŒ λ“± Open API 미제곡 μ¦κΆŒμ‚¬μš©. 보유 μ’…λͺ©μ„ μˆ˜λ™ λ“±λ‘ν•˜λ©΄ **ν˜„μž¬κ°€λŠ” 넀이버 κΈˆμœ΅μ—μ„œ μžλ™ 쑰회** (3λΆ„ μΊμ‹œ)ν•˜μ—¬ 손읡을 계산해 λ°˜ν™˜ν•©λ‹ˆλ‹€. --- ### 5-1. 전체 쑰회 - **URL**: `GET /portfolio` - **Description**: λ“±λ‘λœ λͺ¨λ“  μ’…λͺ©μ˜ ν˜„μž¬κ°€Β·ν‰κ°€κΈˆμ•‘Β·μ†μ΅μ„ ν¬ν•¨ν•˜μ—¬ λ°˜ν™˜ν•©λ‹ˆλ‹€. #### Response ```json { "holdings": [ { "id": 1, "broker": "KB증ꢌ", "ticker": "005930", "name": "μ‚Όμ„±μ „μž", "quantity": 100, "avg_price": 72000, "current_price": 74500, "price_session": "NXT_AFTER", "price_as_of": "2026-05-11T19:21:40+09:00", "eval_amount": 7450000, "profit_amount": 250000, "profit_rate": 3.47 } ], "summary": { "total_buy": 7200000, "total_eval": 7450000, "total_profit": 250000, "total_profit_rate": 3.47 } } ``` > **주의**: ν˜„μž¬κ°€ μ‘°νšŒμ— μ‹€νŒ¨ν•œ μ’…λͺ©μ€ `current_price`, `eval_amount`, `profit_amount`, `profit_rate` κ°€ `null`둜 λ°˜ν™˜λ©λ‹ˆλ‹€. > ν”„λ‘ νŠΈμ—μ„œ `null` 체크 ν›„ `"쑰회 μ‹€νŒ¨"` λ“±μœΌλ‘œ ν‘œμ‹œν•΄ μ£Όμ„Έμš”. > **ν˜„μž¬κ°€ 좜처(`price_session`)**: μ •κ·œμž₯ 마감 ν›„ NXT μ‹œκ°„μ™Έ κ±°λž˜κ°€ μ§„ν–‰ 쀑이면 NXT κ°€κ²©μœΌλ‘œ μžλ™ μ „ν™˜λ©λ‹ˆλ‹€. > - `REGULAR` β€” KRX μ •κ·œμž₯ 진행쀑(09:00–15:30) μ‹€μ‹œκ°„ 가격 > - `NXT_PRE` β€” NXT ν”„λ¦¬λ§ˆμΌ“(08:00–08:50) κ±°λž˜κ°€ > - `NXT_AFTER` β€” NXT μ• ν”„ν„°λ§ˆμΌ“(15:30–20:00) κ±°λž˜κ°€ > - `CLOSED` β€” λͺ¨λ“  μ„Έμ…˜ 마감, μ •κ·œμž₯ μ’…κ°€ λ…ΈμΆœ > > `price_as_of`λŠ” 가격이 λ§ˆμ§€λ§‰μœΌλ‘œ ν˜•μ„±λœ μ‹œκ°(ISO 8601, KST). HTML 폴백 κ²½λ‘œμ—μ„œλŠ” `null`일 수 있음. --- ### 5-2. μ’…λͺ© μΆ”κ°€ - **URL**: `POST /portfolio` - **Status**: `201 Created` #### Request Body ```json { "broker": "KB증ꢌ", "ticker": "005930", "name": "μ‚Όμ„±μ „μž", "quantity": 100, "avg_price": 72000 } ``` | ν•„λ“œ | νƒ€μž… | μ„€λͺ… | |------|------|------| | `broker` | string | μ¦κΆŒμ‚¬λͺ… (자유 μž…λ ₯) | | `ticker` | string | μ’…λͺ© μ½”λ“œ 6자리 | | `name` | string | μ’…λͺ©λͺ… | | `quantity` | integer | 보유 μˆ˜λŸ‰ | | `avg_price` | integer | 평균 λ§€μž…κ°€ (원) | #### Response ```json { "id": 1, "ok": true } ``` --- ### 5-3. μ’…λͺ© μˆ˜μ • - **URL**: `PUT /portfolio/{id}` - **Description**: λ³€κ²½ν•  ν•„λ“œλ§Œ ν¬ν•¨ν•˜λ©΄ λ©λ‹ˆλ‹€ (λΆ€λΆ„ μˆ˜μ •). #### Request Body (λͺ¨λ“  ν•„λ“œ Optional) ```json { "quantity": 150 } ``` #### Response ```json { "ok": true } ``` #### Error (μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” id) ```json { "error": "Item not found" } // HTTP 404 ``` --- ### 5-4. μ’…λͺ© μ‚­μ œ - **URL**: `DELETE /portfolio/{id}` #### Response ```json { "ok": true } ``` #### Error (μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” id) ```json { "error": "Item not found" } // HTTP 404 ```