Here is the indicator you requested.
package jforex.indicators;
import java.awt.Color;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.TimeZone;
import com.dukascopy.api.IBar;
import com.dukascopy.api.IConsole;
import com.dukascopy.api.IIndicators.MaType;
import com.dukascopy.api.Instrument;
import com.dukascopy.api.indicators.DoubleRangeDescription;
import com.dukascopy.api.indicators.IIndicator;
import com.dukascopy.api.indicators.IIndicatorContext;
import com.dukascopy.api.indicators.IndicatorInfo;
import com.dukascopy.api.indicators.IndicatorResult;
import com.dukascopy.api.indicators.InputParameterInfo;
import com.dukascopy.api.indicators.IntegerListDescription;
import com.dukascopy.api.indicators.IntegerRangeDescription;
import com.dukascopy.api.indicators.OptInputParameterInfo;
import com.dukascopy.api.indicators.OutputParameterInfo;
public class TwoInstrumentBBands implements IIndicator {
private IndicatorInfo indicatorInfo;
// INPUTS
private double[][][] inPrice;
private int CHART_IND = 0;
private int SECOND_IND = 1;
private int OPEN = 0;
private int CLOSE = 1;
private int HIGH = 2;
private int LOW = 3;
// OPT INPUTS
private OptInputParameterInfo[] optInputParameterInfos;
private int appliedPrice;
private int bBandsPeriod;
private double deviation;
private Instrument secondInstrument = Instrument.GBPUSD;
// OUTPUTS
private OutputParameterInfo[] outputParameterInfos;
private double[][] output;
// CONTEXT
private IConsole console;
private IIndicator bbands;
public int getLookback() {
return bBandsPeriod - 1;
}
public int getLookforward() {
return 0;
}
/**************
* CALCULATE
**************/
public IndicatorResult calculate(int startIndex, int endIndex) {
if (startIndex - getLookback() < 0) {
startIndex -= startIndex - getLookback();
}
if (startIndex > endIndex) {
return new IndicatorResult(0, 0);
}
int len = endIndex - startIndex + 1;
int inLength = inPrice[CHART_IND][appliedPrice].length;
double[] bbInput = new double[inLength];
for(int i = 0; i < inLength; i++) {
bbInput[i] = inPrice[CHART_IND][appliedPrice][i] / inPrice[SECOND_IND][appliedPrice][i];
}
bbands.setInputParameter(0, bbInput);
bbands.setOptInputParameter(0, bBandsPeriod);
bbands.setOptInputParameter(1, deviation);
bbands.setOptInputParameter(2, deviation);
bbands.setOptInputParameter(3, MaType.EMA.ordinal());
bbands.setOutputParameter(0, output[0]);
bbands.setOutputParameter(1, new double[output[0].length]);
bbands.setOutputParameter(2, output[2]);
bbands.calculate(startIndex, endIndex);
for(int i = 0; i < output[0].length; i++) {
output[1][i] = (output[0][i] + output[2][i])/2;
output[3][i] = bbInput[i + getLookback()];
}
return new IndicatorResult(startIndex, len);
}
public void onStart(IIndicatorContext context) {
this.console = context.getConsole();
int[] priceValues = {OPEN, CLOSE, HIGH, LOW};
String[] priceNames = {"OPEN", "CLOSE", "HIGH", "LOW"};
int[] instrumentValues = new int[Instrument.values().length];
String[] instrumentName = new String[Instrument.values().length];
for (int i = 0; i < instrumentValues.length; i++) {
instrumentValues[i] = i;
instrumentName[i] = Instrument.values()[i].name();
}
inPrice = new double[2][][];
optInputParameterInfos = new OptInputParameterInfo[] {
new OptInputParameterInfo("Bbands applied price",
OptInputParameterInfo.Type.OTHER,
new IntegerListDescription(CLOSE, priceValues, priceNames)),
new OptInputParameterInfo("Bbands period",
OptInputParameterInfo.Type.OTHER,
new IntegerRangeDescription(10, 2, 1000, 1)),
new OptInputParameterInfo("Bbands deviation",
OptInputParameterInfo.Type.OTHER,
new DoubleRangeDescription(1.0, 0.0, 100.0, 0.01, 2)),
new OptInputParameterInfo("Second indicator",
OptInputParameterInfo.Type.OTHER,
new IntegerListDescription(Instrument.EURGBP.ordinal(), instrumentValues, instrumentName)),
};
outputParameterInfos = new OutputParameterInfo[] {
new OutputParameterInfo("Upper",
OutputParameterInfo.Type.DOUBLE,
OutputParameterInfo.DrawingStyle.LINE) {
{
this.setColor(Color.BLUE);
}
},
new OutputParameterInfo("Mid",
OutputParameterInfo.Type.DOUBLE,
OutputParameterInfo.DrawingStyle.LINE) {
{
this.setColor(Color.GRAY);
}
},
new OutputParameterInfo("Lower",
OutputParameterInfo.Type.DOUBLE,
OutputParameterInfo.DrawingStyle.LINE) {
{
this.setColor(Color.RED);
}
},
new OutputParameterInfo("Ratio",
OutputParameterInfo.Type.DOUBLE,
OutputParameterInfo.DrawingStyle.LINE) {
{
this.setColor(new Color(0,153,0));
}
}
};
output = new double[outputParameterInfos.length][];
indicatorInfo = new IndicatorInfo("2IND_BBANDS", "BBands from two indicators", "My indicators", false, false, false, 2, optInputParameterInfos.length, outputParameterInfos.length);
bbands = context.getIndicatorsProvider().getIndicator("BBANDS");
}
public IndicatorInfo getIndicatorInfo() {
return indicatorInfo;
}
public InputParameterInfo getInputParameterInfo(int index) {
if(index == 0) {
return new InputParameterInfo("chart instrument prices", InputParameterInfo.Type.PRICE);
} else if(index == 1) {
return new InputParameterInfo("second instrument prices", InputParameterInfo.Type.PRICE) {
{
setInstrument(secondInstrument);
}
};
}
return null;
}
public OptInputParameterInfo getOptInputParameterInfo(int index) {
if (index <= optInputParameterInfos.length) {
return optInputParameterInfos[index];
}
return null;
}
public OutputParameterInfo getOutputParameterInfo(int index) {
if (index <= outputParameterInfos.length) {
return outputParameterInfos[index];
}
return null;
}
public void setInputParameter(int index, Object array) {
inPrice[index] = (double[][]) array;
}
public void setOptInputParameter(int index, Object value) {
switch (index) {
case 0:
appliedPrice = (Integer) value;
break;
case 1:
bBandsPeriod = (Integer) value;
break;
case 2:
deviation = (Double) value;
break;
case 3:
secondInstrument = Instrument.values()[(Integer) value];
break;
}
}
public void setOutputParameter(int index, Object array) {
output[index] = (double[]) array;
}
// ________________________________
// Support: Some helper methods for printing
private void print(Object... o) {
for (Object ob : o) {
console.getOut().print(ob + " ");
}
console.getOut().println();
}
private void print(Object o) {
console.getOut().println(o);
}
private void print(double[] arr) {
print(arrayToString(arr));
}
private void print(double[][] arr) {
print(arrayToString(arr));
}
private void printIndicatorInfos(IIndicator ind) {
for (int i = 0; i < ind.getIndicatorInfo().getNumberOfInputs(); i++) {
print(ind.getIndicatorInfo().getName() + " Input " + ind.getInputParameterInfo(i).getName() + " " + ind.getInputParameterInfo(i).getType());
}
for (int i = 0; i < ind.getIndicatorInfo().getNumberOfOptionalInputs(); i++) {
print(ind.getIndicatorInfo().getName() + " Opt Input " + ind.getOptInputParameterInfo(i).getName() + " " + ind.getOptInputParameterInfo(i).getType());
}
for (int i = 0; i < ind.getIndicatorInfo().getNumberOfOutputs(); i++) {
print(ind.getIndicatorInfo().getName() + " Output " + ind.getOutputParameterInfo(i).getName() + " " + ind.getOutputParameterInfo(i).getType());
}
}
public static String arrayToString(double[] arr) {
String str = "";
for (int r = 0; r < arr.length; r++) {
str += "[" + r + "] " + (new DecimalFormat("#.#######")).format(arr[r]) + "; ";
}
return str;
}
public static String arrayToString(double[][] arr) {
String str = "";
if (arr == null)
return "null";
for (int r = 0; r < arr.length; r++) {
for (int c = 0; c < arr[r].length; c++) {
str += "[" + r + "][" + c + "] " + (new DecimalFormat("#.#######")).format(arr[r][c]);
}
str += "; ";
}
return str;
}
public String toDecimalToStr(double d) {
return (new DecimalFormat("#.#######")).format(d);
}
public String dateToStr(long time) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss") {
{
setTimeZone(TimeZone.getTimeZone("GMT"));
}
};
return sdf.format(time);
}
// ________________________________
}