ksxt 0.0.8__py3-none-any.whl → 0.0.10__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 +10 -12
  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.8.dist-info → ksxt-0.0.10.dist-info}/METADATA +11 -1
  114. ksxt-0.0.10.dist-info/RECORD +119 -0
  115. {ksxt-0.0.8.dist-info → ksxt-0.0.10.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.8.dist-info/RECORD +0 -49
  140. {ksxt-0.0.8.dist-info → ksxt-0.0.10.dist-info}/LICENSE.txt +0 -0
  141. {ksxt-0.0.8.dist-info → ksxt-0.0.10.dist-info}/top_level.txt +0 -0
ksxt/bithumb.py ADDED
@@ -0,0 +1,504 @@
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
+ import pytz
13
+
14
+ from ksxt.api.bithumb import ImplicitAPI
15
+ from ksxt.base.rest_exchange import RestExchange
16
+ from ksxt.parser.bithumb import BithumbParser
17
+
18
+ import ksxt.models
19
+
20
+
21
+ class Bithumb(RestExchange, ImplicitAPI):
22
+ def __init__(self, config: Dict = None) -> None:
23
+ super().__init__(config, "bithumb.toml")
24
+ self.parser = BithumbParser()
25
+ self.timezone = pytz.timezone("Asia/Seoul")
26
+
27
+ def safe_symbol(self, base_market: str, security: str) -> str:
28
+ return f"{base_market}-{security}"
29
+
30
+ def safe_security(self, symbol: str) -> str:
31
+ if symbol.find("-") < 0:
32
+ return symbol
33
+ return symbol.split("-")[1]
34
+
35
+ def sign(
36
+ self,
37
+ path,
38
+ security_type,
39
+ method_type,
40
+ api_type: Any = "public",
41
+ headers: Optional[Any] = None,
42
+ body: Optional[Any] = None,
43
+ params: Optional[Any] = None,
44
+ config={},
45
+ ):
46
+ host_url = self.apis[self.type]["hostname"]
47
+ destination = self.apis[self.type][security_type][path]["url"]
48
+ version = self.apis[self.type]["version"]
49
+ destination = self.implode_params(destination, params)
50
+
51
+ url = host_url + "/" + version + "/" + destination
52
+
53
+ if api_type == "private":
54
+ payload = {
55
+ "access_key": self.open_key,
56
+ "nonce": str(uuid.uuid4()),
57
+ "timestamp": round(self.milliseconds()),
58
+ }
59
+
60
+ if params is not None and len(params) > 0:
61
+ query = urlencode(params).encode()
62
+
63
+ hash = hashlib.sha512()
64
+ hash.update(query)
65
+ query_hash = hash.hexdigest()
66
+
67
+ payload.update({"query_hash": query_hash, "query_hash_alg": "SHA512"})
68
+
69
+ jwt_token = jwt.encode(payload=payload, key=self.secret_key)
70
+ authorization_token = f"Bearer {jwt_token}"
71
+
72
+ if headers is None:
73
+ headers = {}
74
+ headers.update(
75
+ {"Content-Type": "application/json; charset=utf-8", "Authorization": authorization_token}
76
+ )
77
+
78
+ if method_type.upper() == "POST":
79
+ body = json.dumps(params)
80
+ params = {}
81
+
82
+ return {"url": url, "method": method_type, "headers": headers, "body": body, "params": params}
83
+
84
+ def get_common_response(self, response):
85
+ if "error" in response:
86
+ return self.create_common_response(
87
+ success="1",
88
+ msg_code=self.safe_string(response["error"], "name"),
89
+ msg=self.safe_string(response["error"], "message"),
90
+ info=response,
91
+ )
92
+
93
+ return self.create_common_response(
94
+ success="0",
95
+ msg_code=self.safe_string(response, "name"),
96
+ msg=self.safe_string(response, "message"),
97
+ info=response,
98
+ )
99
+
100
+ def fetch_markets(self, market_name: str = "KRW") -> ksxt.models.KsxtMarketResponse:
101
+ params = {
102
+ # 유의종목 필드과 같은 상세 정보 노출 여부(선택 파라미터)
103
+ "isDetails": True
104
+ }
105
+
106
+ common_header = self.create_common_header(request_params=params)
107
+
108
+ response = self.public_get_fetch_markets(self.extend(params))
109
+
110
+ common_response = self.get_common_response(response=response)
111
+ if common_response.success != "0":
112
+ return ksxt.models.KsxtMarketResponse(header=common_header, response=common_response, info=None)
113
+
114
+ parsed_info = self.parser.parse_markets(response=response, base_market=market_name)
115
+ return ksxt.models.KsxtMarketResponse(header=common_header, response=common_response, info=parsed_info)
116
+
117
+ def fetch_historical_data(
118
+ self, symbol: str, time_frame: str, start: str | None = None, end: str | None = None, base_market: str = "KRW"
119
+ ) -> ksxt.models.KsxtHistoricalDataResponse:
120
+ params = {"market": self.safe_symbol(base_market=base_market, security=symbol), "count": 200}
121
+
122
+ common_header = self.create_common_header(request_params=params)
123
+
124
+ # TODO : time_frame 을 어떻게 고정시킬까? 우리는 분봉, 일봉, 주봉, 월봉 만 지원한다고 가정하면?
125
+ if time_frame.endswith("m"):
126
+ # TODO : parse number
127
+ period = 1
128
+ params.update({"unit": period})
129
+
130
+ response = self.public_get_fetch_security_ohlcv_minute(self.extend(params))
131
+
132
+ elif time_frame.endswith("D"):
133
+ response = self.public_get_fetch_security_ohlcv_day(self.extend(params))
134
+
135
+ elif time_frame.endswith("W"):
136
+ response = self.public_get_fetch_security_ohlcv_week(self.extend(params))
137
+
138
+ elif time_frame.endswith("M"):
139
+ response = self.public_get_fetch_security_ohlcv_month(self.extend(params))
140
+
141
+ common_response = self.get_common_response(response=response)
142
+ if common_response.success != "0":
143
+ return ksxt.models.KsxtHistoricalDataResponse(header=common_header, response=common_response, info=None)
144
+
145
+ parsed_response = self.parser.parse_historical_data(response=response, symbol=symbol, base_market=base_market)
146
+ return ksxt.models.KsxtHistoricalDataResponse(
147
+ header=common_header, response=common_response, info=parsed_response
148
+ )
149
+
150
+ def fetch_ticker(self, symbol: str, base_market: str = "KRW") -> ksxt.models.KsxtTickerResponse:
151
+ params = {"markets": self.safe_symbol(base_market=base_market, security=symbol)}
152
+
153
+ common_header = self.create_common_header(request_params=params)
154
+
155
+ response = self.public_get_fetch_ticker_price(self.extend(params))
156
+
157
+ common_response = self.get_common_response(response=response)
158
+
159
+ # 실패 시 오류 응답 반환
160
+ if common_response.success != "0":
161
+ return ksxt.models.KsxtTickerResponse(header=common_header, response=common_response, info=[])
162
+
163
+ # 데이터 파싱
164
+ parsed_info = self.parser.parse_ticker(response, base_market)
165
+
166
+ return ksxt.models.KsxtTickerResponse(header=common_header, response=common_response, info=parsed_info)
167
+
168
+ def fetch_tickers(self, symbols: List[str], base_market: str = "KRW") -> ksxt.models.KsxtTickersResponse:
169
+ symbol = ",".join([self.safe_symbol(base_market, symbol) for symbol in symbols])
170
+ params = {"markets": symbol}
171
+
172
+ common_header = self.create_common_header(request_params=params)
173
+
174
+ response = self.public_get_fetch_tickers_price(self.extend(params))
175
+
176
+ common_response = self.get_common_response(response=response)
177
+
178
+ # 실패 시 오류 응답 반환
179
+ if common_response.success != "0":
180
+ return ksxt.models.KsxtTickersResponse(header=common_header, response=common_response, info=[])
181
+
182
+ # 데이터 파싱
183
+ parsed_info = self.parser.parse_tickers(response, base_market)
184
+
185
+ return ksxt.models.KsxtTickersResponse(header=common_header, response=common_response, info=parsed_info)
186
+
187
+ def fetch_orderbook(self, symbol: str, base_market: str = "KRW") -> ksxt.models.KsxtSingleOrderBookResponse:
188
+ params = {"markets": self.safe_symbol(base_market, symbol)}
189
+
190
+ common_header = self.create_common_header(request_params=params)
191
+
192
+ response = self.public_get_fetch_orderbook(self.extend(params))
193
+
194
+ common_response = self.get_common_response(response=response)
195
+
196
+ # 실패 시 오류 응답 반환
197
+ if common_response.success != "0":
198
+ return ksxt.models.KsxtSingleOrderBookResponse(header=common_header, response=common_response, info=None)
199
+
200
+ # 데이터 파싱
201
+ parsed_info = self.parser.parse_orderbook(response, base_market)
202
+
203
+ return ksxt.models.KsxtSingleOrderBookResponse(header=common_header, response=common_response, info=parsed_info)
204
+
205
+ def fetch_orderbooks(self, symbols: List[str], base_market: str = "KRW") -> ksxt.models.KsxtMultiOrderBookResponse:
206
+ symbol = ",".join([self.safe_symbol(base_market, symbol) for symbol in symbols])
207
+ params = {"markets": symbol}
208
+
209
+ common_header = self.create_common_header(request_params=params)
210
+
211
+ response = self.public_get_fetch_orderbooks(self.extend(params))
212
+
213
+ common_response = self.get_common_response(response=response)
214
+
215
+ # 실패 시 오류 응답 반환
216
+ if common_response.success != "0":
217
+ return ksxt.models.KsxtMultiOrderBookResponse(header=common_header, response=common_response, info=None)
218
+
219
+ # 데이터 파싱
220
+ parsed_info = self.parser.parse_orderbooks(response, base_market)
221
+
222
+ return ksxt.models.KsxtMultiOrderBookResponse(header=common_header, response=common_response, info=parsed_info)
223
+
224
+ def fetch_balance(self, acc_num: str, base_market: str = "KRW") -> ksxt.models.KsxtBalanceResponse:
225
+ params = {}
226
+
227
+ common_header = self.create_common_header(request_params=params)
228
+
229
+ response = self.private_get_fetch_balance(self.extend(params))
230
+
231
+ common_response = self.get_common_response(response=response)
232
+
233
+ # 실패 시 오류 응답 반환
234
+ if common_response.success != "0":
235
+ return ksxt.models.KsxtBalanceResponse(header=common_header, response=common_response, info=None)
236
+
237
+ # 데이터 파싱
238
+ parsed_info = self.parser.parse_balance(response, base_market)
239
+
240
+ return ksxt.models.KsxtBalanceResponse(header=common_header, response=common_response, info=parsed_info)
241
+
242
+ def fetch_cash(self, acc_num: str, base_market: str = "KRW") -> ksxt.models.KsxtCashResponse:
243
+ params = {}
244
+
245
+ common_header = self.create_common_header(request_params=params)
246
+
247
+ response = self.private_get_fetch_cash(self.extend(params))
248
+
249
+ common_response = self.get_common_response(response=response)
250
+
251
+ # 실패 시 오류 응답 반환
252
+ if common_response.success != "0":
253
+ return ksxt.models.KsxtCashResponse(header=common_header, response=common_response, info=None)
254
+
255
+ # 데이터 파싱
256
+ parsed_info = self.parser.parse_cash(response, base_market)
257
+
258
+ return ksxt.models.KsxtCashResponse(header=common_header, response=common_response, info=parsed_info)
259
+
260
+ def fetch_security(self, symbol: str, base_market: str = "KRW") -> ksxt.models.KsxtSecurityResponse:
261
+ params = {"market": self.safe_symbol(base_market, symbol)}
262
+
263
+ common_header = self.create_common_header(request_params=params)
264
+
265
+ response = self.public_get_fetch_security_info(self.extend(params))
266
+
267
+ common_response = self.get_common_response(response=response)
268
+
269
+ # 실패 시 오류 응답 반환
270
+ if common_response.success != "0":
271
+ return ksxt.models.KsxtSecurityResponse(header=common_header, response=common_response, info=None)
272
+
273
+ # 데이터 파싱
274
+ parsed_info = self.parser.parse_security(response, base_market)
275
+
276
+ return ksxt.models.KsxtSecurityResponse(header=common_header, response=common_response, info=parsed_info)
277
+
278
+ def fetch_trade_fee(self, symbol: Optional[str] = "", base_market: str = "KRW") -> 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 = 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
+ def fetch_open_order_detail(
293
+ self, acc_num: str, order_ids: List[str], base_market: str = "KRW"
294
+ ) -> ksxt.models.KsxtOpenOrderResponse:
295
+ params = {
296
+ "uuids": order_ids,
297
+ #'state': 'wait' #2024.07.27 기준 default 값을 parameter로 설정해서 보내면 API 오류 발생함.
298
+ }
299
+
300
+ common_header = self.create_common_header(request_params=params)
301
+
302
+ response = self.private_get_fetch_opened_order_detail(self.extend(params))
303
+
304
+ common_response = self.get_common_response(response=response)
305
+
306
+ # 실패 시 오류 응답 반환
307
+ if common_response.success != "0":
308
+ return ksxt.models.KsxtOpenOrderResponse(header=common_header, response=common_response, info=None)
309
+
310
+ # 데이터 파싱
311
+ parsed_info = self.parser.parse_open_order_history(response, base_market)
312
+
313
+ return ksxt.models.KsxtOpenOrderResponse(header=common_header, response=common_response, info=parsed_info)
314
+
315
+ def fetch_closed_order_detail(
316
+ self, acc_num: str, order_ids: List[str], base_market: str = "KRW"
317
+ ) -> ksxt.models.KsxtOpenOrderResponse:
318
+ params = {
319
+ "uuids": order_ids,
320
+ #'state': 'wait' #2024.07.27 기준 default 값을 parameter로 설정해서 보내면 API 오류 발생함.
321
+ }
322
+
323
+ common_header = self.create_common_header(request_params=params)
324
+
325
+ response = self.private_get_fetch_closed_order_detail(self.extend(params))
326
+
327
+ common_response = self.get_common_response(response=response)
328
+
329
+ # 실패 시 오류 응답 반환
330
+ if common_response.success != "0":
331
+ return ksxt.models.KsxtOpenOrderResponse(header=common_header, response=common_response, info=None)
332
+
333
+ # 데이터 파싱
334
+ parsed_info = self.parser.parse_closed_order_history(response, base_market)
335
+
336
+ return ksxt.models.KsxtOpenOrderResponse(header=common_header, response=common_response, info=parsed_info)
337
+
338
+ def fetch_open_order(
339
+ self,
340
+ acc_num: str,
341
+ symbol: str | None = "",
342
+ start: str | None = None,
343
+ end: str | None = None,
344
+ base_market: str = "KRW",
345
+ ) -> ksxt.models.KsxtOpenOrderResponse:
346
+ params = {
347
+ "market": self.safe_symbol(base_market, symbol),
348
+ "uuids": "",
349
+ #'state': 'wait' #2024.07.27 기준 default 값을 parameter로 설정해서 보내면 API 오류 발생함.
350
+ }
351
+
352
+ common_header = self.create_common_header(request_params=params)
353
+
354
+ response = self.private_get_fetch_opened_order(self.extend(params))
355
+
356
+ common_response = self.get_common_response(response=response)
357
+
358
+ # 실패 시 오류 응답 반환
359
+ if common_response.success != "0":
360
+ return ksxt.models.KsxtOpenOrderResponse(header=common_header, response=common_response, info=None)
361
+
362
+ # 데이터 파싱
363
+ parsed_info = self.parser.parse_open_order_history(response, base_market)
364
+
365
+ return ksxt.models.KsxtOpenOrderResponse(header=common_header, response=common_response, info=parsed_info)
366
+
367
+ def fetch_closed_order(
368
+ self,
369
+ acc_num: str,
370
+ symbol: Optional[str] = "",
371
+ start: Optional[str] = None,
372
+ end: Optional[str] = None,
373
+ base_market: str = "KRW",
374
+ ) -> ksxt.models.KsxtClosedOrderResponse:
375
+ params = {"market": self.safe_symbol(base_market, symbol), "uuids": "", "state": "done"}
376
+
377
+ common_header = self.create_common_header(request_params=params)
378
+
379
+ response = self.private_get_fetch_closed_order(self.extend(params))
380
+
381
+ common_response = self.get_common_response(response=response)
382
+
383
+ # 실패 시 오류 응답 반환
384
+ if common_response.success != "0":
385
+ return ksxt.models.KsxtClosedOrderResponse(header=common_header, response=common_response, info=None)
386
+
387
+ # 데이터 파싱
388
+ parsed_info = self.parser.parse_closed_order_history(response, base_market)
389
+
390
+ return ksxt.models.KsxtClosedOrderResponse(header=common_header, response=common_response, info=parsed_info)
391
+
392
+ def cancel_order(
393
+ self, acc_num: str, order_id: str, symbol: str | None = "", qty: float = 0, base_market: str = "KRW", **kwargs
394
+ ) -> ksxt.models.KsxtCancelOrderResponse:
395
+ params = {"uuid": order_id}
396
+
397
+ common_header = self.create_common_header(request_params=params)
398
+
399
+ response = self.private_delete_send_cancel_order(self.extend(params))
400
+
401
+ common_response = self.get_common_response(response=response)
402
+
403
+ # 실패 시 오류 응답 반환
404
+ if common_response.success != "0":
405
+ return ksxt.models.KsxtCancelOrderResponse(header=common_header, response=common_response, info=None)
406
+
407
+ # 데이터 파싱
408
+ parsed_info = self.parser.parse_cancel_order(response, base_market)
409
+
410
+ return ksxt.models.KsxtCancelOrderResponse(header=common_header, response=common_response, info=parsed_info)
411
+
412
+ def create_order(
413
+ self,
414
+ acc_num: str,
415
+ symbol: str,
416
+ ticket_type: Literal["EntryLong", "EntryShort", "ExitLong", "ExitShort"],
417
+ otype: Literal["limit", "market"],
418
+ price: Optional[float] = 0,
419
+ qty: Optional[float] = 0,
420
+ amount: Optional[float] = 0,
421
+ base_market: str = "KRW",
422
+ ) -> ksxt.models.KsxtCreateOrderResponse:
423
+
424
+ params = {
425
+ "market": self.safe_symbol(base_market, symbol),
426
+ }
427
+
428
+ if ticket_type == "EntryLong":
429
+ order_side = "bid"
430
+ if otype == "limit":
431
+ params.update({"side": order_side, "volume": qty, "price": price, "ord_type": "limit"})
432
+ response = self.private_post_send_order_entry(self.extend(params))
433
+
434
+ elif otype == "market":
435
+ params.update({"side": order_side, "price": amount, "ord_type": "price"})
436
+ response = self.private_post_send_order_entry_market(self.extend(params))
437
+
438
+ elif ticket_type == "ExitLong":
439
+ order_side = "ask"
440
+ if otype == "limit":
441
+ params.update({"side": order_side, "volume": qty, "price": price, "ord_type": "limit"})
442
+ response = self.private_post_send_order_exit(self.extend(params))
443
+
444
+ elif otype == "market":
445
+ params.update({"side": order_side, "volume": qty, "ord_type": "market"})
446
+ response = self.private_post_send_order_exit_market(self.extend(params))
447
+ else:
448
+ raise ValueError(
449
+ f"Unsupported ticket_type '{ticket_type}'. {__class__.__name__} supports only 'EntryLong' and 'ExitLong'."
450
+ )
451
+
452
+ common_header = self.create_common_header(request_params=params)
453
+ common_response = self.get_common_response(response=response)
454
+
455
+ # 실패 시 오류 응답 반환
456
+ if common_response.success != "0":
457
+ return ksxt.models.KsxtCreateOrderResponse(header=common_header, response=common_response, info=None)
458
+
459
+ # 데이터 파싱
460
+ parsed_info = self.parser.parse_create_order(response, base_market)
461
+
462
+ return ksxt.models.KsxtCreateOrderResponse(header=common_header, response=common_response, info=parsed_info)
463
+
464
+ def fetch_withdrawal_history(
465
+ self, acc_num: str, base_market: str = "KRW"
466
+ ) -> ksxt.models.KsxtWithdrawalHistoryResponse:
467
+ params = {"state": "done", "uuids": "", "txids": ""}
468
+
469
+ common_header = self.create_common_header(request_params=params)
470
+
471
+ response = self.private_get_fetch_withdrawal_history(self.extend(params))
472
+
473
+ common_response = self.get_common_response(response=response)
474
+
475
+ # 실패 시 오류 응답 반환
476
+ if common_response.success != "0":
477
+ return ksxt.models.KsxtWithdrawalHistoryResponse(header=common_header, response=common_response, info=None)
478
+
479
+ # 데이터 파싱
480
+ parsed_info = self.parser.parse_withdrawal_history(response)
481
+
482
+ return ksxt.models.KsxtWithdrawalHistoryResponse(
483
+ header=common_header, response=common_response, info=parsed_info
484
+ )
485
+
486
+ def fetch_deposit_history(self, acc_num: str, base_market: str = "KRW") -> ksxt.models.KsxtDepositHistoryResponse:
487
+ params = {"state": "ACCEPTED", "uuids": "", "txids": ""}
488
+
489
+ common_header = self.create_common_header(request_params=params)
490
+
491
+ response = self.private_get_fetch_deposit_history(self.extend(params))
492
+
493
+ common_response = self.get_common_response(response=response)
494
+
495
+ # 실패 시 오류 응답 반환
496
+ if common_response.success != "0":
497
+ return ksxt.models.KsxtWithdrawalHistoryResponse(header=common_header, response=common_response, info=None)
498
+
499
+ # 데이터 파싱
500
+ parsed_info = self.parser.parse_deposit_history(response)
501
+
502
+ return ksxt.models.KsxtWithdrawalHistoryResponse(
503
+ header=common_header, response=common_response, info=parsed_info
504
+ )
ksxt/config/__init__.py CHANGED
@@ -1,2 +1,3 @@
1
1
  import os
2
- CONFIG_DIR = os.path.dirname(os.path.abspath(__file__))
2
+
3
+ CONFIG_DIR = os.path.dirname(os.path.abspath(__file__))