ksxt 1.0.4__py3-none-any.whl → 1.0.5__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 (77) 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/api/auto/__pycache__/bithumb.cpython-312.pyc +0 -0
  10. ksxt/api/auto/__pycache__/koreainvest.cpython-312.pyc +0 -0
  11. ksxt/api/auto/__pycache__/upbit.cpython-312.pyc +0 -0
  12. ksxt/async_/__pycache__/__init__.cpython-312.pyc +0 -0
  13. ksxt/async_/__pycache__/bithumb.cpython-312.pyc +0 -0
  14. ksxt/async_/__pycache__/koreainvest.cpython-312.pyc +0 -0
  15. ksxt/async_/__pycache__/upbit.cpython-312.pyc +0 -0
  16. ksxt/async_/base/__pycache__/__init__.cpython-312.pyc +0 -0
  17. ksxt/async_/base/__pycache__/async_exchange.cpython-312.pyc +0 -0
  18. ksxt/async_/base/__pycache__/throttler.cpython-312.pyc +0 -0
  19. ksxt/async_/base/async_exchange.py +17 -17
  20. ksxt/async_/bithumb.py +37 -19
  21. ksxt/async_/koreainvest.py +74 -6
  22. ksxt/async_/upbit.py +52 -20
  23. ksxt/base/__pycache__/__init__.cpython-312.pyc +0 -0
  24. ksxt/base/__pycache__/errors.cpython-312.pyc +0 -0
  25. ksxt/base/__pycache__/exchange.cpython-312.pyc +0 -0
  26. ksxt/base/__pycache__/rate_limiter.cpython-312.pyc +0 -0
  27. ksxt/base/__pycache__/rest_exchange.cpython-312.pyc +0 -0
  28. ksxt/base/__pycache__/types.cpython-312.pyc +0 -0
  29. ksxt/base/exchange.py +31 -23
  30. ksxt/base/rest_exchange.py +26 -28
  31. ksxt/bithumb.py +29 -12
  32. ksxt/config/__pycache__/__init__.cpython-312.pyc +0 -0
  33. ksxt/config/token.toml +6 -6
  34. ksxt/koreainvest.py +24 -6
  35. ksxt/market/__pycache__/base.cpython-312.pyc +0 -0
  36. ksxt/market/__pycache__/db.cpython-312.pyc +0 -0
  37. ksxt/market/__pycache__/logging.cpython-312.pyc +0 -0
  38. ksxt/market/__pycache__/manager.cpython-312.pyc +0 -0
  39. ksxt/market/__pycache__/markets.cpython-312.pyc +0 -0
  40. ksxt/market/krx/__pycache__/kosdaq.cpython-312.pyc +0 -0
  41. ksxt/market/krx/__pycache__/kospi.cpython-312.pyc +0 -0
  42. ksxt/market/krx/__pycache__/stock.cpython-312.pyc +0 -0
  43. ksxt/market/us/__pycache__/amex.cpython-312.pyc +0 -0
  44. ksxt/market/us/__pycache__/nasdaq.cpython-312.pyc +0 -0
  45. ksxt/market/us/__pycache__/nyse.cpython-312.pyc +0 -0
  46. ksxt/market/us/__pycache__/stock.cpython-312.pyc +0 -0
  47. ksxt/models/__pycache__/__init__.cpython-312.pyc +0 -0
  48. ksxt/models/__pycache__/balance.cpython-312.pyc +0 -0
  49. ksxt/models/__pycache__/cash.cpython-312.pyc +0 -0
  50. ksxt/models/__pycache__/common.cpython-312.pyc +0 -0
  51. ksxt/models/__pycache__/error.cpython-312.pyc +0 -0
  52. ksxt/models/__pycache__/historical.cpython-312.pyc +0 -0
  53. ksxt/models/__pycache__/market.cpython-312.pyc +0 -0
  54. ksxt/models/__pycache__/order.cpython-312.pyc +0 -0
  55. ksxt/models/__pycache__/orderbook.cpython-312.pyc +0 -0
  56. ksxt/models/__pycache__/ticker.cpython-312.pyc +0 -0
  57. ksxt/models/__pycache__/token.cpython-312.pyc +0 -0
  58. ksxt/models/__pycache__/transaction.cpython-312.pyc +0 -0
  59. ksxt/models/transaction.py +2 -0
  60. ksxt/parser/__pycache__/bithumb.cpython-312.pyc +0 -0
  61. ksxt/parser/__pycache__/koreainvest.cpython-312.pyc +0 -0
  62. ksxt/parser/__pycache__/parser.cpython-312.pyc +0 -0
  63. ksxt/parser/__pycache__/upbit.cpython-312.pyc +0 -0
  64. ksxt/parser/bithumb.py +83 -6
  65. ksxt/parser/koreainvest.py +56 -8
  66. ksxt/parser/parser.py +21 -5
  67. ksxt/parser/upbit.py +87 -10
  68. ksxt/upbit.py +42 -16
  69. ksxt/utils/__pycache__/safer.cpython-312.pyc +0 -0
  70. ksxt/utils/__pycache__/sorter.cpython-312.pyc +0 -0
  71. ksxt/utils/__pycache__/timer.cpython-312.pyc +0 -0
  72. {ksxt-1.0.4.dist-info → ksxt-1.0.5.dist-info}/METADATA +1 -1
  73. ksxt-1.0.5.dist-info/RECORD +123 -0
  74. {ksxt-1.0.4.dist-info → ksxt-1.0.5.dist-info}/WHEEL +1 -1
  75. ksxt-1.0.4.dist-info/RECORD +0 -120
  76. {ksxt-1.0.4.dist-info → ksxt-1.0.5.dist-info}/LICENSE.txt +0 -0
  77. {ksxt-1.0.4.dist-info → ksxt-1.0.5.dist-info}/top_level.txt +0 -0
Binary file
Binary file
Binary file
Binary file
@@ -85,7 +85,7 @@ class AsyncExchange(RestExchange):
85
85
  self.rate_limiters[api_name].release()
86
86
 
87
87
  async def fetch2(
88
- self, path, security_type, params={}, headers: Optional[Any] = None, body: Optional[Any] = None, config={}
88
+ self, path, security_type, params={}, headers: Any | None = None, body: Any | None = None, config={}
89
89
  ):
90
90
  is_activate = self.apis[self.type][security_type][path]["activate"]
91
91
  if not is_activate:
@@ -130,8 +130,8 @@ class AsyncExchange(RestExchange):
130
130
  self,
131
131
  symbol: str,
132
132
  time_frame: str,
133
- start: Optional[str] = None,
134
- end: Optional[str] = None,
133
+ start: datetime | None = None,
134
+ end: datetime | None = None,
135
135
  base_market: str = "KRW",
136
136
  ) -> ksxt.models.KsxtHistoricalDataResponse:
137
137
  raise NotSupportedError(f"{self.id} {self.fetch_historical_data.__qualname__}() is not supported yet.")
@@ -143,7 +143,7 @@ class AsyncExchange(RestExchange):
143
143
  raise NotSupportedError(f"{self.id} {self.fetch_user_info.__qualname__}() is not supported yet.")
144
144
 
145
145
  async def fetch_balance(
146
- self, acc_num: str, base_market: str = "KRW", excluded_symbols: Optional[list[str]] = None
146
+ self, acc_num: str, base_market: str = "KRW", excluded_symbols: list[str] | None = None
147
147
  ) -> ksxt.models.KsxtBalanceResponse:
148
148
  raise NotSupportedError(f"{self.id} {self.fetch_balance.__qualname__}() is not supported yet.")
149
149
 
@@ -157,12 +157,12 @@ class AsyncExchange(RestExchange):
157
157
  raise NotSupportedError(f"{self.id} {self.fetch_screener.__qualname__}() is not supported yet.")
158
158
 
159
159
  async def fetch_deposit_history(
160
- self, acc_num: str, base_market: str = "KRW"
160
+ self, acc_num: str, start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
161
161
  ) -> ksxt.models.KsxtDepositHistoryResponse:
162
162
  raise NotSupportedError(f"{self.id} {self.fetch_deposit_history.__qualname__}() is not supported yet.")
163
163
 
164
164
  async def fetch_withdrawal_history(
165
- self, acc_num: str, base_market: str = "KRW"
165
+ self, acc_num: str, start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
166
166
  ) -> ksxt.models.KsxtWithdrawalHistoryResponse:
167
167
  raise NotSupportedError(f"{self.id} {self.fetch_withdrawal_history.__qualname__}() is not supported yet.")
168
168
 
@@ -172,15 +172,15 @@ class AsyncExchange(RestExchange):
172
172
  symbol: str,
173
173
  ticket_type: Literal["EntryLong", "EntryShort", "ExitLong", "ExitShort"],
174
174
  otype: Literal["limit", "market"],
175
- price: Optional[float] = 0,
176
- qty: Optional[float] = 0,
177
- amount: Optional[float] = 0,
175
+ price: float | None = 0,
176
+ qty: float | None = 0,
177
+ amount: float | None = 0,
178
178
  base_market: str = "KRW",
179
179
  ) -> ksxt.models.KsxtCreateOrderResponse:
180
180
  raise NotSupportedError(f"{self.id} {self.create_order.__qualname__}() is not supported yet.")
181
181
 
182
182
  async def cancel_order(
183
- self, acc_num: str, order_id: str, symbol: Optional[str] = "", qty: float = 0, *args, base_market: str = "KRW"
183
+ self, acc_num: str, order_id: str, symbol: str | None = "", qty: float = 0, *args, base_market: str = "KRW"
184
184
  ) -> ksxt.models.KsxtCancelOrderResponse:
185
185
  raise NotSupportedError(f"{self.id} {self.cancel_order.__qualname__}() is not supported yet.")
186
186
 
@@ -191,7 +191,7 @@ class AsyncExchange(RestExchange):
191
191
  price: float,
192
192
  qty: float,
193
193
  *args,
194
- symbol: Optional[str] = "",
194
+ symbol: str | None = "",
195
195
  base_market: str = "KRW",
196
196
  ):
197
197
  raise NotSupportedError(f"{self.id} {self.modify_order.__qualname__}() is not supported yet.")
@@ -199,9 +199,9 @@ class AsyncExchange(RestExchange):
199
199
  async def fetch_open_order(
200
200
  self,
201
201
  acc_num: str,
202
- symbol: Optional[str] = "",
203
- start: Optional[str] = None,
204
- end: Optional[str] = None,
202
+ symbol: str | None = "",
203
+ start: datetime | None = None,
204
+ end: datetime | None = None,
205
205
  base_market: str = "KRW",
206
206
  ) -> ksxt.models.KsxtOpenOrderResponse:
207
207
  raise NotSupportedError(f"{self.id} {self.fetch_open_order.__qualname__}() is not supported yet.")
@@ -209,9 +209,9 @@ class AsyncExchange(RestExchange):
209
209
  async def fetch_closed_order(
210
210
  self,
211
211
  acc_num: str,
212
- symbol: Optional[str] = "",
213
- start: Optional[str] = None,
214
- end: Optional[str] = None,
212
+ symbol: str | None = "",
213
+ start: datetime | None = None,
214
+ end: datetime | None = None,
215
215
  base_market: str = "KRW",
216
216
  ) -> ksxt.models.KsxtClosedOrderResponse:
217
217
  raise NotSupportedError(f"{self.id} {self.fetch_closed_order.__qualname__}() is not supported yet.")
ksxt/async_/bithumb.py CHANGED
@@ -3,7 +3,7 @@ import hashlib
3
3
  import hmac
4
4
  import json
5
5
  import time
6
- from datetime import datetime
6
+ from datetime import datetime, timezone
7
7
  from typing import Any, Dict, List, Literal, Optional
8
8
  from urllib.parse import urlencode
9
9
  import uuid
@@ -108,10 +108,19 @@ class Bithumb(AsyncExchange, ImplicitAPI):
108
108
  return ksxt.models.KsxtMarketResponse(header=common_header, response=common_response, info=parsed_info)
109
109
 
110
110
  async def fetch_historical_data(
111
- self, symbol: str, time_frame: str, start: str | None = None, end: str | None = None, base_market: str = "KRW"
111
+ self,
112
+ symbol: str,
113
+ time_frame: str,
114
+ start: datetime | None = None,
115
+ end: datetime | None = None,
116
+ base_market: str = "KRW",
112
117
  ) -> ksxt.models.KsxtHistoricalDataResponse:
113
118
  params = {"market": self.safe_symbol(base_market=base_market, security=symbol), "count": 200}
114
119
 
120
+ if end:
121
+ end_utc = end.astimezone(timezone.utc)
122
+ params.update({"to": end_utc.strftime("%Y-%m-%d %H:%M:%S")})
123
+
115
124
  common_header = self.create_common_header(request_params=params)
116
125
 
117
126
  # TODO : time_frame 을 어떻게 고정시킬까? 우리는 분봉, 일봉, 주봉, 월봉 만 지원한다고 가정하면?
@@ -135,7 +144,10 @@ class Bithumb(AsyncExchange, ImplicitAPI):
135
144
  if common_response.success != "0":
136
145
  return ksxt.models.KsxtHistoricalDataResponse(header=common_header, response=common_response, info=None)
137
146
 
138
- parsed_response = self.parser.parse_historical_data(response=response, symbol=symbol, base_market=base_market)
147
+ parsed_response = self.parser.parse_historical_data(
148
+ response=response, symbol=symbol, start=start, end=end, base_market=base_market
149
+ )
150
+
139
151
  return ksxt.models.KsxtHistoricalDataResponse(
140
152
  header=common_header, response=common_response, info=parsed_response
141
153
  )
@@ -294,9 +306,9 @@ class Bithumb(AsyncExchange, ImplicitAPI):
294
306
  async def fetch_open_order(
295
307
  self,
296
308
  acc_num: str,
297
- symbol: str | None = "",
298
- start: str | None = None,
299
- end: str | None = None,
309
+ symbol: Optional[str] = "",
310
+ start: datetime | None = None,
311
+ end: datetime | None = None,
300
312
  base_market: str = "KRW",
301
313
  ) -> ksxt.models.KsxtOpenOrderResponse:
302
314
  params = {
@@ -316,7 +328,9 @@ class Bithumb(AsyncExchange, ImplicitAPI):
316
328
  return ksxt.models.KsxtOpenOrderResponse(header=common_header, response=common_response, info=None)
317
329
 
318
330
  # 데이터 파싱
319
- parsed_info = self.parser.parse_open_order_history(response, base_market)
331
+ parsed_info = self.parser.parse_open_order_history(
332
+ response=response, start=start, end=end, base_market=base_market
333
+ )
320
334
 
321
335
  return ksxt.models.KsxtOpenOrderResponse(header=common_header, response=common_response, info=parsed_info)
322
336
 
@@ -324,8 +338,8 @@ class Bithumb(AsyncExchange, ImplicitAPI):
324
338
  self,
325
339
  acc_num: str,
326
340
  symbol: Optional[str] = "",
327
- start: Optional[str] = None,
328
- end: Optional[str] = None,
341
+ start: datetime | None = None,
342
+ end: datetime | None = None,
329
343
  base_market: str = "KRW",
330
344
  ) -> ksxt.models.KsxtClosedOrderResponse:
331
345
  params = {"market": self.safe_symbol(base_market, symbol), "uuids": "", "state": "done"}
@@ -341,7 +355,9 @@ class Bithumb(AsyncExchange, ImplicitAPI):
341
355
  return ksxt.models.KsxtClosedOrderResponse(header=common_header, response=common_response, info=None)
342
356
 
343
357
  # 데이터 파싱
344
- parsed_info = self.parser.parse_closed_order_history(response, base_market)
358
+ parsed_info = self.parser.parse_closed_order_history(
359
+ response=response, start=start, end=end, base_market=base_market
360
+ )
345
361
 
346
362
  return ksxt.models.KsxtClosedOrderResponse(header=common_header, response=common_response, info=parsed_info)
347
363
 
@@ -413,9 +429,9 @@ class Bithumb(AsyncExchange, ImplicitAPI):
413
429
  return ksxt.models.KsxtCreateOrderResponse(header=common_header, response=common_response, info=parsed_info)
414
430
 
415
431
  async def fetch_withdrawal_history(
416
- self, acc_num: str, base_market: str = "KRW"
432
+ self, acc_num: str, start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
417
433
  ) -> ksxt.models.KsxtWithdrawalHistoryResponse:
418
- params = {"state": "done", "uuids": "", "txids": ""}
434
+ params = {"state": "DONE", "uuids": "", "txids": ""}
419
435
 
420
436
  common_header = self.create_common_header(request_params=params)
421
437
 
@@ -428,14 +444,16 @@ class Bithumb(AsyncExchange, ImplicitAPI):
428
444
  return ksxt.models.KsxtWithdrawalHistoryResponse(header=common_header, response=common_response, info=None)
429
445
 
430
446
  # 데이터 파싱
431
- parsed_info = self.parser.parse_withdrawal_history(response)
447
+ parsed_info = self.parser.parse_withdrawal_history(
448
+ response=response, start=start, end=end, base_market=base_market
449
+ )
432
450
 
433
451
  return ksxt.models.KsxtWithdrawalHistoryResponse(
434
452
  header=common_header, response=common_response, info=parsed_info
435
453
  )
436
454
 
437
455
  async def fetch_deposit_history(
438
- self, acc_num: str, base_market: str = "KRW"
456
+ self, acc_num: str, start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
439
457
  ) -> ksxt.models.KsxtDepositHistoryResponse:
440
458
  params = {"state": "ACCEPTED", "uuids": "", "txids": ""}
441
459
 
@@ -447,11 +465,11 @@ class Bithumb(AsyncExchange, ImplicitAPI):
447
465
 
448
466
  # 실패 시 오류 응답 반환
449
467
  if common_response.success != "0":
450
- return ksxt.models.KsxtWithdrawalHistoryResponse(header=common_header, response=common_response, info=None)
468
+ return ksxt.models.KsxtDepositHistoryResponse(header=common_header, response=common_response, info=None)
451
469
 
452
470
  # 데이터 파싱
453
- parsed_info = self.parser.parse_deposit_history(response)
454
-
455
- return ksxt.models.KsxtWithdrawalHistoryResponse(
456
- header=common_header, response=common_response, info=parsed_info
471
+ parsed_info = self.parser.parse_deposit_history(
472
+ response=response, start=start, end=end, base_market=base_market
457
473
  )
474
+
475
+ return ksxt.models.KsxtDepositHistoryResponse(header=common_header, response=common_response, info=parsed_info)
@@ -248,7 +248,12 @@ class KoreaInvest(AsyncExchange, ImplicitAPI):
248
248
 
249
249
  @AsyncExchange.check_token
250
250
  async def fetch_historical_data_index(
251
- self, symbol: str, time_frame: str, start: str | None = None, end: str | None = None, base_market: str = "KRW"
251
+ self,
252
+ symbol: str,
253
+ time_frame: str,
254
+ start: datetime | None = None,
255
+ end: datetime | None = None,
256
+ base_market: str = "KRW",
252
257
  ) -> ksxt.models.KsxtHistoricalDataResponse:
253
258
  if time_frame.endswith("D"):
254
259
  param_code = "D"
@@ -285,13 +290,22 @@ class KoreaInvest(AsyncExchange, ImplicitAPI):
285
290
  if common_response.success != "0":
286
291
  return ksxt.models.KsxtHistoricalDataResponse(header=common_header, response=common_response, info=None)
287
292
 
288
- parsed_info = self.parser.parse_historical_index_data(response=response, symbol=symbol, base_market=base_market)
293
+ parsed_response = self.parser.parse_historical_index_data(
294
+ response=response, symbol=symbol, start=start, end=end, base_market=base_market
295
+ )
289
296
 
290
- return ksxt.models.KsxtHistoricalDataResponse(header=common_header, response=common_response, info=parsed_info)
297
+ return ksxt.models.KsxtHistoricalDataResponse(
298
+ header=common_header, response=common_response, info=parsed_response
299
+ )
291
300
 
292
301
  @AsyncExchange.check_token
293
302
  async def fetch_historical_data(
294
- self, symbol: str, time_frame: str, start: str | None = None, end: str | None = None, base_market: str = "KRW"
303
+ self,
304
+ symbol: str,
305
+ time_frame: str,
306
+ start: datetime | None = None,
307
+ end: datetime | None = None,
308
+ base_market: str = "KRW",
295
309
  ) -> ksxt.models.KsxtHistoricalDataResponse:
296
310
  if time_frame.endswith("D"):
297
311
  param_code = "D"
@@ -341,9 +355,63 @@ class KoreaInvest(AsyncExchange, ImplicitAPI):
341
355
  if common_response.success != "0":
342
356
  return ksxt.models.KsxtHistoricalDataResponse(header=common_header, response=common_response, info=None)
343
357
 
344
- parsed_info = self.parser.parse_historical_data(response=response, symbol=symbol, base_market=base_market)
358
+ parsed_response = self.parser.parse_historical_data(
359
+ response=response, symbol=symbol, start=start, end=end, base_market=base_market
360
+ )
361
+
362
+ return ksxt.models.KsxtHistoricalDataResponse(
363
+ header=common_header, response=common_response, info=parsed_response
364
+ )
365
+
366
+ @AsyncExchange.check_token
367
+ async def fetch_deposit_history(
368
+ self, acc_num: str, start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
369
+ ) -> ksxt.models.KsxtDepositHistoryResponse:
370
+ params = {"state": "ACCEPTED", "uuids": "", "txids": ""}
371
+
372
+ common_header = self.create_common_header(request_params=params)
373
+
374
+ response = await self.private_get_fetch_deposit_history(self.extend(params))
375
+
376
+ common_response = self.get_common_response(response=response)
377
+
378
+ # 실패 시 오류 응답 반환
379
+ if common_response.success != "0":
380
+ return ksxt.models.KsxtWithdrawalHistoryResponse(header=common_header, response=common_response, info=None)
381
+
382
+ # 데이터 파싱
383
+ parsed_info = self.parser.parse_deposit_history(
384
+ response=response, start=start, end=end, base_market=base_market
385
+ )
386
+
387
+ return ksxt.models.KsxtWithdrawalHistoryResponse(
388
+ header=common_header, response=common_response, info=parsed_info
389
+ )
390
+
391
+ @AsyncExchange.check_token
392
+ async def fetch_withdrawal_history(
393
+ self, acc_num: str, start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
394
+ ) -> ksxt.models.KsxtWithdrawalHistoryResponse:
395
+ params = {"state": "done", "uuids": "", "txids": ""}
396
+
397
+ common_header = self.create_common_header(request_params=params)
398
+
399
+ response = await self.private_get_fetch_withdrawal_history(self.extend(params))
345
400
 
346
- return ksxt.models.KsxtHistoricalDataResponse(header=common_header, response=common_response, info=parsed_info)
401
+ common_response = self.get_common_response(response=response)
402
+
403
+ # 실패 시 오류 응답 반환
404
+ if common_response.success != "0":
405
+ return ksxt.models.KsxtWithdrawalHistoryResponse(header=common_header, response=common_response, info=None)
406
+
407
+ # 데이터 파싱
408
+ parsed_info = self.parser.parse_withdrawal_history(
409
+ response=response, start=start, end=end, base_market=base_market
410
+ )
411
+
412
+ return ksxt.models.KsxtWithdrawalHistoryResponse(
413
+ header=common_header, response=common_response, info=parsed_info
414
+ )
347
415
 
348
416
  @AsyncExchange.check_token
349
417
  async def modify_order(
ksxt/async_/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
 
@@ -110,6 +110,10 @@ class Upbit(AsyncExchange, ImplicitAPI):
110
110
  ) -> ksxt.models.KsxtHistoricalDataResponse:
111
111
  params = {"market": self.safe_symbol(base_market, symbol), "count": 200}
112
112
 
113
+ if end:
114
+ end_utc = end.astimezone(timezone.utc)
115
+ params.update({"to": end_utc.strftime("%Y-%m-%d %H:%M:%S")})
116
+
113
117
  # TODO : time_frame 을 어떻게 고정시킬까? 우리는 분봉, 일봉, 주봉, 월봉 만 지원한다고 가정하면?
114
118
  if time_frame.endswith("m"):
115
119
  # TODO : parse number
@@ -135,9 +139,13 @@ class Upbit(AsyncExchange, ImplicitAPI):
135
139
  if common_response.success != "0":
136
140
  return ksxt.models.KsxtHistoricalDataResponse(header=common_header, response=common_response, info=None)
137
141
 
138
- parsed_info = self.parser.parse_historical_data(response=response, symbol=symbol, base_market=base_market)
142
+ parsed_response = self.parser.parse_historical_data(
143
+ response=response, symbol=symbol, start=start, end=end, base_market=base_market
144
+ )
139
145
 
140
- return ksxt.models.KsxtHistoricalDataResponse(header=common_header, response=common_response, info=parsed_info)
146
+ return ksxt.models.KsxtHistoricalDataResponse(
147
+ header=common_header, response=common_response, info=parsed_response
148
+ )
141
149
 
142
150
  async def fetch_ticker(self, symbol: str, base_market: str = "KRW") -> ksxt.models.KsxtTickerResponse:
143
151
  params = {"markets": self.safe_symbol(base_market, symbol)} # 다중 조회 시, 콤마로 구분 ex. 'KRW-BTC, BTC-ETH'
@@ -276,7 +284,7 @@ class Upbit(AsyncExchange, ImplicitAPI):
276
284
 
277
285
  async def fetch_closed_order_detail(
278
286
  self, acc_num: str, order_ids: List[str], base_market: str = "KRW"
279
- ) -> ksxt.models.KsxtOpenOrderResponse:
287
+ ) -> ksxt.models.KsxtClosedOrderResponse:
280
288
  params = {
281
289
  "uuids": order_ids,
282
290
  }
@@ -289,12 +297,12 @@ class Upbit(AsyncExchange, ImplicitAPI):
289
297
 
290
298
  # 실패 시 오류 응답 반환
291
299
  if common_response.success != "0":
292
- return ksxt.models.KsxtOpenOrderResponse(header=common_header, response=common_response, info=None)
300
+ return ksxt.models.KsxtClosedOrderResponse(header=common_header, response=common_response, info=None)
293
301
 
294
302
  # 데이터 파싱
295
303
  parsed_info = self.parser.parse_closed_order_history(response, base_market)
296
304
 
297
- return ksxt.models.KsxtOpenOrderResponse(header=common_header, response=common_response, info=parsed_info)
305
+ return ksxt.models.KsxtClosedOrderResponse(header=common_header, response=common_response, info=parsed_info)
298
306
 
299
307
  async def fetch_open_order_detail(
300
308
  self, acc_num: str, order_ids: List[str], base_market: str = "KRW"
@@ -321,16 +329,28 @@ class Upbit(AsyncExchange, ImplicitAPI):
321
329
  async def fetch_closed_order(
322
330
  self,
323
331
  acc_num: str,
324
- symbol: Optional[str] = "",
325
- start: Optional[str] = None,
326
- end: Optional[str] = None,
332
+ symbol: str = "",
333
+ start: datetime | None = None,
334
+ end: datetime | None = None,
327
335
  base_market: str = "KRW",
328
336
  ) -> ksxt.models.KsxtClosedOrderResponse:
329
337
  params = {"state": "done"}
330
338
 
331
- if bool(symbol):
339
+ if symbol:
332
340
  params.update({"market": self.safe_symbol(base_market, symbol)})
333
341
 
342
+ if start and end:
343
+ duration = end - start
344
+ if duration.days > 7:
345
+ raise ValueError("The duration between start and end cannot exceed 7 days.")
346
+
347
+ elif start:
348
+ start_timestamp = int(start.timestamp() * 1000)
349
+ params.update({"start_time": start_timestamp})
350
+ elif end:
351
+ end_timestamp = int(end.timestamp() * 1000)
352
+ params.update({"end_time": end_timestamp})
353
+
334
354
  common_header = self.create_common_header(request_params=params)
335
355
 
336
356
  response = await self.private_get_fetch_closed_order(self.extend(params))
@@ -339,21 +359,24 @@ class Upbit(AsyncExchange, ImplicitAPI):
339
359
  if common_response.success != "0":
340
360
  return ksxt.models.KsxtClosedOrderResponse(header=common_header, response=common_response, info=None)
341
361
 
342
- parsed_info = self.parser.parse_closed_order_history(response=response, base_market=base_market)
362
+ # 데이터 파싱
363
+ parsed_info = self.parser.parse_closed_order_history(
364
+ response=response, start=start, end=end, base_market=base_market
365
+ )
343
366
 
344
367
  return ksxt.models.KsxtClosedOrderResponse(header=common_header, response=common_response, info=parsed_info)
345
368
 
346
369
  async def fetch_open_order(
347
370
  self,
348
371
  acc_num: str,
349
- symbol: str | None = "",
350
- start: str | None = None,
351
- end: str | None = None,
372
+ symbol: str = "",
373
+ start: datetime | None = None,
374
+ end: datetime | None = None,
352
375
  base_market: str = "KRW",
353
376
  ) -> ksxt.models.KsxtOpenOrderResponse:
354
377
  params = {"state": "wait"}
355
378
 
356
- if bool(symbol):
379
+ if symbol:
357
380
  params.update({"market": self.safe_symbol(base_market, symbol)})
358
381
 
359
382
  common_header = self.create_common_header(request_params=params)
@@ -364,12 +387,15 @@ class Upbit(AsyncExchange, ImplicitAPI):
364
387
  if common_response.success != "0":
365
388
  return ksxt.models.KsxtOpenOrderResponse(header=common_header, response=common_response, info=None)
366
389
 
367
- parsed_info = self.parser.parse_open_order_history(response=response, base_market=base_market)
390
+ # 데이터 파싱
391
+ parsed_info = self.parser.parse_open_order_history(
392
+ response=response, start=start, end=end, base_market=base_market
393
+ )
368
394
 
369
395
  return ksxt.models.KsxtOpenOrderResponse(header=common_header, response=common_response, info=parsed_info)
370
396
 
371
397
  async def fetch_withdrawal_history(
372
- self, acc_num: str, base_market: str = "KRW"
398
+ self, acc_num: str, start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
373
399
  ) -> ksxt.models.KsxtWithdrawalHistoryResponse:
374
400
  params = {"currency": base_market, "state": "DONE"}
375
401
 
@@ -381,14 +407,17 @@ class Upbit(AsyncExchange, ImplicitAPI):
381
407
  if common_response.success != "0":
382
408
  return ksxt.models.KsxtWithdrawalHistoryResponse(header=common_header, response=common_response, info=None)
383
409
 
384
- parsed_info = self.parser.parse_withdrawal_history(response=response, base_market=base_market)
410
+ # 데이터 파싱
411
+ parsed_info = self.parser.parse_withdrawal_history(
412
+ response=response, start=start, end=end, base_market=base_market
413
+ )
385
414
 
386
415
  return ksxt.models.KsxtWithdrawalHistoryResponse(
387
416
  header=common_header, response=common_response, info=parsed_info
388
417
  )
389
418
 
390
419
  async def fetch_deposit_history(
391
- self, acc_num: str, base_market: str = "KRW"
420
+ self, acc_num: str, start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
392
421
  ) -> ksxt.models.KsxtDepositHistoryResponse:
393
422
  params = {"currency": base_market, "state": "ACCEPTED"}
394
423
 
@@ -400,7 +429,10 @@ class Upbit(AsyncExchange, ImplicitAPI):
400
429
  if common_response.success != "0":
401
430
  return ksxt.models.KsxtDepositHistoryResponse(header=common_header, response=common_response, info=None)
402
431
 
403
- parsed_info = self.parser.parse_deposit_history(response=response, base_market=base_market)
432
+ # 데이터 파싱
433
+ parsed_info = self.parser.parse_deposit_history(
434
+ response=response, start=start, end=end, base_market=base_market
435
+ )
404
436
 
405
437
  return ksxt.models.KsxtDepositHistoryResponse(header=common_header, response=common_response, info=parsed_info)
406
438
 
Binary file