Motivewave very slow with custom indicator added

TradeEscape

Member
Joined
Mar 15, 2023
Posts
8
Likes
3
I just made a simple custom indicator that adds fib TP levels to the standard Supertrend script. When I load it to a chart, the chart update and scroll becomes super slow. Back to normal speed when I delete the custom indicator from the chart. Any idea?
 
Sure, here is the script, appreciate the help:

package com.motivewave.platform.study.overlay;

import com.motivewave.platform.sdk.common.Coordinate;
import com.motivewave.platform.sdk.common.DataContext;
import com.motivewave.platform.sdk.common.Defaults;
import com.motivewave.platform.sdk.common.Enums;
import com.motivewave.platform.sdk.common.Inputs;
import com.motivewave.platform.sdk.common.Util;
import com.motivewave.platform.sdk.common.desc.ColorDescriptor;
import com.motivewave.platform.sdk.common.desc.DoubleDescriptor;
import com.motivewave.platform.sdk.common.desc.IndicatorDescriptor;
import com.motivewave.platform.sdk.common.desc.IntegerDescriptor;
import com.motivewave.platform.sdk.common.desc.MarkerDescriptor;
import com.motivewave.platform.sdk.common.desc.PathDescriptor;
import com.motivewave.platform.sdk.common.desc.SliderDescriptor;
import com.motivewave.platform.sdk.common.desc.ValueDescriptor;
import com.motivewave.platform.sdk.draw.Marker;
import com.motivewave.platform.sdk.study.Study;
import com.motivewave.platform.sdk.study.StudyHeader;
import com.motivewave.platform.sdk.study.RuntimeDescriptor;


import java.awt.Color;

@StudyHeader(
namespace="com.mycompany",
id="ID_SUPERTRENDTP",
rb="com.motivewave.platform.study.nls.strings",
label="SUPERTRENDTP",
menu="GENERAL",
name="SUPERTRENDTP",
desc="SUPERTRENDTP",
signals=true,
overlay=true)
public class SuperTrendTP extends Study {
final static String MULTIPLIER = "multiplier";

protected enum Values { TSL, UP, DOWN, TREND, TP1, TP2, TP3 }
protected enum Signals { BUY, SELL }

// Stored entry-level and base for Fibonacci calcs
private double entryLevel = Double.NaN;
private double baseLevel = Double.NaN;

@Override
public void initialize(Defaults defaults) {
var sd = createSD();
var tab = sd.addTab(get("TAB_GENERAL"));

var inputs = tab.addGroup(get("LBL_INPUTS"));
inputs.addRow(new DoubleDescriptor(MULTIPLIER, get("LBL_MULTIPLIER"), 3, 0.01, 999, 0.01));
inputs.addRow(new IntegerDescriptor(Inputs.PERIOD, get("LBL_ATR_PERIOD"), 7, 1, 999, 1));

var tpGroup = tab.addGroup("Take Profits");
tpGroup.addRow(new DoubleDescriptor("TP1_RATIO", "TP1 %", 161.8, 50, 1000, 0.1));
tpGroup.addRow(new DoubleDescriptor("TP2_RATIO", "TP2 %", 261.8, 50, 1000, 0.1));
tpGroup.addRow(new DoubleDescriptor("TP3_RATIO", "TP3 %", 423.6, 50, 1000, 0.1));

var settings = tab.addGroup(get("LBL_DISPLAY"));
var path = new PathDescriptor(Inputs.PATH, get("LBL_LINE"), defaults.getLineColor(), 1.0f, null, true, false, true);
settings.addRow(path);
settings.addRow(new ColorDescriptor(Inputs.UP_COLOR, get("LBL_UP_COLOR"), defaults.getGreenLine(), true, false));
settings.addRow(new ColorDescriptor(Inputs.DOWN_COLOR, get("LBL_DOWN_COLOR"), defaults.getRedLine(), true, false));
settings.addRow(new MarkerDescriptor(Inputs.UP_MARKER, get("LBL_UP_MARKER"),
Enums.MarkerType.ARROW, Enums.Size.SMALL, defaults.getGreen(), defaults.getLineColor(), true, true));
settings.addRow(new MarkerDescriptor(Inputs.DOWN_MARKER, get("LBL_DOWN_MARKER"),
Enums.MarkerType.ARROW, Enums.Size.SMALL, defaults.getRed(), defaults.getLineColor(), true, true));
settings.addRow(new IndicatorDescriptor(Inputs.IND, get("LBL_INDICATOR"), null, null, false, true, true));

sd.addQuickSettings(MULTIPLIER);
sd.addQuickSettings(new SliderDescriptor(Inputs.PERIOD, get("LBL_ATR_PERIOD"), 7, 1, 9999, true));
sd.addQuickSettings(Inputs.PATH, Inputs.UP_COLOR, Inputs.DOWN_COLOR);

var desc = createRD();
desc.setLabelSettings(MULTIPLIER, Inputs.PERIOD);
desc.exportValue(new ValueDescriptor(Values.TSL, get("LBL_SUPERTREND"), new String[]{MULTIPLIER, Inputs.PERIOD}));
desc.declarePath(Values.TSL, Inputs.PATH);
desc.declareIndicator(Values.TSL, Inputs.IND);
desc.declareSignal(Signals.BUY, get("LBL_BUY_SIGNAL"));
desc.declareSignal(Signals.SELL, get("LBL_SELL_SIGNAL"));
desc.setRangeKeys(Values.TSL);

// Take Profit paths & export
desc.declarePath(Values.TP1, Inputs.PATH);
desc.declarePath(Values.TP2, Inputs.PATH);
desc.declarePath(Values.TP3, Inputs.PATH);
desc.exportValue(new ValueDescriptor(Values.TP1, "TP1"));
desc.exportValue(new ValueDescriptor(Values.TP2, "TP2"));
desc.exportValue(new ValueDescriptor(Values.TP3, "TP3"));
}

@Override
public int getMinBars() {
return getSettings().getInteger(Inputs.PERIOD);
}

@Override
protected void calculate(int index, DataContext ctx) {
int period = getSettings().getInteger(Inputs.PERIOD);
if (index < period) return;
var series = ctx.getDataSeries();

double mult = getSettings().getDouble(MULTIPLIER);
Double atr = series.atr(index, period);
if (atr == null) return;

double mid = (series.getHigh(index) + series.getLow(index)) / 2.0;
double up = mid - mult * atr;
double down = mid + mult * atr;

Double prevUp = series.getDouble(index - 1, Values.UP);
Double prevDown = series.getDouble(index - 1, Values.DOWN);
Double prevTrend = series.getDouble(index - 1, Values.TREND);
double close = series.getClose(index);

// refinement
if (prevUp != null && close > prevUp) up = Util.max(up, prevUp);
if (prevDown != null && close < prevDown) down = Util.min(down, prevDown);

double trend = 1;
if (prevDown != null && close > prevDown) trend = 1;
else if (prevUp != null && close < prevUp) trend = -1;
else if (prevTrend != null) trend = prevTrend;

series.setDouble(index, Values.TSL, trend > 0 ? up : down);
series.setDouble(index, Values.UP, up);
series.setDouble(index, Values.DOWN, down);
series.setDouble(index, Values.TREND, trend);

boolean complete = series.isBarComplete(index);
boolean changed = prevTrend != null && trend != prevTrend;

// On trend change at bar close, capture entry/base and compute fixed TPs
if (changed && complete) {
entryLevel = close;
baseLevel = (trend > 0) ? up : down;
}

// If first valid bar after change or already initialized
if (!Double.isNaN(entryLevel) && !Double.isNaN(baseLevel)) {
double ratio1 = getSettings().getDouble("TP1_RATIO") / 100.0;
double ratio2 = getSettings().getDouble("TP2_RATIO") / 100.0;
double ratio3 = getSettings().getDouble("TP3_RATIO") / 100.0;
double diff = (trend > 0)
? entryLevel - baseLevel
: baseLevel - entryLevel;
double tp1 = (trend > 0)
? entryLevel + diff * ratio1
: entryLevel - diff * ratio1;
double tp2 = (trend > 0)
? entryLevel + diff * ratio2
: entryLevel - diff * ratio2;
double tp3 = (trend > 0)
? entryLevel + diff * ratio3
: entryLevel - diff * ratio3;

series.setDouble(index, Values.TP1, tp1);
series.setDouble(index, Values.TP2, tp2);
series.setDouble(index, Values.TP3, tp3);

series.setPathColor(index, Values.TP1, new Color(255, 165, 0));
series.setPathColor(index, Values.TP2, new Color(0, 128, 255));
series.setPathColor(index, Values.TP3, new Color(128, 0, 128));
}

series.setComplete(index, complete);
}
}
 
I added a counter to control the number of paths drawn (SHOW LAST included in Inputs). See the attached VS2.
 

Attachments

  • Like
Reactions: GAi
Top