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.
- {pyqqq-0.12.170 → pyqqq-0.12.172}/PKG-INFO +1 -1
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyproject.toml +1 -1
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/backtest/broker.py +14 -3
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/tracker.py +9 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/data/realtime.py +5 -3
- {pyqqq-0.12.170 → pyqqq-0.12.172}/README.md +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/__init__.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/ai/__init__.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/ai/daily.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/ai/domestic.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/ai/market_schedule.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/ai/minute.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/backtest/__init__.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/backtest/environment.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/backtest/logger.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/backtest/positionprovider.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/backtest/strategy.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/backtest/utils.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/backtest/wallclock.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/__init__.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/ebest/__init__.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/ebest/domestic_stock.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/ebest/oauth.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/ebest/simple.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/ebest/tr_client.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/helper.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/kis/__init__.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/kis/domestic_stock.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/kis/oauth.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/kis/overseas_stock.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/kis/simple.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/kis/simple_overseas.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/kis/tr_client.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/brokerage/multiprocess_tracker.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/config.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/data/__init__.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/data/daily.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/data/domestic.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/data/index.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/data/minutes.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/data/overseas.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/data/ticks.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/data/us_stocks.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/datatypes.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/executors/__init__.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/executors/hook.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/__init__.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/api_client.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/array.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/casting.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/compute.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/copycat.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/daily_tickers.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/display.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/kvstore.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/limiter.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/local_cache.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/logger.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/market_schedule.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/mock_api.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/position_classifier.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/retry.py +0 -0
- {pyqqq-0.12.170 → pyqqq-0.12.172}/pyqqq/utils/singleton.py +0 -0
|
@@ -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("
|
|
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
|
|
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
|