polars-ta 0.5.2__py3-none-any.whl → 0.5.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.
- polars_ta/_version.py +1 -1
- polars_ta/labels/__init__.py +1 -0
- polars_ta/labels/_nb.py +40 -0
- polars_ta/labels/future.py +165 -0
- polars_ta/performance/returns.py +1 -7
- polars_ta/prefix/labels.py +1 -0
- polars_ta/ta/README.md +12 -0
- polars_ta/talib/README.md +12 -0
- polars_ta/tdx/README.md +10 -0
- polars_ta/utils/numba_.py +2 -0
- polars_ta/wq/arithmetic.py +151 -25
- polars_ta/wq/cross_sectional.py +27 -15
- polars_ta/wq/logical.py +3 -3
- polars_ta/wq/preprocess.py +19 -42
- polars_ta/wq/time_series.py +62 -33
- polars_ta/wq/transformational.py +10 -5
- {polars_ta-0.5.2.dist-info → polars_ta-0.5.4.dist-info}/METADATA +13 -10
- {polars_ta-0.5.2.dist-info → polars_ta-0.5.4.dist-info}/RECORD +20 -14
- {polars_ta-0.5.2.dist-info → polars_ta-0.5.4.dist-info}/WHEEL +1 -2
- polars_ta-0.5.2.dist-info/top_level.txt +0 -1
- {polars_ta-0.5.2.dist-info → polars_ta-0.5.4.dist-info}/licenses/LICENSE +0 -0
polars_ta/wq/cross_sectional.py
CHANGED
@@ -17,7 +17,9 @@ _ols_kwargs = OLSKwargs(null_policy='drop', solve_method='svd')
|
|
17
17
|
|
18
18
|
|
19
19
|
def cs_one_side(x: Expr, is_long: bool = True) -> Expr:
|
20
|
-
"""
|
20
|
+
"""横截面上,将全部资产上调或下调,使得 Alpha 策略转为纯多头配置(当方向参数设为空头时则转为纯空头配置)
|
21
|
+
|
22
|
+
Shifts all instruments up or down so that the Alpha becomes long-only or short-only
|
21
23
|
(if side = short), respectively.
|
22
24
|
|
23
25
|
Examples
|
@@ -54,7 +56,9 @@ def cs_one_side(x: Expr, is_long: bool = True) -> Expr:
|
|
54
56
|
|
55
57
|
|
56
58
|
def cs_scale(x: Expr, scale_: float = 1, long_scale: float = 1, short_scale: float = 1) -> Expr:
|
57
|
-
"""
|
59
|
+
"""横截面上,将输入数据进行比例调整。此外,可通过向运算符添加额外参数,将多头头寸和空头头寸分别映射到独立的缩放比例上
|
60
|
+
|
61
|
+
Scales input to booksize. We can also scale the long positions and short positions to separate scales by mentioning additional parameters to the operator.
|
58
62
|
|
59
63
|
Examples
|
60
64
|
--------
|
@@ -95,7 +99,9 @@ def cs_scale(x: Expr, scale_: float = 1, long_scale: float = 1, short_scale: flo
|
|
95
99
|
|
96
100
|
|
97
101
|
def cs_scale_down(x: Expr, constant: int = 0) -> Expr:
|
98
|
-
"""
|
102
|
+
"""横截面上,将每日数据按比例缩放至 [0,1] 区间,使得最小值映射为 0,最大值映射为 1,并通过减去常数偏移量调整最终结果
|
103
|
+
|
104
|
+
Scales all values in each day proportionately between 0 and 1 such that minimum value maps to 0 and maximum value maps to 1.
|
99
105
|
constant is the offset by which final result is subtracted
|
100
106
|
|
101
107
|
Examples
|
@@ -130,7 +136,9 @@ def cs_scale_down(x: Expr, constant: int = 0) -> Expr:
|
|
130
136
|
|
131
137
|
|
132
138
|
def cs_truncate(x: Expr, max_percent: float = 0.01) -> Expr:
|
133
|
-
"""
|
139
|
+
"""横截面上,将所有 x 的取值截断至 maxPercent 指定的上限值,其中 maxPercent 需以十进制小数形式表示
|
140
|
+
|
141
|
+
Operator truncates all values of x to maxPercent. Here, maxPercent is in decimal notation
|
134
142
|
|
135
143
|
Examples
|
136
144
|
--------
|
@@ -161,8 +169,8 @@ def cs_truncate(x: Expr, max_percent: float = 0.01) -> Expr:
|
|
161
169
|
return x.clip(upper_bound=x.sum() * max_percent)
|
162
170
|
|
163
171
|
|
164
|
-
def cs_fill_except_all_null(x: Expr, value=0) -> Expr:
|
165
|
-
"""
|
172
|
+
def cs_fill_except_all_null(x: Expr, value: float = 0) -> Expr:
|
173
|
+
"""横截面上,全为`null`时,保持`null`,反之`null`填充为`value`
|
166
174
|
|
167
175
|
Examples
|
168
176
|
--------
|
@@ -199,27 +207,29 @@ def cs_fill_except_all_null(x: Expr, value=0) -> Expr:
|
|
199
207
|
|
200
208
|
|
201
209
|
def cs_fill_mean(x: Expr) -> Expr:
|
202
|
-
"""
|
210
|
+
"""横截面上,填充`null`为均值"""
|
203
211
|
return x.fill_null(strategy='mean')
|
204
212
|
|
205
213
|
|
206
|
-
def cs_fill_null(x: Expr, value=0) -> Expr:
|
207
|
-
"""
|
214
|
+
def cs_fill_null(x: Expr, value: float = 0) -> Expr:
|
215
|
+
"""横截面上,填充`null`为`value`"""
|
208
216
|
return x.fill_null(value)
|
209
217
|
|
210
218
|
|
211
219
|
def cs_regression_neut(y: Expr, x: Expr) -> Expr:
|
212
|
-
"""
|
220
|
+
"""横截面上,一元回归残差"""
|
213
221
|
return pls.compute_least_squares(y, x, add_intercept=True, mode='residuals', ols_kwargs=_ols_kwargs)
|
214
222
|
|
215
223
|
|
216
224
|
def cs_regression_proj(y: Expr, x: Expr) -> Expr:
|
217
|
-
"""
|
225
|
+
"""横截面上,一元回归预测"""
|
218
226
|
return pls.compute_least_squares(y, x, add_intercept=True, mode='predictions', ols_kwargs=_ols_kwargs)
|
219
227
|
|
220
228
|
|
221
229
|
def cs_rank(x: Expr, pct: bool = True) -> Expr:
|
222
|
-
"""
|
230
|
+
"""横截面排名。
|
231
|
+
|
232
|
+
Ranks the input among all the instruments and returns an equally distributed number between 0.0 and 1.0. For precise sort, use the rate as 0.
|
223
233
|
|
224
234
|
Parameters
|
225
235
|
----------
|
@@ -269,7 +279,7 @@ def cs_rank(x: Expr, pct: bool = True) -> Expr:
|
|
269
279
|
|
270
280
|
|
271
281
|
def _cs_qcut_rank(x: Expr, q: int = 10) -> Expr:
|
272
|
-
"""
|
282
|
+
"""横截面上等频分箱
|
273
283
|
|
274
284
|
Parameters
|
275
285
|
----------
|
@@ -314,7 +324,9 @@ def _cs_qcut_rank(x: Expr, q: int = 10) -> Expr:
|
|
314
324
|
|
315
325
|
|
316
326
|
def cs_qcut(x: Expr, q: int = 10) -> Expr:
|
317
|
-
"""
|
327
|
+
"""横截面上等频分箱
|
328
|
+
|
329
|
+
Convert float values into indexes for user-specified buckets. Bucket is useful for creating group values, which can be passed to group operators as input.
|
318
330
|
|
319
331
|
Parameters
|
320
332
|
----------
|
@@ -362,7 +374,7 @@ def cs_qcut(x: Expr, q: int = 10) -> Expr:
|
|
362
374
|
|
363
375
|
|
364
376
|
def cs_top_bottom(x: Expr, k: int = 10) -> Expr:
|
365
|
-
"""
|
377
|
+
"""横截面上,排名。前K标记成-1,后K标记成1
|
366
378
|
|
367
379
|
Examples
|
368
380
|
--------
|
polars_ta/wq/logical.py
CHANGED
@@ -12,9 +12,9 @@ def equal(input1: Expr, input2: Expr) -> Expr:
|
|
12
12
|
return input1 == input2
|
13
13
|
|
14
14
|
|
15
|
-
def if_else(
|
16
|
-
"""
|
17
|
-
return when(
|
15
|
+
def if_else(condition: Expr, true_value: Expr, false_value: Expr = None) -> Expr:
|
16
|
+
"""条件判断"""
|
17
|
+
return when(condition).then(true_value).otherwise(false_value)
|
18
18
|
|
19
19
|
|
20
20
|
def is_finite(input1: Expr) -> Expr:
|
polars_ta/wq/preprocess.py
CHANGED
@@ -8,10 +8,12 @@ from polars_ta.wq.cross_sectional import cs_rank
|
|
8
8
|
# ======================
|
9
9
|
# standardize
|
10
10
|
def cs_zscore(x: Expr, ddof: int = 0) -> Expr:
|
11
|
+
"""横截面zscore标准化"""
|
11
12
|
return (x - x.mean()) / x.std(ddof=ddof)
|
12
13
|
|
13
14
|
|
14
15
|
def cs_minmax(x: Expr) -> Expr:
|
16
|
+
"""横截面minmax标准化"""
|
15
17
|
a = x.min()
|
16
18
|
b = x.max()
|
17
19
|
# 这个版本在b-a为整数时,得到的结果不好看
|
@@ -22,12 +24,14 @@ def cs_minmax(x: Expr) -> Expr:
|
|
22
24
|
# ======================
|
23
25
|
# winsorize
|
24
26
|
def cs_quantile(x: Expr, low_limit: float = 0.025, up_limit: float = 0.995) -> Expr:
|
27
|
+
"""横截面分位数去极值"""
|
25
28
|
a = x.quantile(low_limit)
|
26
29
|
b = x.quantile(up_limit)
|
27
30
|
return x.clip(lower_bound=a, upper_bound=b)
|
28
31
|
|
29
32
|
|
30
33
|
def cs_3sigma(x: Expr, n: float = 3.) -> Expr:
|
34
|
+
"""横截面3倍sigma去极值"""
|
31
35
|
# fill_nan will seriously reduce speed. So it's more appropriate for users to handle it themselves
|
32
36
|
# fill_nan(None) 严重拖慢速度,所以还是由用户自己处理更合适
|
33
37
|
a = x.mean()
|
@@ -36,7 +40,13 @@ def cs_3sigma(x: Expr, n: float = 3.) -> Expr:
|
|
36
40
|
|
37
41
|
|
38
42
|
def cs_mad(x: Expr, n: float = 3., k: float = 1.4826) -> Expr:
|
39
|
-
|
43
|
+
"""横截面MAD去极值
|
44
|
+
|
45
|
+
References
|
46
|
+
----------
|
47
|
+
https://en.wikipedia.org/wiki/Median_absolute_deviation
|
48
|
+
|
49
|
+
"""
|
40
50
|
a = x.median()
|
41
51
|
b = (n * k) * (x - a).abs().median()
|
42
52
|
return x.clip(lower_bound=a - b, upper_bound=a + b)
|
@@ -45,7 +55,7 @@ def cs_mad(x: Expr, n: float = 3., k: float = 1.4826) -> Expr:
|
|
45
55
|
# ======================
|
46
56
|
# neutralize
|
47
57
|
def cs_demean(x: Expr) -> Expr:
|
48
|
-
"""
|
58
|
+
"""横截面去均值化
|
49
59
|
|
50
60
|
Notes
|
51
61
|
-----
|
@@ -66,75 +76,42 @@ def cs_demean(x: Expr) -> Expr:
|
|
66
76
|
_ols_kwargs = OLSKwargs(null_policy='drop', solve_method='svd')
|
67
77
|
|
68
78
|
|
69
|
-
# def _residual_multiple(cols: List[Series], add_constant: bool) -> Series:
|
70
|
-
# # 将pl.Struct转成list,这样可以实现传正则,其它也转list
|
71
|
-
# cols = [list(c.struct) if isinstance(c.dtype, Struct) else [c] for c in cols]
|
72
|
-
# # 二维列表转一维列表,再转np.ndarray
|
73
|
-
# cols = [i.to_numpy() for p in cols for i in p]
|
74
|
-
# if add_constant:
|
75
|
-
# cols += [np.ones_like(cols[0])]
|
76
|
-
# yx = np.vstack(cols).T
|
77
|
-
#
|
78
|
-
# # skip nan
|
79
|
-
# mask = np.any(np.isnan(yx), axis=1)
|
80
|
-
# yx_ = yx[~mask, :]
|
81
|
-
#
|
82
|
-
# y = yx_[:, 0]
|
83
|
-
# x = yx_[:, 1:]
|
84
|
-
# coef = np.linalg.lstsq(x, y, rcond=None)[0]
|
85
|
-
# y_hat = np.sum(x * coef, axis=1)
|
86
|
-
# residual = y - y_hat
|
87
|
-
#
|
88
|
-
# # refill
|
89
|
-
# out = np.empty_like(yx[:, 0])
|
90
|
-
# out[~mask] = residual
|
91
|
-
# out[mask] = np.nan
|
92
|
-
# return Series(out, nan_to_null=True)
|
93
|
-
#
|
94
|
-
#
|
95
|
-
# def cs_resid_(y: Expr, *more_x: Expr) -> Expr:
|
96
|
-
# """multivariate regression
|
97
|
-
# 多元回归
|
98
|
-
# """
|
99
|
-
# return map_batches([y, *more_x], lambda xx: _residual_multiple(xx, False))
|
100
|
-
|
101
|
-
|
102
79
|
def cs_resid(y: Expr, *more_x: Expr) -> Expr:
|
103
|
-
"""
|
80
|
+
"""横截面多元回归取残差"""
|
104
81
|
return pls.compute_least_squares(y, *more_x, mode='residuals', ols_kwargs=_ols_kwargs)
|
105
82
|
|
106
83
|
|
107
84
|
def cs_mad_zscore(y: Expr) -> Expr:
|
108
|
-
"""
|
85
|
+
"""横截面去极值、标准化"""
|
109
86
|
return cs_zscore(cs_mad(y))
|
110
87
|
|
111
88
|
|
112
89
|
def cs_mad_zscore_resid(y: Expr, *more_x: Expr) -> Expr:
|
113
|
-
"""
|
90
|
+
"""横截面去极值、标准化、中性化"""
|
114
91
|
return cs_resid(cs_zscore(cs_mad(y)), *more_x)
|
115
92
|
|
116
93
|
|
117
94
|
def cs_mad_rank(y: Expr) -> Expr:
|
118
|
-
"""
|
95
|
+
"""横截面去极值、排名"""
|
119
96
|
return cs_rank(cs_mad(y))
|
120
97
|
|
121
98
|
|
122
99
|
def cs_mad_rank2(y: Expr, m: float) -> Expr:
|
123
|
-
"""
|
100
|
+
"""横截面去极值,排名,移动峰或谷到零点,然后平方。非线性处理
|
124
101
|
|
125
102
|
适合于分层收益V型或倒V的情况"""
|
126
103
|
return (cs_rank(cs_mad(y)) - m) ** 2
|
127
104
|
|
128
105
|
|
129
106
|
def cs_mad_rank2_resid(y: Expr, m: float, *more_x: Expr) -> Expr:
|
130
|
-
"""
|
107
|
+
"""横截面去极值,排名,移动峰或谷到零点,然后平方。回归取残差。非线性处理
|
131
108
|
|
132
109
|
适合于分层收益V型或倒V的情况"""
|
133
110
|
return cs_resid((cs_rank(cs_mad(y)) - m) ** 2, *more_x)
|
134
111
|
|
135
112
|
|
136
113
|
def cs_rank2(y: Expr, m: float) -> Expr:
|
137
|
-
"""
|
114
|
+
"""横截面移动峰或谷到零点,然后平方。非线性处理
|
138
115
|
|
139
116
|
适合于分层收益V型或倒V的情况"""
|
140
117
|
return (cs_rank(y) - m) ** 2
|
polars_ta/wq/time_series.py
CHANGED
@@ -12,7 +12,9 @@ from polars_ta.wq._nb import roll_argmax, roll_argmin, roll_co_kurtosis, roll_co
|
|
12
12
|
|
13
13
|
|
14
14
|
def ts_arg_max(x: Expr, d: int = 5, reverse: bool = True, min_samples: Optional[int] = None) -> Expr:
|
15
|
-
"""
|
15
|
+
"""窗口内最大值出现的相对位置,最近的一天记为第 0 天,最远的一天为第 d-1 天
|
16
|
+
|
17
|
+
Returns the relative index of the max value in the time series for the past d days.
|
16
18
|
If the current day has the max value for the past d days, it returns 0.
|
17
19
|
If previous day has the max value for the past d days, it returns 1.
|
18
20
|
|
@@ -61,7 +63,7 @@ def ts_arg_max(x: Expr, d: int = 5, reverse: bool = True, min_samples: Optional[
|
|
61
63
|
|
62
64
|
|
63
65
|
def ts_arg_min(x: Expr, d: int = 5, reverse: bool = True, min_samples: Optional[int] = None) -> Expr:
|
64
|
-
"""
|
66
|
+
"""窗口内最小值出现的相对位置,最近的一天记为第 0 天,最远的一天为第 d-1 天
|
65
67
|
|
66
68
|
Parameters
|
67
69
|
----------
|
@@ -85,19 +87,21 @@ def ts_arg_min(x: Expr, d: int = 5, reverse: bool = True, min_samples: Optional[
|
|
85
87
|
|
86
88
|
|
87
89
|
def ts_co_kurtosis(x: Expr, y: Expr, d: int = 5, ddof: int = 0, min_samples: Optional[int] = None) -> Expr:
|
90
|
+
"""计算两个序列在滚动窗口内联合分布的协峰度"""
|
88
91
|
minp = min_samples or polars_ta.MIN_SAMPLES or d
|
89
92
|
return struct([x, y]).map_batches(lambda xx: batches_i2_o1(struct_to_numpy(xx, 2), roll_co_kurtosis, d, minp))
|
90
93
|
|
91
94
|
|
92
95
|
def ts_co_skewness(x: Expr, y: Expr, d: int = 5, ddof: int = 0, min_samples: Optional[int] = None) -> Expr:
|
96
|
+
"""计算两个序列在滚动窗口内联合分布的协偏度"""
|
93
97
|
minp = min_samples or polars_ta.MIN_SAMPLES or d
|
94
98
|
return struct([x, y]).map_batches(lambda xx: batches_i2_o1(struct_to_numpy(xx, 2), roll_co_skewness, d, minp))
|
95
99
|
|
96
100
|
|
97
101
|
def ts_corr(x: Expr, y: Expr, d: int = 5, ddof: int = 1, min_samples: Optional[int] = None) -> Expr:
|
98
|
-
"""
|
102
|
+
"""时序滚动相关系数
|
99
103
|
|
100
|
-
|
104
|
+
rolling correlation between two columns
|
101
105
|
|
102
106
|
Parameters
|
103
107
|
----------
|
@@ -236,9 +240,9 @@ def ts_count_nulls(x: Expr, d: int = 5, min_samples: Optional[int] = None) -> Ex
|
|
236
240
|
|
237
241
|
|
238
242
|
def ts_covariance(x: Expr, y: Expr, d: int = 5, ddof: int = 1, min_samples: Optional[int] = None) -> Expr:
|
239
|
-
"""
|
243
|
+
"""时序滚动协方差
|
240
244
|
|
241
|
-
|
245
|
+
rolling covariance between two columns
|
242
246
|
|
243
247
|
Parameters
|
244
248
|
----------
|
@@ -291,7 +295,7 @@ def ts_cum_count(x: Expr) -> Expr:
|
|
291
295
|
|
292
296
|
|
293
297
|
def ts_cum_max(x: Expr) -> Expr:
|
294
|
-
"""
|
298
|
+
"""时序累计最大值
|
295
299
|
|
296
300
|
Examples
|
297
301
|
--------
|
@@ -323,7 +327,7 @@ def ts_cum_max(x: Expr) -> Expr:
|
|
323
327
|
|
324
328
|
|
325
329
|
def ts_cum_min(x: Expr) -> Expr:
|
326
|
-
"""
|
330
|
+
"""时序累计最小值
|
327
331
|
|
328
332
|
Examples
|
329
333
|
--------
|
@@ -492,8 +496,10 @@ def ts_decay_linear(x: Expr, d: int = 30, min_samples: Optional[int] = None) ->
|
|
492
496
|
return x.map_batches(lambda x1: batches_i1_o1(x1.to_numpy().astype(float), roll_decay_linear, d, minp))
|
493
497
|
|
494
498
|
|
495
|
-
def ts_delay(x: Expr, d: int = 1, fill_value=None) -> Expr:
|
496
|
-
"""时序数据移动
|
499
|
+
def ts_delay(x: Expr, d: int = 1, fill_value: float = None) -> Expr:
|
500
|
+
"""时序数据移动
|
501
|
+
|
502
|
+
shift x
|
497
503
|
|
498
504
|
Parameters
|
499
505
|
----------
|
@@ -508,7 +514,7 @@ def ts_delay(x: Expr, d: int = 1, fill_value=None) -> Expr:
|
|
508
514
|
|
509
515
|
|
510
516
|
def ts_delta(x: Expr, d: int = 1) -> Expr:
|
511
|
-
"""
|
517
|
+
"""时序差分"""
|
512
518
|
return x.diff(d)
|
513
519
|
|
514
520
|
|
@@ -551,14 +557,16 @@ def ts_fill_null(x: Expr, limit: int = None) -> Expr:
|
|
551
557
|
|
552
558
|
|
553
559
|
def ts_ir(x: Expr, d: int = 1, min_samples: Optional[int] = None) -> Expr:
|
554
|
-
"""时序滚动信息系数
|
560
|
+
"""时序滚动信息系数
|
561
|
+
|
562
|
+
rolling information ratio"""
|
555
563
|
return ts_mean(x, d, min_samples) / ts_std_dev(x, d, 0, min_samples)
|
556
564
|
|
557
565
|
|
558
566
|
def ts_kurtosis(x: Expr, d: int = 5, bias: bool = False, min_samples: Optional[int] = None) -> Expr:
|
559
|
-
"""
|
567
|
+
"""时序滚动峰度
|
560
568
|
|
561
|
-
|
569
|
+
kurtosis of x for the last d days
|
562
570
|
|
563
571
|
Parameters
|
564
572
|
----------
|
@@ -603,16 +611,18 @@ def ts_kurtosis(x: Expr, d: int = 5, bias: bool = False, min_samples: Optional[i
|
|
603
611
|
|
604
612
|
|
605
613
|
def ts_l2_norm(x: Expr, d: int = 5, min_samples: Optional[int] = None) -> Expr:
|
606
|
-
"""
|
614
|
+
"""欧几里得范数
|
607
615
|
|
608
|
-
|
616
|
+
Euclidean norm
|
617
|
+
"""
|
609
618
|
minp = min_samples or polars_ta.MIN_SAMPLES
|
610
619
|
return x.pow(2).rolling_sum(d, min_samples=minp).sqrt()
|
611
620
|
|
612
621
|
|
613
622
|
def ts_log_diff(x: Expr, d: int = 1) -> Expr:
|
614
|
-
"""
|
623
|
+
"""求对数,然后时序滚动差分
|
615
624
|
|
625
|
+
log(current value of input or x[t] ) - log(previous value of input or x[t-1]).
|
616
626
|
"""
|
617
627
|
return x.log().diff(d)
|
618
628
|
|
@@ -624,7 +634,9 @@ def ts_max(x: Expr, d: int = 30, min_samples: Optional[int] = None) -> Expr:
|
|
624
634
|
|
625
635
|
|
626
636
|
def ts_max_diff(x: Expr, d: int = 30, min_samples: Optional[int] = None) -> Expr:
|
627
|
-
"""
|
637
|
+
"""窗口内最大值与当前值的差异
|
638
|
+
|
639
|
+
x - ts_max(x, d)"""
|
628
640
|
return x - ts_max(x, d, min_samples)
|
629
641
|
|
630
642
|
|
@@ -647,24 +659,30 @@ def ts_min(x: Expr, d: int = 30, min_samples: Optional[int] = None) -> Expr:
|
|
647
659
|
|
648
660
|
|
649
661
|
def ts_min_diff(x: Expr, d: int = 30, min_samples: Optional[int] = None) -> Expr:
|
650
|
-
"""
|
662
|
+
"""窗口内最小值与当前值的差异
|
663
|
+
|
664
|
+
x - ts_min(x, d)"""
|
651
665
|
return x - ts_min(x, d, min_samples)
|
652
666
|
|
653
667
|
|
654
668
|
def ts_min_max_cps(x: Expr, d: int, f: float = 2.0, min_samples: Optional[int] = None) -> Expr:
|
655
|
-
"""
|
669
|
+
"""计算时间窗口内最小值与最大值的总和减去当前值的加权结果
|
670
|
+
|
671
|
+
(ts_min(x, d) + ts_max(x, d)) - f * x"""
|
656
672
|
return (ts_min(x, d, min_samples) + ts_max(x, d, min_samples)) - f * x
|
657
673
|
|
658
674
|
|
659
675
|
def ts_min_max_diff(x: Expr, d: int, f: float = 0.5, min_samples: Optional[int] = None) -> Expr:
|
660
|
-
"""
|
676
|
+
"""计算当前值 x 与基于时间窗口内最小值、最大值的加权组合的差值
|
677
|
+
|
678
|
+
x - f * (ts_min(x, d) + ts_max(x, d))"""
|
661
679
|
return x - f * (ts_min(x, d, min_samples) + ts_max(x, d, min_samples))
|
662
680
|
|
663
681
|
|
664
682
|
def ts_moment(x: Expr, d: int, k: int = 0, min_samples: Optional[int] = None) -> Expr:
|
665
|
-
"""
|
683
|
+
"""滚动k阶中心距
|
666
684
|
|
667
|
-
|
685
|
+
Returns K-th central moment of x for the past d days.
|
668
686
|
|
669
687
|
Parameters
|
670
688
|
----------
|
@@ -679,18 +697,19 @@ def ts_moment(x: Expr, d: int, k: int = 0, min_samples: Optional[int] = None) ->
|
|
679
697
|
|
680
698
|
|
681
699
|
def ts_partial_corr(x: Expr, y: Expr, z: Expr, d: int, min_samples: Optional[int] = None) -> Expr:
|
682
|
-
"""
|
700
|
+
"""滚动偏相关
|
701
|
+
|
702
|
+
Returns partial correlation of x, y, z for the past d days.
|
683
703
|
|
684
|
-
滚动偏相关
|
685
704
|
"""
|
686
705
|
minp = min_samples or polars_ta.MIN_SAMPLES or d
|
687
706
|
return struct([x, y, z]).map_batches(lambda xx: batches_i2_o1(struct_to_numpy(xx, 3), roll_partial_corr, d, minp))
|
688
707
|
|
689
708
|
|
690
709
|
def ts_percentage(x: Expr, d: int, percentage: float = 0.5, min_samples: Optional[int] = None) -> Expr:
|
691
|
-
"""
|
710
|
+
"""滚动百分位数
|
692
711
|
|
693
|
-
|
712
|
+
Returns percentile value of x for the past d days.
|
694
713
|
|
695
714
|
Parameters
|
696
715
|
----------
|
@@ -722,15 +741,22 @@ def ts_rank(x: Expr, d: int = 5, min_samples: Optional[int] = None) -> Expr:
|
|
722
741
|
return x.map_batches(lambda a: roll_rank(a, d, minp, True))
|
723
742
|
|
724
743
|
|
744
|
+
def ts_realized_volatility(close: Expr, d: int = 5, min_samples: Optional[int] = None) -> Expr:
|
745
|
+
"""已实现波动率"""
|
746
|
+
minp = min_samples or polars_ta.MIN_SAMPLES or d
|
747
|
+
return ts_log_diff(close, 1).rolling_std(d, ddof=0, min_samples=minp)
|
748
|
+
|
749
|
+
|
725
750
|
def ts_returns(x: Expr, d: int = 1) -> Expr:
|
726
751
|
"""简单收益率"""
|
727
752
|
return x.pct_change(d)
|
728
753
|
|
729
754
|
|
730
755
|
def ts_scale(x: Expr, d: int = 5, min_samples: Optional[int] = None) -> Expr:
|
731
|
-
"""
|
756
|
+
"""时序滚动缩放
|
757
|
+
|
758
|
+
Returns (x – ts_min(x, d)) / (ts_max(x, d) – ts_min(x, d)) + constant
|
732
759
|
|
733
|
-
时序滚动缩放
|
734
760
|
"""
|
735
761
|
a = ts_min(x, d, min_samples)
|
736
762
|
b = ts_max(x, d, min_samples)
|
@@ -739,9 +765,9 @@ def ts_scale(x: Expr, d: int = 5, min_samples: Optional[int] = None) -> Expr:
|
|
739
765
|
|
740
766
|
|
741
767
|
def ts_skewness(x: Expr, d: int = 5, bias: bool = False, min_samples: Optional[int] = None) -> Expr:
|
742
|
-
"""
|
768
|
+
"""时序滚动偏度
|
743
769
|
|
744
|
-
|
770
|
+
Return skewness of x for the past d days
|
745
771
|
|
746
772
|
Parameters
|
747
773
|
----------
|
@@ -836,8 +862,9 @@ def ts_sum_split_by(x: Expr, by: Expr, d: int = 30, k: int = 10) -> Expr:
|
|
836
862
|
|
837
863
|
|
838
864
|
def ts_triple_corr(x: Expr, y: Expr, z: Expr, d: int, min_samples: Optional[int] = None) -> Expr:
|
839
|
-
"""时序滚动三重相关系数
|
865
|
+
"""时序滚动三重相关系数
|
840
866
|
|
867
|
+
Returns triple correlation of x, y, z for the past d days.
|
841
868
|
|
842
869
|
"""
|
843
870
|
minp = min_samples or polars_ta.MIN_SAMPLES or d
|
@@ -845,7 +872,9 @@ def ts_triple_corr(x: Expr, y: Expr, z: Expr, d: int, min_samples: Optional[int]
|
|
845
872
|
|
846
873
|
|
847
874
|
def ts_weighted_decay(x: Expr, k: float = 0.5, min_samples: Optional[int] = None) -> Expr:
|
848
|
-
"""
|
875
|
+
"""时序滚动加权衰减求和
|
876
|
+
|
877
|
+
Instead of replacing today’s value with yesterday’s as in ts_delay(x, 1),
|
849
878
|
it assigns weighted average of today’s and yesterday’s values with weight on today’s value being k and yesterday’s being (1-k).
|
850
879
|
|
851
880
|
Parameters
|
polars_ta/wq/transformational.py
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
from polars import Expr, when, Boolean, Int32
|
1
|
+
from polars import Expr, when, Boolean, Int32, Float32
|
2
2
|
|
3
3
|
|
4
4
|
def cut(x: Expr, b: float, *more_bins) -> Expr:
|
@@ -86,7 +86,7 @@ def clamp(x: Expr, lower: float = 0, upper: float = 0, inverse: bool = False, ma
|
|
86
86
|
# raise
|
87
87
|
|
88
88
|
|
89
|
-
def
|
89
|
+
def _keep(x: Expr, f: float, period: int = 5) -> Expr:
|
90
90
|
"""This operator outputs value x when f changes and continues to do that for “period” days after f stopped changing. After “period” days since last change of f, NaN is output."""
|
91
91
|
raise
|
92
92
|
|
@@ -211,7 +211,7 @@ def right_tail(x: Expr, minimum: float = 0) -> Expr:
|
|
211
211
|
|
212
212
|
|
213
213
|
def sigmoid(x: Expr) -> Expr:
|
214
|
-
"""
|
214
|
+
"""sigmoid激活函数"""
|
215
215
|
return 1 / (1 + (-x).exp())
|
216
216
|
|
217
217
|
|
@@ -258,10 +258,15 @@ def tail(x: Expr, lower: float = 0, upper: float = 0, newval: float = 0) -> Expr
|
|
258
258
|
|
259
259
|
|
260
260
|
def int_(a: Expr) -> Expr:
|
261
|
-
"""
|
261
|
+
"""bool转int"""
|
262
262
|
return a.cast(Int32)
|
263
263
|
|
264
264
|
|
265
265
|
def bool_(a: Expr) -> Expr:
|
266
|
-
"""
|
266
|
+
"""int转成bool"""
|
267
267
|
return a.cast(Boolean)
|
268
|
+
|
269
|
+
|
270
|
+
def float_(a: Expr) -> Expr:
|
271
|
+
"""int转成float"""
|
272
|
+
return a.cast(Float32)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: polars_ta
|
3
|
-
Version: 0.5.
|
3
|
+
Version: 0.5.4
|
4
4
|
Summary: polars expressions
|
5
5
|
Author-email: wukan <wu-kan@163.com>
|
6
6
|
License: MIT License
|
@@ -24,21 +24,19 @@ License: MIT License
|
|
24
24
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
25
25
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
26
26
|
SOFTWARE.
|
27
|
-
|
28
|
-
Keywords: polars,
|
27
|
+
License-File: LICENSE
|
28
|
+
Keywords: expression,polars,talib
|
29
29
|
Classifier: Development Status :: 4 - Beta
|
30
30
|
Classifier: Programming Language :: Python
|
31
31
|
Requires-Python: >=3.8
|
32
|
-
Description-Content-Type: text/markdown
|
33
|
-
License-File: LICENSE
|
34
|
-
Requires-Dist: polars>=1.28.0
|
35
|
-
Requires-Dist: polars-ols>=0.3.0
|
36
|
-
Requires-Dist: numpy
|
37
32
|
Requires-Dist: numba
|
33
|
+
Requires-Dist: numpy
|
38
34
|
Requires-Dist: pandas
|
35
|
+
Requires-Dist: polars-ols>=0.3.0
|
36
|
+
Requires-Dist: polars>=1.28.0
|
39
37
|
Provides-Extra: talib
|
40
|
-
Requires-Dist:
|
41
|
-
|
38
|
+
Requires-Dist: ta-lib; extra == 'talib'
|
39
|
+
Description-Content-Type: text/markdown
|
42
40
|
|
43
41
|
# polars_ta
|
44
42
|
|
@@ -248,6 +246,11 @@ mkdocs build
|
|
248
246
|
也可以通过以下链接导入:
|
249
247
|
https://polars-ta.readthedocs.io/en/latest/llms-full.txt
|
250
248
|
|
249
|
+
## 提示词
|
250
|
+
由于`llms-full.txt`信息不适合做提示词,所以`tools/prompt.py`提供了生成更简洁算子清单的功能。
|
251
|
+
|
252
|
+
用户也可以直接使用`prompt.txt`(欢迎提示词工程专家帮忙改进,做的更准确)
|
253
|
+
|
251
254
|
## 参考
|
252
255
|
|
253
256
|
- https://github.com/pola-rs/polars
|