ksxt 1.0.4__py3-none-any.whl → 1.0.6__py3-none-any.whl

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.
Files changed (75) hide show
  1. ksxt/__pycache__/__init__.cpython-312.pyc +0 -0
  2. ksxt/__pycache__/bithumb.cpython-312.pyc +0 -0
  3. ksxt/__pycache__/koreainvest.cpython-312.pyc +0 -0
  4. ksxt/__pycache__/upbit.cpython-312.pyc +0 -0
  5. ksxt/api/__pycache__/__init__.cpython-312.pyc +0 -0
  6. ksxt/api/__pycache__/bithumb.cpython-312.pyc +0 -0
  7. ksxt/api/__pycache__/koreainvest.cpython-312.pyc +0 -0
  8. ksxt/api/__pycache__/upbit.cpython-312.pyc +0 -0
  9. ksxt/async_/__pycache__/__init__.cpython-312.pyc +0 -0
  10. ksxt/async_/__pycache__/bithumb.cpython-312.pyc +0 -0
  11. ksxt/async_/__pycache__/koreainvest.cpython-312.pyc +0 -0
  12. ksxt/async_/__pycache__/upbit.cpython-312.pyc +0 -0
  13. ksxt/async_/base/__pycache__/__init__.cpython-312.pyc +0 -0
  14. ksxt/async_/base/__pycache__/async_exchange.cpython-312.pyc +0 -0
  15. ksxt/async_/base/async_exchange.py +23 -17
  16. ksxt/async_/bithumb.py +56 -21
  17. ksxt/async_/koreainvest.py +87 -8
  18. ksxt/async_/upbit.py +67 -24
  19. ksxt/base/__pycache__/__init__.cpython-312.pyc +0 -0
  20. ksxt/base/__pycache__/errors.cpython-312.pyc +0 -0
  21. ksxt/base/__pycache__/exchange.cpython-312.pyc +0 -0
  22. ksxt/base/__pycache__/rate_limiter.cpython-312.pyc +0 -0
  23. ksxt/base/__pycache__/rest_exchange.cpython-312.pyc +0 -0
  24. ksxt/base/__pycache__/types.cpython-312.pyc +0 -0
  25. ksxt/base/exchange.py +42 -23
  26. ksxt/base/rest_exchange.py +32 -28
  27. ksxt/bithumb.py +48 -14
  28. ksxt/config/__pycache__/__init__.cpython-312.pyc +0 -0
  29. ksxt/config/token.toml +3 -7
  30. ksxt/koreainvest.py +37 -8
  31. ksxt/market/__pycache__/base.cpython-312.pyc +0 -0
  32. ksxt/market/__pycache__/db.cpython-312.pyc +0 -0
  33. ksxt/market/__pycache__/logging.cpython-312.pyc +0 -0
  34. ksxt/market/__pycache__/manager.cpython-312.pyc +0 -0
  35. ksxt/market/__pycache__/markets.cpython-312.pyc +0 -0
  36. ksxt/market/krx/__pycache__/kosdaq.cpython-312.pyc +0 -0
  37. ksxt/market/krx/__pycache__/kospi.cpython-312.pyc +0 -0
  38. ksxt/market/krx/__pycache__/stock.cpython-312.pyc +0 -0
  39. ksxt/market/us/__pycache__/amex.cpython-312.pyc +0 -0
  40. ksxt/market/us/__pycache__/nasdaq.cpython-312.pyc +0 -0
  41. ksxt/market/us/__pycache__/nyse.cpython-312.pyc +0 -0
  42. ksxt/market/us/__pycache__/stock.cpython-312.pyc +0 -0
  43. ksxt/models/__pycache__/__init__.cpython-312.pyc +0 -0
  44. ksxt/models/__pycache__/balance.cpython-312.pyc +0 -0
  45. ksxt/models/__pycache__/cash.cpython-312.pyc +0 -0
  46. ksxt/models/__pycache__/common.cpython-312.pyc +0 -0
  47. ksxt/models/__pycache__/error.cpython-312.pyc +0 -0
  48. ksxt/models/__pycache__/historical.cpython-312.pyc +0 -0
  49. ksxt/models/__pycache__/market.cpython-312.pyc +0 -0
  50. ksxt/models/__pycache__/order.cpython-312.pyc +0 -0
  51. ksxt/models/__pycache__/orderbook.cpython-312.pyc +0 -0
  52. ksxt/models/__pycache__/ticker.cpython-312.pyc +0 -0
  53. ksxt/models/__pycache__/token.cpython-312.pyc +0 -0
  54. ksxt/models/__pycache__/transaction.cpython-312.pyc +0 -0
  55. ksxt/models/balance.py +17 -4
  56. ksxt/models/transaction.py +22 -28
  57. ksxt/parser/__pycache__/bithumb.cpython-312.pyc +0 -0
  58. ksxt/parser/__pycache__/koreainvest.cpython-312.pyc +0 -0
  59. ksxt/parser/__pycache__/parser.cpython-312.pyc +0 -0
  60. ksxt/parser/__pycache__/upbit.cpython-312.pyc +0 -0
  61. ksxt/parser/bithumb.py +124 -23
  62. ksxt/parser/koreainvest.py +84 -21
  63. ksxt/parser/parser.py +30 -10
  64. ksxt/parser/upbit.py +134 -27
  65. ksxt/upbit.py +55 -18
  66. ksxt/utils/__pycache__/safer.cpython-312.pyc +0 -0
  67. ksxt/utils/__pycache__/sorter.cpython-312.pyc +0 -0
  68. ksxt/utils/__pycache__/timer.cpython-312.pyc +0 -0
  69. {ksxt-1.0.4.dist-info → ksxt-1.0.6.dist-info}/METADATA +1 -1
  70. ksxt-1.0.6.dist-info/RECORD +119 -0
  71. {ksxt-1.0.4.dist-info → ksxt-1.0.6.dist-info}/WHEEL +1 -1
  72. ksxt/async_/base/__pycache__/throttler.cpython-312.pyc +0 -0
  73. ksxt-1.0.4.dist-info/RECORD +0 -120
  74. {ksxt-1.0.4.dist-info → ksxt-1.0.6.dist-info}/LICENSE.txt +0 -0
  75. {ksxt-1.0.4.dist-info → ksxt-1.0.6.dist-info}/top_level.txt +0 -0
ksxt/parser/upbit.py CHANGED
@@ -1,4 +1,4 @@
1
- from datetime import datetime
1
+ from datetime import datetime, timezone
2
2
  from operator import attrgetter
3
3
  from typing import Dict, List, Optional
4
4
 
@@ -11,10 +11,8 @@ from ksxt.models.orderbook import MultiSymbolOrderBookInfos, OrderBookData, Orde
11
11
  from ksxt.models.ticker import MultiSymbolTickerInfo, TickerInfo
12
12
  from ksxt.models.transaction import (
13
13
  ClosedOrderHistory,
14
- ClosedOrderInfo,
15
14
  DepositHistory,
16
15
  OpenedOrderHistory,
17
- OpenedOrderInfo,
18
16
  TransactionInfo,
19
17
  WithdrawalHistory,
20
18
  )
@@ -56,8 +54,22 @@ class UpbitParser(BaseParser):
56
54
  warning_code=safer.safe_boolean(market, " market_warning"),
57
55
  )
58
56
 
59
- def parse_historical_data(self, response: List[Dict], symbol: str, base_market: str = "KRW") -> HistoricalDataInfo:
57
+ def parse_historical_data(
58
+ self,
59
+ response: List[Dict],
60
+ symbol: str,
61
+ start: datetime | None = None,
62
+ end: datetime | None = None,
63
+ base_market: str = "KRW",
64
+ ) -> HistoricalDataInfo:
60
65
  ohlcv = [self._parse_ohlcva(_, base_market) for _ in response]
66
+
67
+ # Filter by start and end datetime
68
+ if start:
69
+ ohlcv = [data for data in ohlcv if data.datetime.astimezone(timezone.utc) >= start.astimezone(timezone.utc)]
70
+ if end:
71
+ ohlcv = [data for data in ohlcv if data.datetime.astimezone(timezone.utc) <= end.astimezone(timezone.utc)]
72
+
61
73
  sorted_ohlcv = sorter.sort_by(ohlcv, key="datetime")
62
74
 
63
75
  security_name = symbol
@@ -167,7 +179,13 @@ class UpbitParser(BaseParser):
167
179
  return ask_data, bid_data
168
180
 
169
181
  def parse_balance(
170
- self, response: List[Dict], base_market: str = "KRW", excluded_symbols: Optional[list[str]] = None
182
+ self,
183
+ response: List[Dict],
184
+ base_market: str = "KRW",
185
+ excluded_symbols: Optional[list[str]] = None,
186
+ included_symbols: list[str] | None = None,
187
+ filter_delisted: bool = True,
188
+ min_amount: float = 0,
171
189
  ) -> BalanceInfo:
172
190
  # 1. Filter out entries where 'currency' is not the base_market
173
191
  # 2. Ensure 'unit_currency' is the base_market
@@ -178,11 +196,18 @@ class UpbitParser(BaseParser):
178
196
  if data["currency"] != base_market
179
197
  and data["unit_currency"] == base_market
180
198
  and (excluded_symbols is None or data["currency"] not in excluded_symbols)
199
+ and (included_symbols is None or self.safe_symbol(base_market, data["currency"]) in included_symbols)
181
200
  ]
182
201
 
183
202
  # Initialize balance list
184
203
  balances = [self._parse_balance(data, base_market) for data in filtered_data]
185
204
 
205
+ if filter_delisted:
206
+ balances = [balance for balance in balances if balance.price > 0]
207
+
208
+ if min_amount > 0:
209
+ balances = [balance for balance in balances if balance.amount > min_amount]
210
+
186
211
  # 총 매입금액
187
212
  total_amount = sum(bal.price * bal.qty for bal in balances)
188
213
  total_evaluation_amount = sum(bal.evaluation_price * bal.qty for bal in balances)
@@ -202,10 +227,8 @@ class UpbitParser(BaseParser):
202
227
  return BalanceData(
203
228
  symbol=self.safe_symbol(base_market, safer.safe_string(data, "currency")),
204
229
  name=self.safe_symbol(base_market, safer.safe_string(data, "currency")),
205
- evaluation_price=safer.safe_number(data, "avg_buy_price"),
206
230
  price=safer.safe_number(data, "avg_buy_price"),
207
- pnl_amount=0, # 필요에 따라 적절히 설정
208
- pnl_ratio=0, # 필요에 따라 적절히 설정
231
+ evaluation_price=safer.safe_number(data, "avg_buy_price"),
209
232
  qty=safer.safe_number(data, "balance"),
210
233
  free_qty=safer.safe_number(data, "balance") - safer.safe_number(data, "locked"),
211
234
  used_qty=safer.safe_number(data, "locked"),
@@ -262,55 +285,139 @@ class UpbitParser(BaseParser):
262
285
  market_ask_fee=safer.safe_number(response, "maker_ask_fee"),
263
286
  )
264
287
 
265
- def parse_closed_order_history(self, response: List[dict], base_market: str = "KRW") -> ClosedOrderHistory:
288
+ def parse_closed_order_history(
289
+ self, response: List[Dict], start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
290
+ ) -> ClosedOrderHistory:
266
291
  orders = [self._parse_closed_order_info(order, base_market) for order in response]
292
+
293
+ # Filter by start and end datetime
294
+ if start:
295
+ orders = [
296
+ order for order in orders if order.created_at.astimezone(timezone.utc) >= start.astimezone(timezone.utc)
297
+ ]
298
+ if end:
299
+ orders = [
300
+ order for order in orders if order.created_at.astimezone(timezone.utc) <= end.astimezone(timezone.utc)
301
+ ]
302
+
267
303
  return ClosedOrderHistory(history=orders)
268
304
 
269
- def _parse_closed_order_info(self, order: dict, base_market: str = "KRW") -> ClosedOrderInfo:
270
- return ClosedOrderInfo(
305
+ def _parse_closed_order_info(self, order: dict, base_market: str = "KRW") -> TransactionInfo:
306
+ # 현재 API에서 price 값을 제대로 전달해주지 않음.
307
+ if safer.safe_number(order, "price") == 0:
308
+ price = price = safer.safe_number(order, "executed_funds") / safer.safe_number(order, "volume")
309
+ else:
310
+ price = safer.safe_number(order, "price")
311
+
312
+ return TransactionInfo(
271
313
  uuid=safer.safe_string(order, "uuid"),
272
- type=safer.safe_string(order, "side"),
314
+ account_id="",
315
+ transaction_type=safer.safe_string(order, "side"),
273
316
  symbol=self.safe_symbol(base_market, safer.safe_string(order, "market")),
274
- price=safer.safe_number(order, "price"),
317
+ price=price,
275
318
  qty=safer.safe_number(order, "volume"),
276
- amount=safer.safe_number(order, "price") * safer.safe_number(order, "volume"),
277
- fee=safer.safe_number(order, "paid_fee"), # Adjusted to 'paid_fee' to match provided data
278
- created_at=datetime.fromisoformat(safer.safe_string(order, "created_at")),
319
+ amount=safer.safe_number(order, "executed_funds"),
320
+ tax=0,
321
+ fee=safer.safe_number(order, "paid_fee"),
322
+ currency=base_market,
279
323
  order_type=safer.safe_string(order, "ord_type"),
324
+ created_at=datetime.fromisoformat(safer.safe_string(order, "created_at")),
280
325
  )
281
326
 
282
- def parse_open_order_history(self, response: List[dict], base_market: str = "KRW") -> OpenedOrderHistory:
327
+ def parse_open_order_history(
328
+ self, response: List[Dict], start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
329
+ ) -> OpenedOrderHistory:
283
330
  orders = [self._parse_open_order_info(order, base_market) for order in response]
331
+
332
+ # Filter by start and end datetime
333
+ if start:
334
+ orders = [
335
+ order for order in orders if order.created_at.astimezone(timezone.utc) >= start.astimezone(timezone.utc)
336
+ ]
337
+ if end:
338
+ orders = [
339
+ order for order in orders if order.created_at.astimezone(timezone.utc) <= end.astimezone(timezone.utc)
340
+ ]
341
+
284
342
  return OpenedOrderHistory(history=orders)
285
343
 
286
- def _parse_open_order_info(self, order: dict, base_market: str = "KRW") -> OpenedOrderInfo:
287
- return OpenedOrderInfo(
344
+ def _parse_open_order_info(self, order: dict, base_market: str = "KRW") -> TransactionInfo:
345
+ # 현재 API에서 price 값을 제대로 전달해주지 않음.
346
+ if safer.safe_number(order, "price") == 0:
347
+ price = price = safer.safe_number(order, "executed_funds") / safer.safe_number(order, "volume")
348
+ else:
349
+ price = safer.safe_number(order, "price")
350
+
351
+ return TransactionInfo(
288
352
  uuid=safer.safe_string(order, "uuid"),
289
- type=safer.safe_string(order, "side"),
353
+ account_id="",
354
+ transaction_type=safer.safe_string(order, "side"),
290
355
  symbol=self.safe_symbol(base_market, safer.safe_string(order, "market")),
291
- price=safer.safe_number(order, "price"),
356
+ price=price,
292
357
  qty=safer.safe_number(order, "volume"),
293
- amount=safer.safe_number(order, "price") * safer.safe_number(order, "volume"),
294
- fee=safer.safe_number(order, "reserved_fee"),
295
- created_at=datetime.fromisoformat(safer.safe_string(order, "created_at")),
358
+ amount=safer.safe_number(order, "executed_funds"),
359
+ tax=0,
360
+ fee=safer.safe_number(order, "paid_fee"),
361
+ currency=base_market,
296
362
  order_type=safer.safe_string(order, "ord_type"),
363
+ created_at=datetime.fromisoformat(safer.safe_string(order, "created_at")),
297
364
  )
298
365
 
299
- def parse_withdrawal_history(self, response: List[Dict], base_market: str = "KRW") -> WithdrawalHistory:
366
+ def parse_withdrawal_history(
367
+ self, response: List[Dict], start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
368
+ ) -> WithdrawalHistory:
300
369
  parsed_items = [self._parse_transaction_history_item(item, base_market) for item in response]
370
+
371
+ # Filter by start and end datetime
372
+ if start:
373
+ parsed_items = [
374
+ item
375
+ for item in parsed_items
376
+ if item.created_at.astimezone(timezone.utc) >= start.astimezone(timezone.utc)
377
+ ]
378
+ if end:
379
+ parsed_items = [
380
+ item
381
+ for item in parsed_items
382
+ if item.created_at.astimezone(timezone.utc) <= end.astimezone(timezone.utc)
383
+ ]
384
+
301
385
  return WithdrawalHistory(history=parsed_items)
302
386
 
303
- def parse_deposit_history(self, response: List[Dict], base_market: str = "KRW") -> DepositHistory:
387
+ def parse_deposit_history(
388
+ self, response: List[Dict], start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
389
+ ) -> DepositHistory:
304
390
  parsed_items = [self._parse_transaction_history_item(item, base_market) for item in response]
391
+
392
+ # Filter by start and end datetime
393
+ if start:
394
+ parsed_items = [
395
+ item
396
+ for item in parsed_items
397
+ if item.created_at.astimezone(timezone.utc) >= start.astimezone(timezone.utc)
398
+ ]
399
+ if end:
400
+ parsed_items = [
401
+ item
402
+ for item in parsed_items
403
+ if item.created_at.astimezone(timezone.utc) <= end.astimezone(timezone.utc)
404
+ ]
405
+
305
406
  return DepositHistory(history=parsed_items)
306
407
 
307
408
  def _parse_transaction_history_item(self, item: Dict, base_market: str = "KRW") -> TransactionInfo:
308
409
  return TransactionInfo(
309
410
  uuid=safer.safe_string(item, "uuid"),
310
- type=safer.safe_string(item, "type"),
411
+ account_id="",
412
+ transaction_type=safer.safe_string(item, "type"),
413
+ symbol=safer.safe_string(item, "currency"),
414
+ price=1,
415
+ qty=safer.safe_number(item, "amount"),
311
416
  amount=safer.safe_number(item, "amount"),
417
+ tax=0,
312
418
  fee=safer.safe_number(item, "fee"),
313
419
  currency=safer.safe_string(item, "currency"),
420
+ order_type=safer.safe_string(item, "transaction_type"),
314
421
  created_at=datetime.fromisoformat(safer.safe_string(item, "done_at")),
315
422
  )
316
423
 
ksxt/upbit.py CHANGED
@@ -2,7 +2,7 @@ import hashlib
2
2
  import json
3
3
  import time
4
4
  import uuid
5
- from datetime import datetime
5
+ from datetime import datetime, timezone
6
6
  from typing import Any, Dict, List, Literal, Optional
7
7
  from urllib.parse import urlencode
8
8
 
@@ -123,10 +123,19 @@ class Upbit(RestExchange, ImplicitAPI):
123
123
  return ksxt.models.KsxtMarketResponse(header=common_header, response=common_response, info=parsed_info)
124
124
 
125
125
  def fetch_historical_data(
126
- self, symbol: str, time_frame: str, start: str | None = None, end: str | None = None, base_market: str = "KRW"
126
+ self,
127
+ symbol: str,
128
+ time_frame: str,
129
+ start: datetime | None = None,
130
+ end: datetime | None = None,
131
+ base_market: str = "KRW",
127
132
  ) -> ksxt.models.KsxtHistoricalDataResponse:
128
133
  params = {"market": self.safe_symbol(base_market, symbol), "count": 200}
129
134
 
135
+ if end:
136
+ end_utc = end.astimezone(timezone.utc)
137
+ params.update({"to": end_utc.strftime("%Y-%m-%d %H:%M:%S")})
138
+
130
139
  # TODO : time_frame 을 어떻게 고정시킬까? 우리는 분봉, 일봉, 주봉, 월봉 만 지원한다고 가정하면?
131
140
  if time_frame.endswith("m"):
132
141
  # TODO : parse number
@@ -152,9 +161,13 @@ class Upbit(RestExchange, ImplicitAPI):
152
161
  if common_response.success != "0":
153
162
  return ksxt.models.KsxtHistoricalDataResponse(header=common_header, response=common_response, info=None)
154
163
 
155
- parsed_info = self.parser.parse_historical_data(response=response, symbol=symbol, base_market=base_market)
164
+ parsed_response = self.parser.parse_historical_data(
165
+ response=response, symbol=symbol, start=start, end=end, base_market=base_market
166
+ )
156
167
 
157
- return ksxt.models.KsxtHistoricalDataResponse(header=common_header, response=common_response, info=parsed_info)
168
+ return ksxt.models.KsxtHistoricalDataResponse(
169
+ header=common_header, response=common_response, info=parsed_response
170
+ )
158
171
 
159
172
  def fetch_ticker(self, symbol: str, base_market: str = "KRW") -> ksxt.models.KsxtTickerResponse:
160
173
  params = {"markets": self.safe_symbol(base_market, symbol)} # 다중 조회 시, 콤마로 구분 ex. 'KRW-BTC, BTC-ETH'
@@ -225,7 +238,13 @@ class Upbit(RestExchange, ImplicitAPI):
225
238
  return ksxt.models.KsxtMultiOrderBookResponse(header=common_header, response=common_response, info=parsed_info)
226
239
 
227
240
  def fetch_balance(
228
- self, acc_num: str, base_market: str = "KRW", excluded_symbols: Optional[list[str]] = None
241
+ self,
242
+ acc_num: str,
243
+ base_market: str = "KRW",
244
+ excluded_symbols: list[str] | None = None,
245
+ included_symbols: list[str] | None = None,
246
+ filter_delisted: bool = True,
247
+ min_amount: float = 0,
229
248
  ) -> ksxt.models.KsxtBalanceResponse:
230
249
  params = {}
231
250
 
@@ -238,7 +257,12 @@ class Upbit(RestExchange, ImplicitAPI):
238
257
  return ksxt.models.KsxtBalanceResponse(header=common_header, response=common_response, info=None)
239
258
 
240
259
  parsed_info = self.parser.parse_balance(
241
- response=response, base_market=base_market, excluded_symbols=excluded_symbols
260
+ response=response,
261
+ base_market=base_market,
262
+ excluded_symbols=excluded_symbols,
263
+ included_symbols=included_symbols,
264
+ filter_delisted=filter_delisted,
265
+ min_amount=min_amount,
242
266
  )
243
267
 
244
268
  return ksxt.models.KsxtBalanceResponse(header=common_header, response=common_response, info=parsed_info)
@@ -335,8 +359,8 @@ class Upbit(RestExchange, ImplicitAPI):
335
359
  self,
336
360
  acc_num: str,
337
361
  symbol: Optional[str] = "",
338
- start: Optional[str] = None,
339
- end: Optional[str] = None,
362
+ start: datetime | None = None,
363
+ end: datetime | None = None,
340
364
  base_market: str = "KRW",
341
365
  ) -> ksxt.models.KsxtClosedOrderResponse:
342
366
  params = {"state": "done"}
@@ -352,16 +376,18 @@ class Upbit(RestExchange, ImplicitAPI):
352
376
  if common_response.success != "0":
353
377
  return ksxt.models.KsxtClosedOrderResponse(header=common_header, response=common_response, info=None)
354
378
 
355
- parsed_info = self.parser.parse_closed_order_history(response=response, base_market=base_market)
356
-
379
+ # 데이터 파싱
380
+ parsed_info = self.parser.parse_closed_order_history(
381
+ response=response, start=start, end=end, base_market=base_market
382
+ )
357
383
  return ksxt.models.KsxtClosedOrderResponse(header=common_header, response=common_response, info=parsed_info)
358
384
 
359
385
  def fetch_open_order(
360
386
  self,
361
387
  acc_num: str,
362
- symbol: str | None = "",
363
- start: str | None = None,
364
- end: str | None = None,
388
+ symbol: Optional[str] = "",
389
+ start: datetime | None = None,
390
+ end: datetime | None = None,
365
391
  base_market: str = "KRW",
366
392
  ) -> ksxt.models.KsxtOpenOrderResponse:
367
393
  params = {"state": "wait"}
@@ -377,12 +403,15 @@ class Upbit(RestExchange, ImplicitAPI):
377
403
  if common_response.success != "0":
378
404
  return ksxt.models.KsxtOpenOrderResponse(header=common_header, response=common_response, info=None)
379
405
 
380
- parsed_info = self.parser.parse_open_order_history(response=response, base_market=base_market)
406
+ # 데이터 파싱
407
+ parsed_info = self.parser.parse_open_order_history(
408
+ response=response, start=start, end=end, base_market=base_market
409
+ )
381
410
 
382
411
  return ksxt.models.KsxtOpenOrderResponse(header=common_header, response=common_response, info=parsed_info)
383
412
 
384
413
  def fetch_withdrawal_history(
385
- self, acc_num: str, base_market: str = "KRW"
414
+ self, acc_num: str, start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
386
415
  ) -> ksxt.models.KsxtWithdrawalHistoryResponse:
387
416
  params = {"currency": base_market, "state": "DONE"}
388
417
 
@@ -394,13 +423,18 @@ class Upbit(RestExchange, ImplicitAPI):
394
423
  if common_response.success != "0":
395
424
  return ksxt.models.KsxtWithdrawalHistoryResponse(header=common_header, response=common_response, info=None)
396
425
 
397
- parsed_info = self.parser.parse_withdrawal_history(response=response, base_market=base_market)
426
+ # 데이터 파싱
427
+ parsed_info = self.parser.parse_withdrawal_history(
428
+ response=response, start=start, end=end, base_market=base_market
429
+ )
398
430
 
399
431
  return ksxt.models.KsxtWithdrawalHistoryResponse(
400
432
  header=common_header, response=common_response, info=parsed_info
401
433
  )
402
434
 
403
- def fetch_deposit_history(self, acc_num: str, base_market: str = "KRW") -> ksxt.models.KsxtDepositHistoryResponse:
435
+ def fetch_deposit_history(
436
+ self, acc_num: str, start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
437
+ ) -> ksxt.models.KsxtDepositHistoryResponse:
404
438
  params = {"currency": base_market, "state": "ACCEPTED"}
405
439
 
406
440
  common_header = self.create_common_header(request_params=params)
@@ -411,7 +445,10 @@ class Upbit(RestExchange, ImplicitAPI):
411
445
  if common_response.success != "0":
412
446
  return ksxt.models.KsxtDepositHistoryResponse(header=common_header, response=common_response, info=None)
413
447
 
414
- parsed_info = self.parser.parse_deposit_history(response=response, base_market=base_market)
448
+ # 데이터 파싱
449
+ parsed_info = self.parser.parse_deposit_history(
450
+ response=response, start=start, end=end, base_market=base_market
451
+ )
415
452
 
416
453
  return ksxt.models.KsxtDepositHistoryResponse(header=common_header, response=common_response, info=parsed_info)
417
454
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ksxt
3
- Version: 1.0.4
3
+ Version: 1.0.6
4
4
  License: MIT License
5
5
 
6
6
  Copyright © 2023 AMOSA
@@ -0,0 +1,119 @@
1
+ ksxt/__init__.py,sha256=Q4kbXuxaCcQg5Z1T2z31lrUc5Cr95RIyv-y6hNf3R0E,131
2
+ ksxt/bithumb.py,sha256=jiN9hIopmXwUTQn71mR13Z_c0ZDJOXhbJhgpzHRniLs,22641
3
+ ksxt/koreainvest.py,sha256=_3ZbMw7O-I0lWhMcDMRTcb3lCcuUFFp-OeDtUs8S5hA,20805
4
+ ksxt/upbit.py,sha256=2nfO-x_1C9XOoXRm2_cB4hXRV7jxoTP-s7Eqm8u8EJc,22861
5
+ ksxt/__pycache__/__init__.cpython-312.pyc,sha256=99OafUFiZDEhtstgud7UXpCCcOfy20LUICQC7vNbNPc,310
6
+ ksxt/__pycache__/bithumb.cpython-312.pyc,sha256=SI-IV1_1cTRt54m0z5G_Qys0f2jqJ_e91QIGucD1Jrg,25686
7
+ ksxt/__pycache__/koreainvest.cpython-312.pyc,sha256=38FJ1f8w7PnSCALogXBPjVTAoRursY6sIKmNqOxlx08,22472
8
+ ksxt/__pycache__/upbit.cpython-312.pyc,sha256=C3Bv5Gw5FvBjK3hgKeu4Loh7em94wyqTV9qgAdYhhC0,26035
9
+ ksxt/api/__init__.py,sha256=CZ8AedRG8O9vEdSqTaot5sV3nwpxPZoVOYwrFCLUo6M,736
10
+ ksxt/api/bithumb.py,sha256=6apoSNoiEOIkR6xQu4rtCSz7sdNdx3BHeu8-m8omh6E,2177
11
+ ksxt/api/koreainvest.py,sha256=93BASTUUsw39APRFxVqlaOu-keEFuIO3MvHX_6g-AAs,2159
12
+ ksxt/api/upbit.py,sha256=CQN-A0gVoeNoHTZhH8kCaGk1svaOvo5HDyVFfXou_6A,2704
13
+ ksxt/api/__pycache__/__init__.cpython-312.pyc,sha256=1tMXRXoUs6u2hiKjL8_5209aEWMLxAIEABmUj8iNqw4,1374
14
+ ksxt/api/__pycache__/bithumb.cpython-312.pyc,sha256=-tF6txgvtDIqXxIroDh28pgIrEvA9DK_NCzw6DBKcgk,2559
15
+ ksxt/api/__pycache__/koreainvest.cpython-312.pyc,sha256=VftBw8Krzp9VYAZ3RSeBWrqiNkAUyqQfinE2ZjxRueM,2087
16
+ ksxt/api/__pycache__/upbit.cpython-312.pyc,sha256=38hbV6oBqrh4hXrkooxTJluIryuDuSBkbv119mq3Ewg,3014
17
+ ksxt/api/auto/api_generator.py,sha256=R8Q7uFN1wDr_0CUsJJ1nmZhoDBwzjPlKUXrNCsY9QKU,2540
18
+ ksxt/api/auto/bithumb.py,sha256=n6ctGefq28i5CMiItLF1xOZgeDP9F9em4HXfoPUcmqw,1261
19
+ ksxt/api/auto/koreainvest.py,sha256=z4Bf3C7g2W-eQP99oBeM_J0mq2D3PkbQaulrDwxJB04,1582
20
+ ksxt/api/auto/upbit.py,sha256=CtSG0jziqJR4FInHvwDisJfMWCUrUIQQcNPuCGGR7Do,1467
21
+ ksxt/async_/__init__.py,sha256=ztfV65aN2mXamQSfVm3GLYB6cszkvsCSlUyhfe2H_2M,186
22
+ ksxt/async_/bithumb.py,sha256=sVGUSHSm9CKLbhUoz9bDkpxlSJAzqnRaNt30ocWBsKI,20534
23
+ ksxt/async_/koreainvest.py,sha256=6HV-miG50khuvyr634eQb9GlaIIfo8asI_qfDATX90E,23132
24
+ ksxt/async_/upbit.py,sha256=Y0cPAkiZluBCpNj2jX1d-V0olzMZMT8Dyzup2BAnSH0,22783
25
+ ksxt/async_/__pycache__/__init__.cpython-312.pyc,sha256=JMmqx3WOUqRd8bNVJetVrh4iuOE0ihwajLyI0OaHB7U,379
26
+ ksxt/async_/__pycache__/bithumb.cpython-312.pyc,sha256=qL2X3-e3ulLiWHWJQrCYhsNDkxK1mqT4GdH_nVF8GDM,24418
27
+ ksxt/async_/__pycache__/koreainvest.cpython-312.pyc,sha256=Oy71u-nws5BJEiT0mBgi_AxlmqM1Bn7LRRGjguFwCNM,25680
28
+ ksxt/async_/__pycache__/upbit.cpython-312.pyc,sha256=ssF1mktP57F243a0IEogVCuXFoIfYANZvpmCs95DNoo,27751
29
+ ksxt/async_/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ ksxt/async_/base/async_exchange.py,sha256=wUZySn7TE5FMMmJpi1Whpm6pXPObxVaS87HS0jJ35R8,9721
31
+ ksxt/async_/base/__pycache__/__init__.cpython-312.pyc,sha256=S4bPuB8OeLTMdU22fAKRges3VlhAuVM6EBIbb_92gOM,152
32
+ ksxt/async_/base/__pycache__/async_exchange.cpython-312.pyc,sha256=ZiEzacI9o9ppGsg8B9vuyD9F3ZHzMXHwOLlJ4NXtXyw,15858
33
+ ksxt/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
+ ksxt/base/com_exchange.py,sha256=q7C3Bc5q4ENvNGoghnQCN7YLttgwmFoNj9WsH5qxXNQ,287
35
+ ksxt/base/errors.py,sha256=msGHmm9YGUOXOaK_VhOUEt5LvIDMMm6G-io8nQbNgA0,141
36
+ ksxt/base/exchange.py,sha256=tKU37qlYarwGmTySzGu_kQGowc_QRMdm31SGSjeLoZI,16598
37
+ ksxt/base/rate_limiter.py,sha256=9iF6OB-2u0q4nqtng8Tafn-fM3CVQ-DvdNRJ1aSCS3w,3005
38
+ ksxt/base/rest_exchange.py,sha256=_fQqoq7LkJIR8S2YkMF8PqWH-Zx4ibth_f_0BuI8PTo,16103
39
+ ksxt/base/types.py,sha256=3bd3obJhhX1njy_o4LW8hSAHX2MThOI-mZm6iifwno4,59
40
+ ksxt/base/__pycache__/__init__.cpython-312.pyc,sha256=sRTaTlUmf1BjkcBImIDu9hF2H1CO1uFRqOTXjkpSeMo,145
41
+ ksxt/base/__pycache__/errors.cpython-312.pyc,sha256=AcQa0ZFWVvPHzZ_qo7uMQUOTQwwt71FLroolBT77Tgw,621
42
+ ksxt/base/__pycache__/exchange.cpython-312.pyc,sha256=ZjDZ29l8IDEU8GZrw4cnDwBwB9tUYIIDMf4JUIRQCPw,21760
43
+ ksxt/base/__pycache__/rate_limiter.cpython-312.pyc,sha256=b-OiLzKiXR8I8GcuPAYjpDGwHOgywFfOMPJDTxHDDgA,5417
44
+ ksxt/base/__pycache__/rest_exchange.cpython-312.pyc,sha256=dRotNlB7p_iuLMOu9yeQ5_veOr5chTjpmv7TSnuUuS4,23248
45
+ ksxt/base/__pycache__/types.cpython-312.pyc,sha256=JZdcCrwjXkLpp1F5kPwUb8M2Rs3HJxpx0WuhJk-X0kc,231
46
+ ksxt/config/__init__.py,sha256=hkQx56FVJD8Gq1A_KzfOqO8BoqJRTX5TnUmqIignnlc,148
47
+ ksxt/config/bithumb.toml,sha256=JgKgHQVATsLcbxKYvekSRonJ4PjJ5x2ejp1eZHHusrQ,11693
48
+ ksxt/config/koreainvest.toml,sha256=XQRSdEgkWlhbfS6AvJRqQJ_8210i__nfFSI9n3GcgqY,11526
49
+ ksxt/config/token.toml,sha256=L71hM8EBBcZmMtuHUKPGa8sQqg7SUxKCL_ecu98SU1I,431
50
+ ksxt/config/upbit.toml,sha256=1aGKZ3HAV28rrTVGZQ418I9NJwhoRh70Vx03oKacIfY,13439
51
+ ksxt/config/__pycache__/__init__.cpython-312.pyc,sha256=1jLyeKuG_1Uy5_K3mrBPd8h4uRR_9psing5ZdeOKUkw,424
52
+ ksxt/market/base.py,sha256=SzNPJECU2iWaQEUesI_REW_A0by_Tv4hs4Hv8p_sr0I,6856
53
+ ksxt/market/db.py,sha256=ZPr2WlQRUOjhJm1fwFBrdwWG7UJkEpy5Pr0oEQ3Nqb0,386
54
+ ksxt/market/logging.py,sha256=hkyAhzA72-KCGcVavSOHFSz2FU5QJq_gn6WA6kXs_Pw,698
55
+ ksxt/market/manager.py,sha256=kgXrsjFw4O_BPVM2VxQJbm5ryWPG3L-NX1Pm-pN68jE,7301
56
+ ksxt/market/markets.py,sha256=pExEvlLhoLvs2Ipkp-p8_yG3tFgz3U3yB5VAVqD8qdM,545
57
+ ksxt/market/__pycache__/base.cpython-312.pyc,sha256=rKw82jppSUh3WKj-ZTwMe7f0bb45S7BiS0QJVYIf6Ag,11238
58
+ ksxt/market/__pycache__/db.cpython-312.pyc,sha256=UqAmDamjS6fG0HAPbgq9ZZAB1gbmkIgVpvPpdXQTByI,691
59
+ ksxt/market/__pycache__/logging.cpython-312.pyc,sha256=cF9xFQUauuncKAumkOk7ZTOogfwvS_W6xgJ6OBF7gGA,1401
60
+ ksxt/market/__pycache__/manager.cpython-312.pyc,sha256=KBjTJ90x1dSo4_8Vc4pRngsMldrioBsduFXgNlmeh-4,11783
61
+ ksxt/market/__pycache__/markets.cpython-312.pyc,sha256=kuzNGgwZoNVwZ4pC_VdiIek9hxP7yarLxR5YltUYkgs,744
62
+ ksxt/market/krx/kosdaq.py,sha256=CJDKMPp3utH-bmPrrEAzmFx5GSXk_KVhLDdGCAaxaBQ,18626
63
+ ksxt/market/krx/kospi.py,sha256=lRyA-xCjqdyuB87eHFGooIHtpbjy7WcrQ0Rk2ZnCt40,20466
64
+ ksxt/market/krx/stock.py,sha256=IXx4xNYsQgKhuLz1_S0Bd9Scqd6fip75gafRePAFW7U,8111
65
+ ksxt/market/krx/__pycache__/kosdaq.cpython-312.pyc,sha256=rk9C1APZmW42WH8OISrlR-EwpMHrgyGCMRGbaOtPMEE,7516
66
+ ksxt/market/krx/__pycache__/kospi.cpython-312.pyc,sha256=vEzv-Mg9Jq0lwWRySoJIh9g13LOLkpzyxys3mxJJ6CQ,8608
67
+ ksxt/market/krx/__pycache__/stock.cpython-312.pyc,sha256=k9hUlFzTKcTa1pY_VMKOVKvIlzJxdoGYx9APJUjEloA,9012
68
+ ksxt/market/us/amex.py,sha256=ZYlfh1x2eiA8P3DfO2PKj6nIE-O4WQNgDM-CsLqFUVs,5510
69
+ ksxt/market/us/nasdaq.py,sha256=OIBJn16veH36Um-Bhr14K0qBu3ZZwPSWi5sj6zxmkVA,5524
70
+ ksxt/market/us/nyse.py,sha256=eCAcz0saj1RFuyfmJc8cjecwGEDIhvkYVkUp941ZOIw,5507
71
+ ksxt/market/us/stock.py,sha256=hRb4RH2kf-1RaNcWLvE5tg2uCcu6LoPZ0Nc1u6Wpzbc,3675
72
+ ksxt/market/us/__pycache__/amex.cpython-312.pyc,sha256=ISJeRZ9bQHYmH9ltf7aHXUdpGaq2MgRriFm0m182iGU,3380
73
+ ksxt/market/us/__pycache__/nasdaq.cpython-312.pyc,sha256=CmTxTMsNZFWUFkZo_S7pkGWmMQoIQ-gnsfjefvz389k,3394
74
+ ksxt/market/us/__pycache__/nyse.cpython-312.pyc,sha256=ERLmlKoyXwbcK1A1Tep8i-K7v3MUvAlKQrh2pANzZqo,3377
75
+ ksxt/market/us/__pycache__/stock.cpython-312.pyc,sha256=AAb5L9s3z8F7OT0WZl20lWUKg6iEyIifU-Yc1hGsO2w,4975
76
+ ksxt/models/__init__.py,sha256=V7Nr0RHOOXithVTQW12hveavnapS8nGhWQ3JIMwDFTc,706
77
+ ksxt/models/balance.py,sha256=YarLzTXuqqdXYHoOWDx5Hh_K2DXqEoKtNgdii0UINjM,1138
78
+ ksxt/models/cash.py,sha256=sNexdR6Ek-YZ6cVAmre-zf3K30R-6hreHuBQKYzMsPU,303
79
+ ksxt/models/common.py,sha256=HvsNa2wlTeLdnB67untL0UzOQ5r6f2s6Gkfxeh7LTpM,827
80
+ ksxt/models/error.py,sha256=yzpTweHMB-bi7hzD8ATKsK2klJAsbfPEBBa1A5tY6tw,291
81
+ ksxt/models/historical.py,sha256=fWcst4WPimI2Avb4b1kOswfyf3nB4XSMgpTSmm7uTpY,655
82
+ ksxt/models/market.py,sha256=kkH-P1m1HQjJOPT1k4bk9ZgW-_kwIBO_fXHcrRlWlVE,2013
83
+ ksxt/models/order.py,sha256=LJJd-licLirI5WrAM1MItViOX_u5U_fmpBFPpDSdHxE,867
84
+ ksxt/models/orderbook.py,sha256=S1c03QBu1hupN87CMWLgEsh8u2GrZ_Z_BcTUuiKGnR0,773
85
+ ksxt/models/ticker.py,sha256=pPc7GqUOJchLg7qOpKfxhTVpXygF1Otc_M9_KfHFEgY,544
86
+ ksxt/models/token.py,sha256=eUBoX7O0ffC63BN12-1aUjcfE_R1Ylyxr6_U79FLDv0,319
87
+ ksxt/models/transaction.py,sha256=E086NQkIfTuVhmJNmr8_vYGn84c1Vf8_8sgHyBMZFU0,1491
88
+ ksxt/models/__pycache__/__init__.cpython-312.pyc,sha256=juNSOa40CKXj3FcqX7uufkG-nGRv7BeymAsD5iFbtDg,1032
89
+ ksxt/models/__pycache__/balance.cpython-312.pyc,sha256=ojawyH9i68QXJ1ZiQ8KtS2F0iQdSYIahundVhdghYns,2118
90
+ ksxt/models/__pycache__/cash.cpython-312.pyc,sha256=PNyyB9eKOU0OyaMP7p3dg3BYDb21wA0v8zzkXUXTg5E,721
91
+ ksxt/models/__pycache__/common.cpython-312.pyc,sha256=UiwBy-d1G_BCST5Ercj3HnBEO3uURPc1K71nQ25_xjs,1362
92
+ ksxt/models/__pycache__/error.cpython-312.pyc,sha256=PaFS6ijLZsNmHeIEd6M2RKAElyZ1GdmufAspqE1Y78A,773
93
+ ksxt/models/__pycache__/historical.cpython-312.pyc,sha256=9mcQEc1p9YyVovIKOYQlGwYk4s6AdPlg9WY2WQlyMIQ,1290
94
+ ksxt/models/__pycache__/market.cpython-312.pyc,sha256=1JH7CXMZ8kvbdlHqrongsmoq99p5S-vqTYhqK5eMfYQ,3077
95
+ ksxt/models/__pycache__/order.cpython-312.pyc,sha256=2pcwKS9_-I25plh92Gii3d67noYABixnrOjpkMZPnsc,1790
96
+ ksxt/models/__pycache__/orderbook.cpython-312.pyc,sha256=YL_iiIMMfKdjlkNIN4lC-olNrK8LmCBoj56GGpe9ghM,1516
97
+ ksxt/models/__pycache__/ticker.cpython-312.pyc,sha256=SQ4PMAMdWrUomHeyBY-P5STecg1EC46wRmwcCvdx0Sc,1164
98
+ ksxt/models/__pycache__/token.cpython-312.pyc,sha256=NuH6VnrVsPRhUFUspVJwcEl4KyA8hMHdZwsguCxD6M8,794
99
+ ksxt/models/__pycache__/transaction.cpython-312.pyc,sha256=_3vlu_CTVyFd5Zvil8DrDWnc9QODYCg-K3xyhOmZhdQ,2435
100
+ ksxt/parser/bithumb.py,sha256=jPNISv-LBKjATGPx-ukyoZcpurSjCBlHoHva5UBEj8E,18152
101
+ ksxt/parser/koreainvest.py,sha256=6sJ_yMmDb4IVZnEI4facxdTybtW45s9kEeiWrVXxEzs,17328
102
+ ksxt/parser/parser.py,sha256=xdqRS69VMxFupv5dNE4Cb6vq-rmDjlIOuouHj4RP72I,5801
103
+ ksxt/parser/upbit.py,sha256=0Fj5OSih8kziMzz0AijnPhw6mMS5xt96gFo2p5iRyrQ,18875
104
+ ksxt/parser/__pycache__/bithumb.cpython-312.pyc,sha256=sOd7Q5S7o6PmvuV1i1Hn1WHj6wUB7Vt13YTR_XuCMvA,21763
105
+ ksxt/parser/__pycache__/koreainvest.cpython-312.pyc,sha256=hLywsOyhmk0sI7-P9y7VYGd5icB1FVjGYc5ULgIKFW4,20909
106
+ ksxt/parser/__pycache__/parser.cpython-312.pyc,sha256=tyRu43UBQ7e4T-y1Pk2R4SOVWPPjUmuEdaxvGODxq6Y,9029
107
+ ksxt/parser/__pycache__/upbit.cpython-312.pyc,sha256=PjWAseVAchbrKkLOBSltTtjjy9R7Uxw_5U0QCLhkhok,23004
108
+ ksxt/sample/symbol_sync.ipynb,sha256=dnUOgEKdUuEkDo_6LZjmDtVuNh4PPmCN4Ht7Pz-0L9Y,640081
109
+ ksxt/utils/safer.py,sha256=tlXDU9KDxrrM0HT2bv45hkblIgbEYr02NygdYS0jj6c,1289
110
+ ksxt/utils/sorter.py,sha256=j7eN1Qy7Wx3cXcWyRWyO1fVq-M24TrXvcfewPR5axF4,227
111
+ ksxt/utils/timer.py,sha256=4_rhXdQDFkKshS5utWrgTteIe71tVSTL1zNW-IjOngM,1228
112
+ ksxt/utils/__pycache__/safer.cpython-312.pyc,sha256=w-dkk_sa768g7ViIk-YrnhaxKmOu1loBlDFfjHu4PxM,1990
113
+ ksxt/utils/__pycache__/sorter.cpython-312.pyc,sha256=fg2obPlufrTQZLqIrzDKkX6bZQkUbdXyzZNqLjZiG3A,625
114
+ ksxt/utils/__pycache__/timer.cpython-312.pyc,sha256=9YXIdgCoGYeTR2gV86pZO9dG6_ZZ_IUNjJ318Tnb0m0,2004
115
+ ksxt-1.0.6.dist-info/LICENSE.txt,sha256=vyuXQcPOZ9BriMQz3h1k3jQTrKGsAjohf8WQHHf6xqo,1080
116
+ ksxt-1.0.6.dist-info/METADATA,sha256=TshmArNcONvsT895W4msJ8DmgLXB6jXSnEeNCNjxfO8,1649
117
+ ksxt-1.0.6.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
118
+ ksxt-1.0.6.dist-info/top_level.txt,sha256=XLUhkZCur5Pe0BPUV3J0syngIPz7jBb2YlQR4epo5kI,5
119
+ ksxt-1.0.6.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.3.0)
2
+ Generator: setuptools (75.6.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5