Mathematical Functions¶
Functions for numeric casting, rounding, aggregation, statistical analysis, and financial risk conversions. Functions marked vectorized operate element-wise on arrays.
Casting & Cleaning¶
cast_float¶
Vectorized. Attempts to cast value to a float. Returns default if the cast fails (non-numeric strings, None, NaN, inf).
expression_engine.solve('cast_float("1.5")')
# 1.5
expression_engine.solve('cast_float("invalid")')
# None
expression_engine.solve('cast_float("abc", 0.0)')
# 0.0
drop_nan¶
Removes all non-finite values from arr — NaN, inf, and None are discarded. All elements are first cast to float.
import numpy as np
expression_engine.solve('drop_nan(arr)', {'arr': np.array([1.0, float('nan'), None, 2.0, float('inf')])})
# [1., 2.]
Rounding¶
round¶
Vectorized. Rounds value to precision decimal places. Returns None if value or precision is None.
floor¶
Vectorized. Rounds value down (toward negative infinity) to precision decimal places.
expression_engine.solve('floor(5.789, 1)')
# 5.7
expression_engine.solve('floor(-5.567, 2)')
# -5.57
ceil¶
Vectorized. Rounds value up (toward positive infinity) to precision decimal places.
fix¶
Vectorized. Rounds value toward zero to precision decimal places (truncation).
rint¶
Vectorized. Rounds value to the nearest integer. When exactly halfway between two integers, rounds to the nearest even one (banker's rounding).
clip¶
Vectorized. Clamps each element to the range [min_value, max_value]. Pass None to leave a bound open. At least one bound must be provided.
expression_engine.solve('clip(value, 1.0, 4.0)', {'value': 5.0})
# 4.0
expression_engine.solve('clip(value, 1.0, 4.0)', {'value': 0.5})
# 1.0
import numpy as np
expression_engine.solve('clip(values, 0.0, None)', {'values': np.array([-1.0, 0.5, 2.0])})
# [0.0, 0.5, 2.0]
Aggregation¶
sum¶
Returns the sum of all elements. NaN and None are treated as 0.
import numpy as np
expression_engine.solve('sum(values)', {'values': np.array([1.0, 2.0, 3.0])})
# 6.0
expression_engine.solve('sum(values)', {'values': np.array([1.0, float('nan'), None, 3.0])})
# 4.0
prod¶
Returns the product of all elements. NaN and None are treated as 1.
import numpy as np
expression_engine.solve('prod(values)', {'values': np.array([1.0, 2.0, 3.0])})
# 6.0
max¶
Returns the maximum value. Returns default if value is empty.
import numpy as np
expression_engine.solve('max(values)', {'values': np.array([1.0, 3.0, 2.0])})
# 3.0
min¶
Returns the minimum value. Returns default if value is empty.
import numpy as np
expression_engine.solve('min(values)', {'values': np.array([1.0, 3.0, 2.0])})
# 1.0
absmax¶
Returns the element with the largest absolute value. Returns default if value is empty.
import numpy as np
expression_engine.solve('absmax(values)', {'values': np.array([-5.0, 2.0, 3.0])})
# -5.0
Cumulative¶
cumsum¶
Returns an array of running totals. NaN and None are treated as 0.
import numpy as np
expression_engine.solve('cumsum(values)', {'values': np.array([1.0, 2.0, 3.0])})
# [1., 3., 6.]
cumprod¶
Returns an array of running products. NaN and None are treated as 1.
import numpy as np
expression_engine.solve('cumprod(values)', {'values': np.array([1.0, 2.0, 3.0])})
# [1., 2., 6.]
diff¶
Returns first differences — each element minus its predecessor. The output has one fewer element than the input.
import numpy as np
expression_engine.solve('diff(values)', {'values': np.array([1.0, 2.0, 4.0, 7.0])})
# [1., 2., 3.]
Statistical¶
median¶
Returns the median. Returns 0.0 if value is empty.
import numpy as np
expression_engine.solve('median(values)', {'values': np.array([1.0, 2.0, 3.0])})
# 2.0
mean¶
Returns the arithmetic mean. Returns 0.0 if value is empty.
import numpy as np
expression_engine.solve('mean(values)', {'values': np.array([1.0, 2.0, 3.0])})
# 2.0
average¶
Returns the weighted average using weights. If weights is None or sums to 0, returns the simple mean.
import numpy as np
expression_engine.solve('average(values)', {'values': np.array([1.0, 2.0, 3.0])})
# 2.0
expression_engine.solve('average(values, weights)', {
'values': np.array([1.0, 2.0, 3.0]),
'weights': np.array([1.0, 2.0, 3.0])
})
# 2.3333333333333335
std¶
Returns the standard deviation. Returns 0.0 if value is empty.
import numpy as np
expression_engine.solve('std(values)', {'values': np.array([1.0, 2.0, 3.0])})
# 0.816496580927726
var¶
Returns the variance. Returns 0.0 if value is empty.
import numpy as np
expression_engine.solve('var(values)', {'values': np.array([1.0, 2.0, 3.0])})
# 0.6666666666666666
percentile¶
Returns the value at the given percentile (0–100). interpolation controls behavior when the target falls between two data points: 'linear', 'lower', 'higher', 'midpoint', or 'nearest'. Returns 0.0 if value is empty.
import numpy as np
expression_engine.solve('percentile(values, 50.0)', {'values': np.array([1.0, 2.0, 3.0, 4.0, 5.0])})
# 3.0
quantile¶
Like percentile but accepts a quantile in the range 0–1 instead of 0–100. Returns 0.0 if value is empty.
import numpy as np
expression_engine.solve('quantile(values, 0.5)', {'values': np.array([1.0, 2.0, 3.0])})
# 2.0
correlate¶
Computes the discrete, linear cross-correlation of arr_x with arr_y. Both arrays are cast to float (defaulting to 0). mode can be 'valid', 'full', or 'same'.
import numpy as np
expression_engine.solve('correlate(x, y)', {
'x': np.array([1.0, 2.0, 3.0]),
'y': np.array([1.0, 2.0, 3.0])
})
# [14.]
ma¶
Computes the rolling (moving) average of arr over window periods. Elements are cast to float (defaulting to 0.0). The output has len(arr) - window + 1 elements.
import numpy as np
expression_engine.solve('ma(arr, 2)', {'arr': np.array([1.0, 2.0, 3.0, 4.0])})
# [1.5, 2.5, 3.5]
return¶
Computes the period return: the difference between each value and the value window steps earlier. The vacated front positions are treated as 0.
import numpy as np
expression_engine.solve('return(arr, 1)', {'arr': np.array([1.0, 2.0, 3.0])})
# [0., 1., 1.]
Transformations¶
exp¶
Vectorized. Returns \(e^{\text{value}}\). Returns None if value is None.
log¶
Vectorized. Returns the natural logarithm of value. Returns None if value is None.
log2¶
Vectorized. Returns the base-2 logarithm of value. Returns None if value is None.
log10¶
Vectorized. Returns the base-10 logarithm of value. Returns None if value is None.
power¶
Vectorized. Returns value raised to exponent. Returns None if value is None.
square¶
Vectorized. Returns value squared. Shorthand for power(value, 2). Returns None if value is None.
sqrt¶
Vectorized. Returns the square root of value. Returns None if value is None.
cbrt¶
Vectorized. Returns the cube root of value. Returns None if value is None.
abs¶
Vectorized. Returns the absolute value. Returns None if value is None.
sign¶
Vectorized. Returns the sign of value: -1.0 for negative, 0.0 for zero, 1.0 for positive. Returns None if value is None.
scale¶
Linearly rescales the elements of value so that the minimum maps to lower_limit and the maximum maps to upper_limit. Elements are cast to float (defaulting to 0.0).
import numpy as np
expression_engine.solve('scale(values, 0.0, 1.0)', {'values': np.array([0.0, 50.0, 100.0])})
# [0.0, 0.5, 1.0]
Risk Metrics¶
annualize¶
Annualizes a periodic value using the square-root-of-time rule scaled by horizon and year_base (trading days per year, defaults to 252). Returns None if value is None.
vol_to_var¶
Converts a volatility figure to Value at Risk (VaR) at the given confidence level, assuming normality. Returns None if value is None.
vol_to_cvar¶
Converts a volatility figure to Conditional Value at Risk (CVaR) at the given confidence level. Returns None if value is None.
var_to_vol¶
Inverts vol_to_var: converts a VaR figure back to an implied volatility. Returns None if value is None.