pyqqq 0.12.170__tar.gz → 0.12.172__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.170 → pyqqq-0.12.172}/PKG-INFO +1 -1
  2. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyproject.toml +1 -1
  3. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/backtest/broker.py +14 -3
  4. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/tracker.py +9 -0
  5. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/data/realtime.py +5 -3
  6. {pyqqq-0.12.170 → pyqqq-0.12.172}/README.md +0 -0
  7. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/__init__.py +0 -0
  8. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/ai/__init__.py +0 -0
  9. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/ai/daily.py +0 -0
  10. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/ai/domestic.py +0 -0
  11. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/ai/market_schedule.py +0 -0
  12. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/ai/minute.py +0 -0
  13. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/backtest/__init__.py +0 -0
  14. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/backtest/environment.py +0 -0
  15. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/backtest/logger.py +0 -0
  16. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/backtest/positionprovider.py +0 -0
  17. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/backtest/strategy.py +0 -0
  18. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/backtest/utils.py +0 -0
  19. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/backtest/wallclock.py +0 -0
  20. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/__init__.py +0 -0
  21. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/ebest/__init__.py +0 -0
  22. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/ebest/domestic_stock.py +0 -0
  23. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/ebest/oauth.py +0 -0
  24. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/ebest/simple.py +0 -0
  25. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/ebest/tr_client.py +0 -0
  26. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/helper.py +0 -0
  27. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/kis/__init__.py +0 -0
  28. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/kis/domestic_stock.py +0 -0
  29. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/kis/oauth.py +0 -0
  30. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/kis/overseas_stock.py +0 -0
  31. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/kis/simple.py +0 -0
  32. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/kis/simple_overseas.py +0 -0
  33. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/kis/tr_client.py +0 -0
  34. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/multiprocess_tracker.py +0 -0
  35. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/config.py +0 -0
  36. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/data/__init__.py +0 -0
  37. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/data/daily.py +0 -0
  38. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/data/domestic.py +0 -0
  39. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/data/index.py +0 -0
  40. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/data/minutes.py +0 -0
  41. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/data/overseas.py +0 -0
  42. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/data/ticks.py +0 -0
  43. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/data/us_stocks.py +0 -0
  44. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/datatypes.py +0 -0
  45. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/executors/__init__.py +0 -0
  46. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/executors/hook.py +0 -0
  47. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/__init__.py +0 -0
  48. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/api_client.py +0 -0
  49. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/array.py +0 -0
  50. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/casting.py +0 -0
  51. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/compute.py +0 -0
  52. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/copycat.py +0 -0
  53. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/daily_tickers.py +0 -0
  54. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/display.py +0 -0
  55. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/kvstore.py +0 -0
  56. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/limiter.py +0 -0
  57. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/local_cache.py +0 -0
  58. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/logger.py +0 -0
  59. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/market_schedule.py +0 -0
  60. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/mock_api.py +0 -0
  61. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/position_classifier.py +0 -0
  62. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/retry.py +0 -0
  63. {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/singleton.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pyqqq
3
- Version: 0.12.170
3
+ Version: 0.12.172
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.170"
3
+ version = "0.12.172"
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"
@@ -269,10 +269,12 @@ class TradingBroker(BaseBroker):
269
269
  def get_price(self, code: str, data_exchange: Optional[DataExchange] = None) -> Decimal:
270
270
  if data_exchange:
271
271
  price_data = self.data_api.get_price(code, data_exchange=data_exchange)
272
+ if data_exchange == DataExchange.NXT and price_data.get("open_price", 0) == 0: # current_price는 어제의 값을 반환하므로 open_price가 0인지로 NXT 시장 여부 확인
273
+ price_data = self.data_api.get_price(code, data_exchange=DataExchange.KRX)
272
274
  else:
273
- if self.market_nxt_on:
275
+ if self.market_nxt_on: # TODO: 정규장에서도 NXT 가격을 우선 조회하는 것이니 수정 필요
274
276
  price_data = self.data_api.get_price(code, data_exchange=DataExchange.NXT)
275
- if price_data.get("current_price") == 0:
277
+ if price_data.get("open_price", 0) == 0: # current_price는 어제의 값을 반환하므로 open_price가 0인지로 NXT 시장 여부 확인
276
278
  price_data = self.data_api.get_price(code, data_exchange=DataExchange.KRX)
277
279
  else:
278
280
  price_data = self.data_api.get_price(code, data_exchange=DataExchange.KRX)
@@ -285,10 +287,12 @@ class TradingBroker(BaseBroker):
285
287
  def get_minute_price(self, code: str, data_exchange: Optional[DataExchange] = None) -> pd.DataFrame:
286
288
  if data_exchange:
287
289
  result = self.data_api.get_today_minute_data(code, data_exchange=data_exchange)
290
+ if data_exchange == DataExchange.NXT and (result.empty or result.iloc[-1].close == 0):
291
+ result = self.data_api.get_today_minute_data(code, data_exchange=DataExchange.KRX)
288
292
  else:
289
293
  if self.market_nxt_on:
290
294
  result = self.data_api.get_today_minute_data(code, data_exchange=DataExchange.NXT)
291
- if result.iloc[-1].close == 0:
295
+ if result.empty or result.iloc[-1].close == 0:
292
296
  result = self.data_api.get_today_minute_data(code, data_exchange=DataExchange.KRX)
293
297
  else:
294
298
  result = self.data_api.get_today_minute_data(code, data_exchange=DataExchange.KRX)
@@ -297,6 +301,8 @@ class TradingBroker(BaseBroker):
297
301
  def get_daily_price(self, code: str, from_date: dtm.date, to_date: dtm.date, data_exchange: Optional[DataExchange] = None) -> pd.DataFrame:
298
302
  if data_exchange:
299
303
  result = self.data_api.get_historical_daily_data(code, from_date, to_date, adjusted_price=True, data_exchange=data_exchange)
304
+ if data_exchange == DataExchange.NXT and result.empty:
305
+ result = self.data_api.get_historical_daily_data(code, from_date, to_date, adjusted_price=True, data_exchange=DataExchange.KRX)
300
306
  else:
301
307
  if self.market_nxt_on:
302
308
  result = self.data_api.get_historical_daily_data(code, from_date, to_date, adjusted_price=True, data_exchange=DataExchange.NXT)
@@ -309,6 +315,8 @@ class TradingBroker(BaseBroker):
309
315
  def get_orderbook(self, code: str, data_exchange: Optional[DataExchange] = None):
310
316
  if data_exchange:
311
317
  result = self.data_api.get_orderbook(code, data_exchange=data_exchange)
318
+ if data_exchange == DataExchange.NXT and not result:
319
+ result = self.data_api.get_orderbook(code, data_exchange=DataExchange.KRX)
312
320
  else:
313
321
  if self.market_nxt_on:
314
322
  result = self.data_api.get_orderbook(code, data_exchange=DataExchange.NXT)
@@ -326,6 +334,9 @@ class TradingBroker(BaseBroker):
326
334
  return next((o for o in orders if o["order_no"] == order_no), None)
327
335
 
328
336
  def get_positions(self):
337
+ """
338
+ 포지션 조회 (단, NXT 프리마켓, 애프터마켓에서 현재 가격은 NXT 가격으로 조회되지 않음)
339
+ """
329
340
  return self.trading_api.get_positions()
330
341
 
331
342
  def create_order(self, asset_code: str, side: OrderSide, quantity: int, order_type: OrderType = OrderType.MARKET, price: int | Decimal = 0, exchange: OrderExchange = OrderExchange.KRX) -> str:
@@ -311,6 +311,10 @@ class TradingTracker:
311
311
  def _find_pending_order(self, order_no) -> StockOrder:
312
312
  return find(lambda x: x.order_no == order_no, self.pending_orders)
313
313
 
314
+ def _find_order_in_today_orders(self, order_no) -> StockOrder:
315
+ today_orders = self.simple_api.get_today_order_history(order_no=order_no, exchanges=[OrderExchange.KRX, OrderExchange.NXT, OrderExchange.SOR])
316
+ return find(lambda x: x.order_no == order_no, today_orders)
317
+
314
318
  def _find_position(self, asset_code) -> StockPosition:
315
319
  return find(lambda x: x.asset_code == asset_code, self.positions)
316
320
 
@@ -458,6 +462,11 @@ class TradingTracker:
458
462
  event.filled_time,
459
463
  partial,
460
464
  )
465
+
466
+ if order is None:
467
+ self.logger.warn(f"Order not found for order_no: {order_no}")
468
+ order = self._find_order_in_today_orders(order_no)
469
+ self.logger.warn(f"Order found in today's orders: {order}")
461
470
  self._notify_pending_order_update("partial" if partial else "completed", order)
462
471
  self._notify_position_update(position_event_type, position)
463
472
 
@@ -1,4 +1,5 @@
1
- from typing import List
1
+ from typing import List, Union
2
+ from pyqqq.datatypes import DataExchange
2
3
  from pyqqq.utils.api_client import raise_for_status, send_request
3
4
  from pyqqq.utils.logger import get_logger
4
5
  from pyqqq.utils.singleton import singleton
@@ -14,12 +15,13 @@ import datetime as dtm
14
15
  logger = get_logger(__name__)
15
16
 
16
17
 
17
- def get_all_last_trades(codes: List[str] = None):
18
+ def get_all_last_trades(codes: List[str] = None, exchange: str = "KRX"):
18
19
  """
19
20
  모든 종목의 최근 체결 정보를 반환합니다.
20
21
 
21
22
  Args:
22
23
  codes (List[str], optional): 종목 코드 리스트. 모든 종목의 체결 정보를 반환하려면 None을 전달합니다.
24
+ exchange (str, optional): 거래소. 기본값은 "KRX"입니다. 지원하는 거래소는 "KRX", "UN" 입니다.
23
25
 
24
26
  Returns:
25
27
  list:
@@ -54,7 +56,7 @@ def get_all_last_trades(codes: List[str] = None):
54
56
 
55
57
  params = None
56
58
  if codes:
57
- params = {"codes": ",".join(codes) if isinstance(codes, list) else codes}
59
+ params = {"codes": ",".join(codes) if isinstance(codes, list) else codes, "exchange": exchange}
58
60
 
59
61
  r = send_request("GET", f"{c.PYQQQ_API_URL}/domestic-stock/trades", params=params)
60
62
  raise_for_status(r)
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