Skip to content

Instantly share code, notes, and snippets.

@tomas-rampas
Created April 11, 2016 19:23
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tomas-rampas/dedefc877974c0081025a7ebb29b725c to your computer and use it in GitHub Desktop.
Save tomas-rampas/dedefc877974c0081025a7ebb29b725c to your computer and use it in GitHub Desktop.
/**
* Created by Tomas Rampas on 4/10/2016.
*/
import com.dukascopy.api.*;
import com.dukascopy.api.drawings.*;
import com.dukascopy.api.feed.IFeedDescriptor;
import com.dukascopy.api.indicators.*;
import java.awt.*;
import java.util.*;
import java.util.List;
import java.util.concurrent.TimeUnit;
public class VolumeProfile implements IIndicator {
private IndicatorInfo indicatorInfo;
private InputParameterInfo[] inputParameterInfos;
private OptInputParameterInfo[] optInputParameterInfos;
private OutputParameterInfo[] outputParameterInfos;
private IBar[][] inputs = new IBar[1][];
private int timePeriod = 5;
private int hour = 0;
private int minute = 0;
private int width = 21;
private double[][] outputs = new double[1][];
private IFeedDescriptor feedDescriptor;
private IIndicatorChartPanel chart;
private IChartObjectFactory factory;
private IIndicatorContext context;
private static final String GUID = UUID.randomUUID().toString();
//private IFeedDescriptor askTicksFeed, bidTicksFeed;
private IHistory history;
private Instrument instrument;
@Override
public void onStart(IIndicatorContext context) {
indicatorInfo = new IndicatorInfo("Volume Profile", "VolProfile", "Custom Indicators", true, false, false, 1, 1, 1);
inputParameterInfos = new InputParameterInfo[] {new InputParameterInfo("Bars", InputParameterInfo.Type.BAR)};
optInputParameterInfos = new OptInputParameterInfo[] {
new OptInputParameterInfo("No of days", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(timePeriod, 1, 200, 1)),
new OptInputParameterInfo("Hour", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(hour, 0, 23, 1)),
new OptInputParameterInfo("Minute", OptInputParameterInfo.Type.OTHER, new IntegerRangeDescription(minute, 0, 59, 1))
};
outputParameterInfos = new OutputParameterInfo[] {
new OutputParameterInfo("Out", OutputParameterInfo.Type.DOUBLE, OutputParameterInfo.DrawingStyle.LINE)
};
feedDescriptor = context.getFeedDescriptor();
this.context = context;
this.history = this.context.getHistory();
}
@Override
public IndicatorInfo getIndicatorInfo() {
return indicatorInfo;
}
@Override
public InputParameterInfo getInputParameterInfo(int index) {
if (index <= inputParameterInfos.length) {
return inputParameterInfos[index];
}
return null;
}
@Override
public OptInputParameterInfo getOptInputParameterInfo(int index) {
if (index <= optInputParameterInfos.length) {
return optInputParameterInfos[index];
}
return null;
}
@Override
public OutputParameterInfo getOutputParameterInfo(int index) {
if (index <= outputParameterInfos.length) {
return outputParameterInfos[index];
}
return null;
}
@Override
public void setInputParameter(int index, Object array) {
inputs[index] = (IBar[]) array;
}
@Override
public void setOptInputParameter(int index, Object value) {}
@Override
public void setOutputParameter(int index, Object array) {
outputs[index] = (double[]) array;
}
@Override
public int getLookback() {
return 0;
}
@Override
public int getLookforward() { return 0; }
@Override
public IndicatorResult calculate(int startIndex, int endIndex) {
if (startIndex - getLookback() < 0) {
startIndex -= startIndex - getLookback();
}
if (startIndex > endIndex) {
return new IndicatorResult(0, 0);
}
if(factory == null){
chart = context.getIndicatorChartPanel();
//no chart opened - either indicator called from strategy or indicator
if(chart == null){
return new IndicatorResult(startIndex, endIndex-startIndex + 1);
}
factory = chart.getChartObjectFactory();
}
IBar lastDailyBar; long today = 0;
try {
today = history.getStartTimeOfCurrentBar(getInstrument(), Period.DAILY);
//context.getConsole().getOut().println(String.format("Today: %tc", today));
} catch (JFException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
for (int i = startIndex, j = 0; i <= endIndex; i++, j++) {
processBar(today, inputs[0][i].getTime());
}
return new IndicatorResult(startIndex, endIndex-startIndex + 1);
}
private Instrument getInstrument() {
return context.getFeedDescriptor().getInstrument();
}
private void processBar(long today, long timestamp) {
if(TimeUnit.MILLISECONDS.toDays(today-timestamp) > timePeriod) {
return;
}
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(timestamp);
calendar.add(Calendar.HOUR, 24);
long timeoffset = calendar.getTimeInMillis();
long milliseconds = timestamp;
int seconds = (int) (milliseconds / 1000) % 60 ;
int minutes = (int) ((milliseconds / (1000*60)) % 60);
int hours = (int) ((milliseconds / (1000*60*60)) % 24);
context.getConsole().getOut().print(String.format("Last day: %tc %tc", timeoffset,(new Date()).getTime()));
if((seconds == 0 && minutes == minute && hours == hour)){
processDailyVolume(timestamp, timeoffset);
}
}
private void processDailyVolume(long timestamp, long timeoffset) {
try {
long currentTime = (new Date()).getTime();
context.getConsole().getOut().print(String.format("Last day: %tc tc", timeoffset, currentTime));
if( currentTime < timeoffset)
{
timeoffset = currentTime;
}
//context.getConsole().getOut().println(String.format("%tc %tc", timestamp, timeoffset));
double pip = getInstrument().getPipValue();
long lastTick = history.getLastTick(getInstrument()).getTime();
if(timeoffset > lastTick){
timeoffset = lastTick;
}
List<ITick> ticks = history.getTicks(getInstrument(), timestamp, timeoffset);
ITick maxTick = Collections.max(ticks, new Comparator<ITick>() {
@Override
public int compare(ITick o1, ITick o2) {
return Double.compare(o1.getAsk(), o2.getAsk());
}
});
ITick minTick = Collections.min(ticks, new Comparator<ITick>() {
@Override
public int compare(ITick o1, ITick o2) {
return Double.compare(o1.getBid(), o2.getBid());
}
});
context.getConsole().getOut().println(String.format("%tc %tc %d %.1f %.1f", timestamp, timeoffset, ticks.size(),
maxTick.getAsk(), maxTick.getBid()));
int points = (int) (((maxTick.getAsk() - minTick.getBid())/pip));
Integer[] sum = new Integer[points];
int maxTicks = 0;
for (ITick tick : ticks) {
int idx = (int)((tick.getBid() - minTick.getBid())/pip);
if(sum[idx] == null) sum[idx] = 0;
sum[idx]++;
maxTicks = Math.max(sum[idx], maxTicks);
}
context.getConsole().getOut().println(String.format("%tc %tc %d %.1f %.1f", timestamp, timeoffset, ticks.size(),
maxTick.getAsk(), maxTick.getBid()));
if(sum.length < 1) return;
drawVerticalBackLine(timestamp, maxTick, minTick);
long oneTickMiliseconds =(long)((width * 60 * 60 * 1000)/maxTicks);
this.context.getConsole().getOut().println(String.format("%tc %.5f / %.5f %d tick levels %d, %d, %d",
timestamp, minTick.getBid(), maxTick.getAsk(), Arrays.asList(sum).size(), maxTicks, points,
oneTickMiliseconds));
IPolyLineChartObject volBarLasso = factory.createPolyLine(GUID + "poly" + String.valueOf(timestamp));
volBarLasso.addNewPoint(timestamp, minTick.getBid());
for (int k = 0; k < sum.length; k++) {
int sumTicks = 1;
if(sum[k] != null) sumTicks = sum[k];
long toTime = sumTicks * oneTickMiliseconds;
volBarLasso.addNewPoint(timestamp+toTime, minTick.getBid()+(k*pip));
volBarLasso.addNewPoint(timestamp+toTime, minTick.getBid()+((k+1)*pip));
//this.context.getConsole().getOut().println(String.format("%tc %tc %d", milliseconds, milliseconds+toTime, (k)));
String key = GUID + String.valueOf(timestamp) + k;
if(this.chart.get(key) != null) continue;
drawHorizonatalVolumeBar(timestamp, pip, minTick, k, sumTicks, toTime, key);
}
volBarLasso.addNewPoint(timestamp, maxTick.getAsk());
volBarLasso.setLineWidth(2);
volBarLasso.setColor(Color.BLUE);
volBarLasso.setOpacity((float)0.4);
this.chart.add(volBarLasso);
} catch (JFException e) {
// TODO Auto-generated catch block
e.printStackTrace(context.getConsole().getErr());
}
}
private void drawHorizonatalVolumeBar(long timestamp, double pip, ITick minTick, int k, int sumTicks, long toTime, String key) {
// IRectangleChartObject volBar1 = factory.createRectangle(key,
// timestamp, minTick.getBid()+(k*pip), timestamp+toTime, minTick.getBid()+((k+1)*pip));
IShortLineChartObject volBar1 = factory.createShortLine(key,
timestamp, minTick.getBid()+(k*pip), timestamp+toTime, minTick.getBid()+(k*pip));
volBar1.setTooltip(String.format("%.5f Ticks %d", minTick.getBid()+(k*pip), sumTicks));
volBar1.setLineWidth(1);
volBar1.setColor(Color.BLUE);
volBar1.setOpacity((float)0.5);
//volBar1.setFillColor(Color.LIGHT_GRAY);
//volBar1.setFillOpacity((float)0.07);
this.chart.add(volBar1);
}
/**
* Draws verical back line.
* @param timestamp
* @param maxTick
* @param minTick
*/
private void drawVerticalBackLine(long timestamp, ITick maxTick, ITick minTick) {
String key = GUID + String.valueOf(timestamp);
if(this.chart.get(key) != null) return;
IShortLineChartObject line = factory.createShortLine(key,
timestamp, minTick.getBid(), timestamp, maxTick.getAsk());
line.setLineWidth(2);
line.setColor(Color.BLUE);
line.setOpacity((float) 0.4);
this.chart.add(line);
}
}
@frangonve
Copy link

Hello, I'm really a newbie to java. I've downloaded the volume profile indicator and when adding to a chart in jforex I get these error messages:

java.lang.ArrayIndexOutOfBoundsException

and then this message:
07:48:25 Last day: Tue Dec 20 04:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 04:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 05:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 05:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 06:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 06:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 07:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 07:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 08:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 08:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 09:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 09:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 10:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 10:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 11:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 11:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 12:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 12:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 13:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 13:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 14:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 14:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 15:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 15:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 16:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 16:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 17:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 17:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 18:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 18:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 19:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 19:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 20:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 20:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 21:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 21:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 22:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 22:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 23:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Tue Dec 20 23:30:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Wed Dec 21 00:00:00 UTC 2016 Fri Dec 23 07:48:26 UTC 2016Last day: Wed Dec 21 00:00:00 UTC 2016 tcTue Dec 20 00:00:00 UTC 2016 Wed Dec 21 00:00:00 UTC 2016 103835 118.2 118.2

Please can you help?
Cheers

Francisco

@6677028
Copy link

6677028 commented Sep 15, 2018

Hello
You can fix on Jforex 3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment