Files
openstock/README.md
T
2026-06-09 04:51:29 +00:00

18 KiB

openstock

openstock은 증권사 API와 비증권 데이터 API를 CLI로 다루기 위한 Rust 프로그램입니다. 현재 증권사 API는 한국투자증권(KIS) 실전 API를 사용하고, 비증권 데이터는 KIND, Naver, OpenDART provider로 분리합니다.

이 프로그램은 투자 판단을 대신하지 않습니다. order buy, order sell은 실전 주문을 전송할 수 있으므로 실행 전 입력값과 계좌 상태를 반드시 확인해야 합니다.

Architecture

Layer Path Role
Broker API src/apis 증권사별 구현체. 현재 kis가 실전 계좌 조회, 시세 조회, 주문을 담당합니다.
Provider API src/providers 증권사와 무관한 데이터 API. KIND universe, Naver search, OpenDART 공시를 담당합니다.
Core src/core 공통 trait, 출력 JSON, dotenv, HTTP agent, stock schema, cache policy를 담당합니다.
Commands src/commands CLI 명령과 출력 설명 필드를 구성합니다.

Output Contract

모든 정상 출력은 stdout에 JSON object 한 줄로 출력합니다.

{
  "command": "실행 명령 이름",
  "description": "명령 결과 설명",
  "fields": [
    {
      "name": "필드명",
      "description": "AI와 사람이 해석할 수 있는 의미 설명",
      "value": "실제 값"
    }
  ],
  "raw": "원본 또는 상세 데이터"
}

오류는 stderr에 같은 설명형 JSON 구조로 출력합니다.

{
  "command": "명령 이름",
  "description": "실패 설명",
  "fields": [
    {"name": "status", "description": "명령 실행 결과", "value": "error"},
    {"name": "message", "description": "오류 내용", "value": "오류 메시지"}
  ],
  "raw": null
}

Environment Variables

.env 파일에서 읽고, 일부 값은 명령 실행 중 갱신됩니다.

Name Required For Direction Description
KIS_APPKEY KIS login/call/account/market/order read/write 한국투자증권 Open API app key. api login --appkey 실행 시 저장될 수 있습니다.
KIS_APPSECRET KIS login/call/account/market/order read/write 한국투자증권 Open API app secret. api login --appsecret 실행 시 저장될 수 있습니다.
KIS_ACCESS_TOKEN KIS call/account/market/order read/write api login으로 발급 또는 재사용되는 접근 토큰입니다.
KIS_ACCESS_TOKEN_EXPIRED_AT KIS login read/write 접근 토큰 만료 시각입니다. 유효하면 api login은 재발급하지 않습니다.
KIS_TOKEN_TYPE KIS auth metadata write KIS token type입니다. 보통 Bearer입니다.
KIS_ACCESS_TOKEN_EXPIRES_IN KIS auth metadata write 토큰 유효 초 단위 값입니다.
KIS_ACCOUNT account status, order buy, order sell, order status read CANO-ACNT_PRDT_CD 형식 계좌입니다. 예: 12345678-01.
OPENDART_API_KEY dart * read OpenDART API 인증키입니다.

.env.gitignore 대상입니다. 토큰과 계좌번호를 커밋하지 마십시오.

Cache and File IO

로컬 캐시는 .openstock 아래에 생성되며 .gitignore 대상입니다.

Path Writer Reader Retention Description
.openstock/universe/kind/latest.json universe sync universe status/list/chunks/validate protected KIND 상장법인목록 최신 normalized stock list입니다.
.openstock/universe/kind/meta.json universe sync universe status/* protected universe cache metadata입니다.
.openstock/universe/kind/YYYY-MM-DD.json universe sync audit/manual use max 7 files or 25MB 날짜별 universe snapshot입니다.
.openstock/opendart/corp_codes.json dart sync, dart corp/disclosures/show on cache miss dart corp/disclosures/show latest only 상장사 stock_code to corp_code 매핑입니다.
.openstock/opendart/corp_codes_meta.json dart sync dart status latest only OpenDART corp code cache metadata입니다.
.openstock/opendart/documents/{rcept_no}.zip dart document, dart show dart document, dart show max 100 files or 200MB 공시서류 원본 ZIP cache입니다.

캐시 상태와 정리는 다음 명령으로 수행합니다.

openstock cache status
openstock cache prune --dry-run
openstock cache prune

Commands and Data IO

openstock version

Direction Data
Input 없음
External IO 없음
File IO 없음
Output fields name, version
Side effect 없음

openstock api list

등록된 증권사 API와 capability catalog를 반환합니다.

Direction Data
Input 없음
External IO 없음
File IO 없음
Output fields count, apis
Raw null
Side effect 없음

openstock api login [--appkey KEY] [--appsecret SECRET] [--force]

KIS 실전 API 접근 토큰을 발급하거나 유효한 기존 토큰을 재사용합니다.

Direction Data
Input --appkey, --appsecret, --force
Env read KIS_APPKEY, KIS_APPSECRET, KIS_ACCESS_TOKEN, KIS_ACCESS_TOKEN_EXPIRED_AT
Env write KIS_APPKEY, KIS_APPSECRET, KIS_ACCESS_TOKEN, KIS_ACCESS_TOKEN_EXPIRED_AT, KIS_TOKEN_TYPE, KIS_ACCESS_TOKEN_EXPIRES_IN
External IO POST https://openapi.koreainvestment.com:9443/oauth2/tokenP only when token is missing/expired or --force is used
Output fields broker, status, force, credential_source, token_storage, side_effect
Side effect writes auth state to .env

openstock api call <endpoint> --param KEY=VALUE

KIS endpoint를 직접 GET 호출합니다. tr_id 파라미터는 HTTP header로 전송하고 나머지는 query string으로 전송합니다.

Direction Data
Input endpoint, repeated --param KEY=VALUE
Env read KIS_ACCESS_TOKEN, KIS_APPKEY, KIS_APPSECRET
External IO KIS endpoint GET
File IO .env read
Output fields broker, endpoint, params, request_semantics, response, response_semantics
Raw parsed KIS response
Side effect endpoint에 따라 다름. typed command 사용 권장

openstock search <query>

Naver 모바일 주식 검색 API로 종목 후보를 검색합니다.

Direction Data
Input query: 종목명 또는 종목코드
External IO GET https://m.stock.naver.com/front-api/search/autoComplete
File IO 없음
Output fields provider, query, stocks
Raw Naver 원본 JSON
Side effect 없음

stocks 항목은 가능한 경우 code, name, market, market_code, nation_code, category, reuters_code, url을 포함합니다.

openstock universe sync [--force]

KIND 상장법인목록을 받아 stock universe cache를 갱신합니다.

Direction Data
Input --force
External IO GET https://kind.krx.co.kr/corpgeneral/corpList.do?method=download&searchType=13
File write .openstock/universe/kind/latest.json, meta.json, YYYY-MM-DD.json
Output fields source, cache_date, refreshed_at, refreshed, stock_count, counts_by_market
Raw universe metadata
Side effect writes/updates local cache; prunes old snapshots

openstock universe status

Direction Data
Input 없음
File read .openstock/universe/kind/latest.json, meta.json
Output fields source, cache_date, refreshed_at, refreshed, stock_count, counts_by_market
Side effect 없음

openstock universe list [--market MARKET] [--kind KIND] [--offset N] [--limit N]

로컬 universe 종목을 필터링해 반환합니다.

Direction Data
Input `--market KOSPI
File read universe cache
Output fields source, cache_date, total_count, filtered_count, offset, limit, stocks
Side effect cache miss면 sync 시도 가능

openstock universe chunks [--market MARKET] [--kind KIND] [--size N]

Universe를 시장/종류별 chunk로 나눠 순회 단위를 만듭니다.

Direction Data
Input `--market KOSPI
File read universe cache
Output fields source, cache_date, filtered_count, chunk_size, chunk_count, chunks
Side effect 없음

openstock universe validate

로컬 universe가 기대 규모와 대표 종목을 만족하는지 검증합니다.

Direction Data
Input 없음
File read universe cache
Output fields valid, stock_count, counts_by_market, checks, errors
Side effect 없음

openstock market <symbol>

KIS 현재가와 종목/기업 기본 정보를 조회합니다.

Direction Data
Input symbol: 6자리 국내 종목코드
Env read KIS_ACCESS_TOKEN, KIS_APPKEY, KIS_APPSECRET
External IO KIS GET /uapi/domestic-stock/v1/quotations/inquire-price, TR ID FHKST01010100; KIS GET /uapi/domestic-stock/v1/quotations/search-stock-info, TR ID CTPF1002R
Output fields broker, symbol, price, company
Raw KIS price/company 원본 응답
Side effect 없음

openstock market history <symbol> --from YYYYMMDD --to YYYYMMDD [--period D|W|M|Y] [--raw-price]

KIS 기간별 OHLCV를 조회합니다.

Direction Data
Input symbol, --from, --to, --period, --raw-price
Env read KIS_ACCESS_TOKEN, KIS_APPKEY, KIS_APPSECRET
External IO GET /uapi/domestic-stock/v1/quotations/inquire-daily-itemchartprice, TR ID FHKST03010100
Output fields broker, symbol, period, date_range, adjusted, count, candles, summary
Raw normalized payload plus KIS raw response
Side effect 없음

candles는 날짜 오름차순이며 각 항목은 date, open, high, low, close, volume, trading_value, change, change_sign, change_rate를 포함합니다. 숫자는 원본 정밀도 보존을 위해 문자열로 반환합니다.

openstock dart sync [--force]

OpenDART 고유번호 ZIP/XML을 받아 상장사 stock_code to corp_code cache를 갱신합니다.

Direction Data
Input --force
Env read OPENDART_API_KEY
External IO GET https://opendart.fss.or.kr/api/corpCode.xml
File write .openstock/opendart/corp_codes.json, corp_codes_meta.json
Output fields source, cache_date, refreshed_at, refreshed, total_count, listed_count
Side effect writes/updates local cache

openstock dart status

Direction Data
Input 없음
File read OpenDART corp code cache
Output fields source, cache_date, refreshed_at, refreshed, total_count, listed_count
Side effect 없음

openstock dart corp <symbol>

KRX 종목코드를 OpenDART 고유번호로 변환합니다.

Direction Data
Input symbol: 6자리 종목코드
File read/write corp code cache. cache miss 또는 날짜 만료 시 refresh 시도
External IO cache refresh 시 OpenDART corpCode API
Output fields stock_code, corp_code, corp_name, modify_date
Side effect cache refresh 가능

openstock dart disclosures [symbol] [--corp-code CODE] [--from YYYYMMDD] [--to YYYYMMDD] [--corp-cls Y|K|N|E] [--page-no N] [--page-count N]

전체 또는 특정 종목의 공시목록을 조회합니다.

Direction Data
Input optional symbol, optional --corp-code, date range, corp class, page options
Env read OPENDART_API_KEY
File read/write symbol 사용 시 corp code cache read; cache refresh 가능
External IO GET https://opendart.fss.or.kr/api/list.json
Output fields corp_code, from, to, page, resolved, disclosures
Raw OpenDART list response
Side effect cache refresh 가능

disclosures 항목은 OpenDART가 반환하는 corp_cls, corp_code, corp_name, stock_code, rcept_no, report_nm, rcept_dt, flr_nm, rm 등을 포함합니다.

openstock dart document <rcept_no> [--force] [--max-chars N]

접수번호로 공시서류 원본 ZIP을 다운로드하고 XML 본문 텍스트를 추출합니다.

Direction Data
Input rcept_no: 14자리 접수번호, --force, --max-chars
Env read OPENDART_API_KEY
External IO GET https://opendart.fss.or.kr/api/document.xml
File read/write .openstock/opendart/documents/{rcept_no}.zip
Output fields rcept_no, source, viewer_url, cached, zip_path, zip_bytes, files, text, text_chars, truncated
Raw same document object
Side effect writes ZIP cache; prunes old document ZIP files

text는 XML tag, style, script를 제거한 본문입니다. --max-chars를 넘으면 앞부분만 출력하고 truncated=true를 반환합니다.

openstock dart show <symbol> [--from YYYYMMDD] [--to YYYYMMDD] [--index N] [--page-count N] [--force] [--max-chars N]

종목코드 기준으로 공시목록을 조회하고 선택한 공시 원문까지 함께 반환합니다.

Direction Data
Input symbol, optional date range, --index, --page-count, --force, --max-chars
Env read OPENDART_API_KEY
File read/write corp code cache, document ZIP cache
External IO OpenDART list.json; selected document cache miss or --force이면 document.xml
Output fields symbol, resolved, date_range, selected_index, selected_disclosure, disclosures, document
Raw query, resolved corp, selected disclosure, list response, document object
Side effect cache refresh/write 가능

openstock account status

KIS 계좌 잔고와 보유종목을 조회합니다.

Direction Data
Input 없음
Env read KIS_ACCESS_TOKEN, KIS_APPKEY, KIS_APPSECRET, KIS_ACCOUNT
External IO KIS GET /uapi/domestic-stock/v1/trading/inquire-balance
Output fields broker, account, balance, holdings
Raw KIS balance response
Side effect 없음

openstock order buy <symbol> --qty QTY (--price PRICE|--market)

국내주식 매수 주문을 전송합니다.

Direction Data
Input symbol, --qty, one of --price or --market
Env read KIS_ACCESS_TOKEN, KIS_APPKEY, KIS_APPSECRET, KIS_ACCOUNT
External IO KIS POST /uapi/domestic-stock/v1/trading/order-cash, TR ID TTTC0802U
Output fields broker, side, symbol, qty, order_type, price, order
Raw KIS order response
Side effect financial_order: 실전 매수 주문

openstock order sell <symbol> --qty QTY (--price PRICE|--market)

국내주식 매도 주문을 전송합니다.

Direction Data
Input symbol, --qty, one of --price or --market
Env read KIS_ACCESS_TOKEN, KIS_APPKEY, KIS_APPSECRET, KIS_ACCOUNT
External IO KIS POST /uapi/domestic-stock/v1/trading/order-cash, TR ID TTTC0801U
Output fields broker, side, symbol, qty, order_type, price, order
Raw KIS order response
Side effect financial_order: 실전 매도 주문

openstock order status [order_no] [--from YYYYMMDD] [--to YYYYMMDD]

주문 및 체결 내역을 조회합니다.

Direction Data
Input optional order_no, optional date range
Env read KIS_ACCESS_TOKEN, KIS_APPKEY, KIS_APPSECRET, KIS_ACCOUNT
External IO KIS GET /uapi/domestic-stock/v1/trading/inquire-daily-ccld
Output fields broker, account, order_no, orders, summary
Raw KIS order status response
Side effect 없음

openstock cache status

Direction Data
Input 없음
File read .openstock recursively
Output fields root, exists, total_files, total_bytes, namespaces
Side effect 없음

openstock cache prune [--dry-run]

캐시 보존 정책을 적용합니다.

Direction Data
Input --dry-run
File read .openstock cache directories
File delete old universe snapshots, old OpenDART document ZIPs unless --dry-run
Output fields dry_run, deleted_files, deleted_bytes, reports
Side effect deletes local cache files unless dry-run

Stock Schema

Universe 종목은 다음 구조로 정규화됩니다.

Field Type Description
id.symbol string KRX 종목코드. 알파벳 포함 코드를 허용합니다.
id.isin string/null ISIN. 현재 KIND source에서는 null일 수 있습니다.
id.reuters_code string/null Reuters style code.
name string 종목명
market enum KOSPI, KOSDAQ, KONEX, OTHER, UNKNOWN
kind enum common_stock, preferred_stock, etf, etn, spac, reit, other, unknown
industry string/null 업종
sector string/null 섹터. 현재 null 가능
main_product string/null 주요 제품
listed_at string/null 상장일
fiscal_month string/null 결산월
homepage string/null 홈페이지
region string/null 지역
source enum 현재 KIND
source_url string/null 원천 URL
updated_at string/null 캐시 기준일

External Data Sources

Source API Used By
KIS https://openapi.koreainvestment.com:9443 login, account, market, market history, order
KIND https://kind.krx.co.kr/corpgeneral/corpList.do?method=download&searchType=13 universe
Naver https://m.stock.naver.com/front-api/search/autoComplete search
OpenDART https://opendart.fss.or.kr/api/corpCode.xml dart sync/corp/show/disclosures
OpenDART https://opendart.fss.or.kr/api/list.json dart disclosures/show
OpenDART https://opendart.fss.or.kr/api/document.xml dart document/show

Typical Evidence Workflow

openstock api login
openstock universe sync
openstock dart sync
openstock search 삼성전자
openstock market 005930
openstock market history 005930 --from 20260101 --to 20260609
openstock dart show 005930 --from 20260601 --to 20260609 --index 1
openstock account status

At this point the program can collect evidence for a trade decision. Automated candidate generation, risk checking, and backtesting should be implemented before unattended trading.