polars-ta 0.5.3__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 CHANGED
@@ -1 +1 @@
1
- __version__ = "0.5.3"
1
+ __version__ = "0.5.4"
@@ -0,0 +1 @@
1
+ from polars_ta.labels.future import * # noqa
@@ -0,0 +1,40 @@
1
+ import numpy as np
2
+ from numba import jit
3
+ from numpy import full
4
+
5
+
6
+ @jit(nopython=True, nogil=True, cache=True)
7
+ def _triple_barrier(close: np.ndarray, high: np.ndarray, low: np.ndarray, window: int, take_profit: float, stop_loss: float) -> np.ndarray:
8
+ """三重障碍打标法"""
9
+ out = full(close.shape[0], np.nan, dtype=np.float64)
10
+ for i in range(close.shape[0] - window + 1):
11
+ entry_price = close[i]
12
+ if np.isnan(entry_price):
13
+ # out[i] = 0
14
+ continue
15
+ upper_barrier = entry_price * (1 + take_profit)
16
+ lower_barrier = entry_price * (1 - stop_loss)
17
+ for j in range(i + 1, i + window):
18
+ hit_upper = high[j] >= upper_barrier
19
+ hit_lower = low[j] <= lower_barrier
20
+ if hit_upper and hit_lower:
21
+ # TODO 同一天无法知道是先触发止损还是先触发止盈
22
+ # 1. 假定离收盘价远的先触发
23
+ if high[j] - close[j] > close[j] - low[j]:
24
+ out[i] = 1 # 最高价更远,触发止盈
25
+ else:
26
+ out[i] = -1 # 最低价更远,触发止损
27
+
28
+ # out[i] = -1 # 2. 简化处理认为先触发止损
29
+ break
30
+ if hit_upper:
31
+ out[i] = 1 # 止盈
32
+ break
33
+ if hit_lower:
34
+ out[i] = -1 # 止损
35
+ break
36
+ else:
37
+ # out[i] = 0 # 1. 时间到了触发平仓
38
+ out[i] = np.sign(close[j] / entry_price - 1) # 2. 时间到了触发平仓
39
+
40
+ return out
@@ -0,0 +1,165 @@
1
+ """
2
+
3
+ 由于标签的定义比较灵活,所以以下代码主要用于参考
4
+
5
+ Notes
6
+ -----
7
+ 标签都是未来数据,在机器学习中,只能用于`y`,不能用于`X`。
8
+
9
+ References
10
+ ----------
11
+ https://mp.weixin.qq.com/s/XtgYezFsslOfW-QyIMr0VA
12
+ https://github.com/Rachnog/Advanced-Deep-Trading/blob/master/bars-labels-diff/Labeling.ipynb
13
+
14
+ """
15
+ from polars import Expr, struct
16
+
17
+ from polars_ta.labels._nb import _triple_barrier
18
+ from polars_ta.utils.numba_ import batches_i2_o1, struct_to_numpy
19
+ from polars_ta.wq import cut, ts_delay, ts_log_diff, log
20
+
21
+
22
+ def ts_log_return(close: Expr, n: int = 5) -> Expr:
23
+ """将未来数据当成卖出价后移到买入价位置,计算对数收益率
24
+
25
+ Examples
26
+ --------
27
+ ```python
28
+ df = pl.DataFrame({
29
+ 'a': [None, 10, 11, 12, 9, 12, 13],
30
+ }).with_columns(
31
+ out1=ts_log_return(pl.col('a'), 3),
32
+ out2=_ts_log_return(pl.col('a'), 3),
33
+ )
34
+
35
+ shape: (7, 3)
36
+ ┌──────┬───────────┬───────────┐
37
+ │ a ┆ out1 ┆ out2 │
38
+ │ --- ┆ --- ┆ --- │
39
+ │ i64 ┆ f64 ┆ f64 │
40
+ ╞══════╪═══════════╪═══════════╡
41
+ │ null ┆ null ┆ null │
42
+ │ 10 ┆ -0.105361 ┆ -0.105361 │
43
+ │ 11 ┆ 0.087011 ┆ 0.087011 │
44
+ │ 12 ┆ 0.080043 ┆ 0.080043 │
45
+ │ 9 ┆ null ┆ null │
46
+ │ 12 ┆ null ┆ null │
47
+ │ 13 ┆ null ┆ null │
48
+ └──────┴───────────┴───────────┘
49
+ ```
50
+
51
+ """
52
+ # return (close.shift(-n) / close).log()
53
+ return log(ts_delay(close, -n) / close)
54
+
55
+
56
+ def _ts_log_return(close: Expr, n: int = 5) -> Expr:
57
+ """计算对数收益率,但将结果后移
58
+
59
+ 如果打标签方式复杂,这种最终结果后移的方法更方便
60
+ """
61
+ # return (close / close.shift(n)).log().shift(-n)
62
+ return ts_delay(ts_log_diff(close, n), -n)
63
+
64
+
65
+ def ts_simple_return(close: Expr, n: int = 5, threshold: float = 0.0, *more_threshold) -> Expr:
66
+ """简单收益率标签。支持二分类、三分类等。对收益率使用`cut`进行分类
67
+
68
+ Parameters
69
+ ----------
70
+ close
71
+ n:int
72
+ 未来n天
73
+ threshold:float
74
+ 收益率阈值,小于该值为0,大于等于该值为1
75
+ more_threshold:float
76
+ 更多的阈值,用于三分类等。小于该值为1,大于等于该值为2,以此类推
77
+
78
+ Returns
79
+ -------
80
+ Expr
81
+ 标签列, 类型为UInt32, 取值为0, 1, 2, ...
82
+
83
+ Examples
84
+ --------
85
+ ```python
86
+ df = pl.DataFrame({
87
+ 'a': [None, 10., 9.99, 9., 10., 11., 11.],
88
+ }).with_columns(
89
+ out1=label_simple_return(pl.col('a'), 1, 0),
90
+ out2=label_simple_return(pl.col('a'), 1, -0.001, 0.001),
91
+ )
92
+
93
+ shape: (7, 3)
94
+ ┌──────┬──────┬──────┐
95
+ │ a ┆ out1 ┆ out2 │
96
+ │ --- ┆ --- ┆ --- │
97
+ │ f64 ┆ u32 ┆ u32 │
98
+ ╞══════╪══════╪══════╡
99
+ │ null ┆ null ┆ null │
100
+ │ 10.0 ┆ 0 ┆ 0 │
101
+ │ 9.99 ┆ 0 ┆ 0 │
102
+ │ 9.0 ┆ 1 ┆ 2 │
103
+ │ 10.0 ┆ 1 ┆ 2 │
104
+ │ 11.0 ┆ 0 ┆ 1 │
105
+ │ 11.0 ┆ null ┆ null │
106
+ └──────┴──────┴──────┘
107
+
108
+ """
109
+ return cut(close.pct_change(n).shift(-n), threshold, *more_threshold)
110
+
111
+
112
+ def ts_triple_barrier(close: Expr, high: Expr, low: Expr, d: int = 5, take_profit: float = 0.1, stop_loss: float = 0.05) -> Expr:
113
+ """三重障碍打标法
114
+
115
+ Parameters
116
+ ----------
117
+ close:Expr
118
+ 收盘价
119
+ high:Expr
120
+ 最高价
121
+ low:Expr
122
+ 最低价
123
+ d:int
124
+ 时间窗口
125
+ take_profit:float
126
+ 止盈比例
127
+ stop_loss:float
128
+ 止损比例
129
+
130
+ Returns
131
+ -------
132
+ Expr
133
+ 标签列。取值为-1止损, 1止盈,0时间到期
134
+
135
+ Notes
136
+ -----
137
+ 1. `high`, `low`在粗略情况下可用`close`代替
138
+ 2. 时间到期时,根据盈亏返回不同的标签
139
+
140
+ Examples
141
+ --------
142
+ ```python
143
+ df = pl.DataFrame({
144
+ "close": [np.nan, 1, 1, 1.0],
145
+ "high": [np.nan, 1, 1.1, 1],
146
+ "low": [np.nan, 1, 1, 0.95],
147
+ }).with_columns(
148
+ out=ts_triple_barrier(pl.col("close"), pl.col("high"), pl.col("low"), 2, 0.1, 0.05)
149
+ )
150
+
151
+ shape: (4, 4)
152
+ ┌───────┬──────┬──────┬──────┐
153
+ │ close ┆ high ┆ low ┆ out │
154
+ │ --- ┆ --- ┆ --- ┆ --- │
155
+ │ f64 ┆ f64 ┆ f64 ┆ f64 │
156
+ ╞═══════╪══════╪══════╪══════╡
157
+ │ NaN ┆ NaN ┆ NaN ┆ null │
158
+ │ 1.0 ┆ 1.0 ┆ 1.0 ┆ 1.0 │
159
+ │ 1.0 ┆ 1.1 ┆ 1.0 ┆ -1.0 │
160
+ │ 1.0 ┆ 1.0 ┆ 0.95 ┆ null │
161
+ └───────┴──────┴──────┴──────┘
162
+ ```
163
+
164
+ """
165
+ return struct([close, high, low]).map_batches(lambda xx: batches_i2_o1(struct_to_numpy(xx, 3), _triple_barrier, d, take_profit, stop_loss))
@@ -1,12 +1,6 @@
1
1
  from polars import Expr
2
2
 
3
- from polars_ta.wq.arithmetic import log1p, expm1 # noqa
4
- # log return
5
- # 对数收益
6
- from polars_ta.wq.time_series import ts_log_diff as ts_log_return # noqa
7
- # simple percentage return
8
- # 简单收益
9
- from polars_ta.wq.time_series import ts_returns as ts_percent_return # noqa
3
+ from polars_ta.wq.arithmetic import log1p, expm1
10
4
 
11
5
 
12
6
  def ts_cum_return(close: Expr) -> Expr:
@@ -0,0 +1 @@
1
+ from polars_ta.labels import * # noqa
polars_ta/ta/README.md ADDED
@@ -0,0 +1,12 @@
1
+ # polars_ta.ta
2
+
3
+ 1. Files in this folder mimic `talib`, and implement `polars` versions for the same functions
4
+ 2. Since we reduce the functino calls between `Python` and `C` code, it should be faster than `talib`.
5
+ 3. We first try to import from `ta`, then from `wq`, and only implement the function if it is not available.
6
+ 4. When there is a circular dependency, we use `polars` instead.
7
+
8
+
9
+ 1. 本文件夹中模仿`talib`,实现同名函数的`polars`版
10
+ 2. 由于减少了python与c来回调用,理论上比直接调用`talib`快
11
+ 3. 优先从`ta`中导入,然后从`wq`中导入,没有的才实现
12
+ 4. 出现循环依赖时,使用`polars`
@@ -0,0 +1,12 @@
1
+ # polars_ta.talib
2
+
3
+ Inside this package, files are generated by `tools.codegen_talib2`.
4
+ It is a wrapper of `talib` functions, with the following features:
5
+
6
+ 1. Input and output are `Expr` instead of `Series`
7
+ 2. ~~Add skipna feature (not efficient, will update when `polars` support backward fill)~~
8
+
9
+ 本包由`tools.codegen_talib2`自动生成,是对`talib`代码的封装。实现了以下功能
10
+ 1. 输入输出由`Series`改`Expr`
11
+ 2. ~~添加跳过空值功能(效率不高,等`polars`支持反向填充,此部分将更新)~~
12
+
@@ -0,0 +1,10 @@
1
+ # polars_ta.tdx
2
+
3
+ 1. Follows the `tdx` naming convention
4
+ 2. Except for some element-wise functions, all functions are time-series functions. Pay special attention to `MAX` and similar functions.
5
+ 3. First import from `tdx`, then from `wq`, and finally from `ta`. Only implement the function if it is not available.
6
+
7
+
8
+ 1. 函数名称按照通达信来
9
+ 2. 除了部分按元素计算的函数,其它都为时序函数,特别注意`MAX`等一类不要混淆
10
+ 3. 优先从`tdx`中导入,然后从`wq`中导入,最后从`ta`,没有的才实现
polars_ta/utils/numba_.py CHANGED
@@ -27,6 +27,7 @@ def isnan(x):
27
27
 
28
28
  @jit(nopython=True, nogil=True, cache=True)
29
29
  def full_with_window_size(arr, fill_value, dtype=None, window_size: int = 1):
30
+ """创建一个更大的数组,填充后一截数据"""
30
31
  out = full(arr.shape[0] + window_size - 1, fill_value, dtype=dtype)
31
32
  out[window_size - 1:] = arr
32
33
  return out
@@ -34,6 +35,7 @@ def full_with_window_size(arr, fill_value, dtype=None, window_size: int = 1):
34
35
 
35
36
  @jit(nopython=True, nogil=True, cache=True)
36
37
  def sliding_window_with_min_periods(arr, window_size: int, min_periods: int):
38
+ """为rolling准备的数据,当数据长度不足时,用nan填充"""
37
39
  windows = sliding_window_view(arr, window_size)
38
40
  valid_counts = np.sum(~np.isnan(windows), axis=1)
39
41
  # 修改这一行,使用布尔索引而不是np.where
@@ -5,7 +5,7 @@ from polars import max_horizontal, sum_horizontal, min_horizontal, mean_horizont
5
5
 
6
6
 
7
7
  def abs_(x: Expr) -> Expr:
8
- """绝对值
8
+ """求绝对值
9
9
 
10
10
  Examples
11
11
  --------
@@ -39,7 +39,7 @@ def abs_(x: Expr) -> Expr:
39
39
 
40
40
 
41
41
  def add(a: Expr, b: Expr, *args) -> Expr:
42
- """水平多列加
42
+ """水平多列相加
43
43
 
44
44
  Examples
45
45
  --------
@@ -133,12 +133,12 @@ def degrees(x: Expr) -> Expr:
133
133
  return x.degrees()
134
134
 
135
135
 
136
- def densify(x: Expr) -> Expr:
136
+ def _densify(x: Expr) -> Expr:
137
137
  raise
138
138
 
139
139
 
140
140
  def div(x: Expr, y: Expr) -> Expr:
141
- """x/y的整数部分
141
+ """x除以y的整数部分
142
142
 
143
143
  Examples
144
144
  --------
@@ -170,7 +170,9 @@ def div(x: Expr, y: Expr) -> Expr:
170
170
 
171
171
 
172
172
  def divide(x: Expr, y: Expr) -> Expr:
173
- """x/y
173
+ """除法
174
+
175
+ x/y
174
176
 
175
177
  Examples
176
178
  --------
@@ -231,7 +233,9 @@ def exp(x: Expr) -> Expr:
231
233
 
232
234
 
233
235
  def expm1(x: Expr) -> Expr:
234
- """对数收益率 转 简单收益率 convert log return to simple return
236
+ """对数收益率 转 简单收益率
237
+
238
+ convert log return to simple return
235
239
 
236
240
  Examples
237
241
  --------
@@ -266,6 +270,7 @@ def floor(x: Expr) -> Expr:
266
270
 
267
271
  def fraction(x: Expr) -> Expr:
268
272
  """小数部分
273
+
269
274
  This operator removes the whole number part and returns the remaining fraction part with sign.
270
275
 
271
276
  Examples
@@ -306,7 +311,9 @@ def fraction(x: Expr) -> Expr:
306
311
 
307
312
 
308
313
  def inverse(x: Expr) -> Expr:
309
- """1/x
314
+ """倒数
315
+
316
+ 1/x
310
317
 
311
318
  Examples
312
319
  --------
@@ -335,7 +342,7 @@ def inverse(x: Expr) -> Expr:
335
342
 
336
343
 
337
344
  def log(x: Expr) -> Expr:
338
- """e为底的对数
345
+ """e为底的对数
339
346
 
340
347
  Examples
341
348
  --------
@@ -367,7 +374,7 @@ def log(x: Expr) -> Expr:
367
374
 
368
375
 
369
376
  def log10(x: Expr) -> Expr:
370
- """10为底的对数
377
+ """10为底的对数
371
378
 
372
379
  Examples
373
380
  --------
@@ -396,7 +403,9 @@ def log10(x: Expr) -> Expr:
396
403
 
397
404
 
398
405
  def log1p(x: Expr) -> Expr:
399
- """简单收益率 转 对数收益率 convert simple return to log return
406
+ """简单收益率 转 对数收益率
407
+
408
+ convert simple return to log return
400
409
 
401
410
  log(x+1)
402
411
 
@@ -427,7 +436,7 @@ def log1p(x: Expr) -> Expr:
427
436
 
428
437
 
429
438
  def log2(x: Expr) -> Expr:
430
- """2为底的对数
439
+ """2为底的对数
431
440
 
432
441
  Examples
433
442
  --------
@@ -456,12 +465,14 @@ def log2(x: Expr) -> Expr:
456
465
 
457
466
 
458
467
  def max_(a: Expr, b: Expr, *args) -> Expr:
459
- """水平多列最大值 Maximum value of all inputs. At least 2 inputs are required."""
468
+ """水平多列求最大值
469
+
470
+ Maximum value of all inputs. At least 2 inputs are required."""
460
471
  return max_horizontal(a, b, *args)
461
472
 
462
473
 
463
474
  def mean(a: Expr, b: Expr, *args) -> Expr:
464
- """水平多列均值
475
+ """水平多列求均值
465
476
 
466
477
  Examples
467
478
  --------
@@ -492,12 +503,16 @@ def mean(a: Expr, b: Expr, *args) -> Expr:
492
503
 
493
504
 
494
505
  def min_(a: Expr, b: Expr, *args) -> Expr:
495
- """水平多列最小值 Maximum value of all inputs. At least 2 inputs are required."""
506
+ """水平多列求最小值
507
+
508
+ Maximum value of all inputs. At least 2 inputs are required."""
496
509
  return min_horizontal(a, b, *args)
497
510
 
498
511
 
499
512
  def mod(x: Expr, y: Expr) -> Expr:
500
- """x%y
513
+ """求余
514
+
515
+ x%y
501
516
 
502
517
  Examples
503
518
  --------
@@ -528,7 +543,9 @@ def mod(x: Expr, y: Expr) -> Expr:
528
543
 
529
544
 
530
545
  def multiply(a: Expr, b: Expr, *args) -> Expr:
531
- """水平多列乘 Multiply all inputs. At least 2 inputs are required.
546
+ """水平多列相乘
547
+
548
+ Multiply all inputs. At least 2 inputs are required.
532
549
 
533
550
  Examples
534
551
  --------
@@ -569,7 +586,9 @@ def multiply(a: Expr, b: Expr, *args) -> Expr:
569
586
 
570
587
 
571
588
  def power(x: Expr, y: Expr) -> Expr:
572
- """x ** y
589
+ """乘幂
590
+
591
+ x ** y
573
592
 
574
593
  Examples
575
594
  --------
@@ -608,12 +627,14 @@ def radians(x: Expr) -> Expr:
608
627
 
609
628
 
610
629
  def reverse(x: Expr) -> Expr:
611
- """-x"""
630
+ """求相反数"""
612
631
  return -x
613
632
 
614
633
 
615
634
  def round_(x: Expr, decimals: int = 0) -> Expr:
616
- """四舍五入 Round input to closest integer.
635
+ """四舍五入
636
+
637
+ Round input to closest integer.
617
638
 
618
639
  Parameters
619
640
  ----------
@@ -653,7 +674,9 @@ def round_(x: Expr, decimals: int = 0) -> Expr:
653
674
 
654
675
 
655
676
  def round_down(x: Expr, f: int = 1) -> Expr:
656
- """小于输入的f的最大倍数 Round input to greatest multiple of f less than input
677
+ """小于输入的f的最大倍数
678
+
679
+ Round input to greatest multiple of f less than input
657
680
 
658
681
  Parameters
659
682
  ----------
@@ -693,6 +716,8 @@ def round_down(x: Expr, f: int = 1) -> Expr:
693
716
  def s_log_1p(x: Expr) -> Expr:
694
717
  """sign(x) * log10(1 + abs(x))
695
718
 
719
+ 一种结合符号函数和对数变换的复合函数,常用于‌保留数据符号的同时压缩数值范围‌
720
+
696
721
  Examples
697
722
  --------
698
723
  ```python
@@ -729,7 +754,7 @@ def s_log_1p(x: Expr) -> Expr:
729
754
 
730
755
 
731
756
  def sign(x: Expr) -> Expr:
732
- """符号"""
757
+ """符号函数"""
733
758
  if isinstance(x, (Expr, Series)):
734
759
  return x.sign()
735
760
  else:
@@ -737,7 +762,9 @@ def sign(x: Expr) -> Expr:
737
762
 
738
763
 
739
764
  def signed_power(x: Expr, y: Expr) -> Expr:
740
- """x raised to the power of y such that final result preserves sign of x.
765
+ """xy次幂,符号保留
766
+
767
+ x raised to the power of y such that final result preserves sign of x.
741
768
 
742
769
  Examples
743
770
  --------
@@ -793,7 +820,7 @@ def sinh(x: Expr) -> Expr:
793
820
 
794
821
 
795
822
  def softsign(x: Expr) -> Expr:
796
- """softsign是 tanh激活函数的另一个替代选择
823
+ """softsign激活函数
797
824
 
798
825
  Examples
799
826
  --------
@@ -833,7 +860,9 @@ def square(x: Expr) -> Expr:
833
860
 
834
861
 
835
862
  def subtract(x: Expr, y: Expr) -> Expr:
836
- """x-y"""
863
+ """减法
864
+
865
+ x-y"""
837
866
  return x - y
838
867
 
839
868
 
@@ -898,7 +927,7 @@ def tanh(x: Expr) -> Expr:
898
927
 
899
928
 
900
929
  def var(a: Expr, b: Expr, *args) -> Expr:
901
- """水平多列方差
930
+ """水平多列求方差
902
931
 
903
932
  Examples
904
933
  --------
@@ -932,7 +961,7 @@ def var(a: Expr, b: Expr, *args) -> Expr:
932
961
 
933
962
 
934
963
  def std(a: Expr, b: Expr, *args) -> Expr:
935
- """水平多列标准差
964
+ """水平多列求标准差
936
965
 
937
966
  Examples
938
967
  --------
@@ -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
- """Shifts all instruments up or down so that the Alpha becomes long-only or short-only
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
- """Scales input to booksize. We can also scale the long positions and short positions to separate scales by mentioning additional parameters to the operator.
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
- """Scales all values in each day proportionately between 0 and 1 such that minimum value maps to 0 and maximum value maps to 1.
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
- """Operator truncates all values of x to maxPercent. Here, maxPercent is in decimal notation
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
- """全为`null`时,保持`null`,反之`null`填充为`value`
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
- """填充`null`为均值"""
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
- """填充`null`为`value`"""
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
- """排名。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.
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
- """等频分箱 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.
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
- """KK
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(input1: Expr, input2: Expr, input3: Expr = None) -> Expr:
16
- """If input1 is true then return input2 else return input3."""
17
- return when(input1).then(input2).otherwise(input3)
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:
@@ -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
- # https://en.wikipedia.org/wiki/Median_absolute_deviation
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
- """demean
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
@@ -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
- """Returns the relative index of the max value in the time series for the past d days.
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
- """rolling correlation between two columns
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
- """rolling covariance between two columns
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
- """时序数据移动 shift x
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
- """时序滚动信息系数rolling information ratio"""
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
- """kurtosis of x for the last d days
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
- """Euclidean norm
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
- """对数差分。log(current value of input or x[t] ) - log(previous value of input or x[t-1]).
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
- """Returns x - ts_max(x, d)"""
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
- """Returns x - ts_min(x, d)"""
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
- """Returns (ts_min(x, d) + ts_max(x, d)) - f * x"""
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
- """Returns x - f * (ts_min(x, d) + ts_max(x, d))"""
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
- """Returns K-th central moment of x for the past d days.
683
+ """滚动k阶中心距
666
684
 
667
- 滚动k阶中心距
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
- """Returns partial correlation of x, y, z for the past d days.
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
- """Returns percentile value of x for the past d days.
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
- """Returns (x – ts_min(x, d)) / (ts_max(x, d) – ts_min(x, d)) + constant
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
- """Return skewness of x for the past d days
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
- """时序滚动三重相关系数 Returns triple correlation of x, y, z for the past d days.
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
- """加权衰减 Instead of replacing today’s value with yesterday’s as in ts_delay(x, 1),
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
@@ -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 keep(x: Expr, f: float, period: int = 5) -> Expr:
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
- """Returns 1 / (1 + exp(-x))"""
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
- """convert bool to int"""
261
+ """boolint"""
262
262
  return a.cast(Int32)
263
263
 
264
264
 
265
265
  def bool_(a: Expr) -> Expr:
266
- """convert int to bool"""
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
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,expression,talib
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: TA-Lib; extra == "talib"
41
- Dynamic: license-file
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
@@ -1,15 +1,19 @@
1
1
  polars_ta/__init__.py,sha256=ig6f6c1AMSpntwKjqaX3msBzVIwkI7J776IujEmiuvA,123
2
- polars_ta/_version.py,sha256=tgzuqHKcEdKBaP57F5oXxq4XlW2n9J4Fj8ZGu7nGOZg,22
2
+ polars_ta/_version.py,sha256=DITpct-LrdIsTgwx2NgH5Ghx5y8Xgz1YMimy1ZV5RTY,22
3
3
  polars_ta/noise.py,sha256=LJHubBqnWlU3Bz84z07N1JB-b-hAMW2rgBF1BT4m0FE,1471
4
4
  polars_ta/candles/__init__.py,sha256=AW68IuFC0gD4_OyjwLP3p22WSzSIYqlSrsS9fW_15xw,141
5
5
  polars_ta/candles/cdl1.py,sha256=RnRu1QzpqEt5y0-1hlfZRUvza1no-Gj4x_dx2QWxr5A,3130
6
6
  polars_ta/candles/cdl1_limit.py,sha256=1escagSXOS1N0kxrItwfrmrvZ5aQf8jqEXQRRu90Pf0,3914
7
7
  polars_ta/candles/cdl2.py,sha256=jQJTKmyEmv5Pqxe2QIVUyu_fD681rirhgHwksdoaFs0,1122
8
+ polars_ta/labels/__init__.py,sha256=NKANbfheMNIs97jVXgqtZwkfx8RQxH9fY7D_fh1V_Ls,46
9
+ polars_ta/labels/_nb.py,sha256=rNGQOTEeO0tZfYPL7IZkGSjs4DmMIlzX_Y0j1LSqagg,1577
10
+ polars_ta/labels/future.py,sha256=OdERljrbzzLwnjmQaOFNantzv-CEeUpbMasMUfIzGpY,5304
8
11
  polars_ta/performance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
12
  polars_ta/performance/drawdown.py,sha256=9blEXGXT-ficbwbaIqwnY0cIeY9oAL0LrwviZW4wVWU,240
10
- polars_ta/performance/returns.py,sha256=W-Yl-sopicalMFM-oZh1hzsLV2s1uS7iU5UWygUMltE,669
13
+ polars_ta/performance/returns.py,sha256=-2G-RcMEJkL2ESqgwpBixT2Gjlxq2zBi3RJ5btGER-8,440
11
14
  polars_ta/prefix/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
12
15
  polars_ta/prefix/cdl.py,sha256=DS5GACM3biJmzunlUCkiQrZy-ltzQP0vFmCKkfGxS5E,40
16
+ polars_ta/prefix/labels.py,sha256=v15cxwiZ3K3PnSqpYG4821bVZXfZminZU5hSQQiXKKw,39
13
17
  polars_ta/prefix/reports.py,sha256=B2QgdfX6RbZu9ytgaINv3Aq-ZAh_m3cr2pgbpFyL35A,40
14
18
  polars_ta/prefix/ta.py,sha256=qIb3oRmexNZ6LTQ35V194QTLqj8UgzjaYl5ASwqN5pc,4167
15
19
  polars_ta/prefix/talib.py,sha256=6JsrkgDIUsR2bIA7jVywxgWwxiiFuzsCPvbDeAt4qBA,9392
@@ -17,6 +21,7 @@ polars_ta/prefix/tdx.py,sha256=EttaExzqoA3Y3lD-YKA32-5GfJ6jgKjt-nRuoeuK0wQ,11429
17
21
  polars_ta/prefix/wq.py,sha256=PpSLQQ3vD0Mf3Tiz_AFSi--q8p7CkLg9CHh_ayMfoYo,35
18
22
  polars_ta/reports/__init__.py,sha256=KEATtWxhdaO6XScHYN2XE4WkYbYpQvDOEyXgyc2z22g,45
19
23
  polars_ta/reports/cicc.py,sha256=ZpNzHo5h855Xo9IeKeOzlUjjwE5tR8opb11UoJVxGkg,707
24
+ polars_ta/ta/README.md,sha256=XuDf1sMxNrq9QDEiwBaP8cp-skTK3Jr5VClxhsNiYJ4,647
20
25
  polars_ta/ta/__init__.py,sha256=GRI1suzvmLxfyfXAik4zsxqLaijq5MRCO-fUx3qaCl0,351
21
26
  polars_ta/ta/momentum.py,sha256=-W-wZ1oQE9QiUiVgEx7fvnCEkWJnW6j9CxA7Mc-WMGg,5623
22
27
  polars_ta/ta/operators.py,sha256=H_ORq1SeFKLj58vrOTAIa-X135evZNyo4ZE7gaH_7VM,3711
@@ -26,7 +31,9 @@ polars_ta/ta/statistic.py,sha256=dS5dPBszbdlroJ9u5aXBniJmKgPQnuh9zE7miYKzICs,968
26
31
  polars_ta/ta/transform.py,sha256=c4s5l6khVqIer50g6oScdZ1EEPWYANeKm64AkBkPrtY,1789
27
32
  polars_ta/ta/volatility.py,sha256=yQDKLxos521y3RzywOcE0hTj3qIG_2mfqpARpdxQ1KU,836
28
33
  polars_ta/ta/volume.py,sha256=fPd9Po30kFu-cSmYoRQP4_Ypi9oSWROj650-mjwlfwM,739
34
+ polars_ta/talib/README.md,sha256=IC-pwcGYXALKzMlK0C9GeswoUlCDK86mxmrAagzPy8s,537
29
35
  polars_ta/talib/__init__.py,sha256=UZIkJ6tDYTcxBuKqjeKW93Ya_VyzTtNjXefoTqMd5P8,69701
36
+ polars_ta/tdx/README.md,sha256=rI7VUKm6H8_HBpm9MUePuuf1uE8JTfDX1AvPsfMZPPQ,545
30
37
  polars_ta/tdx/__init__.py,sha256=HBVPri6GwiEsFx4op0ZxDa3Yk4MbnPZgth5xJhtnxiA,662
31
38
  polars_ta/tdx/_chip.py,sha256=2eCe-y_0DcBivVjQHXlFwAiY410-hH-KKPrsUcRJcyk,3832
32
39
  polars_ta/tdx/_nb.py,sha256=IV3XrgSYPoR4jnOOT8p7jJWGtnoRrHLw5-fnIOfmMvA,2192
@@ -47,22 +54,21 @@ polars_ta/tdx/trend_feature.py,sha256=uNc4Z46Kyd7Prl0Ftl2ljSAXztTzQtbO28p7gy8iMv
47
54
  polars_ta/tdx/volume.py,sha256=juYM4Qlx2BX5okRCSwuf-6kRUETqDF7MVWUbYIzc4ww,901
48
55
  polars_ta/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
49
56
  polars_ta/utils/helper.py,sha256=rqxBhmA-RhpHd1-qxdYi7OEZloQpPxR30Kz8fJ_hLic,6254
50
- polars_ta/utils/numba_.py,sha256=jiOxEZjdGBr8aFivCQbJllBsZCfQsBJXQ-DyGhTS2cI,5832
57
+ polars_ta/utils/numba_.py,sha256=P0z-81mabX_9zyJOX0Ib1CFmvPl9-SSatzki3dOciVA,5972
51
58
  polars_ta/utils/pandas_.py,sha256=codb51l45TUMngY55twQaUPUxnffjvj8UEOm35zFpNE,1989
52
59
  polars_ta/utils/pit.py,sha256=YNgUE6mbwhrtA-7wyOL0PCUDdwfTQouXwage-cK6efY,4312
53
60
  polars_ta/utils/wrapper.py,sha256=jbR-ZQdzBf5iWvtnJ1HsN9HdepmDbU7fUj4w8Bt2BkU,3422
54
61
  polars_ta/wq/__init__.py,sha256=C3YYJc997XCUI7H_afGT_mj2m4UdHMcql4sboCVvrXU,327
55
62
  polars_ta/wq/_nb.py,sha256=9N7afRiABqdjO1QPnRlP1RIKJ98cQLpv6nF3dsqUA6k,11281
56
63
  polars_ta/wq/_slow.py,sha256=MfWg9FYX8NGNLWN4ezI_awf3pPTqhSq_zo0LOS4nCzw,937
57
- polars_ta/wq/arithmetic.py,sha256=LSqlkHKHQGob079VrQYeqWPW9nCChyDzzWLeFUBBz30,26072
58
- polars_ta/wq/cross_sectional.py,sha256=mHLwuXu9m4ladb6cUJVnH4OofliBSkpzmIZu6TtBoe4,13697
59
- polars_ta/wq/logical.py,sha256=5lttGwQi9oHml7soqmxEwgIVVLpeWO7JSXmQ3-TUqlU,2261
60
- polars_ta/wq/preprocess.py,sha256=xbESoAtsbQgXJMhnLzg4r5o2H9uwPyHfySg5skk_DUg,4188
61
- polars_ta/wq/time_series.py,sha256=iVYIGSQxD3xbiwNPHO7w-Yw0eQ-0nDzRtNzpMXwHwQU,32212
62
- polars_ta/wq/transformational.py,sha256=ktluqo-lcxWysFL3huNypId0EFR1wn1PmyBGO180UQo,7194
64
+ polars_ta/wq/arithmetic.py,sha256=NwyX-K8j9ul7XHHSNuGimBq6f3NvcOGQ4le5PQuaRPc,26346
65
+ polars_ta/wq/cross_sectional.py,sha256=1unrHaPPDQIZACg0CepWn3CXvd_zmQWjNwbXzqZXke8,14518
66
+ polars_ta/wq/logical.py,sha256=PfcPrY3iYoYFDTJ-B1IlCfpab1uTWV7GN1TdRtjauEk,2241
67
+ polars_ta/wq/preprocess.py,sha256=Zpjv7zpU690Ugr5PNnq6CNlUn5qD9sH0SQr5q5AFtys,3444
68
+ polars_ta/wq/time_series.py,sha256=KGVgFSQWiDAOpN7nW0rPE8UE81Q3Co9WwZiY1DWs3KQ,33164
69
+ polars_ta/wq/transformational.py,sha256=HBnxQiS2Pw0fHnRW-aLqbznQVl1SSbZ9OqZG62igiJk,7266
63
70
  polars_ta/wq/vector.py,sha256=Qs-mHC2YsiWXoyMuXZZPzd5W5w_HL1ZgDCj9wRAnqmQ,1902
64
- polars_ta-0.5.3.dist-info/licenses/LICENSE,sha256=nREFtfwxWCCYD-ZA1jMzhhxMyTz-wGWFlnkpgg0DCtQ,1062
65
- polars_ta-0.5.3.dist-info/METADATA,sha256=1Z0TgHnxgqVBsyJZ_qPsutzktCZQo8OBHcpovp8-C4E,8633
66
- polars_ta-0.5.3.dist-info/WHEEL,sha256=wXxTzcEDnjrTwFYjLPcsW_7_XihufBwmpiBeiXNBGEA,91
67
- polars_ta-0.5.3.dist-info/top_level.txt,sha256=eat2IhP79-dIGA4DAFOz1o-95--UDqfjeIgmU9TBsDQ,10
68
- polars_ta-0.5.3.dist-info/RECORD,,
71
+ polars_ta-0.5.4.dist-info/METADATA,sha256=YuA2qBXp9R4_9PbOLyk-ZhjiUdTnNLxXKQmZPvpIjc8,8839
72
+ polars_ta-0.5.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
73
+ polars_ta-0.5.4.dist-info/licenses/LICENSE,sha256=nREFtfwxWCCYD-ZA1jMzhhxMyTz-wGWFlnkpgg0DCtQ,1062
74
+ polars_ta-0.5.4.dist-info/RECORD,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.1.0)
2
+ Generator: hatchling 1.27.0
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-
@@ -1 +0,0 @@
1
- polars_ta