User Defined Functions

Extending the analytics ecosystem through UDFs with the Analytics API


Overview

This analytic processor enables complex calculation to be executed using a provided analytical function implemented using the Analytics API. This feature also provides the ability to set a rolling number of events to be used with the calculation.

Leverage this feature for complex calculations and control the implementation complexity

Key Features

  • Pluggable

  • Analytics API

  • DSL support

Example

The analytic function ema, Exponential Moving Average, is defined inline using the standard Joule DSL

user defined function:
  ema:
    parameters:
      smoothing factor: 0.33333
  fields: [ ask ]
  event history: 12
  assign prefix: ema12

Attributes

AttributeDescriptionData TypeRequired

fields

Fields to calculated from the event

String[]

event history

Number of rolling events to stored and used for the calculation

Integer

assign prefix

Prefix to use for the result assignment. This is used to allow the same function to be used multiple times. If this is not provided the function postfix will be applied e.g. ask_EMA

String Default: Function postfix

Further example

This example demonstrates how you would combine complex calculation with a final analytic expression to trigger an alert.

processing unit:
    pipeline:
      - user defined function:
          ema:
            parameters:
              smoothing factor: 0.33333
          fields: [ ask ]
          event history: 26
          response prefix: ema26
    
      - user defined function:
          ema:
            parameters:
              smoothing factor: 0.33333
          fields: [ ask ]
          event history: 12
          response prefix: ema12
    
      - analytic:
          expression: "ema12_ask - ema26_ask"
          assign to: macd_ask_signal
      
emit:
    select: "symbol, macd_ask_signal"
    having: "macd_ask_signal > 0.05"

Example function implementation

The below is an implementation example for a custom analytics function. Further details can be found in the Analytics API documentation.

@JsonRootName(value = "ema")
public class ExponentialMovingAverage extends AnalyticsFunction<Double> {

    public static final String SMOOTH_FACTOR = "smoothing factor";
    private double smoothFactor = 0.333;

    public ExponentialMovingAverage() {
        super();
    }

    @Override
    public void setParameters(Properties parameters) {
        if (parameters != null && parameters.containsKey(SMOOTH_FACTOR)) {
            smoothFactor = Double.parseDouble(parameters.get(SMOOTH_FACTOR).toString());
        }
    }

    @Override
    public String getVariablePostFixID() {
        return "EMA";
    }

    @Override
    public Double compute(Number[] values, Number previousValue) {
        if (previousValue == null) return Double.NaN;

        if (Double.isNaN(previousValue.doubleValue())) {
            previousValue = values[values.length - 1];
            return (Double)previousValue;
        }

        for (Number d : values) {
            previousValue = (d.doubleValue() * smoothFactor) + (previousValue.doubleValue() * (1 - smoothFactor));
        }
        return previousValue.doubleValue();
    }
}

Last updated