中国版技术指标
polars
中使用技术指标,请使用polars_ta初学量化,技术指标一般使用TA-Lib
,但存在以下问题
TA-Lib
只支持单支序列,要计算多支股票需循环,耗时久。在实现遗传算法挖因子时,意识到如果能将常用的操作都转成算子,将大大简化策略的研究,
特别是将+
、-
、*
、/
等中缀操作符转成ADD()
、SUB()
、MUL()
、DIV()
前缀函数,可直接输到遗传算法工具中
所以开始参考Alpha101
和各券商金融工程研报,试着实现一些算子,但后期实现中发现一些问题
直到看到了MyTT
这个项目才意识到,指标命名参考股票软件的公式才是最方便直接的,可以直接到各股软中复制公式。遇到性能问题再针对性转换即可。
MyTT
,而是重复造轮子呢?TA-Lib
与国内指标不同,区别在哪,没有对比。错过了很好的教学机会ts_
前缀pip install ta_cn -i https://mirrors.aliyun.com/pypi/simple --upgrade
pip install ta_cn[cn] -i https://mirrors.aliyun.com/pypi/simple --upgrade
PyPI
,需要时效更高的安装方法
pip install .[cn] -i https://mirrors.aliyun.com/pypi/simple --upgrade
pip install -e .
import numpy as np
# 新版talib,只要替换引用,并添加一句init即可
import ta_cn.talib as ta
from ta_cn.utils_wide import pushna, pullna
# 原版talib,不支持二维数据
# import talib as ta
# 准备数据
h = np.random.rand(1000000).reshape(-1, 5000) + 10
l = np.random.rand(1000000).reshape(-1, 5000)
c = np.random.rand(1000000).reshape(-1, 5000)
# 指定模式,否则对talib封装的所有函数都不存在
ta.init(mode=2, skipna=False, to_globals=True)
# 几个调用函数演示
r = ta.ATR(h, l, c, timeperiod=10)
print(r)
x, y, z = ta.BBANDS(c, timeperiod=10, nbdevup=2, nbdevdn=2)
print(z)
# 将少量值设置为空,用来模拟停牌
c[c < 0.4] = np.nan
# 提前处理数据,跳过停牌进行计算,再还原的演示
# 嵌套指标时,全为时序指标使用down,或全为截面使用right。混合时此方法不要轻易使用
arr, row, col = pushna(c, direction='down')
rr = ta.SMA(arr, timeperiod=10)
r = pullna(rr, row, col)
print(r)
import numpy as np
from ta_cn.talib import init, set_compatibility_enable, set_compatibility
from ta_cn.tdx.over_bought_over_sold import ATR_CN
from ta_cn.tdx.trend import MACD
# ta_cn.talib库底层是循环调用talib,部分计算效率不高
# 可导入ta_cn中的公式
# 准备数据
h = np.random.rand(10000000).reshape(-1, 50000) + 10
l = np.random.rand(10000000).reshape(-1, 50000)
c = np.random.rand(10000000).reshape(-1, 50000)
init(mode=2, skipna=False)
r = ATR_CN(h, l, c, timeperiod=10)
print(r)
# 设置参数,让MACD中的EMA算法与国内算法相同
set_compatibility_enable(True)
set_compatibility(1)
set_compatibility_enable(False)
x, y, z = MACD(c, fastperiod=12, slowperiod=26, signalperiod=9)
print(z)
二维矩阵计算,的确方便,Alpha101
中的公式很快就可以实现,即支持时序又支持截面,但其中有一个难点,
就是NaN值的处理。pushna
和pullna
可用于解决此问题,但在公式中嵌入就比较棘手。
所以,本项目还特别提供了长表与宽表的装饰器,按照一定的要求套用装饰器,就能让原本不可跳过空值的函数自动跳过空值。 如果明确数据内不会产生空值,可以不使用长宽表装饰器,效率会更快。
处理慢一些,但结果更适合于机器学习。
底层主要通过series_groupby_apply
(针对单列输入)和dataframe_groupby_apply
(针对多列输入)装饰器来实现跳过空值。
import pandas as pd
from ta_cn.imports.long_ta import ATR, SMA
from ta_cn.imports.long_wq import group_neutralize, rank
pd._testing._N = 500
pd._testing._K = 30
open_ = pd._testing.makeTimeDataFrame() + 5
high = pd._testing.makeTimeDataFrame() + 10
low = pd._testing.makeTimeDataFrame() + 5
close = pd._testing.makeTimeDataFrame() + 5
group = close.copy() * 100 // 1 % 5
df = {
'open_': open_.stack(),
'high': high.stack(),
'low': low.stack(),
'close': close.stack(),
'group': group.stack(),
}
df = pd.DataFrame(df)
df.index.names = ['date', 'asset']
kwargs = df.to_dict(orient='series')
# 单输入
r = SMA(df['close'], timeperiod=10)
print(r.unstack())
# 多输入
r = ATR(df['high'], df['low'], df['close'], 10)
print(r.unstack())
# 横截面
r = rank(df['close'])
print(r.unstack())
r = group_neutralize(df['close'], df['group'])
print(r.unstack())
处理速度通常比长表要快。核心是输入需要封装成WArr
,输出要.raw()
提取。
底层通过wide_wraps
装饰器来实现空值跳过,通过long_wraps
装饰器来实现长表函数转宽表函数
import pandas as pd
from ta_cn.imports.wide_ta import ATR
from ta_cn.utils import np_to_pd
from ta_cn.utils_wide import WArr
pd._testing._N = 250
pd._testing._K = 30
h = pd._testing.makeTimeDataFrame() + 10
l = pd._testing.makeTimeDataFrame()
c = pd._testing.makeTimeDataFrame()
# 数据需要封装成特殊对象,实现NaN的堆叠和还原
h_ = WArr.from_array(h, direction='down')
l_ = WArr.from_array(l, direction='down')
c_ = WArr.from_array(c, direction='down')
r = ATR(h_, l_, c_, 10)
# 返回的数据可能是np.ndarray
print(r.raw())
# 可以再封装回pd.DataFrame
d = np_to_pd(r.raw(), copy=False, index=c.index, columns=c.columns)
print(d.iloc[-5:])
参考 指标对比 未完工,待补充
本项目,试着用公式系统实现Alpha101
、Alpha191
,请参考examples文件下的测试示例。它最大的特点是尽量保持原公式的形式,
少改动,防止乱中出错。然后再优化代码提高效率。
ta_cn技术指标交流群: 601477228