Velocity Indicator

Fu510n

Member
Joined
Jan 7, 2025
Posts
15
Likes
10
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);
  }
}

ReshLabsMotiveWave.png
 
Last edited:
Hello,
Thanks for sharing.
What is "package reshlabs" ?
 
In the interest of learning how to write MotiveWave indicators and strategies, I started by setting up a "reshlabs" project in IntelliJ that included the various examples mentioned elsewhere in the forums here (including those provided by MotiveWave). I altered the @StudyHeader on all so they'd be under a separate "Resh Labs" menu, refactored whatever was needed so they'd ALL compile (and ideally run) and started developing/porting code I've written over the years in EasyLanguage & Python.

Having all code rolled into my own package makes it easy to search though ALL other code for examples while I'm trying to figure things out.
 
Top