MyTT 是一个简单易用的 Python 库,它将通达信、同花顺、文华麦语言等指标公式最简化移植到了 Python 中,实现的常见指标包括 MACD、RSI、BOLL、ATR、KDJ、CCI、PSY 等。MyTT 全部基于 numpy 和 pandas 的函数进行封装。
为了方便用户在 DolphinDB 中计算这些技术指标,我们使用 DolphinDB 脚本实现了 MyTT 中包含的指标函数,并封装在 DolphinDB mytt module (mytt.dos)中。 相比于 Python 中的 MyTT 库,DolphinDB mytt module 中的计算函数不仅在批处理中性能有大幅提升,而且支持 DolphinDB 的流式增量计算引擎,可以直接用于实时流计算场景。
因为 DolphinDB mytt module 是基于 DolphinDB V1.30.18 和 DolphinDB V2.00.6 开发的,所以建议用户使用 DolphinDB V1.30.18 和 DolphinDB V2.00.6 及以上版本运行 mytt 指标库中的函数。
1. 函数及参数的命名与用法规范
- Python MyTT 库中所有函数名大写,所有参数名大写,为适应使用者的使用习惯,DolphinDB mytt module 中的函数名、参数、参数默认值均与 MyTT 保持一致。
- 为得到有意义的计算结果,mytt 中函数的参数表示时间跨度的参数均要求至少是 2。
- 由于 LAST 函数与 DolphinDB 中内置关键字冲突,mytt 中将此函数命名为 LAST_。
2. 环境配置
把附件的 mytt.dos 放在节点的 [home]/modules 目录下,[home] 目录由系统配置参数 home 决定,可以通过 getHomeDir()
函数查看。初次使用模块文件时,[home]目录没有 modules 目录,手动创建 modules 目录,然后把 mytt.dos
DolphinDB 模块使用的教程文档:DolphinDB 教程:模块
3. 使用范例
3.1 脚本中直接使用指标函数
对一个向量直接使用 mytt 模块中的 EMA
函数(指数平滑法)进行计算:
3.2 在 SQL 语句中分组使用
用户经常需要在数据表中对多组数据在每组内进行计算。在以下例子中,先构造了一个包含 2 个股票的数据表:
对其中每只股票使用 mytt 模块中的 EMA
函数进行计算:
3.3 返回多个列的结果
某些函数会返回多个列的结果,例如函数 BIAS
(乘离率指标)。
直接使用的例子:
在 SQL 语句中使用的例子:
4. 函数计算性能
本节将以 AVEDEV
函数为例做直接使用的性能对比,同时使用真实股票日频数据对所有函数进行分组使用性能对比。
4.1 直接使用性能对比
在 DolphinDB 中:
对一个长度为 100000 的向量直接使用 mytt 模块中的 AVEDEV
函数,耗时为 25ms。
与之对应的 Python 代码如下:
Python MyTT 库中的 AVEDEV
函数耗时为 25000ms,是 DolphinDB mytt module 中的 AVEDEV
函数的 1000 倍。测试数据量越大,性能差异越显著。
4.2 分组使用性能对比
- 测试数据为上海证券交易所 2020 年,全年 2919 个证券(筛选交易日大于 120)日频交易数据,总记录数为 686,104 条。
- 计算逻辑为按照股票代码进行分组计算各指标。
- 为了测试函数计算性能,DolphinDB 和 Python 测试代码都是单线程运行。
- DolphinDB 测试代码
- Python 测试代码
- 测试数据
- Python MyTT 库
测试结果如下表所示:
序号 | 函数 | Python(ms) | DolphinDB(ms) | 运行时间比 |
1 | RD | 296 | 16 | 18 |
2 | RET | 243 | 13 | 18 |
3 | ABS | 229 | 15 | 15 |
4 | LN | 253 | 25 | 10 |
5 | POW | 311 | 30 | 10 |
6 | SQRT | 248 | 19 | 13 |
7 | MAX | 390 | 34 | 11 |
8 | MIN | 373 | 29 | 12 |
9 | IF | 282 | 21 | 13 |
10 | REF | 740 | 17 | 43 |
11 | DIFF | 662 | 22 | 30 |
12 | STD | 1,263 | 24 | 98 |
13 | SUM | 1,297 | 22 | 58 |
14 | CONST | 258 | 22 | 11 |
15 | HHV | 1,207 | 30 | 40 |
16 | LLV | 1,218 | 31 | 39 |
17 | HHVBARS | 2,952 | 41 | 72 |
18 | LLVBARS | 2,878 | 38 | 75 |
19 | MA | 1,220 | 24 | 50 |
20 | EMA | 1,171 | 26 | 45 |
21 | SMA | 1,199 | 28 | 42 |
22 | WMA | 4,322 | 20 | 216 |
23 | DMA | 1,123 | 27 | 41 |
24 | AVEDEV | 176,652 | 32 | 5,520 |
25 | SLOPE | 53,703 | 29 | 1,851 |
26 | FORCAST | 60,321 | 38 | 1,587 |
27 | LAST | 4,132 | 38 | 108 |
28 | COUNT | 1,249 | 20 | 62 |
29 | EVERY | 1,267 | 28 | 45 |
30 | EXIST | 1,490 | 22 | 67 |
31 | BARSLAST | 559 | 18 | 31 |
32 | BARSLASTCOUNT | 607 | 17 | 35 |
33 | CROSS | 2,088 | 80 | 26 |
34 | LONGCROSS | 6,019 | 94 | 64 |
35 | VALUEWHEN | 968 | 27 | 35 |
36 | BETWEEN | 489 | 42 | 11 |
37 | MACD | 3,060 | 86 | 35 |
38 | KDJ | 4,705 | 144 | 32 |
39 | RSI | 2,539 | 103 | 24 |
40 | WR | 5,632 | 166 | 33 |
41 | BIAS | 5,318 | 135 | 39 |
42 | BOLL | 3,067 | 90 | 34 |
43 | PSY | 2,596 | 82 | 31 |
44 | CCI | 163,681 | 76 | 2,153 |
45 | ATR | 2,281 | 101 | 22 |
46 | BBI | 3,667 | 66 | 55 |
47 | DMI | 6,181 | 250 | 24 |
48 | TAQ | 2,292 | 64 | 35 |
49 | KTN | 3,170 | 164 | 19 |
50 | TRIX | 4,329 | 97 | 44 |
51 | VR | 2,732 | 117 | 23 |
52 | EMV | 4,437 | 132 | 33 |
53 | DPO | 2,455 | 59 | 41 |
54 | BRAR | 4,909 | 156 | 31 |
55 | DFMA | 2,890 | 52 | 55 |
56 | MTM | 1,659 | 43 | 38 |
57 | MASS | 4,602 | 99 | 46 |
58 | ROC | 2,000 | 63 | 31 |
59 | EXPMA | 1,900 | 49 | 38 |
60 | OBV | 1,790 | 94 | 19 |
61 | MFI | 3,488 | 158 | 22 |
62 | ASI | 4,173 | 316 | 13 |
从测试结果分析可知:
- DolphinDB mytt module 中的函数计算性能远远超过 Python MyTT 库,最大的性能差距达到 5520 倍,普遍性能差距在 30 倍左右。
**Python pandas 测试核心代码 **
DolphinDB 测试核心代码
5. 正确性验证
基于 4.2 分组使用性能对比中的测试数据和代码,验证 DolphinDB mytt module 中函数的计算结果是否和 Python MyTT 库一致。
5.1 浮点数精度问题
结果有差异的函数
-
CROSS, LONGCROSS
原因
- 浮点数精度问题
- 对于 CROSS 和 LONGCROSS 函数,在浮点数比较上,DolphinDB mytt module 中的处理比 Python MyTT 库更加严谨。DolphinDB mytt module 中首先会对浮点数 round 保留小数点后 6 位,然后再进行大小判断,而 MyTT 中并没有类似处理,因此对于相同大小的浮点数,Python 的判别可能会出错,如下图所示:
5.2 NULL 值的处理
结果有差异的函数
-
SUM, DMI, EMV, MASS, MFI, ASI
原因
- 若输入向量开始包含空值,则从第一个非空位置开始计算。DolphinDB mytt module 与 Python MyTT 库的计算规则一致。
- 对一个滚动 / 累积窗口长度为 k 的函数,每组最初的 (k-1) 个位置的结果均为空。DolphinDB mytt module 与 Python MyTT 库的计算规则一致。
- 对一个滚动 / 累积窗口长度为 k 的函数,若一组中第一个非空值之后再有空值,Python MyTT 库会对包含 nan 的窗口计算结果都处理为 nan。DolphinDB mytt module 会对窗口内非 NULL 的元素按计算规则计算,得到一个非 NULL 的计算结果。
DolphinDB 代码与结果:
Python 代码与结果:
以滑动窗口求和为例,close 向量的第 2 个元素为空值,DolphinDB mytt module 在计算第 5 个元素(60.9)时,回看过去 5 个窗口内的数据 [99.9, NULL, 84.69, 31.38, 60.9]
,对非 NULL 的元素求和,所以结果向量的第 5 个元素为 276.87。
Python MyTT 库会对包含 nan 的窗口计算结果都处理为 nan,所以结果向量的前 6 个元素都为 nan。
除上述因为浮点数精度问题和 NULL 值的处理问题导致计算结果存在差异外,其余函数计算结果的百分比误差均小于 1e-10。
6. 实时流计算案例
在 DolphinDB V1.30.3 中发布的响应式状态引擎(Reactive State Engine)是许多金融场景流批统一计算中的重要构件,DolphinDB mytt module 在开发时就对其做了适配,使得 mytt 模块中的大部分函数可以在响应式状态引擎中实现增量计算。
- 当前无法在响应式状态引擎中使用的指标函数:
RET, CONST, BARSLAST, BARSLASTCOUNT
,已经规划开发。 - 所有 mytt 中的技术指标函数均支持增量计算。
示例代码如下:
7. DolphinDB mytt 指标列表
7.1 核心工具函数
函数 | 语法 | 解释 |
RD | RN(N, D = 3) | 四舍五入取 3 位小数 |
RET | RET(S, N = 1) | 返回序列 倒数第 N 个值,默认返回最后一个 |
ABS | ABS(S) | 返回序列或数值 S 的绝对值 |
LN | LN(S) | 求序列 S 底是 e 的自然对数 |
POW | POW(S, N) | 求序列 S 的 N 次方 |
SQRT | SQRT(S) | 求序列 S 的平方根 |
MAX | MAX(S1, S2) | 配对比较两个序列,给出比较以后大的序列 |
MIN | MIN(S1, S2) | 配对比较两个序列,给出比较以后小的序列 |
IF | IF(S, A, B) | 序列布尔判断,if S == True return A else B |
REF | REF(S, N = 1) | 对序列整体下移动 N 个单位,返回平移后的序列,会产生 NAN |
DIFF | DIFF(S, N = 1) | 序列 S 的前一个值减后一个值,序列头部会产生 NAN |
STD | STD(S, N) | 求序列 S 的滚动 N 日标准差,返回滚动标准差序列 |
SUM | SUM(S, N) | 对序列 S 求滚动 N 日总和 |
CONST | COUNT(S) | 返回序列 S 最后一个值组成常量序列 |
HHV | HHV(S, N) | 求序列 S 的滚动 N 日最大值,返回滚动最大值序列 |
LLV | LLV(S, N) | 求序列 S 的滚动 N 日最小值,返回滚动最小值序列 |
HHVBARS | HHVBARS(S, N) | 求序列 S 的滚动 N 期内最高值到当前的天数, 返回距离天数序列 |
LLVBARS | LLVBARS(S, N) | 求序列 S 的滚动 N 期内最低值到当前的天数, 返回距离天数序列 |
MA | MA(S, N) | 求序列 S 的 N 日简单移动平均值,返回移动平均序列 |
EMA | EMA(S, N) | 求序列 S 的指数移动平均,为了精度,S>4*N,EMA 至少需要 120 周期 alpha = 2/(span+1) |
SMA | SMA(S, N, M = 1) | 中国式的 SMA,至少需要 120 周期才精确 (雪球 180 周期),alpha = 1/(1+N) |
WMA | WMA(S, N) | 求 S 序列 S 的 N 日加权移动平均,Yn = (1*X1+2*X2+3*X3+...+n*Xn)/(1+2+3+...+n) |
DMA | DMA(S, A) | 求 S 的动态移动平均,A 作平滑因子,必须 0 < A < 1 |
AVEDEV | AVEDEV(S, N) | 求序列 S 的滚动平均绝对偏差 |
SLOPE | SLOPE(S, N) | 求序列 S 的滚动 N 周期内的线性回归模型的斜率 |
FORCAST | FORCAST(S, N) | 求序列 S 的滚动 N 周期内的线性回归模型的预测值 |
LAST_ | LAST_(S, A, B) | BOOL 型判断,从前 A 日到前 B 日一直满足 BOOL 条件,要求 A > B & A > 0 & B >= 0 |
7.2 应用层函数 (通过核心工具函数实现)
函数 | 语法 | 解释 |
COUNT | COUNT(S, N) | 序列 S 是 BOOL 型,求最滚动 N 天内满足 BOOL 为 True 的天数 |
EVERY | EVERY(S, N) | 序列 S 是 BOOL 型,求最滚动 N 天内 全部 满足 BOOL 为 True 的天数 |
EXIST | EXIST(S, N) | 序列 S 是 BOOL 型,判断最滚动 N 天内 是否存在 满足 BOOL 为 True |
BARSLAST | BARSLAST(S) | 序列 S 是 BOOL 型,统计上一次条件成立到当前的周期 |
BARSLASTCOUNT | BARSLASTCOUNT(S) | 序列 S 是 BOOL 型,统计连续满足条件的周期数 |
BARSSINCEN | BARSSINCEN(S, N) | 序列 S 是 BOOL 型,统计滚动周期 N 内第一次满足条件到当前的周期数 |
CROSS | CROSS(S1, S2) | 判断两个序列是否交叉的函数,判断向上金叉穿越 CROSS(MA(C,5),MA(C,10)) ,判断向下死叉穿越 CROSS(MA(C,10),MA(C,5)) |
LONGCROSS | LONGCROSS(S1, S2, N) | 判断两个序列是否在个持一定周期后再交叉的函数,判断两个序列是否再个持 N 周期后再交叉,N = 1 时等同于 CROSS(S1, S2) |
VALUEWHEN | VALUEWHEN(S, X) | 解决当 S 条件成立时, 取 X 的当前值, 否则取 S 的上个成立时对应的 X 值 |
BETWEEN | BETWEEN(S, A, B) | 判断 S 序列是否介于 A 和 B 之间的函数,当 S 处于 A 和 B 之间时为真,包括 A<S<B 或 A>S>B |
7.3 技术指标函数 (全部通过核心工具和应用函数实现)
函数 | 语法 | 解释 |
MACD | MACD(CLOSE, SHORT = 12, LONG = 26, M = 9) | 平滑异同平均线 |
KDJ | KDJ(CLOSE, HIGH, LOW, N = 9, M1 = 3, M2 = 3) | KDJ 指标 |
RSI | RSI(CLOSE, N = 24) | RSI 指标, 和通达信小数点 2 位相同 |
WR | WR(CLOSE, HIGH, LOW, N = 10, N1 = 6) | W&R 威廉指标 |
BIAS | BIAS(CLOSE, L1 = 6, L2 = 12, L3 = 24) | BIAS 乖离率 |
BOLL | BOLL(CLOSE, N = 20, P = 2) | BOLL 指标,布林带 |
PSY | PSY(CLOSE, N = 12, M = 6) | PSY 指标,心理线 |
CCI | CCI(CLOSE, HIGH, LOW, N = 14) | CCI 指标,顺势线 |
ATR | ATR(CLOSE, HIGH, LOW, N = 20) | 真实波动 N 日平均值 |
BBI | BBI(CLOSE, M1 = 3, M2 = 6, M3 = 12, M4 = 20) | BBI 多空指标 |
DMI | DMI(CLOSE, HIGH, LOW, M1 = 14, M2 = 6) | DMI 动向指标 |
TAQ | TAQ(HIGH, LOW, N) | 唐安奇通道 (海龟) 交易指标 |
KTN | KTN(CLOSE, HIGH, LOW, N = 20, M = 10) | 肯特纳交易通道 |
TRIX | TRIX(CLOSE, M1 = 12, M2 = 20) | 三重指数平滑平均线 |
VR | VR(CLOSE, VOL, M1 = 26) | VR 容量比率 |
EMV | EMV(HIGH, LOW, VOL, N = 14, M = 9) | EMV 简易波动指标 |
DPO | DPO(CLOSE, M1 = 20, M2 = 10, M3 = 6) | 区间震荡线 |
BRAR | BRAR(OPEN, CLOSE, HIGH, LOW, M1 = 26) | BRAR-ARBR 情绪指标 |
DFMA | DFMA(CLOSE, N1 = 10, N2 = 50, M = 10) | DFMA 平行线差指标 |
MTM | MTM(CLOSE, N = 12, M = 6) | MTM 动量指标 |
MASS | MASS(HIGH, LOW, N1 = 9, N2 = 25, M = 6) | 梅斯线 |
ROC | ROC(CLOSE, N = 12, M = 6) | 变动率指标 |
EXPMA | EXPMA(CLOSE, N1 = 12, N2 = 50) | 指数平均数指标 |
OBV | OBV(CLOSE, VOL) | 能量潮指标 |
MFI | MFI(CLOSE, HIGH, LOW, VOL, N = 14) | MFI 资金流量 |
ASI | ASI(OPEN, CLOSE, HIGH, LOW, M1 = 26, M2 = 10) | 振动升降指标 |
8. 路线图(Road Map)
- 优化当前无法在响应式状态引擎中使用的指标函数,包括
RET, CONST, BARSLAST, BARSLASTCOUNT
,预计在 DolphinDB V1.30.19 和 DolphinDB V2.00.7 支持上述函数的增量计算和在响应式状态引擎中的使用。 - 长期保持对 Python MyTT 包的同步更新。
附件
计算性能测试环境
- CPU 类型:Intel(R) Core(TM) i7-7700 CPU @ 3.60GHz 3.60 GHz
- 逻辑 CPU 总数:8
- 内存:32GB
- OS:Windows 10