A "basic" indicator to show how quickly non-time-based bars were formed (with 9 time thresholds: 1s, 2s, 3s, 10s, 1m, 3m, 5m, 10m, 10+m). I couldn't figure out how to assign unique colors to a single path using
.

series.setPathColor(index, Values.VELOCITY, velocityColor);
and wasn't able to find meaningful examples or documentation anywhere so if anyone can shed some enlightenment on that front, it would be much appreciated 
Java:
package reshlabs;
import com.motivewave.platform.sdk.common.*;
import com.motivewave.platform.sdk.common.Defaults;
import com.motivewave.platform.sdk.common.desc.*;
import com.motivewave.platform.sdk.common.desc.PathDescriptor;
import com.motivewave.platform.sdk.study.Study;
import com.motivewave.platform.sdk.study.StudyHeader;
import java.awt.Color;
@StudyHeader(
namespace = "com.motivewave",
id = "Velocity",
name = "Velocity",
desc = "Displays velocity of bar formation for non-time-based charts",
menu = "Resh Labs",
overlay = false
// requiresBarUpdates = true // causes calculate() to execute on every tick
)
public class Velocity extends Study
{
final static String
VEL0_IND = "vel0Ind", VEL1_IND = "vel1Ind", VEL2_IND = "vel2Ind",
VEL3_IND = "vel3Ind", VEL4_IND = "vel4Ind", VEL5_IND = "vel5Ind",
VEL6_IND = "vel6Ind", VEL7_IND = "vel7Ind", VEL8_IND = "vel8Ind";
enum Values { VEL0, VEL1, VEL2, VEL3, VEL4, VEL5, VEL6, VEL7, VEL8 }
@Override
public void initialize(Defaults defaults)
{
// debug("Velocity::initialize()");
// Define settings descriptor
var sd = createSD();
var tab = sd.addTab("General");
var grp = tab.addGroup("Velocity");
// setSettingsDescriptor(sd);
var vel0 = new PathDescriptor("vel < 1s", "vel < 1s", Color.WHITE, 1.0f, null, true, false, true);
vel0.setShowAsBars(true);
vel0.setSupportsColor(true);
grp.addRow(vel0);
var vel1 = new PathDescriptor("vel < 2s", "vel < 2s", Color.RED, 1.0f, null, true, false, true);
vel1.setShowAsBars(true);
vel1.setSupportsColor(true);
grp.addRow(vel1);
var vel2 = new PathDescriptor("vel < 3s", "vel < 3s", new Color(208, 0, 0), 1.0f, null, true, false, true); // darker red
vel2.setShowAsBars(true);
vel2.setSupportsColor(true);
grp.addRow(vel2);
var vel3 = new PathDescriptor("vel < 10s", "vel < 10s", new Color(255, 153, 0), 1.0f, null, true, false, true); // orange
vel3.setShowAsBars(true);
vel3.setSupportsColor(true);
grp.addRow(vel3);
var vel4 = new PathDescriptor("vel < 1m", "vel < 1m", Color.YELLOW, 1.0f, null, true, false, true);
vel4.setShowAsBars(true);
vel4.setSupportsColor(true);
grp.addRow(vel4);
var vel5 = new PathDescriptor("vel < 3m", "vel < 3m", Color.GREEN, 1.0f, null, true, false, true);
vel5.setShowAsBars(true);
vel5.setSupportsColor(true);
grp.addRow(vel5);
var vel6 = new PathDescriptor("vel < 5m", "vel < 5m", Color.BLUE, 1.0f, null, true, false, true);
vel6.setShowAsBars(true);
vel6.setSupportsColor(true);
grp.addRow(vel6);
var vel7 = new PathDescriptor("vel < 10m", "vel < 10m", new Color(80, 0, 80), 1.0f, null, true, false, true); // purple
vel7.setShowAsBars(true);
vel7.setSupportsColor(true);
grp.addRow(vel7);
var vel8 = new PathDescriptor("vel >= 10m", "vel >= 10m", new Color(80, 80, 80), 1.0f, null, true, false, true); // dark gray
vel8.setShowAsBars(true);
vel8.setSupportsColor(true);
grp.addRow(vel8);
var desc = createRD();
desc.exportValue(new ValueDescriptor(Values.VEL0, "vel < 1s", new String[]{}));
desc.declarePath(Values.VEL0, "vel < 1s");
desc.setFixedBottomValue(0);
desc.declareIndicator(Values.VEL0, VEL0_IND);
desc.exportValue(new ValueDescriptor(Values.VEL1, "vel < 2s", new String[]{}));
desc.declarePath(Values.VEL1, "vel < 2s");
desc.setFixedBottomValue(0);
desc.declareIndicator(Values.VEL1, VEL1_IND);
desc.exportValue(new ValueDescriptor(Values.VEL2, "vel < 3s", new String[]{}));
desc.declarePath(Values.VEL2, "vel < 3s");
desc.setFixedBottomValue(0);
desc.declareIndicator(Values.VEL2, VEL2_IND);
desc.exportValue(new ValueDescriptor(Values.VEL3, "vel < 10s", new String[]{}));
desc.declarePath(Values.VEL3, "vel < 10s");
desc.setFixedBottomValue(0);
desc.declareIndicator(Values.VEL3, VEL3_IND);
desc.exportValue(new ValueDescriptor(Values.VEL4, "vel < 1m", new String[]{}));
desc.declarePath(Values.VEL4, "vel < 1m");
desc.setFixedBottomValue(0);
desc.declareIndicator(Values.VEL4, VEL4_IND);
desc.exportValue(new ValueDescriptor(Values.VEL5, "vel < 3m", new String[]{}));
desc.declarePath(Values.VEL5, "vel < 3m");
desc.setFixedBottomValue(0);
desc.declareIndicator(Values.VEL5, VEL5_IND);
desc.exportValue(new ValueDescriptor(Values.VEL6, "vel < 5m", new String[]{}));
desc.declarePath(Values.VEL6, "vel < 5m");
desc.setFixedBottomValue(0);
desc.declareIndicator(Values.VEL6, VEL6_IND);
desc.exportValue(new ValueDescriptor(Values.VEL7, "vel < 10m", new String[]{}));
desc.declarePath(Values.VEL7, "vel < 10m");
desc.setFixedBottomValue(0);
desc.declareIndicator(Values.VEL7, VEL7_IND);
desc.exportValue(new ValueDescriptor(Values.VEL8, "vel1", new String[]{}));
desc.declarePath(Values.VEL8, "vel >= 10m");
desc.setFixedBottomValue(0);
desc.declareIndicator(Values.VEL8, VEL8_IND);
desc.setRangeKeys(Values.VEL0, Values.VEL1, Values.VEL2, Values.VEL3, Values.VEL4, Values.VEL5, Values.VEL6, Values.VEL7, Values.VEL8);
}
@Override
public void onBarClose(DataContext ctx)
{
// debug("Velocity::onBarClose()");
}
@Override
protected void calculate(int index, DataContext ctx)
{
var series = ctx.getDataSeries();
if (series.size() < 2 || index < 2) return; // need at least 2 bars for velocity calculation
// Get the time difference (in seconds) between the current and previous bar
double timeNow = series.getStartTime(index); // is this right or + 1
double timePrev = series.getStartTime(index - 1);
double timeDiff = (timeNow - timePrev) / 1000.0;
// Assign colors based on velocity thresholds
if (timeDiff < 1) {
series.setDouble(index, Values.VEL0, 100.0);
} else if (timeDiff < 2) {
series.setDouble(index, Values.VEL1, 100.0);
} else if (timeDiff < 3) {
series.setDouble(index, Values.VEL2, 100.0);
} else if (timeDiff < 10) {
series.setDouble(index, Values.VEL3, 100.0);
} else if (timeDiff < 60) {
series.setDouble(index, Values.VEL4, 100.0);
} else if (timeDiff < 180) {
series.setDouble(index, Values.VEL5, 100.0);
} else if (timeDiff < 300) {
series.setDouble(index, Values.VEL6, 100.0);
} else if (timeDiff < 600) {
series.setDouble(index, Values.VEL7, 100.0);
} else {
series.setDouble(index, Values.VEL8, 100.0);
}
// debug("Velocity::calculate(" + index + ", " + series.size() + ") now=" + timeNow + " prev=" + timePrev + " timeDiff=" + timeDiff);
// series.setPathColor(index, Values.VELOCITY, velocityColor); // why can't I just change the color of a single path/bar?
series.setComplete(index);
}
}

Last edited: