kaq-quant-common 0.2.12__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 (67) hide show
  1. kaq_quant_common/__init__.py +0 -0
  2. kaq_quant_common/api/__init__.py +0 -0
  3. kaq_quant_common/api/common/__init__.py +1 -0
  4. kaq_quant_common/api/common/api_interface.py +38 -0
  5. kaq_quant_common/api/common/auth.py +118 -0
  6. kaq_quant_common/api/rest/__init__.py +0 -0
  7. kaq_quant_common/api/rest/api_client_base.py +42 -0
  8. kaq_quant_common/api/rest/api_server_base.py +135 -0
  9. kaq_quant_common/api/rest/instruction/helper/order_helper.py +342 -0
  10. kaq_quant_common/api/rest/instruction/instruction_client.py +86 -0
  11. kaq_quant_common/api/rest/instruction/instruction_server_base.py +154 -0
  12. kaq_quant_common/api/rest/instruction/models/__init__.py +17 -0
  13. kaq_quant_common/api/rest/instruction/models/account.py +49 -0
  14. kaq_quant_common/api/rest/instruction/models/order.py +248 -0
  15. kaq_quant_common/api/rest/instruction/models/position.py +70 -0
  16. kaq_quant_common/api/rest/instruction/models/transfer.py +32 -0
  17. kaq_quant_common/api/ws/__init__.py +0 -0
  18. kaq_quant_common/api/ws/exchange/models.py +23 -0
  19. kaq_quant_common/api/ws/exchange/ws_exchange_client.py +31 -0
  20. kaq_quant_common/api/ws/exchange/ws_exchange_server.py +440 -0
  21. kaq_quant_common/api/ws/instruction/__init__.py +0 -0
  22. kaq_quant_common/api/ws/instruction/ws_instruction_client.py +82 -0
  23. kaq_quant_common/api/ws/instruction/ws_instruction_server_base.py +139 -0
  24. kaq_quant_common/api/ws/models.py +46 -0
  25. kaq_quant_common/api/ws/ws_client_base.py +235 -0
  26. kaq_quant_common/api/ws/ws_server_base.py +288 -0
  27. kaq_quant_common/common/__init__.py +0 -0
  28. kaq_quant_common/common/ddb_table_monitor.py +106 -0
  29. kaq_quant_common/common/http_monitor.py +69 -0
  30. kaq_quant_common/common/modules/funding_rate_helper.py +137 -0
  31. kaq_quant_common/common/modules/limit_order_helper.py +158 -0
  32. kaq_quant_common/common/modules/limit_order_symbol_monitor.py +76 -0
  33. kaq_quant_common/common/modules/limit_order_symbol_monitor_group.py +69 -0
  34. kaq_quant_common/common/monitor_base.py +84 -0
  35. kaq_quant_common/common/monitor_group.py +97 -0
  36. kaq_quant_common/common/redis_table_monitor.py +123 -0
  37. kaq_quant_common/common/statistics/funding_rate_history_statistics.py +208 -0
  38. kaq_quant_common/common/statistics/kline_history_statistics.py +211 -0
  39. kaq_quant_common/common/ws_wrapper.py +21 -0
  40. kaq_quant_common/config/config.yaml +5 -0
  41. kaq_quant_common/resources/__init__.py +0 -0
  42. kaq_quant_common/resources/kaq_ddb_pool_stream_read_resources.py +56 -0
  43. kaq_quant_common/resources/kaq_ddb_stream_init_resources.py +88 -0
  44. kaq_quant_common/resources/kaq_ddb_stream_read_resources.py +81 -0
  45. kaq_quant_common/resources/kaq_ddb_stream_write_resources.py +359 -0
  46. kaq_quant_common/resources/kaq_mysql_init_resources.py +23 -0
  47. kaq_quant_common/resources/kaq_mysql_resources.py +341 -0
  48. kaq_quant_common/resources/kaq_postgresql_resources.py +58 -0
  49. kaq_quant_common/resources/kaq_quant_hive_resources.py +107 -0
  50. kaq_quant_common/resources/kaq_redis_resources.py +117 -0
  51. kaq_quant_common/utils/__init__.py +0 -0
  52. kaq_quant_common/utils/dagster_job_check_utils.py +29 -0
  53. kaq_quant_common/utils/dagster_utils.py +19 -0
  54. kaq_quant_common/utils/date_util.py +204 -0
  55. kaq_quant_common/utils/enums_utils.py +79 -0
  56. kaq_quant_common/utils/error_utils.py +22 -0
  57. kaq_quant_common/utils/hash_utils.py +48 -0
  58. kaq_quant_common/utils/log_time_utils.py +32 -0
  59. kaq_quant_common/utils/logger_utils.py +97 -0
  60. kaq_quant_common/utils/mytt_utils.py +372 -0
  61. kaq_quant_common/utils/signal_utils.py +23 -0
  62. kaq_quant_common/utils/sqlite_utils.py +169 -0
  63. kaq_quant_common/utils/uuid_utils.py +5 -0
  64. kaq_quant_common/utils/yml_utils.py +148 -0
  65. kaq_quant_common-0.2.12.dist-info/METADATA +66 -0
  66. kaq_quant_common-0.2.12.dist-info/RECORD +67 -0
  67. kaq_quant_common-0.2.12.dist-info/WHEEL +4 -0
@@ -0,0 +1,372 @@
1
+ # MyTT 麦语言-通达信-同花顺指标实现 https://github.com/mpquant/MyTT
2
+ # MyTT高级函数验证版本: https://github.com/mpquant/MyTT/blob/main/MyTT_plus.py
3
+ # Python2老版本pandas特别的MyTT: https://github.com/mpquant/MyTT/blob/main/MyTT_python2.py
4
+ # V2.1 2021-6-6 新增 BARSLAST函数 SLOPE,FORCAST线性回归预测函数
5
+ # V2.3 2021-6-13 新增 TRIX,DPO,BRAR,DMA,MTM,MASS,ROC,VR,ASI等指标
6
+ # V2.4 2021-6-27 新增 EXPMA,OBV,MFI指标, 改进SMA核心函数(核心函数彻底无循环)
7
+ # V2.7 2021-11-21 修正 SLOPE,BARSLAST,函数,新加FILTER,LONGCROSS, 感谢qzhjiang对SLOPE,SMA等函数的指正
8
+ # V2.8 2021-11-23 修正 FORCAST,WMA函数,欢迎qzhjiang,stanene,bcq加入社群,一起来完善myTT库
9
+ # V2.9 2021-11-29 新增 HHVBARS,LLVBARS,CONST, VALUEWHEN功能函数
10
+ # V2.92 2021-11-30 新增 BARSSINCEN函数,现在可以 pip install MyTT 完成安装
11
+ # V3.0 2021-12-04 改进 DMA函数支持序列,新增XS2 薛斯通道II指标
12
+ # V3.1 2021-12-19 新增 TOPRANGE,LOWRANGE一级函数
13
+
14
+ # 以下所有函数如无特别说明,输入参数S均为numpy序列或者列表list,N为整型int
15
+ # 应用层1级函数完美兼容通达信或同花顺,具体使用方法请参考通达信
16
+ import numpy as np
17
+ import pandas as pd
18
+
19
+
20
+ # ------------------ 0级:核心工具函数 --------------------------------------------
21
+ def RD(N, D=3): return np.round(N, D) # 四舍五入取3位小数
22
+
23
+
24
+ def RET(S, N=1): return np.array(S)[-N] # 返回序列倒数第N个值,默认返回最后一个
25
+
26
+
27
+ def ABS(S): return np.abs(S) # 返回N的绝对值
28
+
29
+
30
+ def LN(S): return np.log(S) # 求底是e的自然对数,
31
+
32
+
33
+ def POW(S, N): return np.power(S, N) # 求S的N次方
34
+
35
+
36
+ def SQRT(S): return np.sqrt(S) # 求S的平方根
37
+
38
+
39
+ def MAX(S1, S2): return np.maximum(S1, S2) # 序列max
40
+
41
+
42
+ def MIN(S1, S2): return np.minimum(S1, S2) # 序列min
43
+
44
+
45
+ def IF(S, A, B): return np.where(S, A, B) # 序列布尔判断 return=A if S==True else B
46
+
47
+
48
+ def REF(S, N=1): # 对序列整体下移动N,返回序列(shift后会产生NAN)
49
+ return pd.Series(S).shift(N).values
50
+
51
+
52
+ def DIFF(S, N=1): # 前一个值减后一个值,前面会产生nan
53
+ return pd.Series(S).diff(N).values # np.diff(S)直接删除nan,会少一行
54
+
55
+
56
+ def STD(S, N): # 求序列的N日标准差,返回序列
57
+ return pd.Series(S).rolling(N).std(ddof=0).values
58
+
59
+
60
+ def SUM(S, N): # 对序列求N天累计和,返回序列 N=0对序列所有依次求和
61
+ return pd.Series(S).rolling(N).sum().values if N > 0 else pd.Series(S).cumsum().values
62
+
63
+
64
+ def CONST(S): # 返回序列S最后的值组成常量序列
65
+ return np.full(len(S), S[-1])
66
+
67
+
68
+ def HHV(S, N): # HHV(C, 5) 最近5天收盘最高价
69
+ return pd.Series(S).rolling(N).max().values
70
+
71
+
72
+ def LLV(S, N): # LLV(C, 5) 最近5天收盘最低价
73
+ return pd.Series(S).rolling(N).min().values
74
+
75
+
76
+ def HHVBARS(S, N): # 求N周期内S最高值到当前周期数, 返回序列
77
+ return pd.Series(S).rolling(N).apply(lambda x: np.argmax(x[::-1]), raw=True).values
78
+
79
+
80
+ def LLVBARS(S, N): # 求N周期内S最低值到当前周期数, 返回序列
81
+ return pd.Series(S).rolling(N).apply(lambda x: np.argmin(x[::-1]), raw=True).values
82
+
83
+
84
+ def MA(S, N): # 求序列的N日简单移动平均值,返回序列
85
+ return pd.Series(S).rolling(N).mean().values
86
+
87
+
88
+ def EMA(S, N): # 指数移动平均,为了精度 S>4*N EMA至少需要120周期 alpha=2/(span+1)
89
+ return pd.Series(S).ewm(span=N, adjust=False).mean().values
90
+
91
+
92
+ def SMA(S, N, M=1): # 中国式的SMA,至少需要120周期才精确 (雪球180周期) alpha=1/(1+com)
93
+ return pd.Series(S).ewm(alpha=M / N, adjust=False).mean().values # com=N-M/M
94
+
95
+
96
+ def WMA(S, N): # 通达信S序列的N日加权移动平均 Yn = (1*X1+2*X2+3*X3+...+n*Xn)/(1+2+3+...+n)
97
+ return pd.Series(S).rolling(N).apply(lambda x: x[::-1].cumsum().sum() * 2 / N / (N + 1), raw=True).values
98
+
99
+
100
+ def DMA(S, A): # 求S的动态移动平均,A作平滑因子,必须 0<A<1 (此为核心函数,非指标)
101
+ if isinstance(A, (int, float)): return pd.Series(S).ewm(alpha=A, adjust=False).mean().values
102
+ A = np.array(A);
103
+ A[np.isnan(A)] = 1.0;
104
+ Y = np.zeros(len(S));
105
+ Y[0] = S[0]
106
+ for i in range(1, len(S)): Y[i] = A[i] * S[i] + (1 - A[i]) * Y[i - 1] # A支持序列 by jqz1226
107
+ return Y
108
+
109
+
110
+ def AVEDEV(S, N): # 平均绝对偏差 (序列与其平均值的绝对差的平均值)
111
+ return pd.Series(S).rolling(N).apply(lambda x: (np.abs(x - x.mean())).mean()).values
112
+
113
+
114
+ def SLOPE(S, N): # 返S序列N周期回线性回归斜率
115
+ return pd.Series(S).rolling(N).apply(lambda x: np.polyfit(range(N), x, deg=1)[0], raw=True).values
116
+
117
+
118
+ def FORCAST(S, N): # 返回S序列N周期回线性回归后的预测值, jqz1226改进成序列出
119
+ return pd.Series(S).rolling(N).apply(lambda x: np.polyval(np.polyfit(range(N), x, deg=1), N - 1), raw=True).values
120
+
121
+
122
+ def LAST(S, A, B): # 从前A日到前B日一直满足S_BOOL条件, 要求A>B & A>0 & B>=0
123
+ return np.array(pd.Series(S).rolling(A + 1).apply(lambda x: np.all(x[::-1][B:]), raw=True), dtype=bool)
124
+
125
+
126
+ # ------------------ 1级:应用层函数(通过0级核心函数实现)使用方法请参考通达信--------------------------------
127
+ def COUNT(S, N): # COUNT(CLOSE>O, N): 最近N天满足S_BOO的天数 True的天数
128
+ return SUM(S, N)
129
+
130
+
131
+ def EVERY(S, N): # EVERY(CLOSE>O, 5) 最近N天是否都是True
132
+ return IF(SUM(S, N) == N, True, False)
133
+
134
+
135
+ def EXIST(S, N): # EXIST(CLOSE>3010, N=5) n日内是否存在一天大于3000点
136
+ return IF(SUM(S, N) > 0, True, False)
137
+
138
+
139
+ def FILTER(S, N): # FILTER函数,S满足条件后,将其后N周期内的数据置为0, FILTER(C==H,5)
140
+ for i in range(len(S)): S[i + 1:i + 1 + N] = 0 if S[i] else S[i + 1:i + 1 + N]
141
+ return S # 例:FILTER(C==H,5) 涨停后,后5天不再发出信号
142
+
143
+
144
+ def BARSLAST(S): # 上一次条件成立到当前的周期, BARSLAST(C/REF(C,1)>=1.1) 上一次涨停到今天的天数
145
+ M = np.concatenate(([0], np.where(S, 1, 0)))
146
+ for i in range(1, len(M)): M[i] = 0 if M[i] else M[i - 1] + 1
147
+ return M[1:]
148
+
149
+
150
+ def BARSLASTCOUNT(S): # 统计连续满足S条件的周期数 by jqz1226
151
+ rt = np.zeros(len(S) + 1) # BARSLASTCOUNT(CLOSE>OPEN)表示统计连续收阳的周期数
152
+ for i in range(len(S)): rt[i + 1] = rt[i] + 1 if S[i] else rt[i + 1]
153
+ return rt[1:]
154
+
155
+
156
+ def BARSSINCEN(S, N): # N周期内第一次S条件成立到现在的周期数,N为常量 by jqz1226
157
+ return pd.Series(S).rolling(N).apply(lambda x: N - 1 - np.argmax(x) if np.argmax(x) or x[0] else 0,
158
+ raw=True).fillna(0).values.astype(int)
159
+
160
+
161
+ def CROSS(S1, S2): # 判断向上金叉穿越 CROSS(MA(C,5),MA(C,10)) 判断向下死叉穿越 CROSS(MA(C,10),MA(C,5))
162
+ return np.concatenate(([False], np.logical_not((S1 > S2)[:-1]) & (S1 > S2)[1:])) # 不使用0级函数,移植方便 by jqz1226
163
+
164
+
165
+ def LONGCROSS(S1, S2, N): # 两条线维持一定周期后交叉,S1在N周期内都小于S2,本周期从S1下方向上穿过S2时返回1,否则返回0
166
+ return np.array(np.logical_and(LAST(S1 < S2, N, 1), (S1 > S2)), dtype=bool) # N=1时等同于CROSS(S1, S2)
167
+
168
+
169
+ def VALUEWHEN(S, X): # 当S条件成立时,取X的当前值,否则取VALUEWHEN的上个成立时的X值 by jqz1226
170
+ return pd.Series(np.where(S, X, np.nan)).ffill().values
171
+
172
+
173
+ def BETWEEN(S, A, B): # S处于A和B之间时为真。 包括 A<S<B 或 A>S>B
174
+ return ((A < S) & (S < B)) | ((A > S) & (S > B))
175
+
176
+
177
+ def TOPRANGE(S): # TOPRANGE(HIGH)表示当前最高价是近多少周期内最高价的最大值 by jqz1226
178
+ rt = np.zeros(len(S))
179
+ for i in range(1, len(S)): rt[i] = np.argmin(np.flipud(S[:i] < S[i]))
180
+ return rt.astype('int')
181
+
182
+
183
+ def LOWRANGE(S): # LOWRANGE(LOW)表示当前最低价是近多少周期内最低价的最小值 by jqz1226
184
+ rt = np.zeros(len(S))
185
+ for i in range(1, len(S)): rt[i] = np.argmin(np.flipud(S[:i] > S[i]))
186
+ return rt.astype('int')
187
+
188
+
189
+ # ------------------ 2级:技术指标函数(全部通过0级,1级函数实现) ------------------------------
190
+ def MACD(CLOSE, SHORT=12, LONG=26, M=9): # EMA的关系,S取120日,和雪球小数点2位相同
191
+ DIF = EMA(CLOSE, SHORT) - EMA(CLOSE, LONG);
192
+ DEA = EMA(DIF, M);
193
+ MACD = (DIF - DEA) * 2
194
+ return RD(DIF), RD(DEA), RD(MACD)
195
+
196
+
197
+ def KDJ(CLOSE, HIGH, LOW, N=9, M1=3, M2=3): # KDJ指标
198
+ RSV = (CLOSE - LLV(LOW, N)) / (HHV(HIGH, N) - LLV(LOW, N)) * 100
199
+ K = EMA(RSV, (M1 * 2 - 1));
200
+ D = EMA(K, (M2 * 2 - 1));
201
+ J = K * 3 - D * 2
202
+ return K, D, J
203
+
204
+
205
+ def RSI(CLOSE, N=24): # RSI指标,和通达信小数点2位相同
206
+ DIF = CLOSE - REF(CLOSE, 1)
207
+ return RD(SMA(MAX(DIF, 0), N) / SMA(ABS(DIF), N) * 100)
208
+
209
+
210
+ def WR(CLOSE, HIGH, LOW, N=10, N1=6): # W&R 威廉指标
211
+ WR = (HHV(HIGH, N) - CLOSE) / (HHV(HIGH, N) - LLV(LOW, N)) * 100
212
+ WR1 = (HHV(HIGH, N1) - CLOSE) / (HHV(HIGH, N1) - LLV(LOW, N1)) * 100
213
+ return RD(WR), RD(WR1)
214
+
215
+
216
+ def BIAS(CLOSE, L1=6, L2=12, L3=24): # BIAS乖离率
217
+ BIAS1 = (CLOSE - MA(CLOSE, L1)) / MA(CLOSE, L1) * 100
218
+ BIAS2 = (CLOSE - MA(CLOSE, L2)) / MA(CLOSE, L2) * 100
219
+ BIAS3 = (CLOSE - MA(CLOSE, L3)) / MA(CLOSE, L3) * 100
220
+ return RD(BIAS1), RD(BIAS2), RD(BIAS3)
221
+
222
+
223
+ def BOLL(CLOSE, N=20, P=2): # BOLL指标,布林带
224
+ MID = MA(CLOSE, N);
225
+ UPPER = MID + STD(CLOSE, N) * P
226
+ LOWER = MID - STD(CLOSE, N) * P
227
+ return RD(UPPER), RD(MID), RD(LOWER)
228
+
229
+
230
+ def PSY(CLOSE, N=12, M=6):
231
+ PSY = COUNT(CLOSE > REF(CLOSE, 1), N) / N * 100
232
+ PSYMA = MA(PSY, M)
233
+ return RD(PSY), RD(PSYMA)
234
+
235
+
236
+ def CCI(CLOSE, HIGH, LOW, N=14):
237
+ TP = (HIGH + LOW + CLOSE) / 3
238
+ return (TP - MA(TP, N)) / (0.015 * AVEDEV(TP, N))
239
+
240
+
241
+ def ATR(CLOSE, HIGH, LOW, N=20): # 真实波动N日平均值
242
+ TR = MAX(MAX((HIGH - LOW), ABS(REF(CLOSE, 1) - HIGH)), ABS(REF(CLOSE, 1) - LOW))
243
+ return MA(TR, N)
244
+
245
+
246
+ def BBI(CLOSE, M1=3, M2=6, M3=12, M4=20): # BBI多空指标
247
+ return (MA(CLOSE, M1) + MA(CLOSE, M2) + MA(CLOSE, M3) + MA(CLOSE, M4)) / 4
248
+
249
+
250
+ def DMI(CLOSE, HIGH, LOW, M1=14, M2=6): # 动向指标:结果和同花顺,通达信完全一致
251
+ TR = SUM(MAX(MAX(HIGH - LOW, ABS(HIGH - REF(CLOSE, 1))), ABS(LOW - REF(CLOSE, 1))), M1)
252
+ HD = HIGH - REF(HIGH, 1);
253
+ LD = REF(LOW, 1) - LOW
254
+ DMP = SUM(IF((HD > 0) & (HD > LD), HD, 0), M1)
255
+ DMM = SUM(IF((LD > 0) & (LD > HD), LD, 0), M1)
256
+ PDI = DMP * 100 / TR;
257
+ MDI = DMM * 100 / TR
258
+ ADX = MA(ABS(MDI - PDI) / (PDI + MDI) * 100, M2)
259
+ ADXR = (ADX + REF(ADX, M2)) / 2
260
+ return PDI, MDI, ADX, ADXR
261
+
262
+
263
+ def TAQ(HIGH, LOW, N): # 唐安奇通道(海龟)交易指标,大道至简,能穿越牛熊
264
+ UP = HHV(HIGH, N);
265
+ DOWN = LLV(LOW, N);
266
+ MID = (UP + DOWN) / 2
267
+ return UP, MID, DOWN
268
+
269
+
270
+ def KTN(CLOSE, HIGH, LOW, N=20, M=10): # 肯特纳交易通道, N选20日,ATR选10日
271
+ MID = EMA((HIGH + LOW + CLOSE) / 3, N)
272
+ ATRN = ATR(CLOSE, HIGH, LOW, M)
273
+ UPPER = MID + 2 * ATRN;
274
+ LOWER = MID - 2 * ATRN
275
+ return UPPER, MID, LOWER
276
+
277
+
278
+ def TRIX(CLOSE, M1=12, M2=20): # 三重指数平滑平均线
279
+ TR = EMA(EMA(EMA(CLOSE, M1), M1), M1)
280
+ TRIX = (TR - REF(TR, 1)) / REF(TR, 1) * 100
281
+ TRMA = MA(TRIX, M2)
282
+ return TRIX, TRMA
283
+
284
+
285
+ def VR(CLOSE, VOL, M1=26): # VR容量比率
286
+ LC = REF(CLOSE, 1)
287
+ return SUM(IF(CLOSE > LC, VOL, 0), M1) / SUM(IF(CLOSE <= LC, VOL, 0), M1) * 100
288
+
289
+
290
+ def EMV(HIGH, LOW, VOL, N=14, M=9): # 简易波动指标
291
+ VOLUME = MA(VOL, N) / VOL;
292
+ MID = 100 * (HIGH + LOW - REF(HIGH + LOW, 1)) / (HIGH + LOW)
293
+ EMV = MA(MID * VOLUME * (HIGH - LOW) / MA(HIGH - LOW, N), N);
294
+ MAEMV = MA(EMV, M)
295
+ return EMV, MAEMV
296
+
297
+
298
+ def DPO(CLOSE, M1=20, M2=10, M3=6): # 区间震荡线
299
+ DPO = CLOSE - REF(MA(CLOSE, M1), M2);
300
+ MADPO = MA(DPO, M3)
301
+ return DPO, MADPO
302
+
303
+
304
+ def BRAR(OPEN, CLOSE, HIGH, LOW, M1=26): # BRAR-ARBR 情绪指标
305
+ AR = SUM(HIGH - OPEN, M1) / SUM(OPEN - LOW, M1) * 100
306
+ BR = SUM(MAX(0, HIGH - REF(CLOSE, 1)), M1) / SUM(MAX(0, REF(CLOSE, 1) - LOW), M1) * 100
307
+ return AR, BR
308
+
309
+
310
+ def DFMA(CLOSE, N1=10, N2=50, M=10): # 平行线差指标
311
+ DIF = MA(CLOSE, N1) - MA(CLOSE, N2);
312
+ DIFMA = MA(DIF, M) # 通达信指标叫DMA 同花顺叫新DMA
313
+ return DIF, DIFMA
314
+
315
+
316
+ def MTM(CLOSE, N=12, M=6): # 动量指标
317
+ MTM = CLOSE - REF(CLOSE, N);
318
+ MTMMA = MA(MTM, M)
319
+ return MTM, MTMMA
320
+
321
+
322
+ def MASS(HIGH, LOW, N1=9, N2=25, M=6): # 梅斯线
323
+ MASS = SUM(MA(HIGH - LOW, N1) / MA(MA(HIGH - LOW, N1), N1), N2)
324
+ MA_MASS = MA(MASS, M)
325
+ return MASS, MA_MASS
326
+
327
+
328
+ def ROC(CLOSE, N=12, M=6): # 变动率指标
329
+ ROC = 100 * (CLOSE - REF(CLOSE, N)) / REF(CLOSE, N);
330
+ MAROC = MA(ROC, M)
331
+ return ROC, MAROC
332
+
333
+
334
+ def EXPMA(CLOSE, N1=12, N2=50): # EMA指数平均数指标
335
+ return EMA(CLOSE, N1), EMA(CLOSE, N2);
336
+
337
+
338
+ def OBV(CLOSE, VOL): # 能量潮指标
339
+ return SUM(IF(CLOSE > REF(CLOSE, 1), VOL, IF(CLOSE < REF(CLOSE, 1), -VOL, 0)), 0) / 10000
340
+
341
+
342
+ def MFI(CLOSE, HIGH, LOW, VOL, N=14): # MFI指标是成交量的RSI指标
343
+ TYP = (HIGH + LOW + CLOSE) / 3
344
+ V1 = SUM(IF(TYP > REF(TYP, 1), TYP * VOL, 0), N) / SUM(IF(TYP < REF(TYP, 1), TYP * VOL, 0), N)
345
+ return 100 - (100 / (1 + V1))
346
+
347
+
348
+ def ASI(OPEN, CLOSE, HIGH, LOW, M1=26, M2=10): # 振动升降指标
349
+ LC = REF(CLOSE, 1);
350
+ AA = ABS(HIGH - LC);
351
+ BB = ABS(LOW - LC);
352
+ CC = ABS(HIGH - REF(LOW, 1));
353
+ DD = ABS(LC - REF(OPEN, 1));
354
+ R = IF((AA > BB) & (AA > CC), AA + BB / 2 + DD / 4, IF((BB > CC) & (BB > AA), BB + AA / 2 + DD / 4, CC + DD / 4));
355
+ X = (CLOSE - LC + (CLOSE - OPEN) / 2 + LC - REF(OPEN, 1));
356
+ SI = 16 * X / R * MAX(AA, BB);
357
+ ASI = SUM(SI, M1);
358
+ ASIT = MA(ASI, M2);
359
+ return ASI, ASIT
360
+
361
+
362
+ def XSII(CLOSE, HIGH, LOW, N=102, M=7): # 薛斯通道II
363
+ AA = MA((2 * CLOSE + HIGH + LOW) / 4, 5) # 最新版DMA才支持 2021-12-4
364
+ TD1 = AA * N / 100;
365
+ TD2 = AA * (200 - N) / 100
366
+ CC = ABS((2 * CLOSE + HIGH + LOW) / 4 - MA(CLOSE, 20)) / MA(CLOSE, 20)
367
+ DD = DMA(CLOSE, CC);
368
+ TD3 = (1 + M / 100) * DD;
369
+ TD4 = (1 - M / 100) * DD
370
+ return TD1, TD2, TD3, TD4
371
+
372
+ # 望大家能提交更多指标和函数 https://github.com/mpquant/MyTT
@@ -0,0 +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)
@@ -0,0 +1,169 @@
1
+ import sqlite3
2
+ import os
3
+ import threading
4
+ import pandas as pd
5
+
6
+
7
+ class SqliteRepository:
8
+
9
+ def __init__(self):
10
+ print('sqlite\'s db init ............')
11
+ self.con = None
12
+ self.cur = None
13
+ self.thread_lock = threading.Lock()
14
+
15
+ def connect(self, db_name):
16
+ try:
17
+ self.thread_lock.acquire(blocking=True)
18
+ db_path = os.getcwd() + os.sep + 'kaq_binance_sqlite3_db'
19
+ if not os.path.exists(db_path):
20
+ os.mkdir(db_path)
21
+
22
+ sqlite3_db = db_path + os.sep + db_name
23
+ self.con = sqlite3.connect(sqlite3_db, check_same_thread=False)
24
+ except Exception as e:
25
+ print('【SqliteRepository.connect】异常', db_name, e)
26
+ finally:
27
+ # print('【SqliteRepository.connect】释放锁', db_name)
28
+ self.thread_lock.release()
29
+
30
+ def get_table_info(self, sql):
31
+ '''
32
+ 提取表的字段
33
+ '''
34
+ try:
35
+ self.thread_lock.acquire(True)
36
+ self.cur = self.con.cursor()
37
+ self.cur.execute(sql)
38
+ person_all = self.cur.fetchall()
39
+ # 返回数据
40
+ return person_all
41
+ except Exception as e:
42
+ self.con.rollback()
43
+ print('【sqllite查询失败】', sql, e)
44
+ finally:
45
+ # print('【SqliteRepository.select_data】释放锁', params)
46
+ self.cur.close()
47
+ self.thread_lock.release()
48
+
49
+ def is_table_exists(self, table_name):
50
+ '''
51
+ 表是否存在
52
+ '''
53
+ try:
54
+ self.thread_lock.acquire(True)
55
+ self.cur = self.con.cursor()
56
+ self.cur.execute("PRAGMA table_info({})".format(table_name))
57
+ person_all = self.cur.fetchone()
58
+ # 返回数据
59
+ if person_all is not None:
60
+ return True
61
+ else:
62
+ return False
63
+ except Exception as e:
64
+ self.con.rollback()
65
+ print('【sqllite查询失败】', table_name, e)
66
+ finally:
67
+ # print('【SqliteRepository.select_data】释放锁', params)
68
+ self.cur.close()
69
+ self.thread_lock.release()
70
+
71
+ def close(self):
72
+ try:
73
+ self.thread_lock.acquire(blocking=True)
74
+ self.con.close()
75
+ except Exception as e:
76
+ print('【SqliteRepository.close】异常', e)
77
+ finally:
78
+ # print('【SqliteRepository.close】释放锁')
79
+ self.thread_lock.release()
80
+
81
+ def create_table(self, create_table_sql):
82
+ try:
83
+ self.thread_lock.acquire(blocking=True)
84
+ self.cur = self.con.cursor()
85
+ self.cur.execute(create_table_sql)
86
+ self.con.commit()
87
+ # print('【创建表成功】', create_table_sql)
88
+ except Exception as e:
89
+ print('【sqllite创建表失败】', create_table_sql, e)
90
+ finally:
91
+ # print('【SqliteRepository.create_table】释放锁', create_table_sql)
92
+ self.cur.close()
93
+ self.thread_lock.release()
94
+
95
+ def insert_tab(self, insert_sql, params):
96
+ try:
97
+ self.thread_lock.acquire(True)
98
+ self.cur = self.con.cursor()
99
+ self.cur.execute(insert_sql, params)
100
+ self.con.commit()
101
+ # print('插入成功')
102
+ except Exception as e:
103
+ self.con.rollback()
104
+ print("【sqllite插入失败】", insert_sql, params, e)
105
+ finally:
106
+ # print('【SqliteRepository.insert_tab】释放锁', params)
107
+ self.cur.close()
108
+ self.thread_lock.release()
109
+
110
+ def delete_data(self, delete_sql, params):
111
+ try:
112
+ self.thread_lock.acquire(True)
113
+ self.cur = self.con.cursor()
114
+ self.cur.execute(delete_sql, params)
115
+ self.con.commit()
116
+ # print('删除成功')
117
+ except Exception as e:
118
+ self.con.rollback()
119
+ print('【sqllite删除失败】', e, delete_sql, params)
120
+ finally:
121
+ # print('【SqliteRepository.delete_data】释放锁', params)
122
+ self.cur.close()
123
+ self.thread_lock.release()
124
+
125
+ def update_data(self, update_sql, params):
126
+ try:
127
+ self.thread_lock.acquire(True)
128
+ self.cur = self.con.cursor()
129
+ self.cur.execute(update_sql, params)
130
+ self.con.commit()
131
+ # print('修改成功')
132
+ except Exception as e:
133
+ self.con.rollback()
134
+ # print('【sqllite更新失败】', e, update_sql, params)
135
+ finally:
136
+ # print('【SqliteRepository.update_data】释放锁', params)
137
+ self.cur.close()
138
+ self.thread_lock.release()
139
+
140
+ def select_data(self, select_sql, params):
141
+ try:
142
+ self.thread_lock.acquire(True)
143
+ self.cur = self.con.cursor()
144
+ self.cur.execute(select_sql, params)
145
+ person_all = self.cur.fetchall()
146
+ # 返回数据
147
+ return person_all
148
+ except Exception as e:
149
+ self.con.rollback()
150
+ print('【sqllite查询失败】', select_sql, params, e)
151
+ finally:
152
+ # print('【SqliteRepository.select_data】释放锁', params)
153
+ self.cur.close()
154
+ self.thread_lock.release()
155
+
156
+ # 将pdFrame转为table
157
+ def pd_transfer_table(self, pd_df, table_name):
158
+ try:
159
+ self.thread_lock.acquire(True)
160
+ pd.io.sql.to_sql(pd_df, table_name, self.con, if_exists='replace')
161
+ except Exception as e:
162
+ print('将pdFrame转为table失败', e)
163
+ finally:
164
+ self.thread_lock.release()
165
+
166
+
167
+ sqliteRepository = SqliteRepository()
168
+
169
+
@@ -0,0 +1,5 @@
1
+ import uuid
2
+
3
+
4
+ def generate_uuid() -> str:
5
+ return str(uuid.uuid4())