@2oolkit/kiwoom-cli 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -1
- package/dist/index.js +55 -0
- package/dist/index.js.map +1 -1
- package/dist/mcp.js +65 -0
- package/dist/mcp.js.map +1 -1
- package/package.json +1 -1
- package/skill/SKILL.md +2 -1
- package/skill/references/market-data.md +3 -0
package/README.md
CHANGED
|
@@ -147,6 +147,7 @@ kiwoom-cli ranking volume 당일 거래량 상위 (ka10030)
|
|
|
147
147
|
kiwoom-cli ranking amount 거래대금 상위 (ka10032)
|
|
148
148
|
kiwoom-cli ranking surge 거래량 급증 (ka10023)
|
|
149
149
|
kiwoom-cli ranking prev-volume 전일 거래량 상위 (ka10031)
|
|
150
|
+
kiwoom-cli ranking net-buy [옵션] 수급: 외국인·기관 순매수 상위 (ka90009)
|
|
150
151
|
|
|
151
152
|
kiwoom-cli sector price [-m -c] 업종 현재가 (ka20001)
|
|
152
153
|
kiwoom-cli sector stocks 업종 구성종목 (ka20002)
|
|
@@ -156,6 +157,9 @@ kiwoom-cli sector codes 업종 코드 목록 (ka10101)
|
|
|
156
157
|
```
|
|
157
158
|
순위: `-m 000=전체/001=코스피/101=코스닥`, `-x 1=KRX/2=NXT/3=통합`.
|
|
158
159
|
|
|
160
|
+
수급(`net-buy`, alias `supply`)은 한 번의 ka90009 호출로 외국인·기관 매매상위를 함께 반환합니다:
|
|
161
|
+
`-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`.
|
|
162
|
+
|
|
159
163
|
### `order` — ⚠ `real`에서는 실제 자금
|
|
160
164
|
```
|
|
161
165
|
kiwoom-cli order buy <코드> <수량> [-p 가격] [-t 유형] [-x KRX|NXT|SOR] [--credit] [-y]
|
|
@@ -194,7 +198,7 @@ kiwoom-cli order cancel 0000139 005930 # 잔량 전부 취소
|
|
|
194
198
|
}
|
|
195
199
|
```
|
|
196
200
|
|
|
197
|
-
도구: `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`.
|
|
201
|
+
도구: `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`.
|
|
198
202
|
|
|
199
203
|
주문 도구는 **`confirm: true`를 넘기지 않으면 미리보기만 반환하고 아무것도 실행하지 않습니다** — 에이전트가 실수로 실주문을 낼 수 없습니다.
|
|
200
204
|
|
package/dist/index.js
CHANGED
|
@@ -851,6 +851,7 @@ var ENDPOINTS = {
|
|
|
851
851
|
rankTradeAmount: { apiId: "ka10032", path: PATHS.rkinfo, korean: "\uAC70\uB798\uB300\uAE08\uC0C1\uC704\uC694\uCCAD", listKey: "trde_prica_upper" },
|
|
852
852
|
rankVolumeSurge: { apiId: "ka10023", path: PATHS.rkinfo, korean: "\uAC70\uB798\uB7C9\uAE09\uC99D\uC694\uCCAD", listKey: "trde_qty_sdnin" },
|
|
853
853
|
rankPrevVolume: { apiId: "ka10031", path: PATHS.rkinfo, korean: "\uC804\uC77C\uAC70\uB798\uB7C9\uC0C1\uC704\uC694\uCCAD", listKey: "pred_trde_qty_upper" },
|
|
854
|
+
rankForeignInst: { apiId: "ka90009", path: PATHS.rkinfo, korean: "\uC678\uAD6D\uC778\uAE30\uAD00\uB9E4\uB9E4\uC0C1\uC704\uC694\uCCAD", listKey: "frgnr_orgn_trde_upper" },
|
|
854
855
|
// ── Sector / industry (업종) ───────────────────────────────────────────────
|
|
855
856
|
sectorPrice: { apiId: "ka20001", path: PATHS.sect, korean: "\uC5C5\uC885\uD604\uC7AC\uAC00\uC694\uCCAD", listKey: "inds_cur_prc_tm" },
|
|
856
857
|
sectorStocks: { apiId: "ka20002", path: PATHS.sect, korean: "\uC5C5\uC885\uBCC4\uC8FC\uAC00\uC694\uCCAD", listKey: "inds_stkpc" },
|
|
@@ -1788,6 +1789,21 @@ ${side.toUpperCase()} ${credit ? "(credit) " : ""}${stk} qty ${qty} ${priceLab
|
|
|
1788
1789
|
await submit(def, body, options);
|
|
1789
1790
|
}
|
|
1790
1791
|
|
|
1792
|
+
// src/utils/ranking.ts
|
|
1793
|
+
var NETTRADE_FIELDS = {
|
|
1794
|
+
foreign: { buy: "for_netprps", sell: "for_netslmt" },
|
|
1795
|
+
institution: { buy: "orgn_netprps", sell: "orgn_netslmt" }
|
|
1796
|
+
};
|
|
1797
|
+
function extractNetTrade(rows, prefix, n) {
|
|
1798
|
+
return rows.slice(0, n).map((r, i) => ({
|
|
1799
|
+
rank: i + 1,
|
|
1800
|
+
code: r[`${prefix}_stk_cd`],
|
|
1801
|
+
name: r[`${prefix}_stk_nm`],
|
|
1802
|
+
\uAE08\uC561: won(unpad(r[`${prefix}_amt`] ?? "")),
|
|
1803
|
+
\uC218\uB7C9: won(unpad(r[`${prefix}_qty`] ?? ""))
|
|
1804
|
+
})).filter((x) => x.code);
|
|
1805
|
+
}
|
|
1806
|
+
|
|
1791
1807
|
// src/commands/ranking.ts
|
|
1792
1808
|
function formatRankRow(row) {
|
|
1793
1809
|
return formatFields(row, {
|
|
@@ -1889,6 +1905,45 @@ function registerRankingCommands(program2) {
|
|
|
1889
1905
|
handleError(err);
|
|
1890
1906
|
}
|
|
1891
1907
|
});
|
|
1908
|
+
ranking.command("net-buy").alias("supply").description("Foreign/institution net-buy \uC218\uAE09 ranking (ka90009)").option("-b, --by <foreign|institution|both>", "Investor: foreign=\uC678\uAD6D\uC778, institution=\uAE30\uAD00, both", "both").option("--side <buy|sell>", "buy=\uC21C\uB9E4\uC218, sell=\uC21C\uB9E4\uB3C4", "buy").option("-m, --market <000|001|101>", "Market: 000=all, 001=KOSPI, 101=KOSDAQ", "000").option("-x, --exchange <1|2|3>", "Exchange: 1=KRX, 2=NXT, 3=unified", "1").option("-n, --count <n>", "Top N (1-50)", "10").option("-q, --rank-by <1|2>", "Rank by 1=amount(\uAE08\uC561), 2=quantity(\uC218\uB7C9)", "1").option("-d, --date <YYYYMMDD>", "Query date (default: latest)").option("-o, --output <format>", "Output format (table/json)", "table").action(async (options) => {
|
|
1909
|
+
try {
|
|
1910
|
+
const side = options.side === "sell" ? "sell" : "buy";
|
|
1911
|
+
const by = ["foreign", "institution", "both"].includes(options.by) ? options.by : "both";
|
|
1912
|
+
const investors = by === "both" ? ["foreign", "institution"] : [by];
|
|
1913
|
+
const n = Math.min(Math.max(parseInt(String(options.count), 10) || 10, 1), 50);
|
|
1914
|
+
const client = createClient();
|
|
1915
|
+
const { data } = await client.callEndpoint(ENDPOINTS.rankForeignInst, {
|
|
1916
|
+
mrkt_tp: options.market,
|
|
1917
|
+
amt_qty_tp: options.rankBy === "2" ? "2" : "1",
|
|
1918
|
+
qry_dt_tp: options.date ? "1" : "0",
|
|
1919
|
+
date: options.date || "",
|
|
1920
|
+
stex_tp: options.exchange
|
|
1921
|
+
});
|
|
1922
|
+
const rows = Array.isArray(data?.[ENDPOINTS.rankForeignInst.listKey]) ? data[ENDPOINTS.rankForeignInst.listKey] : [];
|
|
1923
|
+
const fmt = getOutputFormat(options);
|
|
1924
|
+
const sideKo = side === "buy" ? "\uC21C\uB9E4\uC218" : "\uC21C\uB9E4\uB3C4";
|
|
1925
|
+
const labelKo = { foreign: "\uC678\uAD6D\uC778", institution: "\uAE30\uAD00" };
|
|
1926
|
+
if (fmt === "json") {
|
|
1927
|
+
const result = {
|
|
1928
|
+
side,
|
|
1929
|
+
rankBy: options.rankBy === "2" ? "quantity" : "amount"
|
|
1930
|
+
};
|
|
1931
|
+
for (const inv of investors) {
|
|
1932
|
+
result[inv] = extractNetTrade(rows, NETTRADE_FIELDS[inv][side], n);
|
|
1933
|
+
}
|
|
1934
|
+
output(result, "json");
|
|
1935
|
+
return;
|
|
1936
|
+
}
|
|
1937
|
+
for (const inv of investors) {
|
|
1938
|
+
const list = extractNetTrade(rows, NETTRADE_FIELDS[inv][side], n);
|
|
1939
|
+
console.log(`
|
|
1940
|
+
${labelKo[inv]} ${sideKo} TOP${n} (${options.rankBy === "2" ? "\uC218\uB7C9" : "\uAE08\uC561"} \uAE30\uC900)`);
|
|
1941
|
+
output(list, "table");
|
|
1942
|
+
}
|
|
1943
|
+
} catch (err) {
|
|
1944
|
+
handleError(err);
|
|
1945
|
+
}
|
|
1946
|
+
});
|
|
1892
1947
|
}
|
|
1893
1948
|
|
|
1894
1949
|
// src/commands/sector.ts
|