Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,16 @@ pytest -m "not slow" # Skip slow tests
### API Design
```python
# Standard function signature pattern
def get_market_ohlcv_by_date(fromdate: str, todate: str, ticker: str,
adjusted: bool = True) -> DataFrame:
def get_market_ohlcv_by_date(
fromdate: str, todate: str, ticker: str, adjusted: bool = True
) -> DataFrame:
"""
Args:
fromdate (str): YYYYMMDD format
todate (str): YYYYMMDD format
ticker (str): Stock ticker (6-digit code)
adjusted (bool): Return adjusted price

Returns:
DataFrame: Index as datetime, Korean column names
"""
Expand All @@ -79,12 +80,11 @@ class 개별종목시세(KrxWebIo):
@property
def bld(self):
return "dbms/MDC/STAT/standard/MDCSTAT01701"

def fetch(self, strtDd: str, endDd: str, isuCd: str, adjStkPrc: int) -> DataFrame:
# KrxWebIo.read() handles POST with bld parameter injection
result = self.read(strtDd=strtDd, endDd=endDd, isuCd=isuCd,
adjStkPrc=adjStkPrc)
return DataFrame(result['output'])
result = self.read(strtDd=strtDd, endDd=endDd, isuCd=isuCd, adjStkPrc=adjStkPrc)
return DataFrame(result["output"])
```

### Ticker Handling
Expand Down
8 changes: 6 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -89,8 +89,6 @@ jobs:
python-version: "3.11"
- os: macos-latest
python-version: "3.11"
- os: windows-latest
python-version: "3.11"

- os: ubuntu-latest
python-version: "3.12"
Expand All @@ -116,6 +114,9 @@ jobs:
pip install -e .[dev]

- name: Run tests with pytest
env:
KRX_ID: ${{ secrets.KRX_ID }}
KRX_PW: ${{ secrets.KRX_PW }}
run: |
pytest -v --cov=pykrx --cov-report=xml --cov-report=term

Expand Down Expand Up @@ -147,6 +148,9 @@ jobs:
pip install -e .[dev]

- name: Run tests with pytest
env:
KRX_ID: ${{ secrets.KRX_ID }}
KRX_PW: ${{ secrets.KRX_PW }}
run: |
pytest -v --cov=pykrx --cov-report=xml --cov-report=term

Expand Down
6 changes: 4 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,9 @@ Integration 테스트는 `vcrpy`를 사용하여 HTTP 요청을 녹화/재생합
import pytest
from pykrx import stock


class TestStockApi:
@pytest.mark.cassette('stock/ohlcv_20210104.yaml')
@pytest.mark.cassette("stock/ohlcv_20210104.yaml")
def test_get_ohlcv(self, use_cassette):
df = stock.get_market_ohlcv_by_date("20210104", "20210108", "005930")
assert len(df) > 0
Expand Down Expand Up @@ -78,7 +79,8 @@ ruff format --config pyproject.toml . # 포맷 적용

```python
import matplotlib
matplotlib.use('Agg')

matplotlib.use("Agg")
```

8) 브랜치 및 PR 규칙
Expand Down
81 changes: 63 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,33 @@ pytest -v
- 모든 설정은 `pyproject.toml`에서 관리됩니다
- VS Code 사용 시: `ruff` 익스텐션 설치하면 저장 시 자동 포맷 적용

### 1.3 환경변수 설정 (Required Environment Variables)

KRX 로그인이 필요한 API를 사용하려면 아래 두 환경변수를 **반드시** 설정해야 합니다.

| 변수명 | 필수 여부 | 설명 |
|--------|-----------|------|
| `KRX_ID` | **필수** | KRX(한국거래소) 회원 로그인 ID |
| `KRX_PW` | **필수** | KRX(한국거래소) 회원 로그인 비밀번호 |

환경변수가 설정되지 않으면 KRX 로그인이 실패하고 인증이 필요한 데이터를 조회할 수 없습니다.

```bash
# macOS / Linux
export KRX_ID="your_krx_id"
export KRX_PW="your_krx_password"

# Windows (PowerShell)
$env:KRX_ID="your_krx_id"
$env:KRX_PW="your_krx_password"

# Windows (Command Prompt)
set KRX_ID=your_krx_id
set KRX_PW=your_krx_password
```

> **참고:** `.env` 파일을 사용하는 경우 `python-dotenv` 등을 활용해 로드하세요. `.env` 파일은 절대 버전 관리(git)에 포함하지 마세요.

### 지원 Python 버전

이 프로젝트는 다음 Python 버전을 지원합니다:
Expand Down Expand Up @@ -117,8 +144,8 @@ print(tickers)
`get_market_ticker_name` 함수에 티커를 입력하면 종목이름을 반환합니다.
```python
for ticker in stock.get_market_ticker_list():
종목 = stock.get_market_ticker_name(ticker)
print(종목)
종목 = stock.get_market_ticker_name(ticker)
print(종목)
```
```text
SK하이닉스
Expand Down Expand Up @@ -171,6 +198,7 @@ df = stock.get_market_ohlcv("20180427", "20180504", "005930", adjusted=False)
get_stock_ticker_list() 함수와 함께 사용하면 전종목의 OHLCV를 가져올 수 있습니다. 한 번에 너무 많은 정보를 요청하면 KRX 서버가 차단할 수 있으므로 time 모듈을 사용해서 1초 지연 후 요청하도록 코드를 작성했습니다.
```python
import time

for ticker in stock.get_stock_ticker_list():
df = stock.get_market_ohlcv("20181210", "20181212", ticker)
print(df.head())
Expand Down Expand Up @@ -326,7 +354,7 @@ print(df.head())
`매수` 혹은 `매도` 금액을 조회하고 싶다면 `on` 파라미터에 입력할 수 있습니다. 입력하지 않는다면 `순매수` 금액이 조회됩니다.

```python
df = stock.get_market_trading_value_by_date("20210115", "20210122", "005930", on='매도')
df = stock.get_market_trading_value_by_date("20210115", "20210122", "005930", on="매도")
print(df.head())
```

Expand Down Expand Up @@ -362,7 +390,9 @@ print(df.head())
시장의 거래대금을 조회할 때는 `ETF`, `ETN` `ELW`의 포함 여부를 지정할 수 있습니다. 만약 값을 지정하지 않는다면 해당 데이터를 제외한 값을을 반환합니다. 옵션은 `KOSPI`, `KOSDAQ`, `KONEX` 조회할 때만 유효합니다.

```python
df = stock.get_market_trading_value_by_date("20210115", "20210122", "KOSPI", etf=True, etn=True, elw=True)
df = stock.get_market_trading_value_by_date(
"20210115", "20210122", "KOSPI", etf=True, etn=True, elw=True
)
print(df.head())
```

Expand All @@ -379,7 +409,9 @@ print(df.head())

`detail` 옵션을 추가하면 상세한 정보를 얻을 수 있습니다. 옵션은 `KOSPI`, `KOSDAQ`, `KONEX` 조회할 때만 유효합니다.
```python
df = stock.get_market_trading_value_by_date("20210115", "20210122", "KOSPI", etf=True, etn=True, elw=True, detail=True)
df = stock.get_market_trading_value_by_date(
"20210115", "20210122", "KOSPI", etf=True, etn=True, elw=True, detail=True
)
print(df.head())
```

Expand Down Expand Up @@ -416,7 +448,9 @@ print(df.head())
`매수` 혹은 `매도` 거래량만을 조회하고 싶다면 `on` 파라미터에 입력할 수 있습니다. 입력하지 않는다면 `순매수` 수량이 조회됩니다.

```python
df = stock.get_market_trading_volume_by_date("20210115", "20210122", "005930", on='매도')
df = stock.get_market_trading_volume_by_date(
"20210115", "20210122", "005930", on="매도"
)
print(df.head())
```

Expand Down Expand Up @@ -452,7 +486,9 @@ print(df.head())
시장의 거래량을 조회할 때는 `ETF`, `ETN` `ELW`의 포함 여부를 지정할 수 있습니다. 만약 값을 지정하지 않는다면 해당 데이터를 제외한 값을을 반환합니다. 옵션은 `KOSPI`, `KOSDAQ`, `KONEX` 조회할 때만 유효합니다.

```python
df = stock.get_market_trading_volume_by_date("20210115", "20210122", "KOSPI", etf=True, etn=True, elw=True)
df = stock.get_market_trading_volume_by_date(
"20210115", "20210122", "KOSPI", etf=True, etn=True, elw=True
)
print(df.head())
```

Expand All @@ -469,7 +505,9 @@ print(df.head())

`detail` 옵션을 추가하면 상세한 정보를 얻을 수 있습니다. 옵션은 `KOSPI`, `KOSDAQ`, `KONEX` 조회할 때만 유효합니다.
```python
df = stock.get_market_trading_volume_by_date("20210115", "20210122", "KOSPI", etf=True, etn=True, elw=True, detail=True)
df = stock.get_market_trading_volume_by_date(
"20210115", "20210122", "KOSPI", etf=True, etn=True, elw=True, detail=True
)
print(df.head())
```

Expand Down Expand Up @@ -523,7 +561,9 @@ print(df.head())
시장의 거래대금을 조회할 때는 `ETF`, `ETN` `ELW`의 포함 여부를 지정할 수 있습니다. 만약 값을 지정하지 않는다면 해당 데이터를 제외한 값을을 반환합니다. 옵션은 `KOSPI`, `KOSDAQ`, `KONEX` 조회할 때만 유효합니다.

```python
df = stock.get_market_trading_value_by_investor("20210115", "20210122", "KOSPI", etf=True, etn=True, elw=True)
df = stock.get_market_trading_value_by_investor(
"20210115", "20210122", "KOSPI", etf=True, etn=True, elw=True
)
print(df.head())
```

Expand Down Expand Up @@ -575,7 +615,9 @@ print(df.head())
시장의 거래량을 조회할 때는 `ETF`, `ETN` `ELW`의 포함 여부를 지정할 수 있습니다. 만약 값을 지정하지 않는다면 해당 데이터를 제외한 값을을 반환합니다. 옵션은 `KOSPI`, `KOSDAQ`, `KONEX` 조회할 때만 유효합니다.

```python
df = stock.get_market_trading_volume_by_investor("20210115", "20210122", "KOSPI", etf=True, etn=True, elw=True)
df = stock.get_market_trading_volume_by_investor(
"20210115", "20210122", "KOSPI", etf=True, etn=True, elw=True
)
print(df.head())
```

Expand Down Expand Up @@ -667,7 +709,7 @@ print(df.head())
조회합니다. 외국인 보유수량 및 한도소진율은 장개시 시점 기준(금융감독원 외국인투자 관리시스템 제공 전일자 확정치)입니다.

```python
df = stock.get_exhaustion_rates_of_foreign_investment('20200703')
df = stock.get_exhaustion_rates_of_foreign_investment("20200703")
print(df.head())
```

Expand All @@ -683,15 +725,16 @@ print(df.head())

두 번째 파라미터 `market`은 코스피(KOSPI)/코스닥(KOSDAQ)/코넥스(KONEX) 시장을 지정해서 조회할 수 있습니다.
```python
df = stock.get_exhaustion_rates_of_foreign_investment('20200703', "KOSPI")
df = stock.get_exhaustion_rates_of_foreign_investment("20200703", "KOSPI")
print(df.head())
```

세 번째 파라미터 `balance_limit`을 `True`로 지정하면 외국인 보유한도의 제한 종목만 검색할 수 있습니다. 지정하지 않으면 `False` 입니다.
```python
df = stock.get_exhaustion_rates_of_foreign_investment('20200703', "KOSPI",
balance_limit=True)
print(df.head())
df = stock.get_exhaustion_rates_of_foreign_investment(
"20200703", "KOSPI", balance_limit=True
)
print(df.head())
```

#### 2.1.1.15 일자별 외국인 보유량 및 외국인 한도소진률
Expand Down Expand Up @@ -723,7 +766,7 @@ tickers = stock.get_index_ticker_list("19800104")

코스닥 인덱스를 조회할 때는 `market` 옵션을 추가합니다.
```python
tickers = stock.get_index_ticker_list(market='KOSDAQ')
tickers = stock.get_index_ticker_list(market="KOSDAQ")
```

`get_index_name` 함수를 사용해서 티커의 이름을 얻을 수 있습니다.
Expand Down Expand Up @@ -1159,7 +1202,7 @@ print(df.head())
get_etf_ohlcv_by_date() 함수에 frequency 파라미터(d/m/y)를 추가할 수 있습니다.
d는 일자, m은 월, y는 연도를 의미합니다. 다음은 20200101부터 20200531까지의 월별 OHLCV를 출력합니다.
```python
df = stock.get_etf_ohlcv_by_date("20200101", "20200531", "292340", 'm')
df = stock.get_etf_ohlcv_by_date("20200101", "20200531", "292340", "m")
print(df.head())
```
```text
Expand Down Expand Up @@ -1337,7 +1380,9 @@ print(df.head())
티커를 추가하면 개별종목의 일자별 데이터를 조회할 수 있습니다.

```python
df = get_etf_trading_volume_and_value("20220908", "20220916", "580011", "거래대금", "순매수")
df = get_etf_trading_volume_and_value(
"20220908", "20220916", "580011", "거래대금", "순매수"
)
print(df.head())
```

Expand Down
4 changes: 2 additions & 2 deletions pykrx/stock/future_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ def get_future_ohlcv_by_ticker(
# tickers = get_future_ticker_list()
# print(tickers)

# names = get_future_ticker_name('KRDRVFUEST')
# print(names)
names = get_future_ticker_name("KRDRVFUEST")
print(names)

df = get_future_ohlcv("20220902", "KRDRVFUEST")
print(df)
20 changes: 20 additions & 0 deletions pykrx/stock/stock_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -2858,6 +2858,26 @@ def get_stock_major_changes(ticker: str) -> DataFrame:
return krx.get_stock_major_changes(ticker)


def get_market_ohlcv_by_market(market: str):
"""티커별로 정리된 전종목 OHLCV

Args:
date (str): 조회 일자 (YYYYMMDD)
market (str): 조회 시장 (KOSPI/KOSDAQ/KONEX/ALL)

Returns:
DataFrame:
시가 고가 저가 종가 거래량 거래대금
티커
060310 2150 2390 2150 2190 981348 2209370985
095570 3135 3200 3100 3130 89871 282007385
006840 17050 17200 16500 16500 30567 512403000
054620 8550 8740 8400 8650 647596 5525789290
265520 22150 23100 22050 22400 255846 5798313650
"""
return krx.get_market_ohlcv_by_market(market)


if __name__ == "__main__":
pd.set_option("display.expand_frame_repr", False)
# print(get_market_price_change_by_ticker(
Expand Down
18 changes: 17 additions & 1 deletion pykrx/website/comm/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
from pykrx.website.comm.auth import (
build_krx_session,
get_auth_session,
login_krx,
warmup_krx_session,
)
from pykrx.website.comm.util import dataframe_empty_handler, singleton
from pykrx.website.comm.webio import get_session, set_session

__all__ = ["dataframe_empty_handler", "singleton"]
__all__ = [
"dataframe_empty_handler",
"singleton",
"get_auth_session",
"get_session",
"set_session",
"build_krx_session",
"login_krx",
"warmup_krx_session",
]
Loading
Loading