@2oolkit/kiwoom-cli
Advanced tools
+65
-0
@@ -521,2 +521,3 @@ #!/usr/bin/env node | ||
| rankPrevVolume: { apiId: "ka10031", path: PATHS.rkinfo, korean: "\uC804\uC77C\uAC70\uB798\uB7C9\uC0C1\uC704\uC694\uCCAD", listKey: "pred_trde_qty_upper" }, | ||
| rankForeignInst: { apiId: "ka90009", path: PATHS.rkinfo, korean: "\uC678\uAD6D\uC778\uAE30\uAD00\uB9E4\uB9E4\uC0C1\uC704\uC694\uCCAD", listKey: "frgnr_orgn_trde_upper" }, | ||
| // ── Sector / industry (업종) ─────────────────────────────────────────────── | ||
@@ -540,2 +541,11 @@ sectorPrice: { apiId: "ka20001", path: PATHS.sect, korean: "\uC5C5\uC885\uD604\uC7AC\uAC00\uC694\uCCAD", listKey: "inds_cur_prc_tm" }, | ||
| } | ||
| function withCommas(value) { | ||
| const m = value.match(/^([+-]?)(\d+)(\.\d+)?$/); | ||
| if (!m) return value; | ||
| const grouped = m[2].replace(/\B(?=(\d{3})+(?!\d))/g, ","); | ||
| return `${m[1]}${grouped}${m[3] ?? ""}`; | ||
| } | ||
| function won(value) { | ||
| return withCommas(unpad(value)); | ||
| } | ||
| function formatStamp(value) { | ||
@@ -991,2 +1001,24 @@ if (!value) return ""; | ||
| var import_zod5 = require("zod"); | ||
| // src/utils/ranking.ts | ||
| var NETTRADE_FIELDS = { | ||
| foreign: { buy: "for_netprps", sell: "for_netslmt" }, | ||
| institution: { buy: "orgn_netprps", sell: "orgn_netslmt" } | ||
| }; | ||
| function extractNetTrade(rows, prefix, n) { | ||
| return rows.slice(0, n).map((r, i) => ({ | ||
| rank: i + 1, | ||
| code: r[`${prefix}_stk_cd`], | ||
| name: r[`${prefix}_stk_nm`], | ||
| \uAE08\uC561: won(unpad(r[`${prefix}_amt`] ?? "")), | ||
| \uC218\uB7C9: won(unpad(r[`${prefix}_qty`] ?? "")) | ||
| })).filter((x) => x.code); | ||
| } | ||
| function buildNetTradeResult(rows, investors, side, n) { | ||
| const result = {}; | ||
| for (const inv of investors) result[inv] = extractNetTrade(rows, NETTRADE_FIELDS[inv][side], n); | ||
| return result; | ||
| } | ||
| // src/mcp/tools/ranking.ts | ||
| function registerRankingTools(server2) { | ||
@@ -1066,2 +1098,35 @@ tool( | ||
| server2, | ||
| "get_net_buy_ranking", | ||
| { | ||
| description: "Get the foreign/institution net-buy (\uC218\uAE09) ranking (ka90009): top stocks by foreign and/or institutional net buying or selling. One call returns parallel rankings for both investor types.", | ||
| inputSchema: { | ||
| by: import_zod5.z.enum(["foreign", "institution", "both"]).optional().describe("Investor type: foreign=\uC678\uAD6D\uC778, institution=\uAE30\uAD00, both (default both)"), | ||
| side: import_zod5.z.enum(["buy", "sell"]).optional().describe("buy=\uC21C\uB9E4\uC218 (default), sell=\uC21C\uB9E4\uB3C4"), | ||
| market: import_zod5.z.enum(["000", "001", "101"]).optional().describe("000=all, 001=KOSPI, 101=KOSDAQ"), | ||
| exchange: import_zod5.z.enum(["1", "2", "3"]).optional().describe("1=KRX (default), 2=NXT, 3=unified"), | ||
| count: import_zod5.z.number().int().min(1).max(50).optional().describe("Top N (default 10)"), | ||
| rankBy: import_zod5.z.enum(["1", "2"]).optional().describe("Rank by 1=amount \uAE08\uC561 (default), 2=quantity \uC218\uB7C9"), | ||
| date: import_zod5.z.string().optional().describe("Query date YYYYMMDD (default: latest)") | ||
| } | ||
| }, | ||
| async ({ by, side, market, exchange, count, rankBy, date }) => withErrorHandling(async () => { | ||
| const investors = by === "foreign" ? ["foreign"] : by === "institution" ? ["institution"] : ["foreign", "institution"]; | ||
| const netSide = side === "sell" ? "sell" : "buy"; | ||
| const { data } = await clientOrThrow().callEndpoint(ENDPOINTS.rankForeignInst, { | ||
| mrkt_tp: market ?? "000", | ||
| amt_qty_tp: rankBy === "2" ? "2" : "1", | ||
| qry_dt_tp: date ? "1" : "0", | ||
| date: date ?? "", | ||
| stex_tp: exchange ?? "1" | ||
| }); | ||
| const rows = Array.isArray(data?.[ENDPOINTS.rankForeignInst.listKey]) ? data[ENDPOINTS.rankForeignInst.listKey] : []; | ||
| return mcpJson({ | ||
| side: netSide, | ||
| rankBy: rankBy === "2" ? "quantity" : "amount", | ||
| ...buildNetTradeResult(rows, investors, netSide, count ?? 10) | ||
| }); | ||
| }) | ||
| ); | ||
| tool( | ||
| server2, | ||
| "get_sector", | ||
@@ -1068,0 +1133,0 @@ { |
+1
-1
| { | ||
| "name": "@2oolkit/kiwoom-cli", | ||
| "version": "0.1.1", | ||
| "version": "0.1.2", | ||
| "description": "CLI & MCP server for Kiwoom Securities (키움증권) REST API — quote stocks, query charts, manage your account, and place orders from the terminal", | ||
@@ -5,0 +5,0 @@ "author": "haeminmoon", |
+5
-1
@@ -150,2 +150,3 @@ # kiwoom-cli | ||
| kiwoom-cli ranking prev-volume 전일 거래량 상위 (ka10031) | ||
| kiwoom-cli ranking net-buy [옵션] 수급: 외국인·기관 순매수 상위 (ka90009) | ||
@@ -160,2 +161,5 @@ kiwoom-cli sector price [-m -c] 업종 현재가 (ka20001) | ||
| 수급(`net-buy`, alias `supply`)은 한 번의 ka90009 호출로 외국인·기관 매매상위를 함께 반환합니다: | ||
| `-b foreign|institution|both`(기본 both), `--side buy|sell`(기본 buy=순매수), `-n <1-50>`(기본 10), `-q 1=금액/2=수량`(기본 1), `-d YYYYMMDD`(기본 최신). 예: `kiwoom-cli ranking net-buy -b both -n 10`. | ||
| ### `order` — ⚠ `real`에서는 실제 자금 | ||
@@ -199,3 +203,3 @@ ``` | ||
| 도구: `get_stock_info`, `get_price`, `get_orderbook`, `get_daily_price`, `get_recent_trades`, `search_stocks`, `get_chart`, `get_balance`, `get_deposit`, `get_open_orders`, `get_executions`, `get_realized_pnl`, `get_ranking`, `get_sector`, `place_order`, `modify_order`, `cancel_order`. | ||
| 도구: `get_stock_info`, `get_price`, `get_orderbook`, `get_daily_price`, `get_recent_trades`, `search_stocks`, `get_chart`, `get_balance`, `get_deposit`, `get_open_orders`, `get_executions`, `get_realized_pnl`, `get_ranking`, `get_net_buy_ranking`, `get_sector`, `place_order`, `modify_order`, `cancel_order`. | ||
@@ -202,0 +206,0 @@ 주문 도구는 **`confirm: true`를 넘기지 않으면 미리보기만 반환하고 아무것도 실행하지 않습니다** — 에이전트가 실수로 실주문을 낼 수 없습니다. |
@@ -73,5 +73,8 @@ # Market Data Reference | ||
| kiwoom-cli ranking prev-volume # ka10031 — prior-day volume | ||
| kiwoom-cli ranking net-buy -b both # ka90009 — 수급: 외국인·기관 순매수 상위 | ||
| ``` | ||
| Flags: `-m 000=all/001=KOSPI/101=KOSDAQ`, `-x 1=KRX/2=NXT/3=unified`. | ||
| `net-buy` (alias `supply`) extras: `-b foreign|institution|both` (default both), `--side buy|sell` (default buy=순매수), `-n <1-50>` (default 10), `-q 1=금액/2=수량`, `-d YYYYMMDD`. One ka90009 call returns foreign + institution rankings together. | ||
| ## Sectors / industry | ||
@@ -78,0 +81,0 @@ |
+2
-1
@@ -164,2 +164,3 @@ --- | ||
| | `kiwoom-cli ranking volume\|amount\|surge\|prev-volume` | Volume / value / surge / prior-day | | ||
| | `kiwoom-cli ranking net-buy [-b foreign\|institution\|both] [--side buy\|sell]` | 수급: foreign/institution net-buy top (ka90009) | | ||
| | `kiwoom-cli sector price\|stocks\|all\|daily [-m 0\|1\|2] [-c code]` | Sector indices | | ||
@@ -266,3 +267,3 @@ | `kiwoom-cli sector codes` | List sector (업종) codes | | ||
| 17 tools: `get_stock_info`, `get_price`, `get_orderbook`, `get_daily_price`, `get_recent_trades`, `search_stocks`, `get_chart`, `get_balance`, `get_deposit`, `get_open_orders`, `get_executions`, `get_realized_pnl`, `get_ranking`, `get_sector`, `place_order`, `modify_order`, `cancel_order`. Order tools return a preview unless `confirm: true`. | ||
| 18 tools: `get_stock_info`, `get_price`, `get_orderbook`, `get_daily_price`, `get_recent_trades`, `search_stocks`, `get_chart`, `get_balance`, `get_deposit`, `get_open_orders`, `get_executions`, `get_realized_pnl`, `get_ranking`, `get_net_buy_ranking`, `get_sector`, `place_order`, `modify_order`, `cancel_order`. Order tools return a preview unless `confirm: true`. | ||
@@ -269,0 +270,0 @@ ## Resources |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
436498
4.83%3306
3.73%224
1.82%