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.
- ksxt/__init__.py +3 -1
- ksxt/__pycache__/__init__.cpython-312.pyc +0 -0
- ksxt/__pycache__/bithumb.cpython-312.pyc +0 -0
- ksxt/__pycache__/koreainvest.cpython-312.pyc +0 -0
- ksxt/__pycache__/upbit.cpython-312.pyc +0 -0
- ksxt/api/__init__.py +26 -0
- ksxt/api/__pycache__/__init__.cpython-312.pyc +0 -0
- ksxt/api/__pycache__/bithumb.cpython-312.pyc +0 -0
- ksxt/api/__pycache__/koreainvest.cpython-312.pyc +0 -0
- ksxt/api/__pycache__/upbit.cpython-312.pyc +0 -0
- ksxt/api/auto/api_generator.py +54 -0
- ksxt/api/auto/bithumb.py +35 -0
- ksxt/api/auto/koreainvest.py +49 -0
- ksxt/api/auto/upbit.py +39 -0
- ksxt/api/bithumb.py +42 -0
- ksxt/api/koreainvest.py +40 -0
- ksxt/api/upbit.py +54 -0
- ksxt/async_/__init__.py +4 -0
- ksxt/async_/__pycache__/__init__.cpython-312.pyc +0 -0
- ksxt/async_/__pycache__/bithumb.cpython-312.pyc +0 -0
- ksxt/async_/__pycache__/koreainvest.cpython-312.pyc +0 -0
- ksxt/async_/__pycache__/upbit.cpython-312.pyc +0 -0
- ksxt/async_/base/__init__.py +0 -0
- ksxt/async_/base/__pycache__/__init__.cpython-312.pyc +0 -0
- ksxt/async_/base/__pycache__/async_exchange.cpython-312.pyc +0 -0
- ksxt/async_/base/__pycache__/throttler.cpython-312.pyc +0 -0
- ksxt/async_/base/async_exchange.py +232 -0
- ksxt/async_/base/throttler.py +63 -0
- ksxt/async_/bithumb.py +455 -0
- ksxt/async_/koreainvest.py +849 -0
- ksxt/async_/upbit.py +488 -0
- ksxt/base/__pycache__/__init__.cpython-312.pyc +0 -0
- ksxt/base/__pycache__/errors.cpython-312.pyc +0 -0
- ksxt/base/__pycache__/exchange.cpython-312.pyc +0 -0
- ksxt/base/__pycache__/rest_exchange.cpython-312.pyc +0 -0
- ksxt/base/__pycache__/types.cpython-312.pyc +0 -0
- ksxt/base/com_exchange.py +2 -2
- ksxt/base/errors.py +10 -0
- ksxt/base/exchange.py +188 -497
- ksxt/base/rest_exchange.py +297 -113
- ksxt/base/types.py +1 -36
- ksxt/bithumb.py +504 -0
- ksxt/config/__init__.py +2 -1
- ksxt/config/__pycache__/__init__.cpython-312.pyc +0 -0
- ksxt/config/bithumb.toml +380 -0
- ksxt/config/koreainvest.toml +312 -0
- ksxt/config/token.toml +7 -0
- ksxt/config/upbit.toml +428 -0
- ksxt/koreainvest.py +409 -1055
- ksxt/market/__pycache__/base.cpython-312.pyc +0 -0
- ksxt/market/__pycache__/db.cpython-312.pyc +0 -0
- ksxt/market/__pycache__/logging.cpython-312.pyc +0 -0
- ksxt/market/__pycache__/manager.cpython-312.pyc +0 -0
- ksxt/market/__pycache__/markets.cpython-312.pyc +0 -0
- ksxt/market/base.py +50 -50
- ksxt/market/db.py +5 -4
- ksxt/market/krx/__pycache__/kosdaq.cpython-312.pyc +0 -0
- ksxt/market/krx/__pycache__/kospi.cpython-312.pyc +0 -0
- ksxt/market/krx/__pycache__/stock.cpython-312.pyc +0 -0
- ksxt/market/krx/kosdaq.py +150 -147
- ksxt/market/krx/kospi.py +179 -175
- ksxt/market/krx/stock.py +136 -134
- ksxt/market/logging.py +4 -4
- ksxt/market/manager.py +10 -12
- ksxt/market/markets.py +1 -1
- ksxt/market/us/__pycache__/amex.cpython-312.pyc +0 -0
- ksxt/market/us/__pycache__/nasdaq.cpython-312.pyc +0 -0
- ksxt/market/us/__pycache__/nyse.cpython-312.pyc +0 -0
- ksxt/market/us/__pycache__/stock.cpython-312.pyc +0 -0
- ksxt/market/us/amex.py +31 -31
- ksxt/market/us/nasdaq.py +31 -31
- ksxt/market/us/nyse.py +31 -31
- ksxt/market/us/stock.py +20 -28
- ksxt/models/__init__.py +16 -0
- ksxt/models/__pycache__/__init__.cpython-312.pyc +0 -0
- ksxt/models/__pycache__/balance.cpython-312.pyc +0 -0
- ksxt/models/__pycache__/cash.cpython-312.pyc +0 -0
- ksxt/models/__pycache__/common.cpython-312.pyc +0 -0
- ksxt/models/__pycache__/error.cpython-312.pyc +0 -0
- ksxt/models/__pycache__/historical.cpython-312.pyc +0 -0
- ksxt/models/__pycache__/market.cpython-312.pyc +0 -0
- ksxt/models/__pycache__/order.cpython-312.pyc +0 -0
- ksxt/models/__pycache__/orderbook.cpython-312.pyc +0 -0
- ksxt/models/__pycache__/ticker.cpython-312.pyc +0 -0
- ksxt/models/__pycache__/token.cpython-312.pyc +0 -0
- ksxt/models/__pycache__/transaction.cpython-312.pyc +0 -0
- ksxt/models/balance.py +30 -0
- ksxt/models/cash.py +15 -0
- ksxt/models/common.py +31 -0
- ksxt/models/error.py +13 -0
- ksxt/models/historical.py +26 -0
- ksxt/models/market.py +81 -0
- ksxt/models/order.py +42 -0
- ksxt/models/orderbook.py +32 -0
- ksxt/models/ticker.py +25 -0
- ksxt/models/token.py +14 -0
- ksxt/models/transaction.py +79 -0
- ksxt/parser/__pycache__/bithumb.cpython-312.pyc +0 -0
- ksxt/parser/__pycache__/koreainvest.cpython-312.pyc +0 -0
- ksxt/parser/__pycache__/parser.cpython-312.pyc +0 -0
- ksxt/parser/__pycache__/upbit.cpython-312.pyc +0 -0
- ksxt/parser/bithumb.py +300 -0
- ksxt/parser/koreainvest.py +323 -0
- ksxt/parser/parser.py +114 -0
- ksxt/parser/upbit.py +308 -0
- ksxt/upbit.py +499 -0
- ksxt/utils/__pycache__/safer.cpython-312.pyc +0 -0
- ksxt/utils/__pycache__/sorter.cpython-312.pyc +0 -0
- ksxt/utils/__pycache__/timer.cpython-312.pyc +0 -0
- ksxt/utils/safer.py +48 -0
- ksxt/utils/sorter.py +8 -0
- ksxt/utils/timer.py +47 -0
- {ksxt-0.0.8.dist-info → ksxt-0.0.10.dist-info}/METADATA +11 -1
- ksxt-0.0.10.dist-info/RECORD +119 -0
- {ksxt-0.0.8.dist-info → ksxt-0.0.10.dist-info}/WHEEL +1 -1
- ksxt/__pycache__/__init__.cpython-39.pyc +0 -0
- ksxt/__pycache__/koreainvest.cpython-39.pyc +0 -0
- ksxt/base/__pycache__/__init__.cpython-39.pyc +0 -0
- ksxt/base/__pycache__/exchange.cpython-39.pyc +0 -0
- ksxt/base/__pycache__/rest_exchange.cpython-39.pyc +0 -0
- ksxt/base/__pycache__/restexchange.cpython-39.pyc +0 -0
- ksxt/base/__pycache__/types.cpython-39.pyc +0 -0
- ksxt/base/api_response.py +0 -68
- ksxt/config/__pycache__/__init__.cpython-39.pyc +0 -0
- ksxt/config/tr_app.json +0 -381
- ksxt/config/tr_dev.json +0 -446
- ksxt/market/__pycache__/base.cpython-39.pyc +0 -0
- ksxt/market/__pycache__/db.cpython-39.pyc +0 -0
- ksxt/market/__pycache__/logging.cpython-39.pyc +0 -0
- ksxt/market/__pycache__/manager.cpython-39.pyc +0 -0
- ksxt/market/__pycache__/markets.cpython-39.pyc +0 -0
- ksxt/market/krx/__pycache__/kosdaq.cpython-39.pyc +0 -0
- ksxt/market/krx/__pycache__/kospi.cpython-39.pyc +0 -0
- ksxt/market/krx/__pycache__/stock.cpython-39.pyc +0 -0
- ksxt/market/us/__pycache__/amex.cpython-39.pyc +0 -0
- ksxt/market/us/__pycache__/nasdaq.cpython-39.pyc +0 -0
- ksxt/market/us/__pycache__/nyse.cpython-39.pyc +0 -0
- ksxt/market/us/__pycache__/stock.cpython-39.pyc +0 -0
- ksxt-0.0.8.dist-info/RECORD +0 -49
- {ksxt-0.0.8.dist-info → ksxt-0.0.10.dist-info}/LICENSE.txt +0 -0
- {ksxt-0.0.8.dist-info → ksxt-0.0.10.dist-info}/top_level.txt +0 -0
ksxt/__init__.py
CHANGED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
ksxt/api/__init__.py
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
import types
|
2
|
+
|
3
|
+
|
4
|
+
class Entry:
|
5
|
+
def __init__(self, security_type, path, config):
|
6
|
+
# equity, derivative, oversea_equity, oversea_derivative
|
7
|
+
self.security_type = security_type
|
8
|
+
|
9
|
+
# function key
|
10
|
+
self.path = path
|
11
|
+
|
12
|
+
self.config = config
|
13
|
+
|
14
|
+
def unbound_method(_self, params={}):
|
15
|
+
return _self.request(self.path, self.security_type, params, config=self.config)
|
16
|
+
|
17
|
+
self.unbound_method = unbound_method
|
18
|
+
|
19
|
+
def __get__(self, instance, owner):
|
20
|
+
if instance is None:
|
21
|
+
return self.unbound_method
|
22
|
+
else:
|
23
|
+
return types.MethodType(self.unbound_method, instance)
|
24
|
+
|
25
|
+
def __set_name__(self, owner, name):
|
26
|
+
self.name = name
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,54 @@
|
|
1
|
+
import importlib
|
2
|
+
|
3
|
+
|
4
|
+
def generate_class_code(exchange_name: str):
|
5
|
+
try:
|
6
|
+
# Dynamically import the module based on the exchange name
|
7
|
+
module = importlib.import_module(f"{exchange_name}")
|
8
|
+
exchange_methods = module.entries[exchange_name]
|
9
|
+
except ImportError:
|
10
|
+
raise ValueError(f"Module for exchange '{exchange_name}' could not be found.")
|
11
|
+
except AttributeError:
|
12
|
+
raise ValueError(f"Entries for exchange '{exchange_name}' not found in the module.")
|
13
|
+
|
14
|
+
class_code = "class ImplicitAPI:\n"
|
15
|
+
|
16
|
+
# Calculate maximum length for method names for alignment
|
17
|
+
max_length = 0
|
18
|
+
for category, methods in exchange_methods.items():
|
19
|
+
for access, http_methods in methods.items():
|
20
|
+
if isinstance(http_methods, dict):
|
21
|
+
for method, paths in http_methods.items():
|
22
|
+
max_length = max(max_length, *(len(f"{access}_{method}_{path}") for path in paths))
|
23
|
+
elif isinstance(http_methods, list):
|
24
|
+
max_length = max(max_length, *(len(f"{access}_{path}") for path in http_methods))
|
25
|
+
|
26
|
+
for category, methods in exchange_methods.items():
|
27
|
+
class_code += f"\n # {category} API methods\n"
|
28
|
+
for access, http_methods in methods.items():
|
29
|
+
class_code += f"\n # {access} methods\n"
|
30
|
+
if isinstance(http_methods, dict):
|
31
|
+
for method, paths in http_methods.items():
|
32
|
+
class_code += f"\n # {method} requests\n"
|
33
|
+
for path in paths:
|
34
|
+
entry_name = f"{access}_{method}_{path}"
|
35
|
+
# Right-align entry names for better readability
|
36
|
+
class_code += f" {entry_name.ljust(max_length)} = Entry('{category}', '{path}', {{}})\n"
|
37
|
+
elif isinstance(http_methods, list):
|
38
|
+
for path in http_methods:
|
39
|
+
entry_name = f"{access}_{path}"
|
40
|
+
class_code += f" {entry_name.ljust(max_length)} = Entry('{category}', '{path}', {{}})\n"
|
41
|
+
|
42
|
+
return class_code
|
43
|
+
|
44
|
+
|
45
|
+
if __name__ == "__main__":
|
46
|
+
exchange_names = ["bithumb", "koreainvest", "upbit"] # List of exchanges to generate files for
|
47
|
+
|
48
|
+
for exchange_name in exchange_names:
|
49
|
+
class_code = generate_class_code(exchange_name)
|
50
|
+
filename = f"./src/ksxt/api/{exchange_name}.py"
|
51
|
+
with open(filename, "w") as file:
|
52
|
+
file.write("from ksxt.api import Entry\n")
|
53
|
+
file.write("\n")
|
54
|
+
file.write(class_code)
|
ksxt/api/auto/bithumb.py
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
entries = {
|
2
|
+
"bithumb": {
|
3
|
+
"stock": {
|
4
|
+
"public": {
|
5
|
+
"get": [
|
6
|
+
"fetch_markets",
|
7
|
+
"fetch_security_ohlcv_minute",
|
8
|
+
"fetch_security_ohlcv_day",
|
9
|
+
"fetch_security_ohlcv_week",
|
10
|
+
"fetch_security_ohlcv_month",
|
11
|
+
"fetch_ticker_price",
|
12
|
+
"fetch_tickers_price",
|
13
|
+
"fetch_orderbook",
|
14
|
+
"fetch_orderbooks",
|
15
|
+
"fetch_security_info",
|
16
|
+
]
|
17
|
+
},
|
18
|
+
"private": {
|
19
|
+
"get": [
|
20
|
+
"fetch_balance",
|
21
|
+
"fetch_cash",
|
22
|
+
"fetch_trade_fee",
|
23
|
+
"fetch_opened_order",
|
24
|
+
"fetch_opened_order_detail",
|
25
|
+
"fetch_closed_order",
|
26
|
+
"fetch_closed_order_detail",
|
27
|
+
"fetch_withdrawal_history",
|
28
|
+
"fetch_deposit_history",
|
29
|
+
],
|
30
|
+
"post": ["send_order_entry", "send_order_entry_market", "send_order_exit", "send_order_exit_market"],
|
31
|
+
"delete": ["send_cancel_order"],
|
32
|
+
},
|
33
|
+
}
|
34
|
+
}
|
35
|
+
}
|
@@ -0,0 +1,49 @@
|
|
1
|
+
entries = {
|
2
|
+
"koreainvest": {
|
3
|
+
"stock": {
|
4
|
+
"private": {
|
5
|
+
"get": [
|
6
|
+
"fetch_balance",
|
7
|
+
"fetch_cash",
|
8
|
+
"fetch_orderbook",
|
9
|
+
"fetch_security_info",
|
10
|
+
"fetch_ticker_price",
|
11
|
+
"fetch_index_ohlcv",
|
12
|
+
"fetch_security_ohlcv_day",
|
13
|
+
"fetch_security_ohlcv_minute",
|
14
|
+
"fetch_security_ohlcv_month",
|
15
|
+
"fetch_security_ohlcv_week",
|
16
|
+
"fetch_security_ohlcv_year",
|
17
|
+
"fetch_closed_order",
|
18
|
+
"fetch_opened_order",
|
19
|
+
"fetch_pnl",
|
20
|
+
"fetch_screener",
|
21
|
+
"fetch_screener_list",
|
22
|
+
],
|
23
|
+
"post": [
|
24
|
+
"send_modify_order",
|
25
|
+
"send_cancel_order",
|
26
|
+
"send_order_entry",
|
27
|
+
"send_order_exit",
|
28
|
+
"send_order_loan_entry",
|
29
|
+
"send_order_loan_exit",
|
30
|
+
],
|
31
|
+
},
|
32
|
+
"public": {
|
33
|
+
"post": [
|
34
|
+
"generate_token",
|
35
|
+
"revoke_token",
|
36
|
+
]
|
37
|
+
},
|
38
|
+
},
|
39
|
+
},
|
40
|
+
"websocket": {
|
41
|
+
"stock": {
|
42
|
+
"subscribe": {
|
43
|
+
"ticker": ["subscribe_ticker"],
|
44
|
+
"trade": ["subscribe_trade"],
|
45
|
+
"orderbook": ["subscribe_orderbook"],
|
46
|
+
}
|
47
|
+
}
|
48
|
+
},
|
49
|
+
}
|
ksxt/api/auto/upbit.py
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
entries = {
|
2
|
+
"upbit": {
|
3
|
+
"stock": {
|
4
|
+
"public": {
|
5
|
+
"get": [
|
6
|
+
"fetch_markets",
|
7
|
+
"fetch_security_ohlcv_minute",
|
8
|
+
"fetch_security_ohlcv_day",
|
9
|
+
"fetch_security_ohlcv_week",
|
10
|
+
"fetch_security_ohlcv_month",
|
11
|
+
"fetch_ticker_price",
|
12
|
+
"fetch_tickers_price",
|
13
|
+
"fetch_orderbook",
|
14
|
+
"fetch_orderbooks",
|
15
|
+
]
|
16
|
+
},
|
17
|
+
"private": {
|
18
|
+
"get": [
|
19
|
+
"fetch_balance",
|
20
|
+
"fetch_cash",
|
21
|
+
"fetch_security_info",
|
22
|
+
"fetch_trade_fee",
|
23
|
+
"fetch_closed_order_detail",
|
24
|
+
"fetch_opened_order_detail",
|
25
|
+
"fetch_opened_order",
|
26
|
+
"fetch_closed_order",
|
27
|
+
"fetch_withdrawal_history",
|
28
|
+
"fetch_deposit_history",
|
29
|
+
],
|
30
|
+
"post": ["send_order_entry", "send_order_entry_market", "send_order_exit", "send_order_exit_market"],
|
31
|
+
"delete": ["send_cancel_order"],
|
32
|
+
},
|
33
|
+
},
|
34
|
+
"websocket": {
|
35
|
+
"public": ["subscribe_ticker", "subscribe_trade", "subscribe_orderbook", "subscribe_order"],
|
36
|
+
"private": ["subscribe_ticker", "subscribe_trade"],
|
37
|
+
},
|
38
|
+
}
|
39
|
+
}
|
ksxt/api/bithumb.py
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
from ksxt.api import Entry
|
2
|
+
|
3
|
+
|
4
|
+
class ImplicitAPI:
|
5
|
+
|
6
|
+
# stock API methods
|
7
|
+
|
8
|
+
# public methods
|
9
|
+
|
10
|
+
# get requests
|
11
|
+
public_get_fetch_markets = Entry("stock", "fetch_markets", {})
|
12
|
+
public_get_fetch_security_ohlcv_minute = Entry("stock", "fetch_security_ohlcv_minute", {})
|
13
|
+
public_get_fetch_security_ohlcv_day = Entry("stock", "fetch_security_ohlcv_day", {})
|
14
|
+
public_get_fetch_security_ohlcv_week = Entry("stock", "fetch_security_ohlcv_week", {})
|
15
|
+
public_get_fetch_security_ohlcv_month = Entry("stock", "fetch_security_ohlcv_month", {})
|
16
|
+
public_get_fetch_ticker_price = Entry("stock", "fetch_ticker_price", {})
|
17
|
+
public_get_fetch_tickers_price = Entry("stock", "fetch_tickers_price", {})
|
18
|
+
public_get_fetch_orderbook = Entry("stock", "fetch_orderbook", {})
|
19
|
+
public_get_fetch_orderbooks = Entry("stock", "fetch_orderbooks", {})
|
20
|
+
public_get_fetch_security_info = Entry("stock", "fetch_security_info", {})
|
21
|
+
|
22
|
+
# private methods
|
23
|
+
|
24
|
+
# get requests
|
25
|
+
private_get_fetch_balance = Entry("stock", "fetch_balance", {})
|
26
|
+
private_get_fetch_cash = Entry("stock", "fetch_cash", {})
|
27
|
+
private_get_fetch_trade_fee = Entry("stock", "fetch_trade_fee", {})
|
28
|
+
private_get_fetch_opened_order = Entry("stock", "fetch_opened_order", {})
|
29
|
+
private_get_fetch_opened_order_detail = Entry("stock", "fetch_opened_order_detail", {})
|
30
|
+
private_get_fetch_closed_order = Entry("stock", "fetch_closed_order", {})
|
31
|
+
private_get_fetch_closed_order_detail = Entry("stock", "fetch_closed_order_detail", {})
|
32
|
+
private_get_fetch_withdrawal_history = Entry("stock", "fetch_withdrawal_history", {})
|
33
|
+
private_get_fetch_deposit_history = Entry("stock", "fetch_deposit_history", {})
|
34
|
+
|
35
|
+
# post requests
|
36
|
+
private_post_send_order_entry = Entry("stock", "send_order_entry", {})
|
37
|
+
private_post_send_order_entry_market = Entry("stock", "send_order_entry_market", {})
|
38
|
+
private_post_send_order_exit = Entry("stock", "send_order_exit", {})
|
39
|
+
private_post_send_order_exit_market = Entry("stock", "send_order_exit_market", {})
|
40
|
+
|
41
|
+
# delete requests
|
42
|
+
private_delete_send_cancel_order = Entry("stock", "send_cancel_order", {})
|
ksxt/api/koreainvest.py
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
from ksxt.api import Entry
|
2
|
+
|
3
|
+
|
4
|
+
class ImplicitAPI:
|
5
|
+
|
6
|
+
# stock API methods
|
7
|
+
|
8
|
+
# private methods
|
9
|
+
|
10
|
+
# get requests
|
11
|
+
private_get_fetch_balance = Entry("stock", "fetch_balance", {})
|
12
|
+
private_get_fetch_cash = Entry("stock", "fetch_cash", {})
|
13
|
+
private_get_fetch_orderbook = Entry("stock", "fetch_orderbook", {})
|
14
|
+
private_get_fetch_security_info = Entry("stock", "fetch_security_info", {})
|
15
|
+
private_get_fetch_ticker_price = Entry("stock", "fetch_ticker_price", {})
|
16
|
+
private_get_fetch_index_ohlcv = Entry("stock", "fetch_index_ohlcv", {})
|
17
|
+
private_get_fetch_security_ohlcv_day = Entry("stock", "fetch_security_ohlcv_day", {})
|
18
|
+
private_get_fetch_security_ohlcv_minute = Entry("stock", "fetch_security_ohlcv_minute", {})
|
19
|
+
private_get_fetch_security_ohlcv_month = Entry("stock", "fetch_security_ohlcv_month", {})
|
20
|
+
private_get_fetch_security_ohlcv_week = Entry("stock", "fetch_security_ohlcv_week", {})
|
21
|
+
private_get_fetch_security_ohlcv_year = Entry("stock", "fetch_security_ohlcv_year", {})
|
22
|
+
# private_get_fetch_closed_order = Entry('stock', 'fetch_closed_order', {})
|
23
|
+
# private_get_fetch_opened_order = Entry('stock', 'fetch_opened_order', {})
|
24
|
+
# private_get_fetch_pnl = Entry('stock', 'fetch_pnl', {})
|
25
|
+
# private_get_fetch_screener = Entry('stock', 'fetch_screener', {})
|
26
|
+
# private_get_fetch_screener_list = Entry('stock', 'fetch_screener_list', {})
|
27
|
+
|
28
|
+
# post requests
|
29
|
+
private_post_send_modify_order = Entry("stock", "send_modify_order", {})
|
30
|
+
private_post_send_cancel_order = Entry("stock", "send_cancel_order", {})
|
31
|
+
private_post_send_order_entry = Entry("stock", "send_order_entry", {})
|
32
|
+
private_post_send_order_exit = Entry("stock", "send_order_exit", {})
|
33
|
+
private_post_send_order_loan_entry = Entry("stock", "send_order_loan_entry", {})
|
34
|
+
private_post_send_order_loan_exit = Entry("stock", "send_order_loan_exit", {})
|
35
|
+
|
36
|
+
# public methods
|
37
|
+
|
38
|
+
# post requests
|
39
|
+
public_post_generate_token = Entry("token", "generate_token", {})
|
40
|
+
public_post_revoke_token = Entry("token", "revoke_token", {})
|
ksxt/api/upbit.py
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
from ksxt.api import Entry
|
2
|
+
|
3
|
+
|
4
|
+
class ImplicitAPI:
|
5
|
+
|
6
|
+
# stock API methods
|
7
|
+
|
8
|
+
# public methods
|
9
|
+
|
10
|
+
# get requests
|
11
|
+
public_get_fetch_markets = Entry("stock", "fetch_markets", {})
|
12
|
+
public_get_fetch_security_ohlcv_minute = Entry("stock", "fetch_security_ohlcv_minute", {})
|
13
|
+
public_get_fetch_security_ohlcv_day = Entry("stock", "fetch_security_ohlcv_day", {})
|
14
|
+
public_get_fetch_security_ohlcv_week = Entry("stock", "fetch_security_ohlcv_week", {})
|
15
|
+
public_get_fetch_security_ohlcv_month = Entry("stock", "fetch_security_ohlcv_month", {})
|
16
|
+
public_get_fetch_ticker_price = Entry("stock", "fetch_ticker_price", {})
|
17
|
+
public_get_fetch_tickers_price = Entry("stock", "fetch_tickers_price", {})
|
18
|
+
public_get_fetch_orderbook = Entry("stock", "fetch_orderbook", {})
|
19
|
+
public_get_fetch_orderbooks = Entry("stock", "fetch_orderbooks", {})
|
20
|
+
|
21
|
+
# private methods
|
22
|
+
|
23
|
+
# get requests
|
24
|
+
private_get_fetch_balance = Entry("stock", "fetch_balance", {})
|
25
|
+
private_get_fetch_cash = Entry("stock", "fetch_cash", {})
|
26
|
+
private_get_fetch_security_info = Entry("stock", "fetch_security_info", {})
|
27
|
+
private_get_fetch_trade_fee = Entry("stock", "fetch_trade_fee", {})
|
28
|
+
private_get_fetch_closed_order_detail = Entry("stock", "fetch_closed_order_detail", {})
|
29
|
+
private_get_fetch_opened_order_detail = Entry("stock", "fetch_opened_order_detail", {})
|
30
|
+
private_get_fetch_opened_order = Entry("stock", "fetch_opened_order", {})
|
31
|
+
private_get_fetch_closed_order = Entry("stock", "fetch_closed_order", {})
|
32
|
+
private_get_fetch_withdrawal_history = Entry("stock", "fetch_withdrawal_history", {})
|
33
|
+
private_get_fetch_deposit_history = Entry("stock", "fetch_deposit_history", {})
|
34
|
+
|
35
|
+
# post requests
|
36
|
+
private_post_send_order_entry = Entry("stock", "send_order_entry", {})
|
37
|
+
private_post_send_order_entry_market = Entry("stock", "send_order_entry_market", {})
|
38
|
+
private_post_send_order_exit = Entry("stock", "send_order_exit", {})
|
39
|
+
private_post_send_order_exit_market = Entry("stock", "send_order_exit_market", {})
|
40
|
+
|
41
|
+
# delete requests
|
42
|
+
private_delete_send_cancel_order = Entry("stock", "send_cancel_order", {})
|
43
|
+
|
44
|
+
# websocket API methods
|
45
|
+
|
46
|
+
# public methods
|
47
|
+
public_subscribe_ticker = Entry("websocket", "subscribe_ticker", {})
|
48
|
+
public_subscribe_trade = Entry("websocket", "subscribe_trade", {})
|
49
|
+
public_subscribe_orderbook = Entry("websocket", "subscribe_orderbook", {})
|
50
|
+
public_subscribe_order = Entry("websocket", "subscribe_order", {})
|
51
|
+
|
52
|
+
# private methods
|
53
|
+
private_subscribe_ticker = Entry("websocket", "subscribe_ticker", {})
|
54
|
+
private_subscribe_trade = Entry("websocket", "subscribe_trade", {})
|
ksxt/async_/__init__.py
ADDED
Binary file
|
Binary file
|
Binary file
|
Binary file
|
File without changes
|
Binary file
|
Binary file
|
Binary file
|
@@ -0,0 +1,232 @@
|
|
1
|
+
import asyncio
|
2
|
+
import aiohttp
|
3
|
+
import json
|
4
|
+
import os
|
5
|
+
import platform
|
6
|
+
import tomllib
|
7
|
+
from datetime import datetime
|
8
|
+
from pathlib import Path
|
9
|
+
from typing import Any, Dict, Literal, Optional
|
10
|
+
|
11
|
+
import yarl
|
12
|
+
|
13
|
+
from ksxt.async_.base.throttler import Throttler
|
14
|
+
from ksxt.base.errors import NotSupportedError
|
15
|
+
from ksxt.base.rest_exchange import RestExchange
|
16
|
+
from ksxt.config import CONFIG_DIR
|
17
|
+
import ksxt.models
|
18
|
+
|
19
|
+
|
20
|
+
class AsyncExchange(RestExchange):
|
21
|
+
synchronous = False
|
22
|
+
|
23
|
+
def __init__(self, config: Dict = None, filename: str = None):
|
24
|
+
super().__init__(config, filename)
|
25
|
+
|
26
|
+
self.asyncio_loop = asyncio.get_event_loop()
|
27
|
+
self.session = aiohttp.ClientSession()
|
28
|
+
self.throttle = Throttler({}, self.asyncio_loop)
|
29
|
+
|
30
|
+
async def initialize(self):
|
31
|
+
if self.asyncio_loop is None:
|
32
|
+
self.asyncio_loop = asyncio.get_event_loop()
|
33
|
+
if self.session is None:
|
34
|
+
self.session = aiohttp.ClientSession()
|
35
|
+
if self.throttle is None:
|
36
|
+
self.throttle = Throttler({}, self.asyncio_loop)
|
37
|
+
|
38
|
+
async def close(self):
|
39
|
+
if self.session:
|
40
|
+
await self.session.close()
|
41
|
+
self.session = None
|
42
|
+
|
43
|
+
async def __aenter__(self):
|
44
|
+
await self.initialize()
|
45
|
+
return self
|
46
|
+
|
47
|
+
async def __aexit__(self, *args):
|
48
|
+
await self.close()
|
49
|
+
|
50
|
+
def _get_api_from_file(self, filename: str):
|
51
|
+
if filename is None:
|
52
|
+
tr_config_filename = "tr_dev.json" if self.is_dev else "tr_app.json"
|
53
|
+
else:
|
54
|
+
tr_config_filename = filename
|
55
|
+
|
56
|
+
config_path = os.path.join(CONFIG_DIR, tr_config_filename)
|
57
|
+
|
58
|
+
if Path(tr_config_filename).suffix == ".json":
|
59
|
+
with open(
|
60
|
+
config_path,
|
61
|
+
encoding="utf-8",
|
62
|
+
) as f:
|
63
|
+
c = json.load(f)
|
64
|
+
return {"apis": c[self.name]}
|
65
|
+
|
66
|
+
elif Path(tr_config_filename).suffix == ".toml":
|
67
|
+
with open(config_path, mode="rb") as f:
|
68
|
+
c = tomllib.load(f)
|
69
|
+
return c
|
70
|
+
|
71
|
+
async def fetch(self, url, method="GET", headers=None, body=None, params=None):
|
72
|
+
request_headers = headers
|
73
|
+
request_body = str(body).encode() if body else None
|
74
|
+
request_params = params
|
75
|
+
|
76
|
+
session_method = getattr(self.session, method.lower())
|
77
|
+
|
78
|
+
try:
|
79
|
+
async with session_method(
|
80
|
+
url,
|
81
|
+
# yarl.URL(url, encoded=True),
|
82
|
+
headers=request_headers,
|
83
|
+
data=request_body,
|
84
|
+
params=request_params,
|
85
|
+
timeout=aiohttp.ClientTimeout(total=int(self.timeout / 1000)),
|
86
|
+
) as response:
|
87
|
+
http_response = await response.text(errors="replace")
|
88
|
+
json_response = self.parse_json(http_response)
|
89
|
+
return json_response
|
90
|
+
except asyncio.TimeoutError as e:
|
91
|
+
details = f"{self.id} {method} {url}"
|
92
|
+
raise TimeoutError(details) from e
|
93
|
+
|
94
|
+
async def fetch2(
|
95
|
+
self, path, security_type, params={}, headers: Optional[Any] = None, body: Optional[Any] = None, config={}
|
96
|
+
):
|
97
|
+
is_activate = self.apis[self.type][security_type][path]["activate"]
|
98
|
+
if not is_activate:
|
99
|
+
return {
|
100
|
+
"response": {
|
101
|
+
# 성공 실패 여부
|
102
|
+
"success": "-1",
|
103
|
+
# 응답코드
|
104
|
+
"code": "fail",
|
105
|
+
# 응답메세지
|
106
|
+
"message": f"지원하지 않는 함수({path}) 입니다.",
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
# if self.enableRateLimit:
|
111
|
+
# cost = self.calculate_rate_limiter_cost(api, method, path, params, config)
|
112
|
+
# self.throttle(cost)
|
113
|
+
|
114
|
+
# self.lastRestRequestTimestamp = self.milliseconds()
|
115
|
+
|
116
|
+
method_type = self.apis[self.type][security_type][path]["method"]
|
117
|
+
api_type = self.apis[self.type][security_type][path]["api"]
|
118
|
+
request = self.sign(path, security_type, method_type, api_type, headers, body, params, config)
|
119
|
+
return await self.fetch(
|
120
|
+
request["url"], request["method"], request["headers"], request["body"], request["params"]
|
121
|
+
)
|
122
|
+
|
123
|
+
# region base method
|
124
|
+
async def fetch_markets(self, market_name: str) -> ksxt.models.KsxtMarketResponse:
|
125
|
+
raise NotSupportedError(f"{self.id} {self.fetch_markets.__qualname__}() is not supported yet.")
|
126
|
+
|
127
|
+
async def fetch_security(self, symbol: str, base_market: str = "KRW") -> ksxt.models.KsxtSecurityResponse:
|
128
|
+
raise NotSupportedError(f"{self.id} {self.fetch_security.__qualname__}() is not supported yet.")
|
129
|
+
|
130
|
+
async def fetch_ticker(self, symbol: str, base_market: str = "KRW") -> ksxt.models.KsxtTickerResponse:
|
131
|
+
raise NotSupportedError(f"{self.id} {self.fetch_ticker.__qualname__}() is not supported yet.")
|
132
|
+
|
133
|
+
async def fetch_orderbook(self, symbol: str, base_market: str = "KRW") -> ksxt.models.KsxtSingleOrderBookResponse:
|
134
|
+
raise NotSupportedError(f"{self.id} {self.fetch_orderbook.__qualname__}() is not supported yet.")
|
135
|
+
|
136
|
+
async def fetch_historical_data(
|
137
|
+
self,
|
138
|
+
symbol: str,
|
139
|
+
time_frame: str,
|
140
|
+
start: Optional[str] = None,
|
141
|
+
end: Optional[str] = None,
|
142
|
+
base_market: str = "KRW",
|
143
|
+
) -> ksxt.models.KsxtHistoricalDataResponse:
|
144
|
+
raise NotSupportedError(f"{self.id} {self.fetch_historical_data.__qualname__}() is not supported yet.")
|
145
|
+
|
146
|
+
async def fetch_is_holiday(self, dt: datetime, base_market: str = "KRW"):
|
147
|
+
raise NotSupportedError(f"{self.id} {self.fetch_is_holiday.__qualname__}() is not supported yet.")
|
148
|
+
|
149
|
+
async def fetch_user_info(self, base_market: str = "KRW"):
|
150
|
+
raise NotSupportedError(f"{self.id} {self.fetch_user_info.__qualname__}() is not supported yet.")
|
151
|
+
|
152
|
+
async def fetch_balance(self, acc_num: str, base_market: str = "KRW") -> ksxt.models.KsxtBalanceResponse:
|
153
|
+
raise NotSupportedError(f"{self.id} {self.fetch_balance.__qualname__}() is not supported yet.")
|
154
|
+
|
155
|
+
async def fetch_cash(self, acc_num: str, base_market: str = "KRW") -> ksxt.models.KsxtCashResponse:
|
156
|
+
raise NotSupportedError(f"{self.id} {self.fetch_cash.__qualname__}() is not supported yet.")
|
157
|
+
|
158
|
+
async def fetch_screener_list(self, base_market: str = "KRW"):
|
159
|
+
raise NotSupportedError(f"{self.id} {self.fetch_screener_list.__qualname__}() is not supported yet.")
|
160
|
+
|
161
|
+
async def fetch_screener(self, screen_id: str, base_market: str = "KRW"):
|
162
|
+
raise NotSupportedError(f"{self.id} {self.fetch_screener.__qualname__}() is not supported yet.")
|
163
|
+
|
164
|
+
async def fetch_deposit_history(
|
165
|
+
self, acc_num: str, base_market: str = "KRW"
|
166
|
+
) -> ksxt.models.KsxtDepositHistoryResponse:
|
167
|
+
raise NotSupportedError(f"{self.id} {self.fetch_deposit_history.__qualname__}() is not supported yet.")
|
168
|
+
|
169
|
+
async def fetch_withdrawal_history(
|
170
|
+
self, acc_num: str, base_market: str = "KRW"
|
171
|
+
) -> ksxt.models.KsxtWithdrawalHistoryResponse:
|
172
|
+
raise NotSupportedError(f"{self.id} {self.fetch_withdrawal_history.__qualname__}() is not supported yet.")
|
173
|
+
|
174
|
+
async def create_order(
|
175
|
+
self,
|
176
|
+
acc_num: str,
|
177
|
+
symbol: str,
|
178
|
+
ticket_type: Literal["EntryLong", "EntryShort", "ExitLong", "ExitShort"],
|
179
|
+
otype: Literal["limit", "market"],
|
180
|
+
price: Optional[float] = 0,
|
181
|
+
qty: Optional[float] = 0,
|
182
|
+
amount: Optional[float] = 0,
|
183
|
+
base_market: str = "KRW",
|
184
|
+
) -> ksxt.models.KsxtCreateOrderResponse:
|
185
|
+
raise NotSupportedError(f"{self.id} {self.create_order.__qualname__}() is not supported yet.")
|
186
|
+
|
187
|
+
async def cancel_order(
|
188
|
+
self, acc_num: str, order_id: str, symbol: Optional[str] = "", qty: float = 0, *args, base_market: str = "KRW"
|
189
|
+
) -> ksxt.models.KsxtCancelOrderResponse:
|
190
|
+
raise NotSupportedError(f"{self.id} {self.cancel_order.__qualname__}() is not supported yet.")
|
191
|
+
|
192
|
+
async def modify_order(
|
193
|
+
self,
|
194
|
+
acc_num: str,
|
195
|
+
order_id: str,
|
196
|
+
price: float,
|
197
|
+
qty: float,
|
198
|
+
*args,
|
199
|
+
symbol: Optional[str] = "",
|
200
|
+
base_market: str = "KRW",
|
201
|
+
):
|
202
|
+
raise NotSupportedError(f"{self.id} {self.modify_order.__qualname__}() is not supported yet.")
|
203
|
+
|
204
|
+
async def fetch_open_order(
|
205
|
+
self,
|
206
|
+
acc_num: str,
|
207
|
+
symbol: Optional[str] = "",
|
208
|
+
start: Optional[str] = None,
|
209
|
+
end: Optional[str] = None,
|
210
|
+
base_market: str = "KRW",
|
211
|
+
) -> ksxt.models.KsxtOpenOrderResponse:
|
212
|
+
raise NotSupportedError(f"{self.id} {self.fetch_open_order.__qualname__}() is not supported yet.")
|
213
|
+
|
214
|
+
async def fetch_closed_order(
|
215
|
+
self,
|
216
|
+
acc_num: str,
|
217
|
+
symbol: Optional[str] = "",
|
218
|
+
start: Optional[str] = None,
|
219
|
+
end: Optional[str] = None,
|
220
|
+
base_market: str = "KRW",
|
221
|
+
) -> ksxt.models.KsxtClosedOrderResponse:
|
222
|
+
raise NotSupportedError(f"{self.id} {self.fetch_closed_order.__qualname__}() is not supported yet.")
|
223
|
+
|
224
|
+
async def reserve_order(
|
225
|
+
self, acc_num: str, symbol: str, price: float, qty: float, target_date: str, base_market: str = "KRW"
|
226
|
+
):
|
227
|
+
raise NotSupportedError(f"{self.id} {self.reserve_order.__qualname__}() is not supported yet.")
|
228
|
+
|
229
|
+
# endregion base method
|
230
|
+
|
231
|
+
async def sleep(self, milliseconds):
|
232
|
+
return await asyncio.sleep(milliseconds / 1000)
|