This function uses the same implementation pattern as the EMA function.
@AnalyticDefinition(
id = "bollingerband",
stateless = true,
useRawColumn = true,
description = "Bollinger Bands are a momentum indicator used in technical analysis."
)
@JsonRootName(value = "bollinger bands")
public class BollingerBands extends AnalyticsFunction<Map<String, Double>> {
private int deviations = 2;
public BollingerBands(){
super();
}
@Override
public Map<String, Double> compute(Number[] values, Number previousValue, Context context) {
Double mean = Arrays.stream(values).mapToDouble(d-> (double) d).sum() / values.length;
double sqrtmean = 0.0;
for(int i=0; i<values.length; i++){
double s = values[i].doubleValue() - mean;
sqrtmean += s * s;
}
sqrtmean = Math.sqrt( sqrtmean / values.length);
double band = deviations * sqrtmean;
Map<String, Double> results = new HashMap<>();
results.put("upper", mean + band);
results.put("middle", mean );
results.put("lower", mean - band);
return results;
}
@Override
public void setParameters(Properties parameters) {
if( parameters != null && parameters.containsKey("deviations")) {
deviations = Integer.parseInt(parameters.get("deviations").toString());
}
}
@Override
public String getVariablePostFixID() {
return "bollingerband";
}
For Joule to load and initialised the component the analytics class needs to be defined within the plugins.properties file under the META-INF/services directory
Example
# Change and add lines for your analytics classes
com.fractalworks.examples.banking.analytics.BollingerBands