pyqqq 0.12.190__tar.gz → 0.12.191__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.

Files changed (58) hide show
  1. {pyqqq-0.12.190 → pyqqq-0.12.191}/PKG-INFO +1 -1
  2. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyproject.toml +1 -1
  3. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/brokerage/kis/simple.py +13 -1
  4. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/data/minutes.py +61 -70
  5. {pyqqq-0.12.190 → pyqqq-0.12.191}/README.md +0 -0
  6. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/__init__.py +0 -0
  7. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/backtest/__init__.py +0 -0
  8. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/backtest/broker.py +0 -0
  9. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/backtest/environment.py +0 -0
  10. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/backtest/logger.py +0 -0
  11. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/backtest/positionprovider.py +0 -0
  12. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/backtest/strategy.py +0 -0
  13. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/backtest/utils.py +0 -0
  14. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/backtest/wallclock.py +0 -0
  15. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/brokerage/__init__.py +0 -0
  16. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/brokerage/ebest/__init__.py +0 -0
  17. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/brokerage/ebest/domestic_stock.py +0 -0
  18. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/brokerage/ebest/oauth.py +0 -0
  19. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/brokerage/ebest/simple.py +0 -0
  20. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/brokerage/ebest/tr_client.py +0 -0
  21. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/brokerage/helper.py +0 -0
  22. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/brokerage/kis/__init__.py +0 -0
  23. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/brokerage/kis/domestic_stock.py +0 -0
  24. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/brokerage/kis/oauth.py +0 -0
  25. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/brokerage/kis/overseas_stock.py +0 -0
  26. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/brokerage/kis/simple_overseas.py +0 -0
  27. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/brokerage/kis/tr_client.py +0 -0
  28. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/brokerage/multiprocess_tracker.py +0 -0
  29. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/brokerage/tracker.py +0 -0
  30. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/config.py +0 -0
  31. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/data/__init__.py +0 -0
  32. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/data/daily.py +0 -0
  33. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/data/domestic.py +0 -0
  34. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/data/index.py +0 -0
  35. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/data/overseas.py +0 -0
  36. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/data/realtime.py +0 -0
  37. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/data/ticks.py +0 -0
  38. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/data/us_stocks.py +0 -0
  39. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/datatypes.py +0 -0
  40. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/executors/__init__.py +0 -0
  41. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/executors/hook.py +0 -0
  42. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/utils/__init__.py +0 -0
  43. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/utils/api_client.py +0 -0
  44. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/utils/array.py +0 -0
  45. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/utils/casting.py +0 -0
  46. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/utils/compute.py +0 -0
  47. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/utils/copycat.py +0 -0
  48. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/utils/daily_tickers.py +0 -0
  49. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/utils/display.py +0 -0
  50. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/utils/kvstore.py +0 -0
  51. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/utils/limiter.py +0 -0
  52. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/utils/local_cache.py +0 -0
  53. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/utils/logger.py +0 -0
  54. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/utils/market_schedule.py +0 -0
  55. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/utils/mock_api.py +0 -0
  56. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/utils/position_classifier.py +0 -0
  57. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/utils/retry.py +0 -0
  58. {pyqqq-0.12.190 → pyqqq-0.12.191}/pyqqq/utils/singleton.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyqqq
3
- Version: 0.12.190
3
+ Version: 0.12.191
4
4
  Summary: Package for quantitative strategy development on the PyQQQ platform
5
5
  License: MIT
6
6
  Author: PyQQQ team
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "pyqqq"
3
- version = "0.12.190"
3
+ version = "0.12.191"
4
4
  description = "Package for quantitative strategy development on the PyQQQ platform"
5
5
  authors = ["PyQQQ team <pyqqq.cs@gmail.com>"]
6
6
  readme = "README.md"
@@ -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
@@ -25,12 +25,16 @@ def get_all_minute_data(
25
25
  """
26
26
  모든 종목의 분봉 데이터를 반환합니다.
27
27
 
28
- 2024년 4월 9일 데이터 부터 조회 가능합니다.
28
+ 데이터 소스에 따라 데이터 조회 가능 시작일이 다릅니다. LS증권은 추후 제거될 예정입니다.
29
29
 
30
- NXT 거래소 데이터의 조회 가능 시작일은 데이터 소스에 따라 다릅니다. kis는 2025년 3월 4일부터, ebest는 2025년 5월 12일부터 데이터를 조회할 수 있습니다.
30
+ 데이터 소스별 조회 가능 기간:
31
+ 한국투자증권:
32
+ - KRX: 2023년 7월 3일 데이터 부터 조회 가능합니다.
33
+ - NXT: 2025년 3월 4일 데이터 부터 조회 가능합니다.
31
34
 
32
- Note:
33
- - KRX, NXT 거래소의 분봉 데이터를 조회할 있습니다. UN 거래소는 지원되지 않습니다.
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
- - sign (str): 대비부호 (1:상한가 2:상승, 3:보합 4:하한가, 5:하락)
52
- - change (str): 전일 대비 가격 변화
53
- - diff (float): 전일 대비 등락율
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(2024, 5, 2, 15, 30))
64
+ >>> df = get_all_minute_data(datetime.datetime(2025, 8, 12, 15, 30), source="kis", exchange="UN")
74
65
  >>> print(df)
75
- time open high low ... totofferrem totbidrem mdvolumetm msvolumetm
76
- code ...
77
- 000020 2024-05-02 15:30:00 8700 8700 8700 ... 8404 4015 35 1
78
- 000040 2024-05-02 15:30:00 1058 1058 1058 ... 13597 24738 20 0
79
- 000050 2024-05-02 15:30:00 7620 7620 7620 ... 2534 2866 0 0
80
- 000070 2024-05-02 15:30:00 69400 69400 69400 ... 606 724 0 3
81
- 000075 2024-05-02 15:30:00 54900 54900 54900 ... 315 308 0 0
82
-
83
- [5 rows x 23 columns]
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
- 2024년 4월 26일 데이터 부터 조회 가능합니다.
145
+ 데이터 소스에 따라 데이터 조회 가능 시작일이 다릅니다. LS증권은 추후 제거될 예정입니다.
151
146
 
152
- NXT 거래소 데이터의 조회 가능 시작일은 데이터 소스에 따라 다릅니다. kis는 2025년 3월 4일부터, ebest는 2025년 5월 12일부터 데이터를 조회할 수 있습니다.
147
+ 데이터 소스별 조회 가능 기간:
148
+ 한국투자증권:
149
+ - KRX: 2023년 7월 3일 데이터 부터 조회 가능합니다.
150
+ - NXT: 2025년 3월 4일 데이터 부터 조회 가능합니다.
153
151
 
154
- Note:
155
- - KRX, NXT 거래소의 분봉 데이터를 조회할 있습니다. UN 거래소는 지원되지 않습니다.
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
- - sign (str): 대비부호 (1:상한가 2:상승, 3:보합 4:하한가, 5:하락)
178
- - change (str): 전일 대비 가격 변화
179
- - diff (float): 전일 대비 등락율
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(2024, 4, 26), ["005930", "319640"], datetime.timedelta(minutes=1))
200
- >>> print(result["069500"])
201
- open high low close volume sign change diff \
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
- 2024-04-26 09:00:00 77800 77900 77400 77600 1629535 2 1300 1.70
204
- 2024-04-26 09:01:00 77500 77700 77300 77600 2155263 2 1300 1.70
205
- 2024-04-26 09:02:00 77600 77700 77400 77500 2600420 2 1200 1.57
206
- 2024-04-26 09:03:00 77500 77500 77200 77500 3033307 2 1200 1.57
207
- 2024-04-26 09:04:00 77400 77600 77400 77500 3268502 2 1200 1.57
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
- if exchange == DataExchange.UN:
227
- raise ValueError("UN 거래소는 지원되지 않습니다.")
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