kaq-quant-common 0.2.3__py3-none-any.whl → 0.2.4__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/common/modules/funding_rate_helper.py +103 -0
- kaq_quant_common/common/modules/limit_order_helper.py +41 -19
- {kaq_quant_common-0.2.3.dist-info → kaq_quant_common-0.2.4.dist-info}/METADATA +1 -1
- {kaq_quant_common-0.2.3.dist-info → kaq_quant_common-0.2.4.dist-info}/RECORD +5 -4
- {kaq_quant_common-0.2.3.dist-info → kaq_quant_common-0.2.4.dist-info}/WHEEL +0 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
# 避免写入导致阻塞
|
|
2
|
+
import datetime
|
|
3
|
+
import threading
|
|
4
|
+
import time
|
|
5
|
+
|
|
6
|
+
import pandas as pd
|
|
7
|
+
|
|
8
|
+
from kaq_quant_common.resources.kaq_ddb_stream_write_resources import (
|
|
9
|
+
KaqQuantDdbStreamMTWWriteRepository, KaqQuantDdbStreamWriteRepository)
|
|
10
|
+
from kaq_quant_common.utils import logger_utils
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class FundingRateHelper:
|
|
14
|
+
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
ddb: KaqQuantDdbStreamWriteRepository | KaqQuantDdbStreamMTWWriteRepository,
|
|
18
|
+
ddb_table_name: str,
|
|
19
|
+
):
|
|
20
|
+
# 最新快照缓存与刷库线程控制
|
|
21
|
+
self._latest_snapshots: dict[str, tuple] = {}
|
|
22
|
+
self._latest_lock = threading.Lock()
|
|
23
|
+
# 写入到ddb的频率,默认1s
|
|
24
|
+
self._flush_interval_ms = 1000
|
|
25
|
+
self._stop_event = threading.Event()
|
|
26
|
+
self._flusher_thread = threading.Thread(target=self._flush_loop, daemon=True)
|
|
27
|
+
self._flusher_thread.name = "FundingRateHelperFlusherThread"
|
|
28
|
+
self._is_df = False
|
|
29
|
+
|
|
30
|
+
#
|
|
31
|
+
self._ddb = ddb
|
|
32
|
+
self._ddb_table_name = ddb_table_name
|
|
33
|
+
|
|
34
|
+
#
|
|
35
|
+
self._logger = logger_utils.get_logger(self)
|
|
36
|
+
|
|
37
|
+
self._build_data: callable = None
|
|
38
|
+
|
|
39
|
+
def set_build_data(self, build_data: callable):
|
|
40
|
+
self._build_data = build_data
|
|
41
|
+
|
|
42
|
+
def push_data(self, symbol: str, data: dict, arg: dict = None):
|
|
43
|
+
with self._latest_lock:
|
|
44
|
+
self._latest_snapshots[symbol] = (data, arg)
|
|
45
|
+
|
|
46
|
+
def start(self):
|
|
47
|
+
self._flusher_thread.start()
|
|
48
|
+
|
|
49
|
+
def stop(self):
|
|
50
|
+
self._stop_event.set()
|
|
51
|
+
self._flusher_thread.join()
|
|
52
|
+
|
|
53
|
+
def _flush_loop(self):
|
|
54
|
+
# 周期性地将每个symbol的最新快照批量入库
|
|
55
|
+
while not self._stop_event.is_set():
|
|
56
|
+
to_process = None
|
|
57
|
+
with self._latest_lock:
|
|
58
|
+
if self._latest_snapshots:
|
|
59
|
+
to_process = list(self._latest_snapshots.items())
|
|
60
|
+
self._latest_snapshots.clear()
|
|
61
|
+
|
|
62
|
+
if to_process:
|
|
63
|
+
df: pd.DataFrame = None
|
|
64
|
+
list_data: list = []
|
|
65
|
+
now = int(datetime.datetime.now().timestamp() * 1000)
|
|
66
|
+
|
|
67
|
+
for symbol, (data, arg) in to_process:
|
|
68
|
+
sub_df = self._build_data(symbol, data, arg)
|
|
69
|
+
if isinstance(sub_df, pd.DataFrame):
|
|
70
|
+
self._is_df = True
|
|
71
|
+
# 输出一下
|
|
72
|
+
data_first_now = int(sub_df["create_time"].iloc[0])
|
|
73
|
+
if now - data_first_now > 2000:
|
|
74
|
+
self._logger.debug(
|
|
75
|
+
f"数据时间{data_first_now} 与当前时间{now} 差值{now - data_first_now} 超过2000ms"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
if df is None:
|
|
79
|
+
df = sub_df
|
|
80
|
+
else:
|
|
81
|
+
df = pd.concat([df, sub_df], ignore_index=True)
|
|
82
|
+
else:
|
|
83
|
+
list_data = sub_df
|
|
84
|
+
|
|
85
|
+
# 入库
|
|
86
|
+
if self._is_df:
|
|
87
|
+
if df is not None and not df.empty:
|
|
88
|
+
try:
|
|
89
|
+
self._ddb.save2stream_batch(self._ddb_table_name, df=df)
|
|
90
|
+
except Exception as e:
|
|
91
|
+
# 避免刷库异常导致线程退出
|
|
92
|
+
self._logger.error(f"批量写入df失败: {e}")
|
|
93
|
+
else:
|
|
94
|
+
if len(list_data) > 0:
|
|
95
|
+
try:
|
|
96
|
+
self._ddb.save2stream_list(list_data)
|
|
97
|
+
except Exception as e:
|
|
98
|
+
# 避免刷库异常导致线程退出
|
|
99
|
+
self._logger.error(f"批量写入数组失败: {e}")
|
|
100
|
+
|
|
101
|
+
# 是dataFrame的才睡眠,数组处理交由ddb自己控制节奏
|
|
102
|
+
if self._is_df:
|
|
103
|
+
time.sleep(self._flush_interval_ms / 1000.0)
|
|
@@ -4,15 +4,19 @@ import threading
|
|
|
4
4
|
import time
|
|
5
5
|
|
|
6
6
|
import pandas as pd
|
|
7
|
+
|
|
7
8
|
from kaq_quant_common.resources.kaq_ddb_stream_write_resources import (
|
|
8
|
-
KaqQuantDdbStreamWriteRepository
|
|
9
|
-
)
|
|
9
|
+
KaqQuantDdbStreamMTWWriteRepository, KaqQuantDdbStreamWriteRepository)
|
|
10
10
|
from kaq_quant_common.utils import logger_utils
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class LimitOrderHelper:
|
|
14
14
|
|
|
15
|
-
def __init__(
|
|
15
|
+
def __init__(
|
|
16
|
+
self,
|
|
17
|
+
ddb: KaqQuantDdbStreamWriteRepository | KaqQuantDdbStreamMTWWriteRepository,
|
|
18
|
+
ddb_table_name: str,
|
|
19
|
+
):
|
|
16
20
|
# 最新快照缓存与刷库线程控制
|
|
17
21
|
self._latest_snapshots: dict[str, tuple] = {}
|
|
18
22
|
self._latest_lock = threading.Lock()
|
|
@@ -21,6 +25,7 @@ class LimitOrderHelper:
|
|
|
21
25
|
self._stop_event = threading.Event()
|
|
22
26
|
self._flusher_thread = threading.Thread(target=self._flush_loop, daemon=True)
|
|
23
27
|
self._flusher_thread.name = "LimitOrderHelperFlusherThread"
|
|
28
|
+
self._is_df = False
|
|
24
29
|
|
|
25
30
|
#
|
|
26
31
|
self._ddb = ddb
|
|
@@ -56,26 +61,43 @@ class LimitOrderHelper:
|
|
|
56
61
|
|
|
57
62
|
if to_process:
|
|
58
63
|
df: pd.DataFrame = None
|
|
64
|
+
list_data: list = []
|
|
59
65
|
now = int(datetime.datetime.now().timestamp() * 1000)
|
|
60
66
|
|
|
61
67
|
for symbol, (data, arg) in to_process:
|
|
62
68
|
sub_df = self._build_data(symbol, data, arg)
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
69
|
+
if isinstance(sub_df, pd.DataFrame):
|
|
70
|
+
self._is_df = True
|
|
71
|
+
# 输出一下
|
|
72
|
+
data_first_now = int(sub_df["create_time"].iloc[0])
|
|
73
|
+
if now - data_first_now > 2000:
|
|
74
|
+
self._logger.debug(
|
|
75
|
+
f"数据时间{data_first_now} 与当前时间{now} 差值{now - data_first_now} 超过2000ms"
|
|
76
|
+
)
|
|
77
|
+
|
|
78
|
+
if df is None:
|
|
79
|
+
df = sub_df
|
|
80
|
+
else:
|
|
81
|
+
df = pd.concat([df, sub_df], ignore_index=True)
|
|
70
82
|
else:
|
|
71
|
-
|
|
83
|
+
list_data = sub_df
|
|
72
84
|
|
|
73
85
|
# 入库
|
|
74
|
-
if
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
86
|
+
if self._is_df:
|
|
87
|
+
if df is not None and not df.empty:
|
|
88
|
+
try:
|
|
89
|
+
self._ddb.save2stream_batch(self._ddb_table_name, df=df)
|
|
90
|
+
except Exception as e:
|
|
91
|
+
# 避免刷库异常导致线程退出
|
|
92
|
+
self._logger.error(f"批量写入df失败: {e}")
|
|
93
|
+
else:
|
|
94
|
+
if len(list_data) > 0:
|
|
95
|
+
try:
|
|
96
|
+
self._ddb.save2stream_list(list_data)
|
|
97
|
+
except Exception as e:
|
|
98
|
+
# 避免刷库异常导致线程退出
|
|
99
|
+
self._logger.error(f"批量写入数组失败: {e}")
|
|
100
|
+
|
|
101
|
+
# 是dataFrame的才睡眠,数组处理交由ddb自己控制节奏
|
|
102
|
+
if self._is_df:
|
|
103
|
+
time.sleep(self._flush_interval_ms / 1000.0)
|
|
@@ -27,7 +27,8 @@ kaq_quant_common/api/ws/ws_server_base.py,sha256=-JFA5fnYHXPYBZ09aZmhYuhgDHFfJbk
|
|
|
27
27
|
kaq_quant_common/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
28
|
kaq_quant_common/common/ddb_table_monitor.py,sha256=7Yihz_uGGujo_QqqPl45Gp8fwUMMw1auXx5egbzyYlE,3662
|
|
29
29
|
kaq_quant_common/common/http_monitor.py,sha256=_yChiwfVv1c5g_lKgYUjWY40fX61BWVK8SL4kXwRfwk,2375
|
|
30
|
-
kaq_quant_common/common/modules/
|
|
30
|
+
kaq_quant_common/common/modules/funding_rate_helper.py,sha256=BVGNS6E7aVPITOz5u4g7vBUHOrm1S1Uri8psgWxp-BQ,3853
|
|
31
|
+
kaq_quant_common/common/modules/limit_order_helper.py,sha256=Py9DPBXq1-QnjEh6mGQOA7vD3TVNUabnS_rMf0SQx5U,3853
|
|
31
32
|
kaq_quant_common/common/modules/limit_order_symbol_monitor.py,sha256=TBK48qyeCSQvkfDMv3J_0UM7f3OuBRKRFYDcL9kG6Cs,2876
|
|
32
33
|
kaq_quant_common/common/modules/limit_order_symbol_monitor_group.py,sha256=oEqHIwxhqAzckmluHJHZHiHUNmAyaS2JyK2nXO58UhY,2394
|
|
33
34
|
kaq_quant_common/common/monitor_base.py,sha256=E4EUMsO3adNltCDNRgxkvUSbTTfKOL9S1zzN3WkZvpU,2467
|
|
@@ -61,6 +62,6 @@ kaq_quant_common/utils/signal_utils.py,sha256=zBSyEltNTKqkQCsrETd47kEBb3Q_OWUBUn
|
|
|
61
62
|
kaq_quant_common/utils/sqlite_utils.py,sha256=UDDFKfwL0N-jFifl40HdyOCENh2YQfW5so6hRaSJpv0,5722
|
|
62
63
|
kaq_quant_common/utils/uuid_utils.py,sha256=pm_pnXpd8n9CI66x3A20cOEUiriJyqHaKGCeLrgkBxU,71
|
|
63
64
|
kaq_quant_common/utils/yml_utils.py,sha256=gcKjb_-uuUajBGAl5QBPIZTg2wXm7qeeJvtHflj_zOE,4513
|
|
64
|
-
kaq_quant_common-0.2.
|
|
65
|
-
kaq_quant_common-0.2.
|
|
66
|
-
kaq_quant_common-0.2.
|
|
65
|
+
kaq_quant_common-0.2.4.dist-info/METADATA,sha256=J-fMkZRZdJJSSOkTumujjx2t9HhwgxgKtLKtvNqwaTk,1970
|
|
66
|
+
kaq_quant_common-0.2.4.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
67
|
+
kaq_quant_common-0.2.4.dist-info/RECORD,,
|
|
File without changes
|