I use the below my/indicator. Playing a bit with it I get the errors like this:
09:07:02 Error in indicator: java.lang.ArrayIndexOutOfBoundsException: 40 @ jforex.VolumeForce.calculate(VolumeForce.java:61)
09:07:02 Bar times do not match.
09:07:02 Bar times do not match.
etc
It appears I either do something wrong or there is a major flaw in the bars loading on the internal JForex engine.
Theoretically, I should obtain the bars synchronized on both sides Bid and Ask.
Please have a look and let me know. The indicator sometimes do not show that error. Sometime does not draw at all if I change in the chart between Bid/Ask top box. If I scroll the chart the errors appear again.
Can you help. Thank you.
package jforex;
import com.dukascopy.api.IBar;
import com.dukascopy.api.IConsole;
import com.dukascopy.api.JFException;
import com.dukascopy.api.OfferSide;
import com.dukascopy.api.indicators.*;
public class VolumeForce implements IIndicator
{
// indicator name & title
protected static final String iIndName = "VOL_FORCE";
protected static final String iIndTitle = "Volume Force";
private IndicatorInfo indicatorInfo;
private InputParameterInfo[] inputParameterInfos;
private OptInputParameterInfo[] optInputParameterInfos;
private OutputParameterInfo[] outputParameterInfos;
private IBar[] iBidBars, iAskBars;
private double[][] outputs = new double[1][]; // 2 for full volumes
IConsole iConsole;
public void onStart(IIndicatorContext context)
{
IIndicatorsProvider indicatorsProvider = context.getIndicatorsProvider();
iConsole = context.getConsole();
indicatorInfo = new IndicatorInfo(iIndName,iIndTitle,"Custom",false,false,true,2,0,1);
inputParameterInfos = new InputParameterInfo[]
{
new InputParameterInfo("Bid bars",InputParameterInfo.Type.BAR),
new InputParameterInfo("Ask bars",InputParameterInfo.Type.BAR)
};
inputParameterInfos[0].setOfferSide(OfferSide.BID);
inputParameterInfos[1].setOfferSide(OfferSide.ASK);
outputParameterInfos = new OutputParameterInfo[] {new OutputParameterInfo("Volume Force", OutputParameterInfo.Type.DOUBLE,OutputParameterInfo.DrawingStyle.LINE)};
//outputParameterInfos = new OutputParameterInfo[] {new OutputParameterInfo("Bid Volume", OutputParameterInfo.Type.DOUBLE,OutputParameterInfo.DrawingStyle.LINE),
// new OutputParameterInfo("Ask Volume", OutputParameterInfo.Type.DOUBLE,OutputParameterInfo.DrawingStyle.LINE)};
}
public IndicatorResult calculate(int startIndex, int endIndex)
{
//calculating startIndex taking into account lookback value
if(startIndex - getLookback() < 0)
{
startIndex -= startIndex - getLookback();
}
if(startIndex > endIndex)
{
return new IndicatorResult(0,0);
}
int aOutLen = endIndex - startIndex + 1;
double aVolBid, aVolAsk;
for(int i=0;i<aOutLen;i++)
{
boolean aWrongBTime = (iBidBars[startIndex+i].getTime() != iAskBars[startIndex+i].getTime());
//throw new ArrayStoreException("Bar times do not match.");
//iConsole.getOut().println("Bar times do not match.");
aVolBid = iBidBars[startIndex+i].getVolume();
aVolAsk = iAskBars[startIndex+i].getVolume();
if(aVolBid == 0 || aVolAsk == 0 || aWrongBTime)
{
if(aWrongBTime)
iConsole.getOut().println("Bar times do not match.");
outputs[0][i] = -1;
}
else
outputs[0][i] = aVolBid/aVolAsk;
}
return new IndicatorResult(startIndex,aOutLen);
}
public IndicatorInfo getIndicatorInfo()
{
return indicatorInfo;
}
public InputParameterInfo getInputParameterInfo(int index)
{
if(index <= inputParameterInfos.length)
{
return inputParameterInfos[index];
}
return null;
}
public int getLookback()
{
return 5;
}
public int getLookforward()
{
return 0;
}
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)
{
switch (index)
{
case 0:
iBidBars = (IBar[]) array;
break;
case 1:
iAskBars = (IBar[]) array;
break;
default:
throw new ArrayIndexOutOfBoundsException(iIndName+":setInputParameter(). Invalid index: "+index);
}
}
public void setOptInputParameter(int index, Object value)
{
}
public void setOutputParameter(int index, Object array)
{
outputs[index] = (double[]) array;
}
}