pyqqq 0.12.194__tar.gz → 0.12.196__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.194 → pyqqq-0.12.196}/PKG-INFO +1 -1
  2. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyproject.toml +1 -1
  3. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/backtest/broker.py +11 -2
  4. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/brokerage/kis/tr_client.py +7 -6
  5. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/data/domestic.py +2 -1
  6. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/utils/compute.py +2 -2
  7. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/utils/retry.py +4 -2
  8. {pyqqq-0.12.194 → pyqqq-0.12.196}/README.md +0 -0
  9. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/__init__.py +0 -0
  10. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/backtest/__init__.py +0 -0
  11. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/backtest/environment.py +0 -0
  12. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/backtest/logger.py +0 -0
  13. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/backtest/positionprovider.py +0 -0
  14. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/backtest/strategy.py +0 -0
  15. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/backtest/utils.py +0 -0
  16. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/backtest/wallclock.py +0 -0
  17. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/brokerage/__init__.py +0 -0
  18. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/brokerage/ebest/__init__.py +0 -0
  19. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/brokerage/ebest/domestic_stock.py +0 -0
  20. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/brokerage/ebest/oauth.py +0 -0
  21. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/brokerage/ebest/simple.py +0 -0
  22. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/brokerage/ebest/tr_client.py +0 -0
  23. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/brokerage/helper.py +0 -0
  24. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/brokerage/kis/__init__.py +0 -0
  25. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/brokerage/kis/domestic_stock.py +0 -0
  26. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/brokerage/kis/oauth.py +0 -0
  27. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/brokerage/kis/overseas_stock.py +0 -0
  28. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/brokerage/kis/simple.py +0 -0
  29. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/brokerage/kis/simple_overseas.py +0 -0
  30. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/brokerage/multiprocess_tracker.py +0 -0
  31. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/brokerage/tracker.py +0 -0
  32. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/config.py +0 -0
  33. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/data/__init__.py +0 -0
  34. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/data/daily.py +0 -0
  35. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/data/index.py +0 -0
  36. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/data/minutes.py +0 -0
  37. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/data/overseas.py +0 -0
  38. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/data/realtime.py +0 -0
  39. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/data/ticks.py +0 -0
  40. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/data/us_stocks.py +0 -0
  41. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/datatypes.py +0 -0
  42. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/executors/__init__.py +0 -0
  43. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/executors/hook.py +0 -0
  44. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/utils/__init__.py +0 -0
  45. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/utils/api_client.py +0 -0
  46. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/utils/array.py +0 -0
  47. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/utils/casting.py +0 -0
  48. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/utils/copycat.py +0 -0
  49. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/utils/daily_tickers.py +0 -0
  50. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/utils/display.py +0 -0
  51. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/utils/kvstore.py +0 -0
  52. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/utils/limiter.py +0 -0
  53. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/utils/local_cache.py +0 -0
  54. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/utils/logger.py +0 -0
  55. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/utils/market_schedule.py +0 -0
  56. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/utils/mock_api.py +0 -0
  57. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/utils/position_classifier.py +0 -0
  58. {pyqqq-0.12.194 → pyqqq-0.12.196}/pyqqq/utils/singleton.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyqqq
3
- Version: 0.12.194
3
+ Version: 0.12.196
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.194"
3
+ version = "0.12.196"
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"
@@ -597,11 +597,17 @@ class MockBroker(BaseBroker):
597
597
  # 현재 시간 데이터가 없을 경우 전일 종가로 대체
598
598
  last_trading_day = get_last_trading_day(today, exchange=self._get_exchange_code())
599
599
  df = self.get_daily_price(code, last_trading_day, last_trading_day) # 전일 종가는 일봉, 분봉 구분이 필요 없다.
600
- return typed_result(df["close"].iloc[-1])
600
+ if not df.empty:
601
+ return typed_result(df["close"].iloc[-1])
602
+ else:
603
+ return Decimal(0)
601
604
 
602
605
  elif self.time_unit == "days":
603
606
  df = self.get_daily_price(code, today, today)
604
- return typed_result(df["close"].iloc[-1])
607
+ if not df.empty:
608
+ return typed_result(df["close"].iloc[-1])
609
+ else:
610
+ return Decimal(0)
605
611
 
606
612
  else:
607
613
  raise ValueError(f"Invalid time unit: {self.time_unit}")
@@ -814,6 +820,9 @@ class MockBroker(BaseBroker):
814
820
  else:
815
821
  dfs = get_kr_daily_data([code], from_date, end_date, adjusted=True, ascending=True, exchange=DataExchange.KRX)
816
822
 
823
+ if code not in dfs:
824
+ return pd.DataFrame()
825
+
817
826
  df = dfs[code]
818
827
 
819
828
  if not df.empty and end_date == today:
@@ -25,7 +25,7 @@ class KISTRClient:
25
25
  self.corp_data = corp_data
26
26
  self.session = requests.Session()
27
27
 
28
- @retry(requests.HTTPError)
28
+ @retry(requests.RequestException)
29
29
  def request(self, path: str, tr_id: str, tr_cont: str = "", params: dict = None, body: dict = None, method: str = "GET"):
30
30
  """
31
31
  TR 요청을 보내고 응답을 받는 메서드
@@ -132,21 +132,22 @@ class KISTRWebsocketClient:
132
132
  yield data
133
133
 
134
134
  except websockets.exceptions.ConnectionClosedError:
135
- # self.logger.error(f"{self.session_id}: ConnectionClosedError")
135
+ self.logger.error(f"{self.session_id}: ConnectionClosedError")
136
136
  await asyncio.sleep(0.5)
137
137
  continue
138
138
 
139
139
  except ConnectionRefusedError:
140
+ self.logger.error(f"{self.session_id}: ConnectionRefusedError")
140
141
  await asyncio.sleep(0.5)
141
142
  continue
142
143
 
143
- except websockets.ConnectionClosed as e:
144
+ except websockets.ConnectionClosed:
145
+ self.logger.error(f"{self.session_id}: ConnectionClosed")
144
146
  await asyncio.sleep(0.5)
145
- self.logger.exception(e)
146
147
  continue
147
148
 
148
- except ssl.SSLZeroReturnError as e:
149
- self.logger.exception(e)
149
+ except ssl.SSLZeroReturnError:
150
+ self.logger.error(f"{self.session_id}: SSLZeroReturnError")
150
151
  await asyncio.sleep(0.5)
151
152
  continue
152
153
 
@@ -229,7 +229,8 @@ def _isoformat_to_readable(isodate: str) -> str:
229
229
  return ""
230
230
 
231
231
 
232
- @domesticCache.memoize()
232
+ # _get_tickers가 메모이제이션 되어있어서 해당 함수는 캐싱하면 안됨
233
+ # 특히 date가 None으로 쓰는경우가 많은데 캐싱하면 오작동함
233
234
  def get_tickers(
234
235
  date: Optional[dtm.date] = None,
235
236
  market: Optional[str] = None,
@@ -1,6 +1,6 @@
1
1
  import datetime
2
2
  from decimal import ROUND_CEILING, ROUND_FLOOR, ROUND_HALF_UP, Decimal
3
- from typing import Union
3
+ from typing import Union, Optional
4
4
 
5
5
 
6
6
  def quantize_krx_price(price: Union[Decimal, int, float], etf_etn: bool, rounding: str = "floor") -> int:
@@ -50,7 +50,7 @@ def get_krx_tick_size(
50
50
  price: float,
51
51
  etf_etn: bool,
52
52
  market: str = "KOSPI",
53
- date: datetime.date = None,
53
+ date: Optional[datetime.date] = None,
54
54
  ) -> int:
55
55
  """
56
56
  주어진 가격과 금융 상품 유형에 따라 적절한 호가가격단위를 반환합니다.
@@ -1,5 +1,6 @@
1
1
  import time
2
2
  from functools import wraps
3
+ from pyqqq.utils.logger import get_logger
3
4
 
4
5
 
5
6
  def retry(exceptions, total_tries=5, delay=0.5, backoff=2, silently: bool = False):
@@ -28,6 +29,7 @@ def retry(exceptions, total_tries=5, delay=0.5, backoff=2, silently: bool = Fals
28
29
  def decorator(func):
29
30
  @wraps(func)
30
31
  def wrapper(*args, **kwargs):
32
+ logger = get_logger(f"{__name__}.{func.__name__}")
31
33
  current_try = 0
32
34
  while current_try < total_tries:
33
35
  try:
@@ -37,10 +39,10 @@ def retry(exceptions, total_tries=5, delay=0.5, backoff=2, silently: bool = Fals
37
39
  sleep_time = delay * (backoff ** (current_try - 1))
38
40
  if current_try != total_tries:
39
41
  if not silently:
40
- print(f"{str(e)}\nRetrying in {sleep_time} seconds...")
42
+ logger.warning(f"{str(e)}\nRetrying in {sleep_time} seconds...")
41
43
  time.sleep(sleep_time)
42
44
  else:
43
- print("Max retry attempts reached, aborting.")
45
+ logger.error("Max retry attempts reached, aborting.")
44
46
  raise
45
47
  return wrapper
46
48
  return decorator
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