pyqqq 0.12.190__tar.gz → 0.12.192__tar.gz
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.
Potentially problematic release.
This version of pyqqq might be problematic. Click here for more details.
- {pyqqq-0.12.190 → pyqqq-0.12.192}/PKG-INFO +1 -1
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyproject.toml +1 -1
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/brokerage/kis/domestic_stock.py +88 -4
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/brokerage/kis/simple.py +17 -3
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/brokerage/kis/tr_client.py +15 -22
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/data/minutes.py +61 -70
- {pyqqq-0.12.190 → pyqqq-0.12.192}/README.md +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/__init__.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/backtest/__init__.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/backtest/broker.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/backtest/environment.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/backtest/logger.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/backtest/positionprovider.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/backtest/strategy.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/backtest/utils.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/backtest/wallclock.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/brokerage/__init__.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/brokerage/ebest/__init__.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/brokerage/ebest/domestic_stock.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/brokerage/ebest/oauth.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/brokerage/ebest/simple.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/brokerage/ebest/tr_client.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/brokerage/helper.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/brokerage/kis/__init__.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/brokerage/kis/oauth.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/brokerage/kis/overseas_stock.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/brokerage/kis/simple_overseas.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/brokerage/multiprocess_tracker.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/brokerage/tracker.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/config.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/data/__init__.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/data/daily.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/data/domestic.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/data/index.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/data/overseas.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/data/realtime.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/data/ticks.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/data/us_stocks.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/datatypes.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/executors/__init__.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/executors/hook.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/utils/__init__.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/utils/api_client.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/utils/array.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/utils/casting.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/utils/compute.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/utils/copycat.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/utils/daily_tickers.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/utils/display.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/utils/kvstore.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/utils/limiter.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/utils/local_cache.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/utils/logger.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/utils/market_schedule.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/utils/mock_api.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/utils/position_classifier.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/utils/retry.py +0 -0
- {pyqqq-0.12.190 → pyqqq-0.12.192}/pyqqq/utils/singleton.py +0 -0
|
@@ -1169,12 +1169,12 @@ class KISDomesticStock:
|
|
|
1169
1169
|
|
|
1170
1170
|
- stck_bsop_date: 주식 영업 일자
|
|
1171
1171
|
- stck_cntg_hour: 주식 체결 시간
|
|
1172
|
-
- acml_tr_pbmn: 누적 거래 대금
|
|
1173
1172
|
- stck_prpr: 주식 현재가
|
|
1174
|
-
- stck_oprc: 주식 시가
|
|
1173
|
+
- stck_oprc: 주식 시가
|
|
1175
1174
|
- stck_hgpr: 주식 최고가
|
|
1176
1175
|
- stck_lwpr: 주식 최저가
|
|
1177
1176
|
- cntg_vol: 체결 거래량
|
|
1177
|
+
- acml_tr_pbmn: 누적 거래 대금
|
|
1178
1178
|
|
|
1179
1179
|
Raise:
|
|
1180
1180
|
ValueError: API 에러 발생시
|
|
@@ -1985,7 +1985,7 @@ class KISDomesticStock:
|
|
|
1985
1985
|
fid_input_hour_1 (dt.time): 조회 시작시간 (ex. dtm.time(15, 30, 0))
|
|
1986
1986
|
fid_cond_mrkt_div_code (str): FID 조건시장분류코드 - J:주식,ETF,ETN NX:Nextrade UN:통합
|
|
1987
1987
|
fid_pw_data_incu_yn (str): 과거 데이터 포함 여부 - Y:과거 N:당일만 조회
|
|
1988
|
-
fid_fake_tick_incu_yn (str): 허봉 포함 여부 -
|
|
1988
|
+
fid_fake_tick_incu_yn (str): 허봉 포함 여부 - 공백
|
|
1989
1989
|
|
|
1990
1990
|
Returns:
|
|
1991
1991
|
dict:
|
|
@@ -2034,7 +2034,7 @@ class KISDomesticStock:
|
|
|
2034
2034
|
"FID_INPUT_DATE_1": fid_input_date_1.strftime("%Y%m%d"),
|
|
2035
2035
|
"FID_INPUT_HOUR_1": fid_input_hour_1.strftime("%H%M%S"),
|
|
2036
2036
|
"FID_PW_DATA_INCU_YN": fid_pw_data_incu_yn,
|
|
2037
|
-
"FID_FAKE_TICK_INCU_YN":
|
|
2037
|
+
"FID_FAKE_TICK_INCU_YN": "",
|
|
2038
2038
|
}
|
|
2039
2039
|
|
|
2040
2040
|
res_body, res_headers = self._tr_request(url_path, tr_id, params=params)
|
|
@@ -3388,6 +3388,90 @@ class KISDomesticStock:
|
|
|
3388
3388
|
|
|
3389
3389
|
return res_body
|
|
3390
3390
|
|
|
3391
|
+
def order_reserve(
|
|
3392
|
+
self,
|
|
3393
|
+
cano: str,
|
|
3394
|
+
acnt_prdt_cd: str,
|
|
3395
|
+
side: str,
|
|
3396
|
+
pdno: str,
|
|
3397
|
+
ord_dvsn_cd: str,
|
|
3398
|
+
ord_qty: int,
|
|
3399
|
+
ord_unpr: int,
|
|
3400
|
+
loan_dt: dtm.date = None,
|
|
3401
|
+
rvsn_ord_end_dt: dtm.date = None,
|
|
3402
|
+
ldng_dt: dtm.date = None,
|
|
3403
|
+
):
|
|
3404
|
+
"""
|
|
3405
|
+
(국내주식주문) 주식예약주문[v1_국내주식-017]
|
|
3406
|
+
|
|
3407
|
+
국내주식 예약주문 매수/매도 API 입니다.
|
|
3408
|
+
|
|
3409
|
+
[유의사항]
|
|
3410
|
+
1. 예약주문 가능시간 : 15시 40분 ~ 다음 영업일 7시 30분
|
|
3411
|
+
(단, 서버 초기화 작업 시 예약주문 불가 : 23시 40분 ~ 00시 10분)
|
|
3412
|
+
- 예약주문 처리내역은 통보되지 않으므로 주문처리일 장 시작전에 반드시 주문처리 결과를 확인하시기 바랍니다.
|
|
3413
|
+
|
|
3414
|
+
2. 예약주문 안내
|
|
3415
|
+
- 예약종료일 미입력 시 일반예약주문으로 최초 도래하는 영업일에 주문 전송됩니다.
|
|
3416
|
+
- 예약종료일 입력 시 기간예약주문으로 최초 예약주문수량 중 미체결 된 수량에 대해 예약종료일까지 매 영업일 주문이 실행됩니다. (예약종료일은 익영업일부터 달력일 기준으로 공휴일 포함하여 최대 30일이 되는 일자까지 입력가능)
|
|
3417
|
+
- 예약주문 접수 처리순서는 일반/기간예약주문 중 신청일자가 빠른 주문이 우선합니다.
|
|
3418
|
+
- 단, 기간예약주문 자동배치시간(약 15시35분 ~ 15시55분)사이 접수되는 주문의 경우 당일에 한해 순서와 상관없이 처리될 수 있습니다.
|
|
3419
|
+
- 기간예약주문 자동배치시간(약 15시35분 ~ 15시55분)에는 예약주문 조회가 제한 될 수 있습니다.
|
|
3420
|
+
- 기간예약주문은 계좌 당 주문건수 최대 1,000건으로 제한됩니다.
|
|
3421
|
+
|
|
3422
|
+
3. 예약주문 접수내역 중 아래의 사유 등으로 인해 주문이 거부될 수 있사오니, 주문처리일 장 시작전에 반드시 주문처리 결과를 확인하시기 바랍니다.
|
|
3423
|
+
- 주문처리일 기준 : 매수가능금액 부족, 매도가능수량 부족, 주문수량/호가단위 오류, 대주 호가제한, 신용/대주가능종목 변경, 상/하한폭 변경, 시가형성 종목(신규상장 등)의 시장가, 거래서비스 미신청 등
|
|
3424
|
+
|
|
3425
|
+
4. 익일 예상 상/하한가는 조회시점의 현재가로 계산되며 익일의 유/무상증자, 배당, 감자, 합병, 액면변경 등에 의해 변동될 수 있으며 이로 인해 상/하한가를 벗어나 주문이 거부되는 경우가 발생할 수 있사오니, 주문처리일 장 시작전에 반드시 주문처리결과를 확인하시기 바랍니다.
|
|
3426
|
+
|
|
3427
|
+
5. 정리매매종목, ELW, 신주인수권증권, 신주인수권증서 등은 가격제한폭(상/하한가) 적용 제외됩니다.
|
|
3428
|
+
|
|
3429
|
+
6. 영업일 장 시작 후 [기간예약주문] 내역 취소는 해당시점 이후의 예약주문이 취소되는 것으로, 일반주문으로 이미 전환된 주문에는 영향을 미치지 않습니다. 반드시 장 시작전 주문처리결과를 확인하시기 바랍니다.
|
|
3430
|
+
|
|
3431
|
+
Args:
|
|
3432
|
+
cano (str): 종합계좌번호 - 계좌번호 체계(8-2)의 앞 8자리
|
|
3433
|
+
acnt_prdt_cd (str): 계좌상품코드 - 계좌번호 체계(8-2)의 뒤 2자리
|
|
3434
|
+
side (str): 주문 방향 - "sell" 또는 "buy"
|
|
3435
|
+
pdno (str): 종목코드
|
|
3436
|
+
ord_dvsn_cd (str): 주문 구분 코드 - 00:지정가, 01:시장가, 02:조건부지정가, 05:장전 시간외
|
|
3437
|
+
ord_qty (int): 주문 수량
|
|
3438
|
+
ord_unpr (int): 주문 단가
|
|
3439
|
+
loan_dt (dtm.date): 대출일자
|
|
3440
|
+
rsvn_ord_end_dt(dtm.date): 예약주문 종료일자
|
|
3441
|
+
ldng_dt (dtm.date): 대여일자
|
|
3442
|
+
"""
|
|
3443
|
+
|
|
3444
|
+
assert side in ["sell", "buy"]
|
|
3445
|
+
assert ord_dvsn_cd in ["00", "01", "02", "05"]
|
|
3446
|
+
|
|
3447
|
+
if rvsn_ord_end_dt:
|
|
3448
|
+
assert rvsn_ord_end_dt > dtm.date.today(), "rvsn_ord_end_dt must be greater than today"
|
|
3449
|
+
|
|
3450
|
+
url_path = "/uapi/domestic-stock/v1/trading/order-resv"
|
|
3451
|
+
|
|
3452
|
+
tr_id = "CTSC0008U"
|
|
3453
|
+
|
|
3454
|
+
req_body = {
|
|
3455
|
+
"CANO": cano,
|
|
3456
|
+
"ACNT_PRDT_CD": acnt_prdt_cd,
|
|
3457
|
+
"PDNO": pdno,
|
|
3458
|
+
"ORD_QTY": str(ord_qty),
|
|
3459
|
+
"ORD_UNPR": str(ord_unpr),
|
|
3460
|
+
"SLL_BUY_DVSN_CD": "01" if side == "sell" else "02",
|
|
3461
|
+
"ORD_DVSN_CD": ord_dvsn_cd,
|
|
3462
|
+
"ORD_OBJT_CBLC_DVSN_CD": "10", # 현금
|
|
3463
|
+
"LOAN_DT": "" if loan_dt is None else loan_dt.strftime("%Y%m%d"),
|
|
3464
|
+
"RSVN_ORD_END_DT": "" if rvsn_ord_end_dt is None else rvsn_ord_end_dt.strftime("%Y%m%d"),
|
|
3465
|
+
"LDNG_DT": "" if ldng_dt is None else ldng_dt.strftime("%Y%m%d"), # 대여일자
|
|
3466
|
+
}
|
|
3467
|
+
|
|
3468
|
+
res_body, _ = self._tr_request(url_path, tr_id, body=req_body, method="POST")
|
|
3469
|
+
|
|
3470
|
+
if res_body["rt_cd"] != "0":
|
|
3471
|
+
raise ValueError(f"Error: ({res_body['msg_cd']}) {res_body['msg1']}")
|
|
3472
|
+
|
|
3473
|
+
return res_body
|
|
3474
|
+
|
|
3391
3475
|
def order_rvsecncl(
|
|
3392
3476
|
self,
|
|
3393
3477
|
cano: str,
|
|
@@ -335,10 +335,15 @@ class KISSimpleDomesticStock:
|
|
|
335
335
|
if schedule.full_day_closed:
|
|
336
336
|
return _create_minute_dataframe()
|
|
337
337
|
|
|
338
|
-
#
|
|
338
|
+
# KRX 거래소에서 15:30 ~ 17:00 시간대에 API 호출하면 15:30분 데이터는 존재하지 않고, 해당 데이터가 호출시점(마지막) 인덱스에 존재 한다.
|
|
339
|
+
# 이러한 문제를 피하기위해 request_time을 장 종료 시간으로 설정한다.
|
|
340
|
+
requires_volume_correction = False
|
|
339
341
|
if request_time.time() > schedule.close_time:
|
|
340
342
|
request_time = request_datetime.replace(hour=schedule.close_time.hour, minute=schedule.close_time.minute)
|
|
341
343
|
|
|
344
|
+
if data_exchange == DataExchange.KRX:
|
|
345
|
+
requires_volume_correction = True
|
|
346
|
+
|
|
342
347
|
while True:
|
|
343
348
|
CallLimiter().wait_limit_rate(20, scope="kis/inquire_time_itemchartprice")
|
|
344
349
|
|
|
@@ -373,6 +378,13 @@ class KISSimpleDomesticStock:
|
|
|
373
378
|
if request_time.time() < schedule.open_time:
|
|
374
379
|
break
|
|
375
380
|
|
|
381
|
+
# KRX 거래소에서 17시 이후에 API 호출하면 거래량이 2배로 보이는 문제가 있다. 장 마감 이후에는 거래량 검사를 진행한다.
|
|
382
|
+
if requires_volume_correction:
|
|
383
|
+
close = result[0].get("close")
|
|
384
|
+
volume = (result[0].get("cum_value") - result[1].get("cum_value")) / close
|
|
385
|
+
if volume != result[0].get("volume"):
|
|
386
|
+
result[0]["volume"] = int(volume)
|
|
387
|
+
|
|
376
388
|
# 거래대금, 누적거래량 계산
|
|
377
389
|
prev_cum_value = None
|
|
378
390
|
prev_cum_volume = None
|
|
@@ -1085,8 +1097,10 @@ class KISSimpleDomesticStock:
|
|
|
1085
1097
|
event_type = "rejected"
|
|
1086
1098
|
elif cancelled:
|
|
1087
1099
|
event_type = "cancelled"
|
|
1088
|
-
|
|
1089
|
-
org_order_no
|
|
1100
|
+
# IOC 취소될땐 org_order_no가 비어있어서 오류 발생함
|
|
1101
|
+
if org_order_no:
|
|
1102
|
+
order_no = org_order_no # 취소 주문의 경우 원주문번호로 변경
|
|
1103
|
+
org_order_no = None
|
|
1090
1104
|
elif accepted or updated:
|
|
1091
1105
|
event_type = "accepted"
|
|
1092
1106
|
elif executed:
|
|
@@ -12,20 +12,21 @@ import websockets
|
|
|
12
12
|
class KISTRClient:
|
|
13
13
|
logger = get_logger(__name__ + ".KISTRClient")
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
"""
|
|
16
16
|
한국투자증권 TR 요청을 위한 클라이언트
|
|
17
17
|
|
|
18
18
|
Args:
|
|
19
19
|
auth (KISAuth): 인증 정보를 담고 있는 객체
|
|
20
20
|
corp_data (dict): 기업 고객의 경우 추가로 필요한 정보를 담고 있는 객체
|
|
21
|
-
|
|
21
|
+
"""
|
|
22
|
+
|
|
22
23
|
def __init__(self, auth: KISAuth, corp_data: dict = None):
|
|
23
24
|
self.auth = auth
|
|
24
25
|
self.corp_data = corp_data
|
|
25
26
|
|
|
26
27
|
@retry(requests.HTTPError)
|
|
27
|
-
def request(self, path: str, tr_id: str, tr_cont: str =
|
|
28
|
-
|
|
28
|
+
def request(self, path: str, tr_id: str, tr_cont: str = "", params: dict = None, body: dict = None, method: str = "GET"):
|
|
29
|
+
"""
|
|
29
30
|
TR 요청을 보내고 응답을 받는 메서드
|
|
30
31
|
|
|
31
32
|
Args:
|
|
@@ -41,28 +42,22 @@ class KISTRClient:
|
|
|
41
42
|
|
|
42
43
|
Raises:
|
|
43
44
|
requests.HTTPError: 요청이 실패한 경우
|
|
44
|
-
|
|
45
|
+
"""
|
|
45
46
|
headers = {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
47
|
+
"content-type": "application/json; charset=utf-8",
|
|
48
|
+
"authorization": f"Bearer {self.auth.get_token()}",
|
|
49
|
+
"appkey": self.auth.appkey,
|
|
50
|
+
"appsecret": self.auth.appsecret,
|
|
51
|
+
"custtype": "P" if self.corp_data is None else "B",
|
|
52
|
+
"tr_id": tr_id,
|
|
53
|
+
"tr_cont": tr_cont,
|
|
53
54
|
}
|
|
54
55
|
if self.corp_data is not None:
|
|
55
56
|
headers.update(self.corp_data)
|
|
56
57
|
|
|
57
58
|
url = f"{self.auth.host_url}{path}"
|
|
58
59
|
|
|
59
|
-
r = requests.request(
|
|
60
|
-
method=method,
|
|
61
|
-
url=url,
|
|
62
|
-
headers=headers,
|
|
63
|
-
params=params,
|
|
64
|
-
json=body
|
|
65
|
-
)
|
|
60
|
+
r = requests.request(method=method, url=url, headers=headers, params=params, json=body)
|
|
66
61
|
|
|
67
62
|
if r.status_code != 200:
|
|
68
63
|
try:
|
|
@@ -160,9 +155,7 @@ class KISTRWebsocketClient:
|
|
|
160
155
|
await asyncio.sleep(1)
|
|
161
156
|
continue
|
|
162
157
|
|
|
163
|
-
async def recv_with_timeout(
|
|
164
|
-
self, ws: websockets.WebSocketClientProtocol, timeout: int = 1
|
|
165
|
-
) -> str:
|
|
158
|
+
async def recv_with_timeout(self, ws: websockets.WebSocketClientProtocol, timeout: int = 1) -> str:
|
|
166
159
|
"""timeout 초 동안 수신을 대기하고 수신이 없으면 None을 반환한다"""
|
|
167
160
|
try:
|
|
168
161
|
message = await asyncio.wait_for(ws.recv(), timeout=timeout)
|
|
@@ -25,12 +25,16 @@ def get_all_minute_data(
|
|
|
25
25
|
"""
|
|
26
26
|
모든 종목의 분봉 데이터를 반환합니다.
|
|
27
27
|
|
|
28
|
-
|
|
28
|
+
데이터 소스에 따라 데이터 조회 가능 시작일이 다릅니다. LS증권은 추후 제거될 예정입니다.
|
|
29
29
|
|
|
30
|
-
|
|
30
|
+
데이터 소스별 조회 가능 기간:
|
|
31
|
+
한국투자증권:
|
|
32
|
+
- KRX: 2023년 7월 3일 데이터 부터 조회 가능합니다.
|
|
33
|
+
- NXT: 2025년 3월 4일 데이터 부터 조회 가능합니다.
|
|
31
34
|
|
|
32
|
-
|
|
33
|
-
|
|
35
|
+
LS증권(구 이베스트증권):
|
|
36
|
+
- KRX: 2024년 4월 9일 ~ 2025년 7월 18일까지 데이터 조회 가능합니다.
|
|
37
|
+
- NXT: 2025년 5월 12일 ~ 2025년 7월 18일까지 데이터 조회 가능합니다. 단, 30초 간격 데이터는 조회 불가능합니다.
|
|
34
38
|
|
|
35
39
|
Args:
|
|
36
40
|
time (datetime.datetime): 조회할 시간
|
|
@@ -43,50 +47,38 @@ def get_all_minute_data(
|
|
|
43
47
|
|
|
44
48
|
DataFrame의 열은 다음과 같습니다:
|
|
45
49
|
|
|
50
|
+
- time (datetime.datetime): 시간
|
|
46
51
|
- open (int): 시가
|
|
47
52
|
- high (int): 고가
|
|
48
53
|
- low (int): 저가
|
|
49
54
|
- close (int): 종가
|
|
50
|
-
- volume (int):
|
|
51
|
-
-
|
|
52
|
-
-
|
|
53
|
-
-
|
|
54
|
-
- chdegree (float): 체결강도
|
|
55
|
-
- mdvolume (int): 매도체결수량
|
|
56
|
-
- msvolume (int): 매수체결수량
|
|
57
|
-
- revolume (int): 순매수체결량
|
|
58
|
-
- mdchecnt (int): 매도체결건수
|
|
59
|
-
- mschecnt (int): 매수체결건수
|
|
60
|
-
- rechecnt (int): 순체결건수
|
|
61
|
-
- cvolume (int): 체결량
|
|
62
|
-
- mdchecnttm (int): 시간별매도체결건수
|
|
63
|
-
- mschecnttm (int): 시간별매수체결건수
|
|
64
|
-
- totofferrem (int): 매도잔량
|
|
65
|
-
- totbidrem (int): 매수잔량
|
|
66
|
-
- mdvolumetm (int): 시간별매도체결량
|
|
67
|
-
- msvolumetm (int): 시간별매수체결량
|
|
55
|
+
- volume (int): 거래량
|
|
56
|
+
- value (int): 거래대금
|
|
57
|
+
- cum_value (int): 누적거래대금
|
|
58
|
+
- cum_volume (int): 누적거래량
|
|
68
59
|
|
|
69
60
|
Raises:
|
|
70
61
|
ValueError: 지원하지 않는 거래소 코드가 전달된 경우.
|
|
71
62
|
|
|
72
63
|
Examples:
|
|
73
|
-
>>> df = get_all_minute_data(datetime.datetime(
|
|
64
|
+
>>> df = get_all_minute_data(datetime.datetime(2025, 8, 12, 15, 30), source="kis", exchange="UN")
|
|
74
65
|
>>> print(df)
|
|
75
|
-
|
|
76
|
-
code
|
|
77
|
-
000020
|
|
78
|
-
000040
|
|
79
|
-
000050
|
|
80
|
-
000070
|
|
81
|
-
000075
|
|
82
|
-
|
|
83
|
-
|
|
66
|
+
time open high low close volume value cum_volume cum_value
|
|
67
|
+
code
|
|
68
|
+
000020 2025-08-12 15:30:00 6510 6510 6510 6510 356 2317560 33208 216896450
|
|
69
|
+
000040 2025-08-12 15:30:00 586 586 586 586 34968 20491248 4617389 2743895196
|
|
70
|
+
000050 2025-08-12 15:30:00 7290 7290 7290 7290 402 2930580 32918 241933340
|
|
71
|
+
000070 2025-08-12 15:30:00 84400 84400 84400 84400 281 23716400 30040 2566753150
|
|
72
|
+
000075 2025-08-12 15:30:00 83500 83500 83500 83500 0 0 0 0
|
|
73
|
+
... ... ... ... ... ... ... ... ... ...
|
|
74
|
+
950170 2025-08-12 15:30:00 6310 6310 6310 6310 388 2448280 191052 1193696490
|
|
75
|
+
950190 2025-08-12 15:30:00 10010 10010 10010 10010 257 2572570 18808 189271460
|
|
76
|
+
950200 2025-08-12 15:30:00 3670 3670 3670 3670 101 370670 8521 31384290
|
|
77
|
+
950210 2025-08-12 15:30:00 14170 14170 14170 14170 2732 38712440 153357 2203865640
|
|
78
|
+
950220 2025-08-12 15:30:00 1193 1193 1193 1193 1335 1592655 829086 1005055869
|
|
84
79
|
"""
|
|
85
80
|
tz = pytz.timezone("Asia/Seoul")
|
|
86
|
-
|
|
87
81
|
exchange = DataExchange.validate(exchange)
|
|
88
|
-
if exchange == DataExchange.UN:
|
|
89
|
-
raise ValueError("UN 거래소는 지원되지 않습니다.")
|
|
90
82
|
|
|
91
83
|
url = f"{c.PYQQQ_API_URL}/domestic-stock/ohlcv/minutes/all/{time.date()}/{time.strftime('%H%M')}"
|
|
92
84
|
params = {
|
|
@@ -128,6 +120,9 @@ def get_all_minute_data(
|
|
|
128
120
|
if k in dtypes:
|
|
129
121
|
dtypes[k] = np.dtype("float64")
|
|
130
122
|
|
|
123
|
+
if source == "kis":
|
|
124
|
+
df = df[["code", "time", "open", "high", "low", "close", "volume", "value", "cum_volume", "cum_value"]]
|
|
125
|
+
|
|
131
126
|
df = df.astype(dtypes)
|
|
132
127
|
df.set_index("code", inplace=True)
|
|
133
128
|
|
|
@@ -147,12 +142,16 @@ def get_all_day_data(
|
|
|
147
142
|
"""
|
|
148
143
|
지정된 날짜에 대해 하나 이상의 주식 코드에 대한 전체 분별 OHLCV(시가, 고가, 저가, 종가, 거래량) 데이터를 검색하여 반환합니다.
|
|
149
144
|
|
|
150
|
-
|
|
145
|
+
데이터 소스에 따라 데이터 조회 가능 시작일이 다릅니다. LS증권은 추후 제거될 예정입니다.
|
|
151
146
|
|
|
152
|
-
|
|
147
|
+
데이터 소스별 조회 가능 기간:
|
|
148
|
+
한국투자증권:
|
|
149
|
+
- KRX: 2023년 7월 3일 데이터 부터 조회 가능합니다.
|
|
150
|
+
- NXT: 2025년 3월 4일 데이터 부터 조회 가능합니다.
|
|
153
151
|
|
|
154
|
-
|
|
155
|
-
|
|
152
|
+
LS증권(구 이베스트증권):
|
|
153
|
+
- KRX: 2024년 4월 26일 ~ 2025년 7월 17일까지 데이터 조회 가능합니다.
|
|
154
|
+
- NXT: 조회 불가합니다.
|
|
156
155
|
|
|
157
156
|
Args:
|
|
158
157
|
date (datetime.date): 데이터를 검색할 날짜.
|
|
@@ -169,42 +168,35 @@ def get_all_day_data(
|
|
|
169
168
|
|
|
170
169
|
DataFrame의 열은 다음과 같습니다:
|
|
171
170
|
|
|
171
|
+
- time (datetime.datetime): 시간
|
|
172
172
|
- open (int): 시가
|
|
173
173
|
- high (int): 고가
|
|
174
174
|
- low (int): 저가
|
|
175
175
|
- close (int): 종가
|
|
176
|
-
- volume (int):
|
|
177
|
-
-
|
|
178
|
-
-
|
|
179
|
-
-
|
|
180
|
-
- chdegree (float): 체결강도
|
|
181
|
-
- mdvolume (int): 매도체결수량
|
|
182
|
-
- msvolume (int): 매수체결수량
|
|
183
|
-
- revolume (int): 순매수체결량
|
|
184
|
-
- mdchecnt (int): 매도체결건수
|
|
185
|
-
- mschecnt (int): 매수체결건수
|
|
186
|
-
- rechecnt (int): 순체결건수
|
|
187
|
-
- cvolume (int): 체결량
|
|
188
|
-
- mdchecnttm (int): 시간별매도체결건수
|
|
189
|
-
- mschecnttm (int): 시간별매수체결건수
|
|
190
|
-
- totofferrem (int): 매도잔량
|
|
191
|
-
- totbidrem (int): 매수잔량
|
|
192
|
-
- mdvolumetm (int): 시간별매도체결량
|
|
193
|
-
- msvolumetm (int): 시간별매수체결량
|
|
176
|
+
- volume (int): 거래량
|
|
177
|
+
- value (int): 거래대금
|
|
178
|
+
- cum_volume (int): 누적거래량
|
|
179
|
+
- cum_value (int): 누적거래대금
|
|
194
180
|
|
|
195
181
|
Raises:
|
|
196
182
|
requests.exceptions.RequestException: PYQQQ API로부터 데이터를 검색하는 과정에서 오류가 발생한 경우.
|
|
197
183
|
|
|
198
184
|
Examples:
|
|
199
|
-
>>> result = get_all_day_data(datetime.date(
|
|
200
|
-
>>> print(result["
|
|
201
|
-
|
|
185
|
+
>>> result = get_all_day_data(datetime.date(2025, 8, 12), codes=["005930", "319640"], source="kis", exchange="UN")
|
|
186
|
+
>>> print(result["005930"])
|
|
187
|
+
open high low close volume value cum_volume cum_value
|
|
202
188
|
time
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
189
|
+
2025-08-12 08:00:00 71100 71300 71000 71200 39907 2840499700 39907 2840499700
|
|
190
|
+
2025-08-12 08:01:00 71200 71200 71100 71200 17688 1258243300 57595 4098743000
|
|
191
|
+
2025-08-12 08:02:00 71200 71300 71100 71300 37311 2656578100 94906 6755321100
|
|
192
|
+
2025-08-12 08:03:00 71200 71300 71200 71300 12086 861096800 106992 7616417900
|
|
193
|
+
2025-08-12 08:04:00 71300 71300 71200 71300 14868 1059991500 121860 8676409400
|
|
194
|
+
... ... ... ... ... ... ... ... ...
|
|
195
|
+
2025-08-12 19:56:00 71200 71300 71200 71300 3507 250012700 22367898 1603227575600
|
|
196
|
+
2025-08-12 19:57:00 71200 71300 71200 71200 6834 487156900 22374732 1603714732500
|
|
197
|
+
2025-08-12 19:58:00 71200 71300 71200 71300 9708 692159000 22384440 1604406891500
|
|
198
|
+
2025-08-12 19:59:00 71300 71400 71200 71400 10540 751223500 22394980 1605158115000
|
|
199
|
+
2025-08-12 20:00:00 71400 71400 71400 71400 0 0 22394980 1605158115000
|
|
208
200
|
"""
|
|
209
201
|
assert isinstance(date, datetime.date), "date must be a datetime.date object"
|
|
210
202
|
assert type(date) is datetime.date, "date must be a datetime.date object"
|
|
@@ -223,12 +215,11 @@ def get_all_day_data(
|
|
|
223
215
|
target_codes = codes if isinstance(codes, list) else [codes]
|
|
224
216
|
|
|
225
217
|
exchange = DataExchange.validate(exchange)
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
elif exchange == DataExchange.NXT or source == "kis":
|
|
229
|
-
url = f"{c.PYQQQ_API_URL}/domestic-stock/ohlcv/minutes/{date}"
|
|
230
|
-
else:
|
|
218
|
+
|
|
219
|
+
if source == "ebest":
|
|
231
220
|
url = f"{c.PYQQQ_API_URL}/domestic-stock/ohlcv/half-minutes/{date}"
|
|
221
|
+
else:
|
|
222
|
+
url = f"{c.PYQQQ_API_URL}/domestic-stock/ohlcv/minutes/{date}"
|
|
232
223
|
|
|
233
224
|
r = send_request(
|
|
234
225
|
"GET",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|