pyqqq 0.12.175__tar.gz → 0.12.176__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 (63) hide show
  1. {pyqqq-0.12.175 → pyqqq-0.12.176}/PKG-INFO +1 -1
  2. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyproject.toml +1 -1
  3. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/data/realtime.py +14 -16
  4. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/daily_tickers.py +41 -16
  5. {pyqqq-0.12.175 → pyqqq-0.12.176}/README.md +0 -0
  6. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/__init__.py +0 -0
  7. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/ai/__init__.py +0 -0
  8. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/ai/daily.py +0 -0
  9. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/ai/domestic.py +0 -0
  10. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/ai/market_schedule.py +0 -0
  11. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/ai/minute.py +0 -0
  12. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/backtest/__init__.py +0 -0
  13. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/backtest/broker.py +0 -0
  14. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/backtest/environment.py +0 -0
  15. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/backtest/logger.py +0 -0
  16. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/backtest/positionprovider.py +0 -0
  17. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/backtest/strategy.py +0 -0
  18. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/backtest/utils.py +0 -0
  19. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/backtest/wallclock.py +0 -0
  20. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/__init__.py +0 -0
  21. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/ebest/__init__.py +0 -0
  22. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/ebest/domestic_stock.py +0 -0
  23. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/ebest/oauth.py +0 -0
  24. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/ebest/simple.py +0 -0
  25. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/ebest/tr_client.py +0 -0
  26. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/helper.py +0 -0
  27. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/kis/__init__.py +0 -0
  28. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/kis/domestic_stock.py +0 -0
  29. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/kis/oauth.py +0 -0
  30. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/kis/overseas_stock.py +0 -0
  31. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/kis/simple.py +0 -0
  32. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/kis/simple_overseas.py +0 -0
  33. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/kis/tr_client.py +0 -0
  34. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/multiprocess_tracker.py +0 -0
  35. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/tracker.py +0 -0
  36. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/config.py +0 -0
  37. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/data/__init__.py +0 -0
  38. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/data/daily.py +0 -0
  39. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/data/domestic.py +0 -0
  40. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/data/index.py +0 -0
  41. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/data/minutes.py +0 -0
  42. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/data/overseas.py +0 -0
  43. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/data/ticks.py +0 -0
  44. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/data/us_stocks.py +0 -0
  45. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/datatypes.py +0 -0
  46. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/executors/__init__.py +0 -0
  47. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/executors/hook.py +0 -0
  48. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/__init__.py +0 -0
  49. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/api_client.py +0 -0
  50. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/array.py +0 -0
  51. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/casting.py +0 -0
  52. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/compute.py +0 -0
  53. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/copycat.py +0 -0
  54. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/display.py +0 -0
  55. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/kvstore.py +0 -0
  56. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/limiter.py +0 -0
  57. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/local_cache.py +0 -0
  58. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/logger.py +0 -0
  59. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/market_schedule.py +0 -0
  60. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/mock_api.py +0 -0
  61. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/position_classifier.py +0 -0
  62. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/retry.py +0 -0
  63. {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/singleton.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyqqq
3
- Version: 0.12.175
3
+ Version: 0.12.176
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.175"
3
+ version = "0.12.176"
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"
@@ -1,16 +1,16 @@
1
- from typing import List, Union
2
- from pyqqq.datatypes import DataExchange
3
- from pyqqq.utils.api_client import raise_for_status, send_request
4
- from pyqqq.utils.logger import get_logger
5
- from pyqqq.utils.singleton import singleton
6
- import pyqqq.config as c
7
1
  import asyncio
2
+ import datetime as dtm
3
+ import inspect
4
+ import json
8
5
  import os
6
+ from typing import List
7
+
9
8
  import websockets
10
- import json
11
- import inspect
12
- import datetime as dtm
13
9
 
10
+ import pyqqq.config as c
11
+ from pyqqq.utils.api_client import raise_for_status, send_request
12
+ from pyqqq.utils.logger import get_logger
13
+ from pyqqq.utils.singleton import singleton
14
14
 
15
15
  logger = get_logger(__name__)
16
16
 
@@ -21,21 +21,17 @@ def get_all_last_trades(codes: List[str] = None, exchange: str = "KRX"):
21
21
 
22
22
  Args:
23
23
  codes (List[str], optional): 종목 코드 리스트. 모든 종목의 체결 정보를 반환하려면 None을 전달합니다.
24
- exchange (str, optional): 거래소. 기본값은 "KRX"입니다. 지원하는 거래소는 "KRX", "UN" 입니다.
24
+ exchange (str): 거래소. 기본값은 "KRX"입니다. 지원하는 거래소는 "KRX", "UN" 입니다.
25
25
 
26
26
  Returns:
27
27
  list:
28
28
  - dict:
29
- - chetime (str): 체결시간
30
- - sign (str): 전일대비구분
29
+ - sign (int): 전일대비구분
31
30
  - change (int): 전일대비가격
32
31
  - drate (float): 전일대비등락율
33
32
  - price (int): 체결가
34
- - opentime (str): 시가시간
35
33
  - open (int): 시가
36
- - hightime (str): 고가시간
37
34
  - high (int): 고가
38
- - lowtime (str): 저가시간
39
35
  - low (int): 저가
40
36
  - cgubun (str): 체결구분
41
37
  - cvolume (int): 체결량
@@ -51,7 +47,9 @@ def get_all_last_trades(codes: List[str] = None, exchange: str = "KRX"):
51
47
  - status (str): 장정보
52
48
  - jnilvolume (int): 전일동시간대거래량
53
49
  - shcode (str): 종목코드
54
-
50
+ - exchname (str): 거래소명
51
+ - date (str): 체결일자
52
+ - update_time (str): 업데이트 시간
55
53
  """
56
54
 
57
55
  params = {"exchange": exchange}
@@ -4,7 +4,7 @@ from functools import lru_cache
4
4
 
5
5
  import pandas as pd
6
6
  from pyqqq.data import domestic
7
- from pyqqq.utils import market_schedule
7
+ from pyqqq.utils.market_schedule import is_full_day_closed, get_last_trading_day
8
8
  from pyqqq.utils.logger import get_bare_logger as get_logger
9
9
 
10
10
 
@@ -24,7 +24,10 @@ class DailyTickers:
24
24
  self._initialized = True
25
25
 
26
26
  self._today = dtm.date.today()
27
- self._date = market_schedule.get_last_trading_day()
27
+ if is_full_day_closed(self._today):
28
+ self._date = get_last_trading_day(self._today)
29
+ else:
30
+ self._date = self._today
28
31
  self._tickers = None
29
32
  self._change_date()
30
33
 
@@ -34,69 +37,91 @@ class DailyTickers:
34
37
  @lru_cache(maxsize=30) # memory_profiler 로 확인 결과 하루치 fetch 결과가 약 2.5MiB
35
38
  @staticmethod
36
39
  def fetch_tickers(date: dtm.date) -> pd.DataFrame:
37
- DailyTickers.logger.debug(f'\tfetch_tickers date={date}')
40
+ DailyTickers.logger.debug(f'\tfetch_tickers date={date} cache_info={DailyTickers.fetch_tickers.cache_info()}')
38
41
  return domestic.get_tickers(date)
39
42
 
40
- def _change_date(self, date: Optional[dtm.date] = None):
43
+ def _change_date(self, date: Optional[dtm.date] = None, force: bool = False):
41
44
  """_tickers 가 비었거나 날짜가 바뀌었으면 새로 채워넣는다."""
42
45
  if not date:
43
46
  if self._chk_days_passed():
44
47
  self._today = dtm.date.today()
45
- date = market_schedule.get_last_trading_day()
48
+ if is_full_day_closed(self._today):
49
+ date = get_last_trading_day(self._today)
50
+ else:
51
+ date = self._today
46
52
  else:
47
53
  date = self._date
48
54
 
55
+ if force:
56
+ DailyTickers.fetch_tickers.cache_clear()
57
+ self._tickers = None
58
+
49
59
  if self._tickers is None or self._date != date:
50
60
  self._date = date
51
61
  self.logger.debug(f'\tdate changed. date={self._date} wait for get_tickers()')
52
62
  self._tickers = DailyTickers.fetch_tickers(self._date)
53
63
 
54
- def get_tickers(self, date: Optional[dtm.date] = None) -> pd.DataFrame:
64
+ def get_tickers(self, date: Optional[dtm.date] = None, force: bool = False) -> pd.DataFrame:
55
65
  """
56
66
  종목정보 가져오기
57
67
  """
58
- self._change_date(date)
68
+ self._change_date(date, force)
59
69
  return self._tickers
60
70
 
61
- def get_ticker_info(self, code: str, date: Optional[dtm.date] = None) -> Tuple[Optional[str], Optional[str]]:
71
+ def get_ticker_info(self, code: str, date: Optional[dtm.date] = None, force: bool = False) -> Tuple[Optional[str], Optional[str]]:
62
72
  """
63
73
  종목정보 가져오기
64
74
  """
65
- self._change_date(date)
75
+ self._change_date(date, force)
66
76
 
67
77
  # self.logger.debug(f'\tget_ticker_info code={code} date={self._date}')
68
78
  try:
69
79
  name = self._tickers.loc[code, 'name']
70
80
  type = self._tickers.loc[code, 'type']
71
81
  except KeyError:
72
- self.logger.error(f'KeyError on get_ticker_info. code={code}')
82
+ try:
83
+ self._change_date(date, True)
84
+ name = self._tickers.loc[code, 'name']
85
+ type = self._tickers.loc[code, 'type']
86
+ except KeyError:
87
+ self.logger.warning(f'KeyError on get_ticker_info. code={code}')
73
88
  return (None, None)
74
89
 
75
90
  return (name, type)
76
91
 
77
- def get_listing_date(self, code: str) -> Optional[dtm.date]:
92
+ def get_listing_date(self, code: str, date: Optional[dtm.date] = None, force: bool = False) -> Optional[dtm.date]:
78
93
  """
79
94
  상장일 가져오기
80
95
  """
96
+ self._change_date(date, force)
97
+
81
98
  try:
82
99
  list_date = self._tickers.loc[code, 'listing_date']
83
100
  except KeyError:
84
- self.logger.error(f'KeyError on get_listing_date. code={code}')
101
+ try:
102
+ self._change_date(date, True)
103
+ list_date = self._tickers.loc[code, 'listing_date']
104
+ except KeyError:
105
+ self.logger.warning(f'KeyError on get_listing_date. code={code}')
85
106
  return None
86
107
 
87
108
  return dtm.datetime.strptime(list_date, "%Y%m%d").date() if list_date else None
88
109
 
89
- def get_ticker_upper_limit(self, code: str, date: Optional[dtm.date] = None) -> Optional[int]:
110
+ def get_ticker_upper_limit(self, code: str, date: Optional[dtm.date] = None, force: bool = False) -> Optional[int]:
90
111
  """
91
112
  상한가 가져오기
92
113
  """
93
- self._change_date(date)
114
+ self._change_date(date, force)
94
115
 
95
116
  # self.logger.debug(f'\tget_ticker_upper_limit code={code} date={self._date}')
96
117
  try:
97
118
  upper_limit = self._tickers.loc[code, 'upper_limit']
98
119
  except KeyError:
99
- self.logger.error(f'KeyError on get_ticker_upper_limit. code={code}')
100
- return None
120
+ try:
121
+ self._change_date(date, True)
122
+ upper_limit = self._tickers.loc[code, 'upper_limit']
123
+ except KeyError:
124
+ self.logger.warning(f'KeyError on get_ticker_upper_limit. code={code}')
125
+ return None
101
126
 
102
127
  return int(upper_limit) if upper_limit else None
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