Skip to content

[기능]: 환율 기간별 조회 기능 추가 #79

@softyoungha

Description

@softyoungha

빠른 문제 해결을 위해 다음을 확인했나요?

  • PyKis Issues에서 검색했지만 유사한 기능을 찾지 못했습니다.

기능 설명

안녕하세요, python-kis를 잘 사용하고 있는 사용자입니다.

환율 조회가 필요한 상태인데요,

Image

kis 문서를 보면 환율 조회가 가능해서 다음과 같이 구현해보아서 직접 사용하고 있습니다.

from pykis.api.stock.daily_chart import (
        TIMEZONE,
        drop_after,
        KisResponse,
        KisChartBase,
        KisChartBar,

        KisList,
        raise_not_found,
        MARKET_TYPE,
        KisChartBarRepr,
        KisDatetime,
        KisDecimal,
        KisInt,
        KisAny,
        safe_divide,
        ExDateType,
        EX_DATE_TYPE_CODE_MAP,
        STOCK_SIGN_TYPE,
        STOCK_SIGN_TYPE_MAP,
        STOCK_SIGN_TYPE_KOR_MAP,
    Decimal,
    KisDynamic
    )
    from datetime import date, timedelta, tzinfo

    class KisCurrencyDailyChartBar(KisChartBarRepr, KisDynamic):
        """한국투자증권 환율 기간 차트 봉"""

        time: datetime = KisDatetime("%Y%m%d", timezone=TIMEZONE)["stck_bsop_date"]
        """시간 (현지시간)"""
        time_kst: datetime = KisDatetime("%Y%m%d", timezone=TIMEZONE)["stck_bsop_date"]
        """시간 (한국시간)"""
        open: Decimal = KisDecimal["ovrs_nmix_oprc"]
        """시가"""
        close: Decimal = KisDecimal["ovrs_nmix_prpr"]
        """종가 (현재가)"""
        high: Decimal = KisDecimal["ovrs_nmix_hgpr"]
        """고가"""
        low: Decimal = KisDecimal["ovrs_nmix_lwpr"]
        """저가"""

        @property
        def price(self) -> Decimal:
            """현재가 (종가)"""
            return self.close

        @property
        def volume(self):
            return Decimal("0")

        @property
        def amount(self):
            return Decimal("0")

    class KisCurrencyDailyChart(KisResponse, KisChartBase):
        """한국투자증권 환율 기간 차트"""

        symbol: str
        """종목코드"""
        market: MARKET_TYPE = "KRX"
        """상품유형타입"""

        timezone: tzinfo = TIMEZONE
        """시간대"""
        bars: list[KisChartBar] = KisList(KisCurrencyDailyChartBar)["output2"]
        """차트"""

        def __init__(self, symbol: str) -> None:
            self.symbol = symbol

        def __pre_init__(self, data: dict[str, Any]) -> None:
            super().__pre_init__(data)

            data["output2"] = [x for x in data["output2"] if x]

    client = _get_kis_client()

    def currency_daily_chart(
        start: date | timedelta | None = None,
        end: date | None = None,
        period: Literal["day", "week", "month", "year"] = "day",
    ):
        """
        한국투자증권 국내 기간 차트 조회

        국내주식시세 -> 국내주식기간별시세(일/주/월/년)[v1_국내주식-016]
        (업데이트 날짜: 2023-10-02)

        Args:
            symbol (str): 종목 코드
            start (date, optional): 조회 시작 시간. timedelta인 경우 최근 timedelta만큼의 봉을 조회합니다. Defaults to None.
            end (date, optional): 조회 종료 시간. Defaults to None.
            period (Literal["day", "week", "month", "year"], optional): 조회 기간. Defaults to "day".

        Raises:
            KisAPIError: API 호출에 실패한 경우
            KisNotFoundError: 조회 결과가 없는 경우
            ValueError: 조회 파라미터가 올바르지 않은 경우
        """
        if not end:
            end = datetime.now(TIMEZONE).date()

        if isinstance(start, datetime):
            start = start.date()

        if isinstance(end, datetime):
            end = end.date()

        if isinstance(start, date) and end and start > end:
            start, end = end, start

        cursor = end
        chart = None
        period_delta = timedelta(
            days=1 if period == "day" else 7 if period == "week" else 30 if period == "month" else 365)

        while True:
            result = client.fetch(
                "/uapi/overseas-price/v1/quotations/inquire-daily-chartprice",
                api="FHKST03030100",
                params={
                    "FID_COND_MRKT_DIV_CODE": "X",
                    "FID_INPUT_ISCD": "FX@KRWKFTC",
                    "FID_INPUT_DATE_1": start.strftime("%Y%m%d") if isinstance(start, date) else "00000101",
                    "FID_INPUT_DATE_2": cursor.strftime("%Y%m%d"),
                    "FID_PERIOD_DIV_CODE": (
                        "D" if period == "day" else "W" if period == "week" else "M" if period == "month" else "Y"
                    ),
                },
                response_type=KisCurrencyDailyChart(symbol="FX@KRWKFTC"),
                domain="real",
            )

            if not chart:
                chart = result

            if not result.bars:
                break

            last = result.bars[-1].time.date()

            if cursor and cursor < last:
                break

            if chart and result != chart:
                chart.bars.extend(result.bars)

            if isinstance(start, timedelta):
                start = (chart.bars[0].time - start).date()

            if start and last <= start:
                break

            cursor = last - period_delta

        return drop_after(
            chart,
            start=start,
            end=end,
        )

해당 요청 실제로 찔렀을 때 response는 다음과 같습니다.

# output1
hts_kor_isnm	한글 종목명	원/달러
stck_shrn_iscd	종목 코드	FX@KRWKFTC
ovrs_nmix_prpr	현재가	1468.0000
ovrs_nmix_prdy_clpr	전일 종가	1465.9000
ovrs_nmix_prdy_vrss	전일 대비 등락	+2.1000
prdy_vrss_sign	등락 부호	2 = 상승
prdy_ctrt	등락률(%)	0.14
ovrs_prod_oprc	시가	1467.0000
ovrs_prod_hgpr	고가	1471.1000
ovrs_prod_lwpr	저가	1464.2000
acml_vol	누적 거래량	0 (환율은 거래량 없음)

# output2
{
  "stck_bsop_date": "20230601",
  "ovrs_nmix_prpr": "1321.6000", // 종가
  "ovrs_nmix_oprc": "1321.0000", // 시가
  "ovrs_nmix_hgpr": "1323.1000", // 고가
  "ovrs_nmix_lwpr": "1318.1000", // 저가
  "acml_vol": "0",
  "mod_yn": "N"
}

FX@KRWKFTC 요 값이 원/달러 심볼인데,
요 심볼값은 인덱스 리스트에서 조회하면 확인할 수가 잇습니다.

|       | 심볼       | 한글명            | 영문명     |
|------:|:-----------|:------------------|:-----------|
| 12204 | FX@ARS     | 페소/달러         | 아르헨티나 |
| 12205 | FX@AUD     | 달러/호주달러     | 호주       |
| 12206 | FX@BRL     | 레알/달러         | 브라질     |
| 12207 | FX@CAD     | 캐나다달러/달러   | 캐나다     |
| 12208 | FX@CHF     | 프랑/달러         | 스위스     |
| 12209 | FX@CNY     | 위엔/달러         | 중국       |
| 12210 | FX@CZK     | 코루나/달러       | 체코       |
| 12211 | FX@DKK     | 크로네/달러       | 덴마크     |
| 12212 | FX@EUR     | 달러/유로         | 유럽연합   |
| 12213 | FX@GBP     | 달러/파운드       | 영국       |
| 12214 | FX@HKD     | 홍콩달러/달러     | 홍콩       |
| 12215 | FX@HUF     | 포린트/달러       | 헝가리     |
| 12216 | FX@IDR     | 루피/달러         | 인도       |
| 12217 | FX@INR     | 루피아/달러       | 인도네시아 |
| 12218 | FX@JPY     | 엔/달러           | 일본       |
| 12219 | FX@KRW     | 원/달러(KMB)      | 대한민국   |
| 12220 | FX@KRWJS   | 원/엔             | 대한민국   |
| 12221 | FX@KRWKFTC | 원/달러           | 대한민국   |
| 12222 | FX@KWD     | 디나르/달러       | 쿠웨이트   |
| 12223 | FX@MXN     | 누에바페소/달러   | 멕시코     |
| 12224 | FX@MYR     | 링기트/달러       | 말레이지아 |
| 12225 | FX@NOK     | 크로네/달러       | 노르웨이   |
| 12226 | FX@NZD     | 달러/뉴질랜드달러 | 뉴질랜드   |
| 12227 | FX@PHP     | 페소/달러         | 필리핀     |
| 12228 | FX@PLN     | 즐로티/달러       | 폴란드     |
| 12229 | FX@PSA     | 페소/달러         | 칠레       |
| 12230 | FX@RUR     | 루블/달러         | 러시아     |
| 12231 | FX@SAR     | 리알/달러         | 사우디     |
| 12232 | FX@SEK     | 크로나/달러       | 스웨덴     |
| 12233 | FX@SGD     | 싱가포르달러/달러 | 싱가포르   |
| 12234 | FX@THB     | 바트/달러         | 태국       |
| 12235 | FX@TRY     | 리라/달러         | 터키       |
| 12236 | FX@TWD     | 대만달러/달러     | 대만       |
| 12237 | FX@VEB     | 볼리바르/달러     | 베네주엘라 |
| 12238 | FX@VND     | 동/달러           | 베트남     |
| 12239 | FX@ZAR     | 랜드/달러         | 남아공     |

사용 사례

No response

추가 정보

현재 국내외 관련 기능만 있는 걸로 봐서 해당 라이브러리에서 미장 외에 다른 해외 거래소를 지원하는 건 아닌 것 같은데요
만약 요거 PR을 만들게 되면 원/달러 환율만 추가하는게 나을지, 아니면 모든 거래소 코드를 추가하는게 나을지 고민이 필요해보입니다

PR를 통해 라이브러리에 기여하고 싶으신가요?

  • 네, PR을 제출하여 도움을 주고 싶습니다!

Metadata

Metadata

Assignees

No one assigned

    Labels

    기능새로운 기능 또는 요청

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions