kaq-quant-common 0.2.7__py3-none-any.whl → 0.2.8__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.
- kaq_quant_common/api/common/__init__.py +1 -1
- kaq_quant_common/api/common/api_interface.py +38 -38
- kaq_quant_common/api/rest/api_client_base.py +42 -42
- kaq_quant_common/api/rest/instruction/helper/order_helper.py +342 -342
- kaq_quant_common/api/rest/instruction/models/__init__.py +17 -17
- kaq_quant_common/api/rest/instruction/models/transfer.py +32 -32
- kaq_quant_common/api/ws/exchange/models.py +23 -23
- kaq_quant_common/api/ws/exchange/ws_exchange_server.py +440 -440
- kaq_quant_common/common/ddb_table_monitor.py +106 -106
- kaq_quant_common/common/http_monitor.py +69 -69
- kaq_quant_common/common/modules/funding_rate_helper.py +36 -21
- kaq_quant_common/common/modules/limit_order_helper.py +60 -23
- kaq_quant_common/common/monitor_base.py +84 -84
- kaq_quant_common/common/monitor_group.py +97 -97
- kaq_quant_common/common/ws_wrapper.py +21 -21
- kaq_quant_common/resources/kaq_ddb_stream_write_resources.py +172 -96
- kaq_quant_common/utils/logger_utils.py +5 -5
- kaq_quant_common/utils/signal_utils.py +23 -23
- kaq_quant_common/utils/uuid_utils.py +5 -5
- {kaq_quant_common-0.2.7.dist-info → kaq_quant_common-0.2.8.dist-info}/METADATA +1 -1
- {kaq_quant_common-0.2.7.dist-info → kaq_quant_common-0.2.8.dist-info}/RECORD +22 -22
- {kaq_quant_common-0.2.7.dist-info → kaq_quant_common-0.2.8.dist-info}/WHEEL +1 -1
|
@@ -1,28 +1,31 @@
|
|
|
1
1
|
import os
|
|
2
2
|
import queue
|
|
3
|
+
import threading
|
|
3
4
|
import time
|
|
5
|
+
import traceback
|
|
4
6
|
from typing import Optional, Union
|
|
7
|
+
|
|
5
8
|
import dolphindb as ddb
|
|
6
|
-
from kaq_quant_common.utils import yml_utils
|
|
7
9
|
import numpy as np
|
|
8
10
|
import pandas as pd
|
|
9
|
-
import
|
|
11
|
+
from kaq_quant_common.utils import yml_utils
|
|
10
12
|
from kaq_quant_common.utils.logger_utils import get_logger
|
|
11
|
-
import traceback
|
|
12
13
|
from typing_extensions import deprecated
|
|
13
14
|
|
|
14
15
|
mutex = threading.Lock()
|
|
15
16
|
|
|
17
|
+
|
|
16
18
|
# 方式一: 异步调用
|
|
17
19
|
class KaqQuantDdbStreamWriteRepository:
|
|
18
|
-
|
|
20
|
+
"""
|
|
19
21
|
异步不等待写入
|
|
20
|
-
|
|
22
|
+
"""
|
|
23
|
+
|
|
21
24
|
def __init__(self, host, port, user, passwd):
|
|
22
25
|
self.logger = get_logger(self)
|
|
23
|
-
|
|
26
|
+
"""
|
|
24
27
|
创建ddb连接 && 添加ddb流数据表支持
|
|
25
|
-
|
|
28
|
+
"""
|
|
26
29
|
try:
|
|
27
30
|
mutex.acquire()
|
|
28
31
|
self.session = ddb.session(enableASYNC=True)
|
|
@@ -34,14 +37,14 @@ class KaqQuantDdbStreamWriteRepository:
|
|
|
34
37
|
# 需要注意的是 fetchSize 取值不能小于 8192 (记录条数)
|
|
35
38
|
self.size = 8192
|
|
36
39
|
except Exception as e:
|
|
37
|
-
self.logger.error(f
|
|
40
|
+
self.logger.error(f"KaqQuantDdbStreamWriteRepository.__init__ is occured error: {str(e)} - {str(traceback.format_exc())}")
|
|
38
41
|
finally:
|
|
39
42
|
mutex.release()
|
|
40
|
-
|
|
43
|
+
|
|
41
44
|
def save_rows(self, ddb_table_name: str, rows: Optional[Union[np.ndarray, list]] = None):
|
|
42
|
-
|
|
45
|
+
"""
|
|
43
46
|
调用此方法之前, 需要将dataframe中的字符串类型的值 ,添加引号
|
|
44
|
-
|
|
47
|
+
"""
|
|
45
48
|
if rows is None:
|
|
46
49
|
return
|
|
47
50
|
# 获取维度
|
|
@@ -51,77 +54,139 @@ class KaqQuantDdbStreamWriteRepository:
|
|
|
51
54
|
formatted_values = []
|
|
52
55
|
for row in rows:
|
|
53
56
|
# 这里的 row 是 np.array([1767708564161, "BTC", 92500.1])
|
|
54
|
-
row = [f'
|
|
55
|
-
formatted_values.append(f
|
|
57
|
+
row = [f"'{v}'" if isinstance(v, str) else str(v) for v in row]
|
|
58
|
+
formatted_values.append(f"({', '.join(row)})")
|
|
56
59
|
script = f"insert into {ddb_table_name} values {', '.join(str(x) for x in formatted_values)}"
|
|
57
|
-
|
|
60
|
+
|
|
58
61
|
self.session.run(script, clearMemory=True)
|
|
59
62
|
except Exception as e:
|
|
60
|
-
self.logger.error(
|
|
63
|
+
self.logger.error(
|
|
64
|
+
f"KaqQuantDdbStreamWriteRepository.save_rows is occured error: tableName is {ddb_table_name} - {str(e)} - {str(traceback.format_exc())}"
|
|
65
|
+
)
|
|
61
66
|
else:
|
|
62
67
|
# 是一行数据,调用 insert
|
|
63
|
-
formatted_values = [f'
|
|
68
|
+
formatted_values = [f"'{v}'" if isinstance(v, str) else str(v) for v in rows]
|
|
64
69
|
script = f"insert into {ddb_table_name} values({', '.join(str(x) for x in formatted_values)})"
|
|
65
70
|
try:
|
|
66
71
|
self.session.run(script, clearMemory=True)
|
|
67
72
|
except Exception as e:
|
|
68
|
-
self.logger.error(
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
73
|
+
self.logger.error(
|
|
74
|
+
f"KaqQuantDdbStreamWriteRepository.save_rows is occured error: tableName is {ddb_table_name} - {str(e)} - {str(traceback.format_exc())}"
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
def save2stream(self, ddb_table_name: str, df: pd.DataFrame):
|
|
78
|
+
"""
|
|
72
79
|
调用此方法之前, 需要将dataframe中的字符串类型的值 ,添加引号
|
|
73
|
-
|
|
80
|
+
"""
|
|
74
81
|
# 遍历每列的数据类型
|
|
75
82
|
for column, dtype in df.dtypes.items():
|
|
76
|
-
if dtype ==
|
|
77
|
-
df[column] = '
|
|
83
|
+
if dtype == "object" or dtype == "str":
|
|
84
|
+
df[column] = "'" + df[column] + "'"
|
|
78
85
|
for index, row in df.iterrows():
|
|
79
86
|
script = f"insert into {ddb_table_name} values({', '.join(str(x) for x in row.values)})"
|
|
80
87
|
try:
|
|
81
88
|
self.session.run(script, clearMemory=True)
|
|
82
89
|
except Exception as e:
|
|
83
|
-
self.logger.error(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
90
|
+
self.logger.error(
|
|
91
|
+
f"KaqQuantDdbStreamWriteRepository.save2stream is occured error: tableName is {ddb_table_name} - {str(e)} - {str(traceback.format_exc())}"
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
def build_insert_values_fast(self, data: pd.DataFrame | list):
|
|
95
|
+
if data.empty:
|
|
87
96
|
return []
|
|
88
|
-
dtypes =
|
|
97
|
+
dtypes = data.dtypes.tolist()
|
|
89
98
|
# 提前确定哪些列需要加引号
|
|
90
|
-
str_idx = {i for i, dt in enumerate(dtypes) if dt == object or dt ==
|
|
99
|
+
str_idx = {i for i, dt in enumerate(dtypes) if dt == object or dt == "object" or dt == "str"}
|
|
91
100
|
# 转成 ndarray,减少 pandas 参与
|
|
92
|
-
arr =
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
return
|
|
105
|
-
|
|
106
|
-
def
|
|
107
|
-
|
|
101
|
+
arr = data.to_numpy()
|
|
102
|
+
|
|
103
|
+
# 使用内部函数避免lambda闭包问题,提升性能
|
|
104
|
+
def format_value(i, v):
|
|
105
|
+
if v is None or (isinstance(v, float) and np.isnan(v)):
|
|
106
|
+
return "NULL"
|
|
107
|
+
elif i in str_idx:
|
|
108
|
+
return f"'{v}'"
|
|
109
|
+
else:
|
|
110
|
+
return str(v)
|
|
111
|
+
|
|
112
|
+
# 使用列表推导式一次性生成所有行,避免多次append
|
|
113
|
+
return ["(" + ", ".join(format_value(i, v) for i, v in enumerate(row)) + ")" for row in arr]
|
|
114
|
+
|
|
115
|
+
def build_insert_values_fast_list(self, data: list):
|
|
116
|
+
if not data:
|
|
117
|
+
return []
|
|
118
|
+
#
|
|
119
|
+
first_row = data[0]
|
|
120
|
+
str_idx = {i for i, v in enumerate(first_row) if type(v) is str}
|
|
121
|
+
|
|
122
|
+
# 优化:使用 type() 代替 isinstance() 减少函数调用开销
|
|
123
|
+
def format_value(i, v):
|
|
124
|
+
if v is None:
|
|
125
|
+
return "NULL"
|
|
126
|
+
# 如果在字符串索引中,直接格式化(避免 isinstance)
|
|
127
|
+
if i in str_idx:
|
|
128
|
+
return f"'{v}'"
|
|
129
|
+
|
|
130
|
+
# 使用 type() 比 isinstance() 更快
|
|
131
|
+
v_type = type(v)
|
|
132
|
+
if v_type is float:
|
|
133
|
+
if np.isnan(v):
|
|
134
|
+
return "NULL"
|
|
135
|
+
return str(v)
|
|
136
|
+
if v_type is str:
|
|
137
|
+
return f"'{v}'" # 第一行可能是 None 导致误判
|
|
138
|
+
return str(v)
|
|
139
|
+
|
|
140
|
+
# 使用列表推导式一次性生成所有行
|
|
141
|
+
return ["(" + ", ".join(format_value(i, v) for i, v in enumerate(row)) + ")" for row in data]
|
|
142
|
+
|
|
143
|
+
def save2stream_batch(self, ddb_table_name: str, df: pd.DataFrame):
|
|
144
|
+
"""
|
|
108
145
|
调用此方法之前, 需要将dataframe中的字符串类型的值 ,添加引号
|
|
109
|
-
|
|
146
|
+
"""
|
|
110
147
|
try:
|
|
111
|
-
start1 = time.monotonic_ns()
|
|
148
|
+
# start1 = time.monotonic_ns()
|
|
112
149
|
row = self.build_insert_values_fast(df)
|
|
113
|
-
values =
|
|
150
|
+
values = ", ".join(row)
|
|
114
151
|
script = f"insert into {ddb_table_name} values {values}"
|
|
115
|
-
start2 = time.monotonic_ns()
|
|
152
|
+
# start2 = time.monotonic_ns()
|
|
116
153
|
self.session.run(script, clearMemory=True)
|
|
117
|
-
end = time.monotonic_ns()
|
|
118
|
-
if "KAQ_QUANT_LOG" in os.environ:
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
154
|
+
# end = time.monotonic_ns()
|
|
155
|
+
# if "KAQ_QUANT_LOG" in os.environ:
|
|
156
|
+
# diff = end - start2
|
|
157
|
+
# if diff > 1_000_000_0: # 超过1毫秒
|
|
158
|
+
# self.logger.warning(
|
|
159
|
+
# f"KaqQuantDdbStreamWriteRepository.save2stream_batch cost time is only write : {end - start2} ns, save2stream_batch :{end - start1} ns, batch size is {len(df)}, tableName is {ddb_table_name}"
|
|
160
|
+
# )
|
|
122
161
|
except Exception as e:
|
|
123
|
-
self.logger.error(
|
|
124
|
-
|
|
162
|
+
self.logger.error(
|
|
163
|
+
f"KaqQuantDdbStreamWriteRepository.save2stream_batch is occured error: tableName is {ddb_table_name} - {str(e)} - {str(traceback.format_exc())}"
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
def save2stream_batch_list(self, ddb_table_name: str, data: list):
|
|
167
|
+
"""
|
|
168
|
+
调用此方法之前, 需要将数组中的字符串类型的值 ,添加引号
|
|
169
|
+
"""
|
|
170
|
+
try:
|
|
171
|
+
# start1 = time.monotonic_ns()
|
|
172
|
+
row = self.build_insert_values_fast_list(data)
|
|
173
|
+
values = ", ".join(row)
|
|
174
|
+
script = f"insert into {ddb_table_name} values {values}"
|
|
175
|
+
# start2 = time.monotonic_ns()
|
|
176
|
+
self.session.run(script, clearMemory=True)
|
|
177
|
+
# end = time.monotonic_ns()
|
|
178
|
+
# if "KAQ_QUANT_LOG" in os.environ:
|
|
179
|
+
# diff = end - start2
|
|
180
|
+
# if diff > 1_000_000_0: # 超过1毫秒
|
|
181
|
+
# self.logger.warning(
|
|
182
|
+
# f"KaqQuantDdbStreamWriteRepository.save2stream_batch_list cost time is only write : {end - start2} ns, save2stream_batch_list :{end - start1} ns, batch size is {len(data)}, tableName is {ddb_table_name}"
|
|
183
|
+
# )
|
|
184
|
+
except Exception as e:
|
|
185
|
+
self.logger.error(
|
|
186
|
+
f"KaqQuantDdbStreamWriteRepository.save2stream_batch_list is occured error: tableName is {ddb_table_name} - {str(e)} - {str(traceback.format_exc())}"
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
|
|
125
190
|
# 方式二: 同步调用,但有python端的队列等待
|
|
126
191
|
class DDBAsyncDFWriter:
|
|
127
192
|
def __init__(self, appender, batch_size=1000, flush_interval_ms=80):
|
|
@@ -129,10 +194,10 @@ class DDBAsyncDFWriter:
|
|
|
129
194
|
self.appender = appender
|
|
130
195
|
self.batch_size = batch_size
|
|
131
196
|
self.flush_interval = flush_interval_ms / 1000.0
|
|
132
|
-
|
|
197
|
+
|
|
133
198
|
self.queue = queue.Queue(maxsize=10000)
|
|
134
199
|
self.running = True
|
|
135
|
-
|
|
200
|
+
|
|
136
201
|
self.thread = threading.Thread(target=self._worker, daemon=True)
|
|
137
202
|
self.thread.start()
|
|
138
203
|
|
|
@@ -165,9 +230,7 @@ class DDBAsyncDFWriter:
|
|
|
165
230
|
|
|
166
231
|
now = time.time()
|
|
167
232
|
# 触发条件:行数够了,或时间到了,或者程序正在停止
|
|
168
|
-
if buffer and (current_rows >= self.batch_size or
|
|
169
|
-
(now - last_flush_time) >= self.flush_interval or
|
|
170
|
-
not self.running):
|
|
233
|
+
if buffer and (current_rows >= self.batch_size or (now - last_flush_time) >= self.flush_interval or not self.running):
|
|
171
234
|
self._do_flush(buffer)
|
|
172
235
|
buffer = []
|
|
173
236
|
current_rows = 0
|
|
@@ -190,67 +253,80 @@ class DDBAsyncDFWriter:
|
|
|
190
253
|
"""
|
|
191
254
|
self.logger.warning("正在停止 DDBAsyncDFWriter 并清空残留数据...")
|
|
192
255
|
self.running = False
|
|
193
|
-
self.thread.join()
|
|
256
|
+
self.thread.join() # 等待工作线程处理完最后一批 buffer
|
|
194
257
|
self.logger.info("DDBAsyncDFWriter 已安全停止。")
|
|
195
|
-
|
|
258
|
+
|
|
259
|
+
|
|
196
260
|
class KaqQuantDdbStreamWriteSyncRepository:
|
|
197
|
-
|
|
261
|
+
"""
|
|
198
262
|
使用appender直接写入的方式
|
|
199
|
-
|
|
263
|
+
"""
|
|
264
|
+
|
|
200
265
|
def __init__(self, host, port, user, passwd, tableName=None, batch_size=1000, flush_interval_ms=80):
|
|
201
266
|
if tableName is None:
|
|
202
|
-
raise ValueError(f
|
|
267
|
+
raise ValueError(f"Error tableName, please set. tableName={tableName}")
|
|
203
268
|
self.tableName = tableName
|
|
204
269
|
self.logger = get_logger(self)
|
|
205
|
-
|
|
270
|
+
"""
|
|
206
271
|
创建ddb连接 && 添加ddb流数据表支持
|
|
207
|
-
|
|
272
|
+
"""
|
|
208
273
|
try:
|
|
209
274
|
mutex.acquire()
|
|
210
275
|
self.session = ddb.session()
|
|
211
276
|
self.session.connect(host, port, user, passwd, tryReconnectNums=100, reconnect=True, keepAliveTime=1000, readTimeout=10, writeTimeout=5)
|
|
212
|
-
|
|
213
|
-
self.batch_writer = DDBAsyncDFWriter(
|
|
277
|
+
|
|
278
|
+
self.batch_writer = DDBAsyncDFWriter(
|
|
279
|
+
ddb.TableAppender(table_name=self.tableName, conn=self.session), batch_size=batch_size, flush_interval_ms=flush_interval_ms
|
|
280
|
+
)
|
|
214
281
|
# 需要注意的是 fetchSize 取值不能小于 8192 (记录条数)
|
|
215
282
|
self.size = 8192
|
|
216
283
|
except Exception as e:
|
|
217
|
-
self.logger.error(f
|
|
284
|
+
self.logger.error(f"KaqQuantDdbTableStreamWriteRepository.__init__ is occured error: {str(e)} - {str(traceback.format_exc())}")
|
|
218
285
|
finally:
|
|
219
286
|
mutex.release()
|
|
220
|
-
|
|
287
|
+
|
|
221
288
|
# @deprecated("请确保pandas数据与ddb表的数据类型一致.")
|
|
222
|
-
def insert(self, df
|
|
223
|
-
|
|
289
|
+
def insert(self, df: pd.DataFrame):
|
|
290
|
+
"""
|
|
224
291
|
dataframe中日期等类型与ddb流表中一致,例如:
|
|
225
292
|
df['create_time'] = pd.to_datetime(df['create_time'], unit='ms')
|
|
226
293
|
df['event_time'] = pd.to_datetime(df['event_time'], unit='ms')
|
|
227
|
-
|
|
294
|
+
"""
|
|
228
295
|
try:
|
|
229
296
|
self.batch_writer.add_df(df)
|
|
230
297
|
except Exception as e:
|
|
231
|
-
self.logger.error(f
|
|
298
|
+
self.logger.error(f"KaqQuantDdbTableStreamWriteRepository.insert is occured error: {str(e)} - {str(traceback.format_exc())}")
|
|
299
|
+
|
|
232
300
|
|
|
233
301
|
# 方式三: 异步调用, 但属于ddb的client内部的c++多线程解析与写入,适合一条条写入
|
|
234
|
-
class KaqQuantDdbStreamMTWWriteRepository:
|
|
235
|
-
def __init__(self, host, port, user, passwd, tableName=None, batch_size=1000, throttle=50, partitionCol=
|
|
302
|
+
class KaqQuantDdbStreamMTWWriteRepository:
|
|
303
|
+
def __init__(self, host, port, user, passwd, tableName=None, batch_size=1000, throttle=50, partitionCol="", threadCount=1):
|
|
236
304
|
self.logger = get_logger(self)
|
|
237
|
-
|
|
305
|
+
"""
|
|
238
306
|
创建ddb连接 && 添加ddb流数据表支持
|
|
239
|
-
|
|
307
|
+
"""
|
|
240
308
|
try:
|
|
241
309
|
mutex.acquire()
|
|
242
310
|
self.session = ddb.session(enableASYNC=True)
|
|
243
311
|
self.session.connect(host, port, user, passwd, tryReconnectNums=100, reconnect=True, keepAliveTime=1000, readTimeout=10, writeTimeout=5)
|
|
244
312
|
self.batch_writer = ddb.MultithreadedTableWriter(
|
|
245
|
-
host,
|
|
246
|
-
|
|
313
|
+
host,
|
|
314
|
+
port,
|
|
315
|
+
user,
|
|
316
|
+
passwd,
|
|
317
|
+
tableName=tableName,
|
|
318
|
+
dbPath="",
|
|
319
|
+
batchSize=batch_size,
|
|
320
|
+
throttle=throttle,
|
|
321
|
+
threadCount=threadCount,
|
|
322
|
+
partitionCol=partitionCol,
|
|
247
323
|
)
|
|
248
324
|
except Exception as e:
|
|
249
|
-
self.logger.error(f
|
|
325
|
+
self.logger.error(f"KaqQuantDdbStreamMTWWriteRepository.__init__ is occured error: {str(e)} - {str(traceback.format_exc())}")
|
|
250
326
|
finally:
|
|
251
327
|
mutex.release()
|
|
252
|
-
|
|
253
|
-
def save2stream_batch(self, df:pd.DataFrame=pd.DataFrame(), cols:list=[]):
|
|
328
|
+
|
|
329
|
+
def save2stream_batch(self, df: pd.DataFrame = pd.DataFrame(), cols: list = []):
|
|
254
330
|
try:
|
|
255
331
|
if cols is None or len(cols) <= 0:
|
|
256
332
|
for _, row in df.iterrows():
|
|
@@ -261,23 +337,23 @@ class KaqQuantDdbStreamMTWWriteRepository:
|
|
|
261
337
|
_args = [row[i] for i in cols]
|
|
262
338
|
self.batch_writer.insert(*_args)
|
|
263
339
|
except Exception as e:
|
|
264
|
-
self.logger.error(f
|
|
265
|
-
|
|
266
|
-
def save2stream_list(self, row:list=[]):
|
|
340
|
+
self.logger.error(f"KaqQuantDdbStreamMTWWriteRepository.insert is occured error: {str(e)} - {str(traceback.format_exc())}")
|
|
341
|
+
|
|
342
|
+
def save2stream_list(self, row: list = []):
|
|
267
343
|
try:
|
|
268
344
|
if row is None or len(row) <= 0:
|
|
269
345
|
return
|
|
270
346
|
self.batch_writer.insert(*row)
|
|
271
347
|
except Exception as e:
|
|
272
|
-
self.logger.error(f
|
|
273
|
-
|
|
348
|
+
self.logger.error(f"KaqQuantDdbStreamMTWWriteRepository.insert is occured error: {str(e)} - {str(traceback.format_exc())}")
|
|
349
|
+
|
|
274
350
|
def stop(self):
|
|
275
|
-
|
|
351
|
+
"""
|
|
276
352
|
结束调用
|
|
277
|
-
|
|
353
|
+
"""
|
|
278
354
|
self.batch_writer.waitForThreadCompletion()
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
if __name__ ==
|
|
355
|
+
|
|
356
|
+
|
|
357
|
+
if __name__ == "__main__":
|
|
282
358
|
host, port, user, passwd = yml_utils.get_ddb_info(os.getcwd())
|
|
283
|
-
kaq = KaqQuantDdbStreamWriteRepository(host, port, user, passwd)
|
|
359
|
+
kaq = KaqQuantDdbStreamWriteRepository(host, port, user, passwd)
|
|
@@ -13,7 +13,7 @@ logger.add(
|
|
|
13
13
|
# 输出到标准输出(控制台)
|
|
14
14
|
sink=sys.stdout,
|
|
15
15
|
# TODO 配置
|
|
16
|
-
level="
|
|
16
|
+
level="INFO",
|
|
17
17
|
#
|
|
18
18
|
# format="{time} {level} [{extra[module]}] {message}", # 显示绑定的module
|
|
19
19
|
format=(
|
|
@@ -36,9 +36,9 @@ def _is_dagster_env():
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
def get_logger(obj: Union[str, object] = None):
|
|
39
|
-
|
|
39
|
+
'''
|
|
40
40
|
获取logger
|
|
41
|
-
|
|
41
|
+
'''
|
|
42
42
|
|
|
43
43
|
is_dagster_env = _is_dagster_env()
|
|
44
44
|
|
|
@@ -46,9 +46,9 @@ def get_logger(obj: Union[str, object] = None):
|
|
|
46
46
|
if isinstance(obj, str):
|
|
47
47
|
# do nothing
|
|
48
48
|
name = obj
|
|
49
|
-
elif hasattr(obj,
|
|
49
|
+
elif hasattr(obj, '__class__'):
|
|
50
50
|
name = obj.__class__.__name__
|
|
51
|
-
elif hasattr(obj,
|
|
51
|
+
elif hasattr(obj, '__name__'):
|
|
52
52
|
name = obj.__name__
|
|
53
53
|
else:
|
|
54
54
|
name = ""
|
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
import signal
|
|
2
|
-
import sys
|
|
3
|
-
|
|
4
|
-
# 1. 为目标信号(例如 SIGINT,即 Ctrl+C 触发)维护一个处理函数列表
|
|
5
|
-
signal_handlers = []
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
# 2. 定义「总处理函数」:触发时依次执行列表中的所有处理逻辑
|
|
9
|
-
def total_handler(signalnum, frame):
|
|
10
|
-
# 依次调用所有注册的处理函数
|
|
11
|
-
for handler in signal_handlers:
|
|
12
|
-
handler(signalnum, frame)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
# 3. 注册「总处理函数」到目标信号(例如 SIGINT)
|
|
16
|
-
# SIGTERM:Dagster通常发送此信号进行终止
|
|
17
|
-
# SIGINT:对应Ctrl+C,用于本地测试
|
|
18
|
-
signal.signal(signal.SIGTERM, total_handler)
|
|
19
|
-
signal.signal(signal.SIGINT, total_handler)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
def register_signal_handler(handler):
|
|
23
|
-
signal_handlers.append(handler)
|
|
1
|
+
import signal
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
# 1. 为目标信号(例如 SIGINT,即 Ctrl+C 触发)维护一个处理函数列表
|
|
5
|
+
signal_handlers = []
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
# 2. 定义「总处理函数」:触发时依次执行列表中的所有处理逻辑
|
|
9
|
+
def total_handler(signalnum, frame):
|
|
10
|
+
# 依次调用所有注册的处理函数
|
|
11
|
+
for handler in signal_handlers:
|
|
12
|
+
handler(signalnum, frame)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# 3. 注册「总处理函数」到目标信号(例如 SIGINT)
|
|
16
|
+
# SIGTERM:Dagster通常发送此信号进行终止
|
|
17
|
+
# SIGINT:对应Ctrl+C,用于本地测试
|
|
18
|
+
signal.signal(signal.SIGTERM, total_handler)
|
|
19
|
+
signal.signal(signal.SIGINT, total_handler)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def register_signal_handler(handler):
|
|
23
|
+
signal_handlers.append(handler)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import uuid
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
def generate_uuid() -> str:
|
|
5
|
-
return str(uuid.uuid4())
|
|
1
|
+
import uuid
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def generate_uuid() -> str:
|
|
5
|
+
return str(uuid.uuid4())
|
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
kaq_quant_common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
2
2
|
kaq_quant_common/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
3
|
-
kaq_quant_common/api/common/__init__.py,sha256=
|
|
4
|
-
kaq_quant_common/api/common/api_interface.py,sha256=
|
|
3
|
+
kaq_quant_common/api/common/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
|
|
4
|
+
kaq_quant_common/api/common/api_interface.py,sha256=E59C2Gh51wmy9NpD9y_SnCh_J-ZbZhT7rUsaORWzXHI,962
|
|
5
5
|
kaq_quant_common/api/common/auth.py,sha256=XqirJRL4D01YfSrBY4hyugw-Op6OJveNE--AnaqhYTQ,3987
|
|
6
6
|
kaq_quant_common/api/rest/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
kaq_quant_common/api/rest/api_client_base.py,sha256
|
|
7
|
+
kaq_quant_common/api/rest/api_client_base.py,sha256=LYpqjjVGbVRVyP8qdmlgMelUtEY-jGA0JlMJy9d1r4w,1673
|
|
8
8
|
kaq_quant_common/api/rest/api_server_base.py,sha256=URrvzerHIE6XQLERYFcFH1ftLbCYTz3sENAxFD0HWY0,4653
|
|
9
|
-
kaq_quant_common/api/rest/instruction/helper/order_helper.py,sha256=
|
|
9
|
+
kaq_quant_common/api/rest/instruction/helper/order_helper.py,sha256=eZ-iEZ7HegHYkqpflwKicbdLlp12gcV2wEtBVNLMBiQ,13195
|
|
10
10
|
kaq_quant_common/api/rest/instruction/instruction_client.py,sha256=NwTEypC4eajGq8oWIgvKSbIAO-KMPH4jQ-7J2b9iN4g,4037
|
|
11
11
|
kaq_quant_common/api/rest/instruction/instruction_server_base.py,sha256=pq1wghAlgtm10aWz70-x1OAqtoRH3lBu-HsIuVRHkqY,6223
|
|
12
|
-
kaq_quant_common/api/rest/instruction/models/__init__.py,sha256=
|
|
12
|
+
kaq_quant_common/api/rest/instruction/models/__init__.py,sha256=fx5pnfcf9L5KvAqhsQBZkl9fUf9oABuroLGZqDNycpc,312
|
|
13
13
|
kaq_quant_common/api/rest/instruction/models/account.py,sha256=Lj12EvWNxEt7k9dAKSsFhTJDmLX553duMRa5NroJW30,1375
|
|
14
14
|
kaq_quant_common/api/rest/instruction/models/order.py,sha256=F941DPXlbsklpc8jHLaJ2nQZiUmjPt0zyL_bagijSzI,6847
|
|
15
15
|
kaq_quant_common/api/rest/instruction/models/position.py,sha256=OqtfWWcpGhbijJbwJqERkeFxPiIkzdBnhPx5CfXj8W0,1744
|
|
16
|
-
kaq_quant_common/api/rest/instruction/models/transfer.py,sha256=
|
|
16
|
+
kaq_quant_common/api/rest/instruction/models/transfer.py,sha256=htjk4hb9THUZP4REW5gtyPdo850jHPtHPWFLPA2ERzo,775
|
|
17
17
|
kaq_quant_common/api/ws/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
18
|
-
kaq_quant_common/api/ws/exchange/models.py,sha256=
|
|
18
|
+
kaq_quant_common/api/ws/exchange/models.py,sha256=RPD5cDRQyISguTjO5Si1V5hJza8Uyr4u2EZEHNFtLb8,664
|
|
19
19
|
kaq_quant_common/api/ws/exchange/ws_exchange_client.py,sha256=Q9ymPcehpUW-lYilBlL7HU4JXkW9jA3kHFYLxnd-pJU,996
|
|
20
|
-
kaq_quant_common/api/ws/exchange/ws_exchange_server.py,sha256=
|
|
20
|
+
kaq_quant_common/api/ws/exchange/ws_exchange_server.py,sha256=z2aJfpx-iHIs7V1PmGFwqZS8t4-I9RiicbQOrfF4d7c,19910
|
|
21
21
|
kaq_quant_common/api/ws/instruction/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
22
22
|
kaq_quant_common/api/ws/instruction/ws_instruction_client.py,sha256=j8FgMUeuZvz8siknEYoLwElVRgHSX0x29F7dxNWPrsE,3154
|
|
23
23
|
kaq_quant_common/api/ws/instruction/ws_instruction_server_base.py,sha256=zXS0gO8eKkz6sVzY4Ei1RcQhW5_Tb32OQ-g3lbQD_pc,5033
|
|
@@ -25,24 +25,24 @@ kaq_quant_common/api/ws/models.py,sha256=onvZydQBWIoSSTmabZDlLgYCa1TppuCQJb5noO3
|
|
|
25
25
|
kaq_quant_common/api/ws/ws_client_base.py,sha256=QiQnZN3DJUIpP0YDLskx_A5Axu9pdSoQm4slnAQYhUE,9463
|
|
26
26
|
kaq_quant_common/api/ws/ws_server_base.py,sha256=-JFA5fnYHXPYBZ09aZmhYuhgDHFfJbkX-ppnbLfTexY,11574
|
|
27
27
|
kaq_quant_common/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
|
-
kaq_quant_common/common/ddb_table_monitor.py,sha256=
|
|
29
|
-
kaq_quant_common/common/http_monitor.py,sha256=
|
|
30
|
-
kaq_quant_common/common/modules/funding_rate_helper.py,sha256=
|
|
31
|
-
kaq_quant_common/common/modules/limit_order_helper.py,sha256=
|
|
28
|
+
kaq_quant_common/common/ddb_table_monitor.py,sha256=7Yihz_uGGujo_QqqPl45Gp8fwUMMw1auXx5egbzyYlE,3662
|
|
29
|
+
kaq_quant_common/common/http_monitor.py,sha256=_yChiwfVv1c5g_lKgYUjWY40fX61BWVK8SL4kXwRfwk,2375
|
|
30
|
+
kaq_quant_common/common/modules/funding_rate_helper.py,sha256=jSlokGh2wYYOOTj83FrUeyrcngU-lgpjvK0FawFCxdo,4840
|
|
31
|
+
kaq_quant_common/common/modules/limit_order_helper.py,sha256=3JHLP72RxmNiKNk8lC8nRb9yIDK2nhR-xbdXFTNCyrU,6044
|
|
32
32
|
kaq_quant_common/common/modules/limit_order_symbol_monitor.py,sha256=TBK48qyeCSQvkfDMv3J_0UM7f3OuBRKRFYDcL9kG6Cs,2876
|
|
33
33
|
kaq_quant_common/common/modules/limit_order_symbol_monitor_group.py,sha256=oEqHIwxhqAzckmluHJHZHiHUNmAyaS2JyK2nXO58UhY,2394
|
|
34
|
-
kaq_quant_common/common/monitor_base.py,sha256=
|
|
35
|
-
kaq_quant_common/common/monitor_group.py,sha256=
|
|
34
|
+
kaq_quant_common/common/monitor_base.py,sha256=E4EUMsO3adNltCDNRgxkvUSbTTfKOL9S1zzN3WkZvpU,2467
|
|
35
|
+
kaq_quant_common/common/monitor_group.py,sha256=cNLD-vU6CI8_2u5oV_joxDavK64weaUD0UND1__Hfuo,2862
|
|
36
36
|
kaq_quant_common/common/redis_table_monitor.py,sha256=nckt1-Jq2hU2fBA-OWSRyoSwOCmDZg79u1VRaAI7ArA,4464
|
|
37
37
|
kaq_quant_common/common/statistics/funding_rate_history_statistics.py,sha256=DFEhotfQkv83pzkGghDXb0sSFJo4rYpS2AkVXLANIl0,8533
|
|
38
38
|
kaq_quant_common/common/statistics/kline_history_statistics.py,sha256=pQgWkP7Z0nRUm1FBb3ssy_uHFs4mnYLuTXFkz36PHWk,7839
|
|
39
|
-
kaq_quant_common/common/ws_wrapper.py,sha256=
|
|
39
|
+
kaq_quant_common/common/ws_wrapper.py,sha256=JNJ0CIjDXgCsRjOLSbCi7ysYDHw7tT_aK7V4ADqw3vA,452
|
|
40
40
|
kaq_quant_common/config/config.yaml,sha256=ST_QBLo7kwVaoNOvuN3mpeSF7LPNSWdD7EjxrBYZYBs,230
|
|
41
41
|
kaq_quant_common/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
42
42
|
kaq_quant_common/resources/kaq_ddb_pool_stream_read_resources.py,sha256=q4P96rSrEcWn9ki09UD0vw00iFq_bpgOFTrRzVG7uCA,2537
|
|
43
43
|
kaq_quant_common/resources/kaq_ddb_stream_init_resources.py,sha256=0MxxbajocTFzcRD344rfZQPKOwwuqCbyoT6dQpIox-o,3349
|
|
44
44
|
kaq_quant_common/resources/kaq_ddb_stream_read_resources.py,sha256=WShsXMoL8o-JZvrtAd7H2Cg-vrE47QbsdGgURaQwiZs,3165
|
|
45
|
-
kaq_quant_common/resources/kaq_ddb_stream_write_resources.py,sha256=
|
|
45
|
+
kaq_quant_common/resources/kaq_ddb_stream_write_resources.py,sha256=Z_-CHXh390OTMUx9Cf1I1rTWE7RLC_GwFVxopcYOKoQ,15148
|
|
46
46
|
kaq_quant_common/resources/kaq_mysql_init_resources.py,sha256=UcqWey6LgoMqvLq1SxK33nS6-rkViGYhzUPxcrucOks,827
|
|
47
47
|
kaq_quant_common/resources/kaq_mysql_resources.py,sha256=282jpXvYlEQNx-hicYTNBHDii85KYgN7BQQSMS9aPFM,13211
|
|
48
48
|
kaq_quant_common/resources/kaq_postgresql_resources.py,sha256=iG1eYkciI0xUIBdEpGqKGOLBFxvVrfbBoTuaOmhQ0v0,1762
|
|
@@ -56,12 +56,12 @@ kaq_quant_common/utils/enums_utils.py,sha256=8pswCiVH4rf0vhGduhxgxt4xkNIqkBcJkTF
|
|
|
56
56
|
kaq_quant_common/utils/error_utils.py,sha256=u9jGnfQItSSgCeFJf8_67ud_F_uV_sY5Dh5HcbILJDs,423
|
|
57
57
|
kaq_quant_common/utils/hash_utils.py,sha256=uAiRbiIpPjVLWD-6X0EZtn6_zDkiMDIcjVqEhWn54vU,1672
|
|
58
58
|
kaq_quant_common/utils/log_time_utils.py,sha256=thuCD6j6eu9YUuhBBq2DGkrDpXVh1PvuoUozR1S8q9g,832
|
|
59
|
-
kaq_quant_common/utils/logger_utils.py,sha256=
|
|
59
|
+
kaq_quant_common/utils/logger_utils.py,sha256=uj4Z0QEdm8-BnUdqvWHmg9BT-mhS35KefQhHTi1U9gY,2526
|
|
60
60
|
kaq_quant_common/utils/mytt_utils.py,sha256=gMdxJu_PV140Sxwjtnv5ppf483PPgsudPDlbNRsk_PU,14078
|
|
61
|
-
kaq_quant_common/utils/signal_utils.py,sha256=
|
|
61
|
+
kaq_quant_common/utils/signal_utils.py,sha256=zBSyEltNTKqkQCsrETd47kEBb3Q_OWUBUn2W5wonFyU,711
|
|
62
62
|
kaq_quant_common/utils/sqlite_utils.py,sha256=UDDFKfwL0N-jFifl40HdyOCENh2YQfW5so6hRaSJpv0,5722
|
|
63
|
-
kaq_quant_common/utils/uuid_utils.py,sha256=
|
|
63
|
+
kaq_quant_common/utils/uuid_utils.py,sha256=pm_pnXpd8n9CI66x3A20cOEUiriJyqHaKGCeLrgkBxU,71
|
|
64
64
|
kaq_quant_common/utils/yml_utils.py,sha256=gcKjb_-uuUajBGAl5QBPIZTg2wXm7qeeJvtHflj_zOE,4513
|
|
65
|
-
kaq_quant_common-0.2.
|
|
66
|
-
kaq_quant_common-0.2.
|
|
67
|
-
kaq_quant_common-0.2.
|
|
65
|
+
kaq_quant_common-0.2.8.dist-info/METADATA,sha256=Vpw8yaybO3loNes1UmtfsmT0saExZ9EJQjN_nhlKhTY,1970
|
|
66
|
+
kaq_quant_common-0.2.8.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
67
|
+
kaq_quant_common-0.2.8.dist-info/RECORD,,
|