11# Elvers Operator Specification
22
33Complete reference for all operators. Each entry documents signature, mathematical
4- definition, null/edge-case behavior, and design rationale where elvers diverges
5- from common platforms.
4+ definition, null/edge-case behavior, and design rationale.
65
76---
87
@@ -40,10 +39,6 @@ operation:
4039| add / subtract | 0 | null treated as 0 |
4140| multiply | 1 | null treated as 1 |
4241
43- > ** vs WQ:** WorldQuant uses ` NaN ` terminology and ` filter=false ` default.
44- > elvers is identical in behavior but uses ` null ` throughout and spells
45- > the parameter as ` filter=True ` (Python convention).
46-
4742### Division by Zero
4843
4944All divisions are guarded at ` abs(denominator) < 1e-10 ` , returning null.
@@ -74,10 +69,10 @@ variance or standard deviation documents which ddof it uses.
7469- Null handling: nulls are excluded from ranking and remain null in output.
7570- Formula: ` average_rank / count_of_non_null `
7671
77- > ** vs WQ: ** WorldQuant ` rank(x) ` outputs range ** [ 0, 1 ] ** inclusive of zero
78- > ( ` Rank(x) = (0.5, 0.25, 0.75, 1, 0) ` in their docs). elvers intentionally
79- > excludes zero because a rank of 0 is ambiguous -- it could mean "missing" or
80- > "lowest". Range (0 , 1] ensures every ranked value is unambiguously present .
72+ Design rationale: a rank of 0 is ambiguous -- it could mean "missing" or
73+ "lowest". Range (0, 1 ] ensures every ranked value is unambiguously present
74+ and distinguishable from null. For 5 instruments, ranks are
75+ ` (0.2, 0.4, 0.6, 0.8 , 1.0) ` , not ` (0, 0.25, 0.5, 0.75, 1.0) ` .
8176
8277** Time-series ` ts_rank(x, window) ` :**
8378- Output range: (0, 1] (same convention).
@@ -103,9 +98,9 @@ from contaminating signals.
103983 . If any value in the window is zero, the product is 0.
104994 . If any value is null, it propagates (min_samples applies).
105100
106- > ** vs WQ: ** WorldQuant does not document negative-value handling for
107- > ` ts_product ` . A naive ` exp(sum(log(x))) ` implementation silently returns
108- > NaN/null for negative inputs. elvers handles this correctly .
101+ A naive ` exp(sum(log(x))) ` implementation silently fails for negative inputs
102+ because ` log(x) ` is undefined for ` x < 0 ` . The sign-magnitude approach avoids
103+ this by operating on absolute values and tracking the sign separately .
109104
110105---
111106
@@ -441,9 +436,8 @@ Cross-sectional rank normalized to (0, 1].
441436- Null: excluded from ranking, remain null
442437- Formula: ` average_rank / count_of_non_null `
443438
444- > ** vs WQ:** ` Rank(x) = (0.5, 0.25, 0.75, 1, 0) ` in WQ for input ` (4,3,6,10,2) ` .
445- > elvers returns ` (0.6, 0.4, 0.8, 1.0, 0.2) ` -- no zero, strictly positive.
446- > This avoids ambiguity between "rank zero" and "missing data".
439+ For input ` (4, 3, 6, 10, 2) ` across 5 instruments, elvers returns
440+ ` (0.6, 0.4, 0.8, 1.0, 0.2) ` -- strictly positive, no zero.
447441
448442### ` zscore(x) `
449443
0 commit comments