ksxt 1.0.3__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 (36) hide show
  1. ksxt/__pycache__/bithumb.cpython-312.pyc +0 -0
  2. ksxt/__pycache__/koreainvest.cpython-312.pyc +0 -0
  3. ksxt/__pycache__/upbit.cpython-312.pyc +0 -0
  4. ksxt/api/__pycache__/bithumb.cpython-312.pyc +0 -0
  5. ksxt/api/__pycache__/koreainvest.cpython-312.pyc +0 -0
  6. ksxt/api/__pycache__/upbit.cpython-312.pyc +0 -0
  7. ksxt/async_/__pycache__/bithumb.cpython-312.pyc +0 -0
  8. ksxt/async_/__pycache__/koreainvest.cpython-312.pyc +0 -0
  9. ksxt/async_/__pycache__/upbit.cpython-312.pyc +0 -0
  10. ksxt/async_/base/__pycache__/async_exchange.cpython-312.pyc +0 -0
  11. ksxt/async_/base/async_exchange.py +19 -17
  12. ksxt/async_/bithumb.py +41 -21
  13. ksxt/async_/koreainvest.py +80 -8
  14. ksxt/async_/upbit.py +58 -22
  15. ksxt/base/__pycache__/exchange.cpython-312.pyc +0 -0
  16. ksxt/base/__pycache__/rest_exchange.cpython-312.pyc +0 -0
  17. ksxt/base/exchange.py +33 -66
  18. ksxt/base/rest_exchange.py +28 -29
  19. ksxt/bithumb.py +33 -14
  20. ksxt/koreainvest.py +30 -8
  21. ksxt/models/__pycache__/transaction.cpython-312.pyc +0 -0
  22. ksxt/models/transaction.py +2 -0
  23. ksxt/parser/__pycache__/bithumb.cpython-312.pyc +0 -0
  24. ksxt/parser/__pycache__/koreainvest.cpython-312.pyc +0 -0
  25. ksxt/parser/__pycache__/parser.cpython-312.pyc +0 -0
  26. ksxt/parser/__pycache__/upbit.cpython-312.pyc +0 -0
  27. ksxt/parser/bithumb.py +102 -12
  28. ksxt/parser/koreainvest.py +66 -12
  29. ksxt/parser/parser.py +25 -7
  30. ksxt/parser/upbit.py +106 -16
  31. ksxt/upbit.py +48 -18
  32. {ksxt-1.0.3.dist-info → ksxt-1.0.5.dist-info}/METADATA +1 -1
  33. {ksxt-1.0.3.dist-info → ksxt-1.0.5.dist-info}/RECORD +36 -36
  34. {ksxt-1.0.3.dist-info → ksxt-1.0.5.dist-info}/WHEEL +1 -1
  35. {ksxt-1.0.3.dist-info → ksxt-1.0.5.dist-info}/LICENSE.txt +0 -0
  36. {ksxt-1.0.3.dist-info → ksxt-1.0.5.dist-info}/top_level.txt +0 -0
ksxt/base/exchange.py CHANGED
@@ -3,7 +3,7 @@ import json
3
3
  from datetime import datetime
4
4
  import time
5
5
  import pytz
6
- from typing import Dict, Optional
6
+ from typing import Dict
7
7
  import ast
8
8
 
9
9
  from requests import Session
@@ -24,7 +24,7 @@ class Exchange:
24
24
  session_lifetime = 10
25
25
  # 세션의 마지막 사용 시간
26
26
  session_last_used: time = None
27
-
27
+
28
28
  timeout = 10000 # milliseconds = seconds * 1000
29
29
  synchronous = True
30
30
 
@@ -85,8 +85,8 @@ class Exchange:
85
85
  self,
86
86
  symbol: str,
87
87
  time_frame: str,
88
- start: Optional[str] = None,
89
- end: Optional[str] = None,
88
+ start: datetime | None = None,
89
+ end: datetime | None = None,
90
90
  base_market: str = "KRW",
91
91
  ):
92
92
  """
@@ -95,8 +95,8 @@ class Exchange:
95
95
  Args:
96
96
  symbol (str): 종목코드
97
97
  time_frame (str): 봉조회기준
98
- start (Optional[str], optional): 조회 시작일. Defaults to None.
99
- end (Optional[str], optional): 조회 종료일. Defaults to None.
98
+ start (datetime | None, optional): 조회 시작일. Defaults to None.
99
+ end (datetime | None, optional): 조회 종료일. Defaults to None.
100
100
  base_market (str, optional): Market 구분 코드. Defaults to 'KRW'.
101
101
  """
102
102
  pass
@@ -139,13 +139,14 @@ class Exchange:
139
139
  """
140
140
  pass
141
141
 
142
- def fetch_balance(self, acc_num: str, base_market: str = "KRW"):
142
+ def fetch_balance(self, acc_num: str, base_market: str = "KRW", excluded_symbols: list[str] | None = None):
143
143
  """
144
144
  보유 자산 조회
145
145
 
146
146
  Args:
147
147
  acc_num (str): 계좌 번호
148
148
  base_market (str, optional): Market 구분 코드. Defaults to 'KRW'.
149
+ excluded_symbols (list[str] | None, optional): 제외할 종목 리스트. Defaults to None.
149
150
  """
150
151
  pass
151
152
 
@@ -178,22 +179,30 @@ class Exchange:
178
179
  """
179
180
  pass
180
181
 
181
- def fetch_deposit_history(self, acc_num: str, base_market: str = "KRW"):
182
+ def fetch_deposit_history(
183
+ self, acc_num: str, start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
184
+ ):
182
185
  """
183
186
  입금 내역 조회
184
187
 
185
188
  Args:
186
189
  acc_num (str): 계좌 번호
190
+ start (datetime | None, optional): 조회 시작일. Defaults to None.
191
+ end (datetime | None, optional): 조회 종료일. Defaults to None.
187
192
  base_market (str, optional): Market 구분 코드. Defaults to 'KRW'.
188
193
  """
189
194
  pass
190
195
 
191
- def fetch_withdrawal_history(self, acc_num: str, base_market: str = "KRW"):
196
+ def fetch_withdrawal_history(
197
+ self, acc_num: str, start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
198
+ ):
192
199
  """
193
200
  출금 내역 조회
194
201
 
195
202
  Args:
196
203
  acc_num (str): 계좌 번호
204
+ start (datetime | None, optional): 조회 시작일. Defaults to None.
205
+ end (datetime | None, optional): 조회 종료일. Defaults to None.
197
206
  base_market (str, optional): Market 구분 코드. Defaults to 'KRW'.
198
207
  """
199
208
  pass
@@ -228,7 +237,7 @@ class Exchange:
228
237
  pass
229
238
 
230
239
  def cancel_order(
231
- self, acc_num: str, order_id: str, symbol: Optional[str] = "", qty: float = 0, *args, base_market: str = "KRW"
240
+ self, acc_num: str, order_id: str, symbol: str | None = "", qty: float = 0, *args, base_market: str = "KRW"
232
241
  ):
233
242
  """
234
243
  미체결 주문 취소
@@ -236,7 +245,7 @@ class Exchange:
236
245
  Args:
237
246
  acc_num (str): 계좌정보(계좌번호, 지갑정보)
238
247
  order_id (str): 주문 정보(주문 id)
239
- symbol (str, optional): 종목정보(종목코드). Defaults to ''.
248
+ symbol (str | None, optional): 종목정보(종목코드). Defaults to ''.
240
249
  qty (float, optional): 수량. Defaults to 0..
241
250
  base_market (str, optional): Market 구분 코드. Defaults to 'KRW'.
242
251
  """
@@ -245,9 +254,9 @@ class Exchange:
245
254
  def fetch_open_order(
246
255
  self,
247
256
  acc_num: str,
248
- symbol: Optional[str] = "",
249
- start: Optional[str] = None,
250
- end: Optional[str] = None,
257
+ symbol: str | None = "",
258
+ start: datetime | None = None,
259
+ end: datetime | None = None,
251
260
  base_market: str = "KRW",
252
261
  ):
253
262
  """
@@ -255,9 +264,9 @@ class Exchange:
255
264
 
256
265
  Args:
257
266
  acc_num (str): 계좌정보(계좌번호, 지갑정보)
258
- symbol (str, optional): 종목정보(종목코드) Defaults to ''.
259
- start (str, optional): 조회 시작일자(YYYYMMDD). Defaults to None.
260
- end (str, optional): 조회 종료일자(YYYYMMDD). Defaults to None.
267
+ symbol (str | None, optional): 종목정보(종목코드) Defaults to ''.
268
+ start (datetime | None, optional): 조회 시작일자. Defaults to None.
269
+ end (datetime | None, optional): 조회 종료일자. Defaults to None.
261
270
  base_market (str, optional): Market 구분 코드. Defaults to 'KRW'.
262
271
  """
263
272
  pass
@@ -265,9 +274,9 @@ class Exchange:
265
274
  def fetch_closed_order(
266
275
  self,
267
276
  acc_num: str,
268
- symbol: Optional[str] = "",
269
- start: Optional[str] = None,
270
- end: Optional[str] = None,
277
+ symbol: str | None = "",
278
+ start: datetime | None = None,
279
+ end: datetime | None = None,
271
280
  base_market: str = "KRW",
272
281
  ):
273
282
  """
@@ -275,9 +284,9 @@ class Exchange:
275
284
 
276
285
  Args:
277
286
  acc_num (str): 계좌정보(계좌번호, 지갑정보)
278
- symbol (str, optional): 종목정보(종목코드) Defaults to ''.
279
- start (str, optional): 조회 시작일자(YYYYMMDD). Defaults to None.
280
- end (str, optional): 조회 종료일자(YYYYMMDD). Defaults to None.
287
+ symbol (str | None, optional): 종목정보(종목코드) Defaults to ''.
288
+ start (datetime | None, optional): 조회 시작일자. Defaults to None.
289
+ end (datetime | None, optional): 조회 종료일자. Defaults to None.
281
290
  base_market (str, optional): Market 구분 코드. Defaults to 'KRW'.
282
291
  """
283
292
  pass
@@ -300,48 +309,6 @@ class Exchange:
300
309
 
301
310
  # endregion broker
302
311
 
303
- # TODO : @abstractmethod로 제약을 하는게 나을까?는 고민 필요.
304
- def get_success_response(self, result):
305
- pass
306
-
307
- def get_success_response(self, response_code, msg_code, msg, org_data):
308
- return {
309
- "response": {
310
- # 성공 실패 여부
311
- "success": response_code,
312
- # 응답코드
313
- "code": msg_code,
314
- # 응답메세지
315
- "message": msg,
316
- # 원본 데이터
317
- "info": org_data,
318
- },
319
- "header": {},
320
- }
321
-
322
- def get_error_response(self, error_code, error_message, org_data=None):
323
- return {
324
- "response": {
325
- # 성공 실패 여부
326
- "success": "-1",
327
- # 응답코드
328
- "code": error_code,
329
- # 응답메세지
330
- "message": error_message,
331
- # 원본 데이터
332
- "info": org_data,
333
- },
334
- "header": {},
335
- }
336
-
337
- def update_success_response_header(self, response: dict, header: dict):
338
- response["header"].update(header)
339
- return response
340
-
341
- def update_success_response_body(self, response: dict, body: dict):
342
- response.update(body)
343
- return response
344
-
345
312
  def create_common_response(self, success: str, msg_code: str, msg: str, info: dict) -> CommonResponse:
346
313
  return CommonResponse(success=success, msg_code=msg_code, msg=msg, info=info)
347
314
 
@@ -370,7 +337,7 @@ class Exchange:
370
337
  def set_attr(self, attrs):
371
338
  for key in attrs:
372
339
  if hasattr(self, key) and isinstance(getattr(self, key), dict):
373
- setattr(self, key, self.deep_extend(getattr(self, key), attrs[key]))
340
+ setattr(self, key, Exchange.deep_extend(getattr(self, key), attrs[key]))
374
341
  else:
375
342
  setattr(self, key, attrs[key])
376
343
 
@@ -5,7 +5,7 @@ import toml
5
5
  import os
6
6
  from pathlib import Path
7
7
 
8
- from typing import Any, Dict, List, Literal, Optional
8
+ from typing import Any, Dict, List, Literal
9
9
 
10
10
  from datetime import datetime, UTC
11
11
  import pytz
@@ -44,7 +44,6 @@ class RestExchange(Exchange):
44
44
  def __init__(self, config: Dict = None, filename: str = None) -> None:
45
45
  super().__init__()
46
46
 
47
-
48
47
  self.rate_limiters: Dict[str, RateLimiterContext] = {}
49
48
 
50
49
  self.headers = dict() if self.headers is None else self.headers
@@ -233,16 +232,14 @@ class RestExchange(Exchange):
233
232
  security_type,
234
233
  method_type,
235
234
  api_type: Any = "public",
236
- headers: Optional[Any] = None,
237
- body: Optional[Any] = None,
238
- params: Optional[Any] = None,
235
+ headers: Any | None = None,
236
+ body: Any | None = None,
237
+ params: Any | None = None,
239
238
  config={},
240
239
  ):
241
240
  pass
242
241
 
243
- def fetch2(
244
- self, path, security_type, params={}, headers: Optional[Any] = None, body: Optional[Any] = None, config={}
245
- ):
242
+ def fetch2(self, path, security_type, params={}, headers: Any | None = None, body: Any | None = None, config={}):
246
243
  is_activate = self.is_activate(path=path, security_type=security_type)
247
244
  if not is_activate:
248
245
  return {
@@ -267,9 +264,7 @@ class RestExchange(Exchange):
267
264
  request = self.sign(path, security_type, method_type, api_type, headers, body, params, config)
268
265
  return self.fetch(request["url"], request["method"], request["headers"], request["body"], request["params"])
269
266
 
270
- def request(
271
- self, path, security_type, params={}, headers: Optional[Any] = None, body: Optional[Any] = None, config={}
272
- ):
267
+ def request(self, path, security_type, params={}, headers: Any | None = None, body: Any | None = None, config={}):
273
268
  return self.fetch2(path, security_type, params, headers, body, config)
274
269
 
275
270
  # region base method
@@ -297,8 +292,8 @@ class RestExchange(Exchange):
297
292
  self,
298
293
  symbol: str,
299
294
  time_frame: str,
300
- start: Optional[str] = None,
301
- end: Optional[str] = None,
295
+ start: datetime | None = None,
296
+ end: datetime | None = None,
302
297
  base_market: str = "KRW",
303
298
  ) -> ksxt.models.KsxtHistoricalDataResponse:
304
299
  raise NotSupportedError(f"{self.id} {self.fetch_historical_data_index.__qualname__}() is not supported yet.")
@@ -308,8 +303,8 @@ class RestExchange(Exchange):
308
303
  self,
309
304
  symbol: str,
310
305
  time_frame: str,
311
- start: Optional[str] = None,
312
- end: Optional[str] = None,
306
+ start: datetime | None = None,
307
+ end: datetime | None = None,
313
308
  base_market: str = "KRW",
314
309
  ) -> ksxt.models.KsxtHistoricalDataResponse:
315
310
  raise NotSupportedError(f"{self.id} {self.fetch_historical_data.__qualname__}() is not supported yet.")
@@ -323,7 +318,9 @@ class RestExchange(Exchange):
323
318
  raise NotSupportedError(f"{self.id} {self.fetch_user_info.__qualname__}() is not supported yet.")
324
319
 
325
320
  @check_token
326
- def fetch_balance(self, acc_num: str, base_market: str = "KRW") -> ksxt.models.KsxtBalanceResponse:
321
+ def fetch_balance(
322
+ self, acc_num: str, base_market: str = "KRW", excluded_symbols: list[str] | None = None
323
+ ) -> ksxt.models.KsxtBalanceResponse:
327
324
  raise NotSupportedError(f"{self.id} {self.fetch_balance.__qualname__}() is not supported yet.")
328
325
 
329
326
  @check_token
@@ -343,12 +340,14 @@ class RestExchange(Exchange):
343
340
  raise NotSupportedError(f"{self.id} {self.fetch_screener.__qualname__}() is not supported yet.")
344
341
 
345
342
  @check_token
346
- def fetch_deposit_history(self, acc_num: str, base_market: str = "KRW") -> ksxt.models.KsxtDepositHistoryResponse:
343
+ def fetch_deposit_history(
344
+ self, acc_num: str, start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
345
+ ) -> ksxt.models.KsxtDepositHistoryResponse:
347
346
  raise NotSupportedError(f"{self.id} {self.fetch_deposit_history.__qualname__}() is not supported yet.")
348
347
 
349
348
  @check_token
350
349
  def fetch_withdrawal_history(
351
- self, acc_num: str, base_market: str = "KRW"
350
+ self, acc_num: str, start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
352
351
  ) -> ksxt.models.KsxtWithdrawalHistoryResponse:
353
352
  raise NotSupportedError(f"{self.id} {self.fetch_withdrawal_history.__qualname__}() is not supported yet.")
354
353
 
@@ -359,16 +358,16 @@ class RestExchange(Exchange):
359
358
  symbol: str,
360
359
  ticket_type: Literal["EntryLong", "EntryShort", "ExitLong", "ExitShort"],
361
360
  otype: Literal["limit", "market"],
362
- price: Optional[float] = 0,
363
- qty: Optional[float] = 0,
364
- amount: Optional[float] = 0,
361
+ price: float | None = 0,
362
+ qty: float | None = 0,
363
+ amount: float | None = 0,
365
364
  base_market: str = "KRW",
366
365
  ) -> ksxt.models.KsxtCreateOrderResponse:
367
366
  raise NotSupportedError(f"{self.id} {self.create_order.__qualname__}() is not supported yet.")
368
367
 
369
368
  @check_token
370
369
  def cancel_order(
371
- self, acc_num: str, order_id: str, symbol: Optional[str] = "", qty: float = 0, *args, base_market: str = "KRW"
370
+ self, acc_num: str, order_id: str, symbol: str | None = "", qty: float = 0, *args, base_market: str = "KRW"
372
371
  ) -> ksxt.models.KsxtCancelOrderResponse:
373
372
  raise NotSupportedError(f"{self.id} {self.cancel_order.__qualname__}() is not supported yet.")
374
373
 
@@ -380,7 +379,7 @@ class RestExchange(Exchange):
380
379
  price: float,
381
380
  qty: float,
382
381
  *args,
383
- symbol: Optional[str] = "",
382
+ symbol: str | None = "",
384
383
  base_market: str = "KRW",
385
384
  ) -> ksxt.models.KsxtModifyOrderResponse:
386
385
  raise NotSupportedError(f"{self.id} {self.modify_order.__qualname__}() is not supported yet.")
@@ -389,9 +388,9 @@ class RestExchange(Exchange):
389
388
  def fetch_open_order(
390
389
  self,
391
390
  acc_num: str,
392
- symbol: Optional[str] = "",
393
- start: Optional[str] = None,
394
- end: Optional[str] = None,
391
+ symbol: str | None = "",
392
+ start: datetime | None = None,
393
+ end: datetime | None = None,
395
394
  base_market: str = "KRW",
396
395
  ) -> ksxt.models.KsxtOpenOrderResponse:
397
396
  raise NotSupportedError(f"{self.id} {self.fetch_open_order.__qualname__}() is not supported yet.")
@@ -400,9 +399,9 @@ class RestExchange(Exchange):
400
399
  def fetch_closed_order(
401
400
  self,
402
401
  acc_num: str,
403
- symbol: Optional[str] = "",
404
- start: Optional[str] = None,
405
- end: Optional[str] = None,
402
+ symbol: str | None = "",
403
+ start: datetime | None = None,
404
+ end: datetime | None = None,
406
405
  base_market: str = "KRW",
407
406
  ) -> ksxt.models.KsxtClosedOrderResponse:
408
407
  raise NotSupportedError(f"{self.id} {self.fetch_closed_order.__qualname__}() is not supported yet.")
ksxt/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
@@ -119,6 +119,10 @@ class Bithumb(RestExchange, ImplicitAPI):
119
119
  ) -> ksxt.models.KsxtHistoricalDataResponse:
120
120
  params = {"market": self.safe_symbol(base_market=base_market, security=symbol), "count": 200}
121
121
 
122
+ if end:
123
+ end_utc = end.astimezone(timezone.utc)
124
+ params.update({"to": end_utc.strftime("%Y-%m-%d %H:%M:%S")})
125
+
122
126
  common_header = self.create_common_header(request_params=params)
123
127
 
124
128
  # TODO : time_frame 을 어떻게 고정시킬까? 우리는 분봉, 일봉, 주봉, 월봉 만 지원한다고 가정하면?
@@ -142,7 +146,10 @@ class Bithumb(RestExchange, ImplicitAPI):
142
146
  if common_response.success != "0":
143
147
  return ksxt.models.KsxtHistoricalDataResponse(header=common_header, response=common_response, info=None)
144
148
 
145
- parsed_response = self.parser.parse_historical_data(response=response, symbol=symbol, base_market=base_market)
149
+ parsed_response = self.parser.parse_historical_data(
150
+ response=response, symbol=symbol, start=start, end=end, base_market=base_market
151
+ )
152
+
146
153
  return ksxt.models.KsxtHistoricalDataResponse(
147
154
  header=common_header, response=common_response, info=parsed_response
148
155
  )
@@ -221,7 +228,9 @@ class Bithumb(RestExchange, ImplicitAPI):
221
228
 
222
229
  return ksxt.models.KsxtMultiOrderBookResponse(header=common_header, response=common_response, info=parsed_info)
223
230
 
224
- def fetch_balance(self, acc_num: str, base_market: str = "KRW") -> ksxt.models.KsxtBalanceResponse:
231
+ def fetch_balance(
232
+ self, acc_num: str, base_market: str = "KRW", excluded_symbols: Optional[list[str]] = None
233
+ ) -> ksxt.models.KsxtBalanceResponse:
225
234
  params = {}
226
235
 
227
236
  common_header = self.create_common_header(request_params=params)
@@ -235,7 +244,7 @@ class Bithumb(RestExchange, ImplicitAPI):
235
244
  return ksxt.models.KsxtBalanceResponse(header=common_header, response=common_response, info=None)
236
245
 
237
246
  # 데이터 파싱
238
- parsed_info = self.parser.parse_balance(response, base_market)
247
+ parsed_info = self.parser.parse_balance(response, base_market, excluded_symbols=excluded_symbols)
239
248
 
240
249
  return ksxt.models.KsxtBalanceResponse(header=common_header, response=common_response, info=parsed_info)
241
250
 
@@ -339,8 +348,8 @@ class Bithumb(RestExchange, ImplicitAPI):
339
348
  self,
340
349
  acc_num: str,
341
350
  symbol: str | None = "",
342
- start: str | None = None,
343
- end: str | None = None,
351
+ start: datetime | None = None,
352
+ end: datetime | None = None,
344
353
  base_market: str = "KRW",
345
354
  ) -> ksxt.models.KsxtOpenOrderResponse:
346
355
  params = {
@@ -360,7 +369,9 @@ class Bithumb(RestExchange, ImplicitAPI):
360
369
  return ksxt.models.KsxtOpenOrderResponse(header=common_header, response=common_response, info=None)
361
370
 
362
371
  # 데이터 파싱
363
- parsed_info = self.parser.parse_open_order_history(response, base_market)
372
+ parsed_info = self.parser.parse_open_order_history(
373
+ response=response, start=start, end=end, base_market=base_market
374
+ )
364
375
 
365
376
  return ksxt.models.KsxtOpenOrderResponse(header=common_header, response=common_response, info=parsed_info)
366
377
 
@@ -368,8 +379,8 @@ class Bithumb(RestExchange, ImplicitAPI):
368
379
  self,
369
380
  acc_num: str,
370
381
  symbol: Optional[str] = "",
371
- start: Optional[str] = None,
372
- end: Optional[str] = None,
382
+ start: datetime | None = None,
383
+ end: datetime | None = None,
373
384
  base_market: str = "KRW",
374
385
  ) -> ksxt.models.KsxtClosedOrderResponse:
375
386
  params = {"market": self.safe_symbol(base_market, symbol), "uuids": "", "state": "done"}
@@ -385,7 +396,9 @@ class Bithumb(RestExchange, ImplicitAPI):
385
396
  return ksxt.models.KsxtClosedOrderResponse(header=common_header, response=common_response, info=None)
386
397
 
387
398
  # 데이터 파싱
388
- parsed_info = self.parser.parse_closed_order_history(response, base_market)
399
+ parsed_info = self.parser.parse_closed_order_history(
400
+ response=response, start=start, end=end, base_market=base_market
401
+ )
389
402
 
390
403
  return ksxt.models.KsxtClosedOrderResponse(header=common_header, response=common_response, info=parsed_info)
391
404
 
@@ -462,7 +475,7 @@ class Bithumb(RestExchange, ImplicitAPI):
462
475
  return ksxt.models.KsxtCreateOrderResponse(header=common_header, response=common_response, info=parsed_info)
463
476
 
464
477
  def fetch_withdrawal_history(
465
- self, acc_num: str, base_market: str = "KRW"
478
+ self, acc_num: str, start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
466
479
  ) -> ksxt.models.KsxtWithdrawalHistoryResponse:
467
480
  params = {"state": "done", "uuids": "", "txids": ""}
468
481
 
@@ -477,13 +490,17 @@ class Bithumb(RestExchange, ImplicitAPI):
477
490
  return ksxt.models.KsxtWithdrawalHistoryResponse(header=common_header, response=common_response, info=None)
478
491
 
479
492
  # 데이터 파싱
480
- parsed_info = self.parser.parse_withdrawal_history(response)
493
+ parsed_info = self.parser.parse_withdrawal_history(
494
+ response=response, start=start, end=end, base_market=base_market
495
+ )
481
496
 
482
497
  return ksxt.models.KsxtWithdrawalHistoryResponse(
483
498
  header=common_header, response=common_response, info=parsed_info
484
499
  )
485
500
 
486
- def fetch_deposit_history(self, acc_num: str, base_market: str = "KRW") -> ksxt.models.KsxtDepositHistoryResponse:
501
+ def fetch_deposit_history(
502
+ self, acc_num: str, start: datetime | None = None, end: datetime | None = None, base_market: str = "KRW"
503
+ ) -> ksxt.models.KsxtDepositHistoryResponse:
487
504
  params = {"state": "ACCEPTED", "uuids": "", "txids": ""}
488
505
 
489
506
  common_header = self.create_common_header(request_params=params)
@@ -497,7 +514,9 @@ class Bithumb(RestExchange, ImplicitAPI):
497
514
  return ksxt.models.KsxtWithdrawalHistoryResponse(header=common_header, response=common_response, info=None)
498
515
 
499
516
  # 데이터 파싱
500
- parsed_info = self.parser.parse_deposit_history(response)
517
+ parsed_info = self.parser.parse_deposit_history(
518
+ response=response, start=start, end=end, base_market=base_market
519
+ )
501
520
 
502
521
  return ksxt.models.KsxtWithdrawalHistoryResponse(
503
522
  header=common_header, response=common_response, info=parsed_info
ksxt/koreainvest.py CHANGED
@@ -124,7 +124,9 @@ class KoreaInvest(RestExchange, ImplicitAPI):
124
124
  )
125
125
 
126
126
  @RestExchange.check_token
127
- def fetch_balance(self, acc_num: str, base_market: str = "KRW") -> ksxt.models.KsxtBalanceResponse:
127
+ def fetch_balance(
128
+ self, acc_num: str, base_market: str = "KRW", excluded_symbols: Optional[list[str]] = None
129
+ ) -> ksxt.models.KsxtBalanceResponse:
128
130
  if base_market == "KRW":
129
131
  params = {
130
132
  "CANO": acc_num[:8],
@@ -150,7 +152,9 @@ class KoreaInvest(RestExchange, ImplicitAPI):
150
152
  if common_response.success != "0":
151
153
  return ksxt.models.KsxtBalanceResponse(header=common_header, response=common_response, info=None)
152
154
 
153
- parsed_info = self.parser.parse_balance(response=response, base_market=base_market)
155
+ parsed_info = self.parser.parse_balance(
156
+ response=response, base_market=base_market, excluded_symbols=excluded_symbols
157
+ )
154
158
 
155
159
  return ksxt.models.KsxtBalanceResponse(header=common_header, response=common_response, info=parsed_info)
156
160
 
@@ -244,7 +248,12 @@ class KoreaInvest(RestExchange, ImplicitAPI):
244
248
 
245
249
  @RestExchange.check_token
246
250
  def fetch_historical_data_index(
247
- 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",
248
257
  ) -> ksxt.models.KsxtHistoricalDataResponse:
249
258
  if time_frame.endswith("D"):
250
259
  param_code = "D"
@@ -281,13 +290,22 @@ class KoreaInvest(RestExchange, ImplicitAPI):
281
290
  if common_response.success != "0":
282
291
  return ksxt.models.KsxtHistoricalDataResponse(header=common_header, response=common_response, info=None)
283
292
 
284
- 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
+ )
285
296
 
286
- 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
+ )
287
300
 
288
301
  @RestExchange.check_token
289
302
  def fetch_historical_data(
290
- 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",
291
309
  ) -> ksxt.models.KsxtHistoricalDataResponse:
292
310
  if time_frame.endswith("D"):
293
311
  param_code = "D"
@@ -337,9 +355,13 @@ class KoreaInvest(RestExchange, ImplicitAPI):
337
355
  if common_response.success != "0":
338
356
  return ksxt.models.KsxtHistoricalDataResponse(header=common_header, response=common_response, info=None)
339
357
 
340
- 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
+ )
341
361
 
342
- return ksxt.models.KsxtHistoricalDataResponse(header=common_header, response=common_response, info=parsed_info)
362
+ return ksxt.models.KsxtHistoricalDataResponse(
363
+ header=common_header, response=common_response, info=parsed_response
364
+ )
343
365
 
344
366
  @RestExchange.check_token
345
367
  def modify_order(
@@ -13,6 +13,8 @@ class TransactionInfo(BaseModel):
13
13
 
14
14
  # 금액
15
15
  amount: float
16
+ # 세금
17
+ tax: Optional[float] = 0
16
18
  # 수수료
17
19
  fee: Optional[float] = 0
18
20