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.
- {pyqqq-0.12.175 → pyqqq-0.12.176}/PKG-INFO +1 -1
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyproject.toml +1 -1
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/data/realtime.py +14 -16
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/daily_tickers.py +41 -16
- {pyqqq-0.12.175 → pyqqq-0.12.176}/README.md +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/__init__.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/ai/__init__.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/ai/daily.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/ai/domestic.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/ai/market_schedule.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/ai/minute.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/backtest/__init__.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/backtest/broker.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/backtest/environment.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/backtest/logger.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/backtest/positionprovider.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/backtest/strategy.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/backtest/utils.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/backtest/wallclock.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/__init__.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/ebest/__init__.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/ebest/domestic_stock.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/ebest/oauth.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/ebest/simple.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/ebest/tr_client.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/helper.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/kis/__init__.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/kis/domestic_stock.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/kis/oauth.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/kis/overseas_stock.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/kis/simple.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/kis/simple_overseas.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/kis/tr_client.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/multiprocess_tracker.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/brokerage/tracker.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/config.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/data/__init__.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/data/daily.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/data/domestic.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/data/index.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/data/minutes.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/data/overseas.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/data/ticks.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/data/us_stocks.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/datatypes.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/executors/__init__.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/executors/hook.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/__init__.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/api_client.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/array.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/casting.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/compute.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/copycat.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/display.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/kvstore.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/limiter.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/local_cache.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/logger.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/market_schedule.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/mock_api.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/position_classifier.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/retry.py +0 -0
- {pyqqq-0.12.175 → pyqqq-0.12.176}/pyqqq/utils/singleton.py +0 -0
|
@@ -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
|
|
24
|
+
exchange (str): 거래소. 기본값은 "KRX"입니다. 지원하는 거래소는 "KRX", "UN" 입니다.
|
|
25
25
|
|
|
26
26
|
Returns:
|
|
27
27
|
list:
|
|
28
28
|
- dict:
|
|
29
|
-
-
|
|
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
|
|
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.
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
100
|
-
|
|
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
|
|
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
|