There are three types of technical indicators
- Time series indicators. Must be sorted by time, and then calculated. It is difficult to handle null in the middle.
- Cross-sectional indicators. No order requirement, the whole row is calculated, and there may be a null, which needs to be compatible.
- Single element indicators. Can be single-column, multi-column, and can be calculated in any way.
In terms of calculation, time series indicators have one more dimension than cross-sectional indicators. For example
-
cs_rankis a cross-sectional sort -
ts_rankis to calculatecs_rankin a rolling time window, take[-1]each time, and then concatenate them -
cs_zscorefirst aggregates to calculatemeanandstd, then broadcastmeanandstd, and perform a one-dimensional calculation withx
So common technical indicators are generally the flexible application of aggregation and broadcasting
Since ts_ indicators are based on cs_, theoretically rolling can be used directly, but in practice, it is generally not used in this way.
cs_ is generally rewritten in cython, numba, etc., and if you mix ts_ and cs_, ts_ will make thousands of cs_ call.
So it is common to put rolling operations into cython, numba, etc. as well.
-
Expr.map_batchescan be used to call third-party libraries, such asTA-Lib, bottleneck. But because of the input and output format requirements, you need to wrap the third-party API with a function.- Both input and output can only be one column. If you want to support multiple columns, you need to convert them to
pl.Struct. After that, you need to useunnestto splitpl.Struct. - The output must be
pl.Series
- Both input and output can only be one column. If you want to support multiple columns, you need to convert them to
-
Start to use
register_expr_namespaceto simplify the code- Implementation helper.py
- Usage demo demo_ta1.py
- Pros: Easy to use
- Cons:
- The
member function call modeis not convenient for inputting into genetic algorithms for factor mining __getattribute__dynamic method call is very flexible, but losesIDEsupport.
- The
-
Prefix expression. Convert all member functions into formulas
- Implementation wrapper.py
- Usage demo demo_ta2.py
- Pros: Can be input into our implementation of genetic algorithms
- Cons:
__getattribute__dynamic method call is very flexible, but losesIDEsupport.
-
Code generation.
- Implementation codegen_talib.py
- Generated result will be at __init__.py
- Usage demo demo_ta3.py
- Pros:
- Can be input into our implementation of genetic algorithms
IDEsupport
用使用方式来说,指标分为三种
- 时序指标。必须按时间排序,然后计算,中段出现null比较难处理
- 截面指标。对顺序无要求,整行计算即可,数据会有null,需要能兼容
- 单元素指标。可单列、多列,可任意方式计算
从计算原理上来说,时序指标比截面指标多了一个计算维度。例如
cs_rank是横截面排序- 而
ts_rank是对数据滚动时间窗口计算cs_rank,每次取[-1],然后拼接起来
又例如
cs_zscore先聚合计算mean和std- 然后将
mean与std广播,与x进行一维计算
所以常见的技术指标一般是聚合与广播的灵活应用
由于ts_指标基于cs_,理论上直接rolling即可,但在实践中一般不这么用,因为为了求快,cs_一般是更底层的语言编写,如cython、numba等,
本来cs_版python与底层只交互一次,而ts_调用cs_版会导致交互千万次,性能极低
一般是把rolling操作也放在底层,在底层循环调用cs_底层版
Expr.map_batches可以实现调用第三方库,如TA-Lib, bottleneck。但因为对输入与输出格式有要求,所以还需要用函数对第三方API封装一下。- 输入输出都只能是一列,如要支持多列需转换成
pl.Struct。事后pl.Struct要拆分需使用unnest - 输出必须是
pl.Series
- 输入输出都只能是一列,如要支持多列需转换成
- 参数多,代码长。开始使用
register_expr_namespace来简化代码- 实现代码helper.py
- 使用演示demo_ta1.py
- 优点:使用简单
- 不足:
成员函数调用模式不便于输入到遗传算法中进行因子挖掘 - 不足:
__getattribute__动态方法调用非常灵活,但失去了IDE智能提示
- 前缀表达式。将所有的成员函数都转换成公式
- 实现代码wrapper.py
- 使用演示demo_ta2.py
- 优点:可以输入到遗传算法
- 不足:
__getattribute__动态方法调用非常灵活,但失去了IDE智能提示
- 代码自动生成。
- 实现代码codegen_talib.py
- 生成结果__init__.py
- 使用演示demo_ta3.py
- 优点:即可以输入到遗传算法,
IDE还有智能提示