ksxt 0.0.7__py3-none-any.whl → 0.0.9__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 (141) hide show
  1. ksxt/__init__.py +3 -1
  2. ksxt/__pycache__/__init__.cpython-312.pyc +0 -0
  3. ksxt/__pycache__/bithumb.cpython-312.pyc +0 -0
  4. ksxt/__pycache__/koreainvest.cpython-312.pyc +0 -0
  5. ksxt/__pycache__/upbit.cpython-312.pyc +0 -0
  6. ksxt/api/__init__.py +26 -0
  7. ksxt/api/__pycache__/__init__.cpython-312.pyc +0 -0
  8. ksxt/api/__pycache__/bithumb.cpython-312.pyc +0 -0
  9. ksxt/api/__pycache__/koreainvest.cpython-312.pyc +0 -0
  10. ksxt/api/__pycache__/upbit.cpython-312.pyc +0 -0
  11. ksxt/api/auto/api_generator.py +54 -0
  12. ksxt/api/auto/bithumb.py +35 -0
  13. ksxt/api/auto/koreainvest.py +49 -0
  14. ksxt/api/auto/upbit.py +39 -0
  15. ksxt/api/bithumb.py +42 -0
  16. ksxt/api/koreainvest.py +40 -0
  17. ksxt/api/upbit.py +54 -0
  18. ksxt/async_/__init__.py +4 -0
  19. ksxt/async_/__pycache__/__init__.cpython-312.pyc +0 -0
  20. ksxt/async_/__pycache__/bithumb.cpython-312.pyc +0 -0
  21. ksxt/async_/__pycache__/koreainvest.cpython-312.pyc +0 -0
  22. ksxt/async_/__pycache__/upbit.cpython-312.pyc +0 -0
  23. ksxt/async_/base/__init__.py +0 -0
  24. ksxt/async_/base/__pycache__/__init__.cpython-312.pyc +0 -0
  25. ksxt/async_/base/__pycache__/async_exchange.cpython-312.pyc +0 -0
  26. ksxt/async_/base/__pycache__/throttler.cpython-312.pyc +0 -0
  27. ksxt/async_/base/async_exchange.py +232 -0
  28. ksxt/async_/base/throttler.py +63 -0
  29. ksxt/async_/bithumb.py +455 -0
  30. ksxt/async_/koreainvest.py +849 -0
  31. ksxt/async_/upbit.py +488 -0
  32. ksxt/base/__pycache__/__init__.cpython-312.pyc +0 -0
  33. ksxt/base/__pycache__/errors.cpython-312.pyc +0 -0
  34. ksxt/base/__pycache__/exchange.cpython-312.pyc +0 -0
  35. ksxt/base/__pycache__/rest_exchange.cpython-312.pyc +0 -0
  36. ksxt/base/__pycache__/types.cpython-312.pyc +0 -0
  37. ksxt/base/com_exchange.py +2 -2
  38. ksxt/base/errors.py +10 -0
  39. ksxt/base/exchange.py +188 -497
  40. ksxt/base/rest_exchange.py +297 -113
  41. ksxt/base/types.py +1 -36
  42. ksxt/bithumb.py +504 -0
  43. ksxt/config/__init__.py +2 -1
  44. ksxt/config/__pycache__/__init__.cpython-312.pyc +0 -0
  45. ksxt/config/bithumb.toml +380 -0
  46. ksxt/config/koreainvest.toml +312 -0
  47. ksxt/config/token.toml +7 -0
  48. ksxt/config/upbit.toml +428 -0
  49. ksxt/koreainvest.py +409 -1055
  50. ksxt/market/__pycache__/base.cpython-312.pyc +0 -0
  51. ksxt/market/__pycache__/db.cpython-312.pyc +0 -0
  52. ksxt/market/__pycache__/logging.cpython-312.pyc +0 -0
  53. ksxt/market/__pycache__/manager.cpython-312.pyc +0 -0
  54. ksxt/market/__pycache__/markets.cpython-312.pyc +0 -0
  55. ksxt/market/base.py +50 -50
  56. ksxt/market/db.py +5 -4
  57. ksxt/market/krx/__pycache__/kosdaq.cpython-312.pyc +0 -0
  58. ksxt/market/krx/__pycache__/kospi.cpython-312.pyc +0 -0
  59. ksxt/market/krx/__pycache__/stock.cpython-312.pyc +0 -0
  60. ksxt/market/krx/kosdaq.py +150 -147
  61. ksxt/market/krx/kospi.py +179 -175
  62. ksxt/market/krx/stock.py +136 -134
  63. ksxt/market/logging.py +4 -4
  64. ksxt/market/manager.py +11 -13
  65. ksxt/market/markets.py +1 -1
  66. ksxt/market/us/__pycache__/amex.cpython-312.pyc +0 -0
  67. ksxt/market/us/__pycache__/nasdaq.cpython-312.pyc +0 -0
  68. ksxt/market/us/__pycache__/nyse.cpython-312.pyc +0 -0
  69. ksxt/market/us/__pycache__/stock.cpython-312.pyc +0 -0
  70. ksxt/market/us/amex.py +31 -31
  71. ksxt/market/us/nasdaq.py +31 -31
  72. ksxt/market/us/nyse.py +31 -31
  73. ksxt/market/us/stock.py +20 -28
  74. ksxt/models/__init__.py +16 -0
  75. ksxt/models/__pycache__/__init__.cpython-312.pyc +0 -0
  76. ksxt/models/__pycache__/balance.cpython-312.pyc +0 -0
  77. ksxt/models/__pycache__/cash.cpython-312.pyc +0 -0
  78. ksxt/models/__pycache__/common.cpython-312.pyc +0 -0
  79. ksxt/models/__pycache__/error.cpython-312.pyc +0 -0
  80. ksxt/models/__pycache__/historical.cpython-312.pyc +0 -0
  81. ksxt/models/__pycache__/market.cpython-312.pyc +0 -0
  82. ksxt/models/__pycache__/order.cpython-312.pyc +0 -0
  83. ksxt/models/__pycache__/orderbook.cpython-312.pyc +0 -0
  84. ksxt/models/__pycache__/ticker.cpython-312.pyc +0 -0
  85. ksxt/models/__pycache__/token.cpython-312.pyc +0 -0
  86. ksxt/models/__pycache__/transaction.cpython-312.pyc +0 -0
  87. ksxt/models/balance.py +30 -0
  88. ksxt/models/cash.py +15 -0
  89. ksxt/models/common.py +31 -0
  90. ksxt/models/error.py +13 -0
  91. ksxt/models/historical.py +26 -0
  92. ksxt/models/market.py +81 -0
  93. ksxt/models/order.py +42 -0
  94. ksxt/models/orderbook.py +32 -0
  95. ksxt/models/ticker.py +25 -0
  96. ksxt/models/token.py +14 -0
  97. ksxt/models/transaction.py +79 -0
  98. ksxt/parser/__pycache__/bithumb.cpython-312.pyc +0 -0
  99. ksxt/parser/__pycache__/koreainvest.cpython-312.pyc +0 -0
  100. ksxt/parser/__pycache__/parser.cpython-312.pyc +0 -0
  101. ksxt/parser/__pycache__/upbit.cpython-312.pyc +0 -0
  102. ksxt/parser/bithumb.py +300 -0
  103. ksxt/parser/koreainvest.py +323 -0
  104. ksxt/parser/parser.py +114 -0
  105. ksxt/parser/upbit.py +308 -0
  106. ksxt/upbit.py +499 -0
  107. ksxt/utils/__pycache__/safer.cpython-312.pyc +0 -0
  108. ksxt/utils/__pycache__/sorter.cpython-312.pyc +0 -0
  109. ksxt/utils/__pycache__/timer.cpython-312.pyc +0 -0
  110. ksxt/utils/safer.py +48 -0
  111. ksxt/utils/sorter.py +8 -0
  112. ksxt/utils/timer.py +47 -0
  113. {ksxt-0.0.7.dist-info → ksxt-0.0.9.dist-info}/METADATA +11 -1
  114. ksxt-0.0.9.dist-info/RECORD +119 -0
  115. {ksxt-0.0.7.dist-info → ksxt-0.0.9.dist-info}/WHEEL +1 -1
  116. ksxt/__pycache__/__init__.cpython-39.pyc +0 -0
  117. ksxt/__pycache__/koreainvest.cpython-39.pyc +0 -0
  118. ksxt/base/__pycache__/__init__.cpython-39.pyc +0 -0
  119. ksxt/base/__pycache__/exchange.cpython-39.pyc +0 -0
  120. ksxt/base/__pycache__/rest_exchange.cpython-39.pyc +0 -0
  121. ksxt/base/__pycache__/restexchange.cpython-39.pyc +0 -0
  122. ksxt/base/__pycache__/types.cpython-39.pyc +0 -0
  123. ksxt/base/api_response.py +0 -68
  124. ksxt/config/__pycache__/__init__.cpython-39.pyc +0 -0
  125. ksxt/config/tr_app.json +0 -381
  126. ksxt/config/tr_dev.json +0 -446
  127. ksxt/market/__pycache__/base.cpython-39.pyc +0 -0
  128. ksxt/market/__pycache__/db.cpython-39.pyc +0 -0
  129. ksxt/market/__pycache__/logging.cpython-39.pyc +0 -0
  130. ksxt/market/__pycache__/manager.cpython-39.pyc +0 -0
  131. ksxt/market/__pycache__/markets.cpython-39.pyc +0 -0
  132. ksxt/market/krx/__pycache__/kosdaq.cpython-39.pyc +0 -0
  133. ksxt/market/krx/__pycache__/kospi.cpython-39.pyc +0 -0
  134. ksxt/market/krx/__pycache__/stock.cpython-39.pyc +0 -0
  135. ksxt/market/us/__pycache__/amex.cpython-39.pyc +0 -0
  136. ksxt/market/us/__pycache__/nasdaq.cpython-39.pyc +0 -0
  137. ksxt/market/us/__pycache__/nyse.cpython-39.pyc +0 -0
  138. ksxt/market/us/__pycache__/stock.cpython-39.pyc +0 -0
  139. ksxt-0.0.7.dist-info/RECORD +0 -49
  140. {ksxt-0.0.7.dist-info → ksxt-0.0.9.dist-info}/LICENSE.txt +0 -0
  141. {ksxt-0.0.7.dist-info → ksxt-0.0.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,63 @@
1
+ import asyncio
2
+ import collections
3
+ from time import time
4
+
5
+
6
+ class Throttler:
7
+ def __init__(self, config, loop=None):
8
+ self.loop = loop
9
+ self.config = {
10
+ "refillRate": 1.0,
11
+ "delay": 0.001,
12
+ "cost": 1.0,
13
+ "tokens": 0,
14
+ "maxCapacity": 2000,
15
+ "capacity": 1.0,
16
+ }
17
+
18
+ self.config.update(config)
19
+ self.queue = collections.deque()
20
+ self.running = False
21
+
22
+ async def looper(self):
23
+ last_timestamp = time() * 1000
24
+ while self.running:
25
+ future, cost = self.queue[0]
26
+ cost = self.config["cost"] if cost is None else cost
27
+ if self.config["tokens"] >= 0:
28
+ self.config["tokens"] -= cost
29
+
30
+ if not future.done():
31
+ future.set_result(None)
32
+
33
+ self.queue.popleft()
34
+
35
+ # context switch
36
+ await asyncio.sleep(0)
37
+
38
+ if len(self.queue) == 0:
39
+ self.running = False
40
+ else:
41
+ await asyncio.sleep(self.config["delay"])
42
+ now = time() * 1000
43
+ elapsed = now - last_timestamp
44
+ last_timestamp = now
45
+ self.config["tokens"] = min(
46
+ self.config["tokens"] + elapsed * self.config["refillRate"], self.config["capacity"]
47
+ )
48
+
49
+ def __call__(self, cost=None):
50
+ future = asyncio.Future()
51
+ if len(self.queue) > self.config["maxCapacity"]:
52
+ raise RuntimeError(
53
+ "throttle queue is over maxCapacity ("
54
+ + str(int(self.config["maxCapacity"]))
55
+ + "), see https://github.com/ccxt/ccxt/issues/11645#issuecomment-1195695526"
56
+ )
57
+
58
+ self.queue.append((future, cost))
59
+ if not self.running:
60
+ self.running = True
61
+ asyncio.ensure_future(self.looper(), loop=self.loop)
62
+
63
+ return future
ksxt/async_/bithumb.py ADDED
@@ -0,0 +1,455 @@
1
+ import base64
2
+ import hashlib
3
+ import hmac
4
+ import json
5
+ import time
6
+ from datetime import datetime
7
+ from typing import Any, Dict, List, Literal, Optional
8
+ from urllib.parse import urlencode
9
+ import uuid
10
+
11
+ import jwt
12
+
13
+ from ksxt.api.bithumb import ImplicitAPI
14
+ from ksxt.async_.base.async_exchange import AsyncExchange
15
+ from ksxt.parser.bithumb import BithumbParser
16
+
17
+ import ksxt.models
18
+
19
+
20
+ class Bithumb(AsyncExchange, ImplicitAPI):
21
+ def __init__(self, config: Dict = None):
22
+ super().__init__(config, "bithumb.toml")
23
+ self.parser = BithumbParser()
24
+
25
+ def safe_symbol(self, base_market: str, security: str) -> str:
26
+ return f"{base_market}-{security}"
27
+
28
+ def sign(
29
+ self,
30
+ path,
31
+ security_type,
32
+ method_type,
33
+ api_type: Any = "public",
34
+ headers: Optional[Any] = None,
35
+ body: Optional[Any] = None,
36
+ params: Optional[Any] = None,
37
+ config={},
38
+ ):
39
+ host_url = self.apis[self.type]["hostname"]
40
+ destination = self.apis[self.type][security_type][path]["url"]
41
+ version = self.apis[self.type]["version"]
42
+ destination = self.implode_params(destination, params)
43
+
44
+ url = host_url + "/" + version + "/" + destination
45
+
46
+ if api_type == "private":
47
+ payload = {
48
+ "access_key": self.open_key,
49
+ "nonce": str(uuid.uuid4()),
50
+ "timestamp": round(self.milliseconds()),
51
+ }
52
+
53
+ if params is not None and len(params) > 0:
54
+ query = urlencode(params).encode()
55
+
56
+ hash = hashlib.sha512()
57
+ hash.update(query)
58
+ query_hash = hash.hexdigest()
59
+
60
+ payload.update({"query_hash": query_hash, "query_hash_alg": "SHA512"})
61
+
62
+ jwt_token = jwt.encode(payload=payload, key=self.secret_key)
63
+ authorization_token = f"Bearer {jwt_token}"
64
+
65
+ if headers is None:
66
+ headers = {}
67
+ headers.update(
68
+ {"Content-Type": "application/json; charset=utf-8", "Authorization": authorization_token}
69
+ )
70
+
71
+ if method_type.upper() == "POST":
72
+ body = json.dumps(params)
73
+ params = {}
74
+
75
+ return {"url": url, "method": method_type, "headers": headers, "body": body, "params": params}
76
+
77
+ def get_common_response(self, response):
78
+ if "error" in response:
79
+ return self.create_common_response(
80
+ success="1",
81
+ msg_code=self.safe_string(response["error"], "name"),
82
+ msg=self.safe_string(response["error"], "message"),
83
+ info=response,
84
+ )
85
+
86
+ return self.create_common_response(
87
+ success="0",
88
+ msg_code=self.safe_string(response, "name"),
89
+ msg=self.safe_string(response, "message"),
90
+ info=response,
91
+ )
92
+
93
+ async def fetch_markets(self, market_name: str = "KRW") -> ksxt.models.KsxtMarketResponse:
94
+ params = {
95
+ # 유의종목 필드과 같은 상세 정보 노출 여부(선택 파라미터)
96
+ "isDetails": "True"
97
+ }
98
+
99
+ common_header = self.create_common_header(request_params=params)
100
+
101
+ response = await self.public_get_fetch_markets(self.extend(params))
102
+
103
+ common_response = self.get_common_response(response=response)
104
+ if common_response.success != "0":
105
+ return ksxt.models.KsxtMarketResponse(header=common_header, response=common_response, info=None)
106
+
107
+ parsed_info = self.parser.parse_markets(response=response, base_market=market_name)
108
+ return ksxt.models.KsxtMarketResponse(header=common_header, response=common_response, info=parsed_info)
109
+
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"
112
+ ) -> ksxt.models.KsxtHistoricalDataResponse:
113
+ params = {"market": self.safe_symbol(base_market=base_market, security=symbol), "count": 200}
114
+
115
+ common_header = self.create_common_header(request_params=params)
116
+
117
+ # TODO : time_frame 을 어떻게 고정시킬까? 우리는 분봉, 일봉, 주봉, 월봉 만 지원한다고 가정하면?
118
+ if time_frame.endswith("m"):
119
+ # TODO : parse number
120
+ period = 1
121
+ params.update({"unit": period})
122
+
123
+ response = await self.public_get_fetch_security_ohlcv_minute(self.extend(params))
124
+
125
+ elif time_frame.endswith("D"):
126
+ response = await self.public_get_fetch_security_ohlcv_day(self.extend(params))
127
+
128
+ elif time_frame.endswith("W"):
129
+ response = await self.public_get_fetch_security_ohlcv_week(self.extend(params))
130
+
131
+ elif time_frame.endswith("M"):
132
+ response = await self.public_get_fetch_security_ohlcv_month(self.extend(params))
133
+
134
+ common_response = self.get_common_response(response=response)
135
+ if common_response.success != "0":
136
+ return ksxt.models.KsxtHistoricalDataResponse(header=common_header, response=common_response, info=None)
137
+
138
+ parsed_response = self.parser.parse_historical_data(response=response, symbol=symbol, base_market=base_market)
139
+ return ksxt.models.KsxtHistoricalDataResponse(
140
+ header=common_header, response=common_response, info=parsed_response
141
+ )
142
+
143
+ async def fetch_ticker(self, symbol: str, base_market: str = "KRW") -> ksxt.models.KsxtTickerResponse:
144
+ params = {"markets": self.safe_symbol(base_market=base_market, security=symbol)}
145
+
146
+ common_header = self.create_common_header(request_params=params)
147
+
148
+ response = await self.public_get_fetch_ticker_price(self.extend(params))
149
+
150
+ common_response = self.get_common_response(response=response)
151
+
152
+ # 실패 시 오류 응답 반환
153
+ if common_response.success != "0":
154
+ return ksxt.models.KsxtTickerResponse(header=common_header, response=common_response, info=[])
155
+
156
+ # 데이터 파싱
157
+ parsed_info = self.parser.parse_ticker(response, base_market)
158
+
159
+ return ksxt.models.KsxtTickerResponse(header=common_header, response=common_response, info=parsed_info)
160
+
161
+ async def fetch_tickers(self, symbols: List[str], base_market: str = "KRW") -> ksxt.models.KsxtTickersResponse:
162
+ symbol = ",".join([self.safe_symbol(base_market, symbol) for symbol in symbols])
163
+ params = {"markets": symbol}
164
+
165
+ common_header = self.create_common_header(request_params=params)
166
+
167
+ response = await self.public_get_fetch_tickers_price(self.extend(params))
168
+
169
+ common_response = self.get_common_response(response=response)
170
+
171
+ # 실패 시 오류 응답 반환
172
+ if common_response.success != "0":
173
+ return ksxt.models.KsxtTickersResponse(header=common_header, response=common_response, info=[])
174
+
175
+ # 데이터 파싱
176
+ parsed_info = self.parser.parse_tickers(response, base_market)
177
+
178
+ return ksxt.models.KsxtTickersResponse(header=common_header, response=common_response, info=parsed_info)
179
+
180
+ async def fetch_orderbook(self, symbol: str, base_market: str = "KRW") -> ksxt.models.KsxtSingleOrderBookResponse:
181
+ params = {"markets": self.safe_symbol(base_market, symbol)}
182
+
183
+ common_header = self.create_common_header(request_params=params)
184
+
185
+ response = await self.public_get_fetch_orderbook(self.extend(params))
186
+
187
+ common_response = self.get_common_response(response=response)
188
+
189
+ # 실패 시 오류 응답 반환
190
+ if common_response.success != "0":
191
+ return ksxt.models.KsxtSingleOrderBookResponse(header=common_header, response=common_response, info=None)
192
+
193
+ # 데이터 파싱
194
+ parsed_info = self.parser.parse_orderbook(response, base_market)
195
+
196
+ return ksxt.models.KsxtSingleOrderBookResponse(header=common_header, response=common_response, info=parsed_info)
197
+
198
+ async def fetch_orderbooks(
199
+ self, symbols: List[str], base_market: str = "KRW"
200
+ ) -> ksxt.models.KsxtMultiOrderBookResponse:
201
+ symbol = ",".join([self.safe_symbol(base_market, symbol) for symbol in symbols])
202
+ params = {
203
+ #'markets': self.safe_symbol(base_market, symbol)
204
+ "markets": symbol # 이렇게 해야 정상동작!
205
+ }
206
+
207
+ common_header = self.create_common_header(request_params=params)
208
+
209
+ response = await self.public_get_fetch_orderbooks(self.extend(params))
210
+
211
+ common_response = self.get_common_response(response=response)
212
+
213
+ # 실패 시 오류 응답 반환
214
+ if common_response.success != "0":
215
+ return ksxt.models.KsxtMultiOrderBookResponse(header=common_header, response=common_response, info=None)
216
+
217
+ # 데이터 파싱
218
+ parsed_info = self.parser.parse_orderbooks(response, base_market)
219
+
220
+ return ksxt.models.KsxtMultiOrderBookResponse(header=common_header, response=common_response, info=parsed_info)
221
+
222
+ async def fetch_balance(self, acc_num: str, base_market: str = "KRW") -> ksxt.models.KsxtBalanceResponse:
223
+ params = {}
224
+
225
+ common_header = self.create_common_header(request_params=params)
226
+
227
+ response = await self.private_get_fetch_balance(self.extend(params))
228
+
229
+ common_response = self.get_common_response(response=response)
230
+
231
+ # 실패 시 오류 응답 반환
232
+ if common_response.success != "0":
233
+ return ksxt.models.KsxtBalanceResponse(header=common_header, response=common_response, info=None)
234
+
235
+ # 데이터 파싱
236
+ parsed_info = self.parser.parse_balance(response, base_market)
237
+
238
+ return ksxt.models.KsxtBalanceResponse(header=common_header, response=common_response, info=parsed_info)
239
+
240
+ async def fetch_cash(self, acc_num: str, base_market: str = "KRW") -> ksxt.models.KsxtCashResponse:
241
+ params = {}
242
+
243
+ common_header = self.create_common_header(request_params=params)
244
+
245
+ response = await self.private_get_fetch_cash(self.extend(params))
246
+
247
+ common_response = self.get_common_response(response=response)
248
+
249
+ # 실패 시 오류 응답 반환
250
+ if common_response.success != "0":
251
+ return ksxt.models.KsxtCashResponse(header=common_header, response=common_response, info=None)
252
+
253
+ # 데이터 파싱
254
+ parsed_info = self.parser.parse_cash(response, base_market)
255
+
256
+ return ksxt.models.KsxtCashResponse(header=common_header, response=common_response, info=parsed_info)
257
+
258
+ async def fetch_security(self, symbol: str, base_market: str = "KRW") -> ksxt.models.KsxtSecurityResponse:
259
+ params = {"market": self.safe_symbol(base_market, symbol)}
260
+
261
+ common_header = self.create_common_header(request_params=params)
262
+
263
+ response = await self.public_get_fetch_security_info(self.extend(params))
264
+
265
+ common_response = self.get_common_response(response=response)
266
+
267
+ # 실패 시 오류 응답 반환
268
+ if common_response.success != "0":
269
+ return ksxt.models.KsxtSecurityResponse(header=common_header, response=common_response, info=None)
270
+
271
+ # 데이터 파싱
272
+ parsed_info = self.parser.parse_security(response, base_market)
273
+
274
+ return ksxt.models.KsxtSecurityResponse(header=common_header, response=common_response, info=parsed_info)
275
+
276
+ async def fetch_trade_fee(
277
+ self, symbol: Optional[str] = "", base_market: str = "KRW"
278
+ ) -> ksxt.models.KsxtTradeFeeResponse:
279
+ params = {"market": self.safe_symbol(base_market, symbol)}
280
+
281
+ common_header = self.create_common_header(request_params=params)
282
+
283
+ response = await self.private_get_fetch_trade_fee(self.extend(params))
284
+
285
+ common_response = self.get_common_response(response=response)
286
+ if common_response.success != "0":
287
+ return ksxt.models.KsxtTradeFeeResponse(header=common_header, response=common_response, info=None)
288
+
289
+ parsed_info = self.parser.parse_trade_fee(response, base_market)
290
+ return ksxt.models.KsxtTradeFeeResponse(header=common_header, response=common_response, info=parsed_info)
291
+
292
+ async def fetch_open_order(
293
+ self,
294
+ acc_num: str,
295
+ symbol: str | None = "",
296
+ start: str | None = None,
297
+ end: str | None = None,
298
+ base_market: str = "KRW",
299
+ ) -> ksxt.models.KsxtOpenOrderResponse:
300
+ params = {
301
+ "market": self.safe_symbol(base_market, symbol),
302
+ "uuids": "",
303
+ #'state': 'wait'
304
+ }
305
+
306
+ common_header = self.create_common_header(request_params=params)
307
+
308
+ response = await self.private_get_fetch_opened_order(self.extend(params))
309
+
310
+ common_response = self.get_common_response(response=response)
311
+
312
+ # 실패 시 오류 응답 반환
313
+ if common_response.success != "0":
314
+ return ksxt.models.KsxtOpenOrderResponse(header=common_header, response=common_response, info=None)
315
+
316
+ # 데이터 파싱
317
+ parsed_info = self.parser.parse_open_order_history(response, base_market)
318
+
319
+ return ksxt.models.KsxtOpenOrderResponse(header=common_header, response=common_response, info=parsed_info)
320
+
321
+ async def fetch_closed_order(
322
+ self,
323
+ acc_num: str,
324
+ symbol: Optional[str] = "",
325
+ start: Optional[str] = None,
326
+ end: Optional[str] = None,
327
+ base_market: str = "KRW",
328
+ ) -> ksxt.models.KsxtClosedOrderResponse:
329
+ params = {"market": self.safe_symbol(base_market, symbol), "uuids": "", "state": "done"}
330
+
331
+ common_header = self.create_common_header(request_params=params)
332
+
333
+ response = await self.private_get_fetch_closed_order(self.extend(params))
334
+
335
+ common_response = self.get_common_response(response=response)
336
+
337
+ # 실패 시 오류 응답 반환
338
+ if common_response.success != "0":
339
+ return ksxt.models.KsxtClosedOrderResponse(header=common_header, response=common_response, info=None)
340
+
341
+ # 데이터 파싱
342
+ parsed_info = self.parser.parse_closed_order_history(response, base_market)
343
+
344
+ return ksxt.models.KsxtClosedOrderResponse(header=common_header, response=common_response, info=parsed_info)
345
+
346
+ async def cancel_order(
347
+ self, acc_num: str, order_id: str, symbol: str | None = "", qty: float = 0, base_market: str = "KRW", **kwargs
348
+ ) -> ksxt.models.KsxtCancelOrderResponse:
349
+ params = {"uuid": order_id}
350
+
351
+ common_header = self.create_common_header(request_params=params)
352
+
353
+ response = await self.private_delete_send_cancel_order(self.extend(params))
354
+
355
+ common_response = self.get_common_response(response=response)
356
+
357
+ # 실패 시 오류 응답 반환
358
+ if common_response.success != "0":
359
+ return ksxt.models.KsxtCancelOrderResponse(header=common_header, response=common_response, info=None)
360
+
361
+ # 데이터 파싱
362
+ parsed_info = self.parser.parse_cancel_order(response, base_market)
363
+
364
+ return ksxt.models.KsxtCancelOrderResponse(header=common_header, response=common_response, info=parsed_info)
365
+
366
+ async def create_order(
367
+ self,
368
+ acc_num: str,
369
+ symbol: str,
370
+ ticket_type: Literal["EntryLong", "EntryShort", "ExitLong", "ExitShort"],
371
+ otype: Literal["limit", "market"],
372
+ price: Optional[float] = 0,
373
+ qty: Optional[float] = 0,
374
+ amount: Optional[float] = 0,
375
+ base_market: str = "KRW",
376
+ ) -> ksxt.models.KsxtCreateOrderResponse:
377
+ params = {
378
+ "market": self.safe_symbol(base_market, symbol),
379
+ }
380
+
381
+ if ticket_type == "EntryLong":
382
+ order_side = "bid"
383
+ if otype == "limit":
384
+ params.update({"side": order_side, "volume": qty, "price": price, "ord_type": "limit"})
385
+ response = await self.private_post_send_order_entry(self.extend(params))
386
+
387
+ elif otype == "market":
388
+ params.update({"side": order_side, "price": amount, "ord_type": "price"})
389
+ response = await self.private_post_send_order_entry_market(self.extend(params))
390
+
391
+ elif ticket_type == "ExitLong":
392
+ order_side = "ask"
393
+ if otype == "limit":
394
+ params.update({"side": order_side, "volume": qty, "price": price, "ord_type": "limit"})
395
+ response = await self.private_post_send_order_exit(self.extend(params))
396
+
397
+ elif otype == "market":
398
+ params.update({"side": order_side, "volume": qty, "ord_type": "market"})
399
+ response = await self.private_post_send_order_exit_market(self.extend(params))
400
+
401
+ common_header = self.create_common_header(request_params=params)
402
+ common_response = self.get_common_response(response=response)
403
+
404
+ # 실패 시 오류 응답 반환
405
+ if common_response.success != "0":
406
+ return ksxt.models.KsxtCreateOrderResponse(header=common_header, response=common_response, info=None)
407
+
408
+ # 데이터 파싱
409
+ parsed_info = self.parser.parse_create_order(response, base_market)
410
+
411
+ return ksxt.models.KsxtCreateOrderResponse(header=common_header, response=common_response, info=parsed_info)
412
+
413
+ async def fetch_withdrawal_history(
414
+ self, acc_num: str, base_market: str = "KRW"
415
+ ) -> ksxt.models.KsxtWithdrawalHistoryResponse:
416
+ params = {"state": "done", "uuids": "", "txids": ""}
417
+
418
+ common_header = self.create_common_header(request_params=params)
419
+
420
+ response = await self.private_get_fetch_withdrawal_history(self.extend(params))
421
+
422
+ common_response = self.get_common_response(response=response)
423
+
424
+ # 실패 시 오류 응답 반환
425
+ if common_response.success != "0":
426
+ return ksxt.models.KsxtWithdrawalHistoryResponse(header=common_header, response=common_response, info=None)
427
+
428
+ # 데이터 파싱
429
+ parsed_info = self.parser.parse_withdrawal_history(response)
430
+
431
+ return ksxt.models.KsxtWithdrawalHistoryResponse(
432
+ header=common_header, response=common_response, info=parsed_info
433
+ )
434
+
435
+ async def fetch_deposit_history(
436
+ self, acc_num: str, base_market: str = "KRW"
437
+ ) -> ksxt.models.KsxtDepositHistoryResponse:
438
+ params = {"state": "ACCEPTED", "uuids": "", "txids": ""}
439
+
440
+ common_header = self.create_common_header(request_params=params)
441
+
442
+ response = await self.private_get_fetch_deposit_history(self.extend(params))
443
+
444
+ common_response = self.get_common_response(response=response)
445
+
446
+ # 실패 시 오류 응답 반환
447
+ if common_response.success != "0":
448
+ return ksxt.models.KsxtWithdrawalHistoryResponse(header=common_header, response=common_response, info=None)
449
+
450
+ # 데이터 파싱
451
+ parsed_info = self.parser.parse_deposit_history(response)
452
+
453
+ return ksxt.models.KsxtWithdrawalHistoryResponse(
454
+ header=common_header, response=common_response, info=parsed_info
455
+ )