Your custom indicator is a recalculate all indicator, which means that the output values depend on the input count, consider calculating the indicator over 1000 candles:
package jforex.charts.ind;
import java.util.Arrays;
import com.dukascopy.api.Configurable;
import com.dukascopy.api.DataType;
import com.dukascopy.api.IAccount;
import com.dukascopy.api.IBar;
import com.dukascopy.api.IChart;
import com.dukascopy.api.IConsole;
import com.dukascopy.api.IContext;
import com.dukascopy.api.IHistory;
import com.dukascopy.api.IIndicators;
import com.dukascopy.api.IIndicators.AppliedPrice;
import com.dukascopy.api.IMessage;
import com.dukascopy.api.IStrategy;
import com.dukascopy.api.ITick;
import com.dukascopy.api.ITimedData;
import com.dukascopy.api.Instrument;
import com.dukascopy.api.JFException;
import com.dukascopy.api.OfferSide;
import com.dukascopy.api.Period;
import com.dukascopy.api.feed.IFeedDescriptor;
import com.dukascopy.api.indicators.IIndicator;
import com.dukascopy.api.indicators.IIndicatorAppearanceInfo;
import com.dukascopy.api.indicators.OutputParameterInfo;
/**
* The strategy calculates indicators with the same parameters
* as they appear on the last selected chart
*
*/
public class CalculateIndicatorsFromChartRecalcAll implements IStrategy {
private IIndicators indicators;
private IHistory history;
private IConsole console;
private IChart chart;
@Configurable("")
public int dataCount = 10;
@Configurable("")
public int reacalcAllBuffer = 1000;
@Override
public void onStart(IContext context) throws JFException {
indicators = context.getIndicators();
history = context.getHistory();
console = context.getConsole();
chart = context.getLastActiveChart();
if (chart == null) {
console.getErr().println("No chart opened!");
return;
}
IFeedDescriptor feedDescriptor = chart.getFeedDescriptor();
if(feedDescriptor.getDataType() == DataType.TICKS){
console.getWarn().println("Tick charts need to get calculate with from-to method");
return;
}
for (IIndicatorAppearanceInfo info : chart.getIndicatorApperanceInfos()) {
AppliedPrice[] appliedPrices = new AppliedPrice[info.getDrawingStyles().length];
Arrays.fill(appliedPrices, AppliedPrice.CLOSE);
OfferSide[] offerSides = new OfferSide[info.getDrawingStyles().length];
Arrays.fill(offerSides, chart.getSelectedOfferSide());
IIndicator indicator = indicators.getIndicator(info.getName());
ITimedData feedData = history.getFeedData(feedDescriptor, 0);
int candlesBefore = indicator.getIndicatorInfo().isRecalculateAll() ? reacalcAllBuffer + dataCount : dataCount;
Object[] result = indicators.calculateIndicator(feedDescriptor, offerSides, info.getName(), appliedPrices, info.getOptParams(), candlesBefore, feedData
.getTime(), 0);
for (int i = 0; i < indicator.getIndicatorInfo().getNumberOfOutputs(); i++) {
OutputParameterInfo.Type outputType = indicator.getOutputParameterInfo(i).getType();
String resultStr =
outputType == OutputParameterInfo.Type.DOUBLE ? arrayToString((double[]) result[i], candlesBefore - dataCount)
: outputType == OutputParameterInfo.Type.INT ? Arrays.toString((int[]) result[i])
: "object outputs need special processing";
console.getOut().format("%s %s last %s values: %s", info.getName(), indicator.getOutputParameterInfo(i).getName(), dataCount, resultStr).println();
}
}
context.stop();
}
private static String arrayToString(double[] arr, int from) {
StringBuffer sb = new StringBuffer();
for (int r = from; r < arr.length; r++) {
sb.append(String.format("[%s] %.7f; ", r, arr[r]));
}
return sb.toString();
}
@Override
public void onTick(Instrument instrument, ITick tick) throws JFException {}
@Override
public void onBar(Instrument instrument, Period period, IBar askBar, IBar bidBar) throws JFException {}
@Override
public void onMessage(IMessage message) throws JFException {}
@Override
public void onAccount(IAccount account) throws JFException {}
@Override
public void onStop() throws JFException {}
}