v2.11.0 — API 파라미터 감사 (Tranche B)#28
Merged
Merged
Conversation
--trade의 기본값이 실제로는 순매도(2) 데이터를 반환하고 있었다. 스펙(ka10066 Request Body)은 trde_tp를 0:순매수, 1:매수, 2:매도로 정의하는데 기존 Choice(["1","2"])/default="2"는 진짜 순매수 코드 0을 아예 받을 수 없었고 help는 반대로 "2=순매수"라고 안내했다. - --trade: HumanChoice(TRDE_TP_NET_BUY_BUY_SELL), default="net-buy" (net-buy=0/buy=1/sell=2) - --amount-qty: HumanChoice(AMT_QTY_TP_STD) (amount=1/quantity=2, 값은 변경 없음 — presentation만 전환) - --market: MARKET_ALL로 전환, 스펙에 있는 000:전체(all) 추가 지원 - --exchange: EXCHANGE_ALL이 이미 스펙(1:KRX,2:NXT,3:통합)과 일치해 변경 없음 Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…euse guard (ka10066)
Review round 1 on the ka10066 매매구분 fix:
- CHANGELOG wrongly claimed raw numeric --trade/--amount-qty codes were no
longer valid. HumanChoice.convert() backward-compat-allows raw codes by
design; verified live that --trade 0/1/2 and --amount-qty 1/2 all still
work. Reframed the entry: E-side name conversion is non-breaking, the
only real breaking change is --trade's default flipping trde_tp 2->0.
- Renamed AMT_QTY_TP_STD -> AMT_QTY_TP_1_2 so the name itself encodes the
wire codes, since ka10051/ka10131 use an identical {amount,quantity} key
set with different codes (0/1) and nothing in "STD" would have stopped
a future misreuse. Reserved AMT_QTY_TP_0_1 in a comment for that pair.
- Added the missing --market kosdaq coverage test for after-close.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
amt_qty_tp 스펙은 0:금액,1:수량인데 기존 Choice(["1","2"])/default="1"은
한 칸 밀려 있어 기본값이 실제로는 수량을 반환했고 스펙에 없는 값 2도
선택 가능했다. AMT_QTY_TP_0_1(Task 8이 예약해 둔 이름)로 교체하고
default="amount"(wire "0")로 정정.
같은 자리의 다른 4개 옵션도 함께 정리(Tranche B+E는 한 사이트에서 둘 다
처리):
- --period(dt): 자유 텍스트 -> HumanChoice(recent/3d/5d/10d/20d/120d/range),
0이 "시작/종료일자로 조회" 모드 전환임을 스펙에서 확인, 기본값 wire "5" 불변
- --net-type(netslmt_tp): 자유 텍스트 -> HumanChoice({"net-buy":"2"}) (스펙상
고정값 1개), wire "2" 불변
- --stock-sector(stk_inds_tp): Choice(["0","1"]) -> HumanChoice(stock/sector),
wire "0" 불변
- --exchange(stex_tp): 이미 EXCHANGE_ALL로 스펙과 일치, 변경 없음
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
자유 입력이던 --period가 열거형이 되면서 이전에 그대로 전송되던 스펙 미정의 값(예: --period 7)이 이제 전송 전에 거부된다. 하위호환 절에 이 축소를 적지 않아 리뷰에서 지적됐다 — 이름 추가는 하위호환이지만 값 제한은 아니다. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
ka10063 요청 바디 6개 필드 중 5개가 스펙과 어긋나 있었다: - invsr 기본값이 ka10058 invsr_tp 코드북을 복붙한 스펙 밖 값 "1000" (스펙 Length=1) -> INTRADAY_INVESTOR + HumanChoice, default="foreign"(6) - mrkt_tp가 MARKET_TWO(kospi/kosdaq)라 스펙의 000:전체를 못 씀 -> MARKET_ALL - amt_qty_tp가 자유 텍스트(스펙상 값 1개뿐) -> AMT_QTY_TP_COMBINED enum - frgn_all/smtm_netprps_tp가 원시 0/1 노출 -> 공용 CHECK_YES_NO - stex_tp(EXCHANGE_ALL)는 이미 스펙과 일치해 손대지 않음 TDD로 진행: invsr=="6" 단언 테스트를 먼저 작성해 기존 "1000"으로 실패하는 것을 확인한 뒤 수정. 15개 테스트 추가(796 = 781 + 15), ruff clean.
fix(stock) 커밋과 분리해 breaking 두 건(invsr 기본값 1000->6, amount-qty 자유텍스트->enum)과 non-breaking human-readable 이름 추가를 구분 기록.
…O 개명 (ka10063)
리뷰 발견 2건 수정:
1. CHANGELOG가 --investor-type을 (a) 기본값 변경으로만 breaking
처리했지만, 이 옵션은 원래 type= 없는 자유 텍스트였으므로 (c)
자유텍스트->enum narrowing이기도 하다. 실측 회귀 2건을 기록:
--investor-type 1000(이전 기본값)과 --investor-type 9 둘 다
이전엔 그대로 전송됐지만 지금은 exit 1. 하위호환 문단의 과잉
주장("숫자 코드를 직접 넘기던 스크립트는 그대로 동작합니다")도
새 매핑에 있는 값(스펙이 정의한 코드)으로 범위를 좁혔다 —
--amount-qty가 이미 받고 있던 처리와 동일하게 맞춤.
2. _constants.py의 CHECK_YES_NO를 CHECK_YES_1_NO_0으로 개명.
이름에 wire 값(1/0)과 극성을 박아 넣어 AMT_QTY_TP_1_2/
AMT_QTY_TP_0_1 명명 관례와 맞추고, stock.py에 남아있는 무관한
click.Choice(["0","1"]) 6곳(indc_tp 등)이 이 이름에 이끌려
재사용되는 것을 막았다. 순수 rename — 전송값/기본값 변경 없음.
pytest tests/test_stock.py -q: 56 passed. ruff check kiwoom_cli/: All
checks passed. 두 회귀 모두 실제 CLI 실행으로 재확인함(추측 아님).
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
credit inquiry(kt20017)는 필수 stk_cd를 받을 인자가 없어 {}만 전송해
호출이 원천적으로 성립하지 않았다. 종목코드를 위치 인자로 추가해
{"stk_cd": code}를 전송한다.
credit available(kt20016)은 필수 mrkt_deal_tp를 누락했다. --market
(CREDIT_MARKET: all=%, kospi=1, kosdaq=0 — MARKET_KOSPI_KOSDAQ와 극성
반대, 항상 전송), --grade(CREDIT_GRADE, 항상 전송), --code(선택,
미지정 시 stk_cd 키 자체를 생략)를 추가했다.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…017) Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
README의 stock daily --type week 예제를 stock chart week로 교체하고, CHANGELOG [Unreleased]에 이 릴리스의 유일한 진짜 breaking 변경을 기재.
--market이 형제 API(ka90007)에서 복붙된 "0"/"1"을 보내고 있었다. ka90005/ ka90010의 mrkt_tp는 10자리 P-코드이고 값이 stex_tp와 연동된다 (docs/미국 REST API 문서.xlsx). --market을 kospi/kosdaq Choice로 바꾸고 PROGRAM_MARKET_BY_EXCHANGE[market][stex_tp]로 해석하도록 수정했다. --exchange도 KRX/NXT만 받던 것을 EXCHANGE_ALL(all=3 포함)로 확장했다 — stex_tp=3(통합) 분기가 실제로 존재하는데 이전에는 지정할 방법이 없었다. 두 API 스펙 시트가 코스닥+통합 코드를 다르게 적고 있다(ka90005: P101_AL02, ka90010: P001_AL02) — 워크북/키움 공식 GitHub 전체에서 동일하게 나타나는 모순이라 키움 소스로는 판정 불가. 사용자 결정으로 코스닥 계열 접두사(P101_)에 맞춰 두 API 모두 P101_AL02로 통일했다 (_constants.py의 PROGRAM_MARKET_BY_EXCHANGE 주석에 근거 기록). amt_qty_tp/min_tic_tp도 원시 코드 옵션이었던 것을 HumanChoice로 전환 (AMT_QTY_TP_1_2 재사용, MIN_TIC_TP 신설). Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
…010) Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
ka10030(rank volume)/ka10032(rank amount)의 mang_stk_incls 극성 반전을 바로잡고 ka10030은 15종 종목필터를 온전히 노출하는 --stock-condition으로 분리했다. ka10038(broker-by-stock)은 --period/--from·--to 동시 지정 시 기간(dt) 우선이 조용히 이기던 것을 막고 스펙대로 --from/--to일 때 dt 키를 아예 제외하도록 고쳤다. ka30002(elw broker-top)의 --issuer 기본값이 자릿수부터 틀린(12자리, 필드는 3자리) 무효값이었던 것을 제거하고 필수 옵션으로 바꿨다. 두 명령의 나머지 자유 텍스트 옵션도 HumanChoice로 전환. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
ka10030/ka10032 mang_stk_incls 극성 반전, --stock-condition 신설, ka10038 --period/--from·--to 상호배타, ka30002 --issuer 필수화, enum 전환 목록을 CHANGELOG에 기록. 모든 주장은 CLI 실행으로 확인. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
… requires both --from/--to Two review findings on 11d1486/3964b3f: - _constants.py: STOCK_CONDITION's name translates to 종목조건 (Korean name of the raw-text stk_cnd field used by ~10 market.py commands), but the constant actually holds ka10030's mang_stk_incls codes. Extended the comment to warn a future stk_cnd->HumanChoice conversion off reusing this constant. No behavior change. - market.py rank_broker_by_stock (ka10038): has_range = bool(strt_dt or end_dt) let a lone --from (or --to) through, sending {strt_dt: "...", end_dt: "", dt: <key excluded>} — an under-specified request. The spec's blank-dt rule only applies when both start and end date are given. Added a guard requiring --from and --to together, exiting 1 (INVALID_INPUT) otherwise. Added tests for each one-sided case asserting exit 1 and no request sent. Updated CHANGELOG Fixed/Breaking entries, wording verified against actual CLI output.
qry_dt_tp 기본값이 "0"(기간으로 조회)이라 --from/--to가 required=True인데도 API가 그 필수 날짜를 무시하고 있었고, mmcm_cd(Required=Y)는 기본값이 빈 문자열이었다. --date-type 기본값을 "1"(start-end)로 바꾸고 --broker를 필수로 승격했다. --date-type/--pot/--sort/--days 네 옵션도 HumanChoice로 전환(하위호환 raw 코드 유지). dt 코드북은 ka10038의 off-by-one 코드북과 값이 다르므로(5일=5, 정상) 절대 합치지 말 것을 상수 주석에 명시. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
The Breaking bullet claimed --date-type/--pot/--sort/--days were free text and got narrowed to an enum. Verified against 857fc98: all four already carried click.Choice with numeric codes, and --date-type 9 fails identically before/after (exit 1). The accepted set only widened (human-readable names added alongside existing codes), which the Non-breaking section already documents accurately — so the false bullet is just deleted. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
지정가 계열(limit/vwap-limit/twap-limit/loc/stop-limit)에서 --price 없이 주문하면 ord_uv=""로 조용히 전송되고 있었다. ust20000/ust20001 스펙: "trde_tp가 00(지정가),30(LOC)...인 경우 필수 입력". US_MARKET_TYPES의 여집합으로 US_LIMIT_TYPES를 신설하고, _validate_us_type에 반대 방향 가드를 추가했다. 국내(kt10000/kt10001)는 조건부 필수 문구가 스펙에 없어 대상에서 제외했다. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
Breaking: --price 없이 지정가 계열을 호출하던 스크립트는 이제 exit 1 — 다만 그 호출은 원래 정상 동작한 적이 없었다(ord_uv="" 전송). 국내 경로는 스펙 근거 부족으로 의도적으로 그대로 두었다는 점도 함께 기록. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
여섯 개 작업이 각자 이어붙인 Fixed/Breaking/Non-breaking 헤딩이 8번 반복되던 것을 각 1개로 병합했다. 내용 변경 없이 순서만 정리했다. - Non-breaking인데 Breaking에 있던 두 항목을 이동: credit inquiry/available의 CREDIT_MARKET 극성 설명(자체 결론이 이미 "하위호환 깨짐 아님"), program time/daily-trend의 --exchange all 추가(순수 확장) - bool(strt_dt or end_dt)를 버그로 서술한 Fixed 항목 삭제 — 같은 Unreleased 구간 안에서 도입되고(11d1486) 세 커밋 뒤에 고쳐진(857fc98) 릴리스 내부 리그레션이라, 배포된 적 없는 버그를 배포된 것처럼 적어 독자를 오도했다. 옆의 Breaking 항목이 실제 사용자 영향(--from/--to 한쪽만 주면 exit 1)을 이미 정확히 설명한다 - 미국 --price 가드 항목에서 "(컨트롤러가 워크북에서 직접 확인)" 제거, 영향받는 명령 목록에 --dry-run 추가(order buy NVDA 10 --type limit --dry-run도 이제 exit 1) CLI로 직접 실행해 확인: --exchange all 추가는 기본 호출 body 불변, credit 커맨드 둘 다 이전엔 옵션이 하나도 없었음, --dry-run이 가격 가드보다 먼저 걸림.
여집합으로 정의하는 방식은 실수를 막지 못하고 비대칭으로 만들 뿐이다. 새 주문유형을 US_MARKET_TYPES에 추가하는 걸 잊으면 조용히 지정가 계열로 분류돼 --price를 요구하게 된다 — 즉 시장가 계열 신규 유형이 정당한 무가격 주문을 거부당하는 쪽으로만 실패한다. 주문 경로에서는 이 방향이 의도한 선택(과잉 거부가 가격 누락 주문 전송보다 안전)이라는 점을 주석에 명시했다. 정의 자체는 변경하지 않았다 — 동작 변화 없음.
이전 Choice 목록 ["1","2"]에서 2는 실제로 amt_qty_tp="2"로 전송됐지만 새 AMT_QTY_TP_0_1에는 없는 값이라 이제 exit 1이다. 값 집합이 줄었으므로 옵션이 이미 Choice였더라도 breaking이다. Non-breaking 쪽에서 "숫자 코드는 그대로 동작한다"고 단언하던 문장도 스펙이 정의한 코드로 한정해 새 breaking 항목과 어긋나지 않게 고쳤다.
program time-trend/daily-trend의 --unit·--tick-type과 investor consecutive의 --period·--net-type은 fe289c7 시점에 전부 type= 없는 자유 텍스트였다. 매핑 밖 값이 이제 거부되므로 non-breaking이 아니라 breaking이다. Non-breaking 쪽에 꼬리말로 붙어 있던 축소 고백 두 군데를 걷어내고, 기존 breaking 축소 목록에 항목 하나로 합쳤다.
"dt 키를 빼고 빈 문자열인 채로 전송했다"는 서술은 브랜치 중간 커밋 11d1486의 상태였고 857fc98에서 고쳐져 릴리스된 적이 없다. fe289c7의 실제 코드는 날짜와 함께 dt="1"을 항상 보내 기간 조회가 이기고 있었다. 결론(breaking)은 그대로 두고 이전 동작 설명만 고쳤다.
account/market/stock만 손으로 나열하다 보니 order 그룹이 통째로 빠져 금현물 주문의 --order-type(GOLD_ORDER_TYPES) 2건이 집계에서 누락돼 있었다. 루트 cli부터 내려가도록 바꿔 그룹이 새로 생겨도 자동으로 잡히게 했고, 실제 측정값 55로 고정했다. 개수만 맞으면 통과하는 것을 막으려고 금현물 두 건은 이름으로도 못 박았다. 매핑 레지스트리 테스트에도 데코레이터에 물려 있는데 빠져 있던 13개를 채웠다 (GOLD_ORDER_TYPES, CREDIT_MARKET, AMT_QTY_TP_0_1, AMT_QTY_TP_1_2, INTRADAY_INVESTOR, MIN_TIC_TP 등).
배포되는 주석에 task 번호와 docs/superpowers/plans/... 경로가 남아 있었다. 그 플랜 저장소는 비공개라 읽는 사람에게 아무 의미가 없다. 내용은 그대로 두고 참조만 걷어냈다. AMT_QTY_TP_0_1의 경우 사라진 C4 링크 자리에 왜 합치면 안 되는지(키 집합이 같아 조용히 통과하고 극성만 뒤집힌 값이 나간다)를 직접 적었다. 절대 합치지 말 것 경고는 전부 유지.
ka10030 시트가 500 코드를 "500만주이상"으로 적어 이웃 항목들의 산술 패턴과 어긋나는 탓에 500k라는 이름을 "보수적 선택"으로만 적어 뒀었다. 키움 공식 kwcli의 maps/arguments.csv가 rankings today-volume의 같은 필드를 9개 값 전부 우리와 동일하게(500k=500 포함) 매핑하고 있어 확인됐다. CHANGELOG에도 같은 유보 문구가 있어 함께 고쳤다.
두 맵을 서로 바꿔 끼워도 기존 891개 테스트가 전부 통과했다. 공유 키의 전송값이 전부 같아 잘못된 값이 나가지는 않지만, 형제 쌍마다 분리를 고정해 온 이 브랜치의 방식과 어긋나 비어 있던 자리다. 유일하게 드러나는 차이인 ka10030 전용 200/300으로 양쪽을 고정했다. rank volume은 200k/300k를 받아 200/300을 보내야 하고, elw broker-top은 같은 값을 exit 1로 거부해야 한다. 맵을 맞바꾸면 4개 전부 실패한다.
국내 지정가 주문의 ord_uv 가드 관련 서술을 교정했습니다. kwcli가 배포하는 order_price_policies.csv에 국내 지정가 --price required가 명시돼 있어, "근거가 없다"는 기존 설명은 사실과 달랐습니다. 가드 자체는 다음 릴리스로 미룹니다 — 서버가 빈 값을 거부하므로 잘못된 주문이 나가지는 않습니다. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
README의 금현물 매수 예제가 --type market을 쓰고 있었습니다. 금현물에는 시장가가 없어 v0.2.1부터 동작하지 않던 예제입니다. 지정가로 바꾸고 이유를 주석으로 남겼습니다. Excel은 v2.9.0 이후 갱신이 없어 61개 커밋만큼 밀려 있었습니다. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
키움 스펙 대비 잘못 전송되던 API 파라미터를 교정하고, 자유 텍스트 옵션을 human-readable enum으로 전환했습니다. 15개 API(ka10066, ka10131, ka10063, kt20016, kt20017, ka10005, ka90005, ka90010, ka10030, ka10032, ka10038, ka30002, ka10043, ust20000, ust20001)가 대상입니다.
테스트 757 → 895, ruff clean.
Breaking
stock daily --type제거 — 주/월 조회는stock chart사용market rank volume --include-managed→--stock-condition(15종 종목필터, boolean이 아니었음)market elw broker-top --issuer,stock trader-analysis --broker필수화credit inquiry가 종목코드를 위치 인자로 받음--price누락 시 전송 전exit 1HumanChoice로 계속 동작)stock investor consecutive --amount-qty 2거부 — 스펙에 없는 값이었음검토
브랜치 전체를 세 갈래로 리뷰했습니다: 태스크 간 상호작용, 스펙 대비 전송값, CHANGELOG 정확성. 모든 리뷰는 프로덕션 코드를 되돌려 테스트가 실제로 실패하는지 확인하는 방식으로 검증했습니다.
전송값 검토에서 kwcli가 배포하는
arguments.csv가 이 브랜치의 값 매핑과 문자 단위로 일치함을 확인했습니다. 값 오류는 나오지 않았습니다.리뷰에서 나온 7건을 수정했습니다. 가장 중요한 건
--amount-qty 2제거가 breaking으로 공시되지 않은 채 Non-breaking 항목이 정반대 내용을 주장하던 문제였습니다.HumanChoice고정 테스트가order그룹을 훑지 않아 금현물 주문 2건을 놓치고 있던 것도 함께 고쳤습니다(53 → 55, CLI 트리 전체 순회로 변경).다음 릴리스로 미룬 것
ord_uv가드 — 국내도 빈 문자열을 전송하지만 서버가 거부하므로 잘못된 주문은 나가지 않습니다.exit 1대신exit 2가 반환되는 차이입니다. kwcli의order_price_policies.csv에 근거가 있어 다음 릴리스에 넣습니다.--exchange3곳 정리 (ka10030, ka90006, ka90007) — 세 스펙 모두3:통합을 지원하지만 아직 KRX/NXT만 받습니다. Tranche E에서 한 번에 처리하려고 의도적으로 남겼습니다. 그래서 이번 릴리스는rank volume과rank amount가--exchange all지원 여부에서 서로 다릅니다.🤖 Generated with Claude Code