Cainer Trend

Since we have the cainer arrows is anyone willing to make the cainer trend that goes with it that’s on TOS?

Looks like the Cainer Arrow indicator got removed in the last update, Might be a bug.

Here is the js code for the cainer arrows:

const predef = require("./tools/predef");
const meta = require("./tools/meta");
const medianPrice = require(’./tools/medianPrice’);

const p = require("./tools/plotting");
const SMA = require("./tools/SMA");
const EMA = require("./tools/EMA");
const MMA = require("./tools/MMA");
const MovingHigh = require("./tools/MovingHigh");
const MovingLow = require("./tools/MovingLow");
const trueRange = require("./tools/trueRange");

class CainerArrows {
init() {
//EMA Code
this.emaSlow = EMA(this.props.emaLength);
this.smaVol = SMA(30);
this.slow = 0;
this.volavg = 0;

    //Kama Code
    this.erLength = this.props.efficiencyRatioLength;
    this.fastSf = 2.0 / (this.props.fastLength + 1);
    this.slowSf = 2.0 / (this.props.slowLength + 1);
    this.lastKama = undefined;
    
    //Choose what price type we're using
    switch (this.props.priceType) {
        case 'high':
            this.getPriceVal = (d) => d.high();
            break;
        case 'low':
            this.getPriceVal = (d) => d.low();
            break;
        case 'open':
            this.getPriceVal = (d) => d.open();
            break;
        case 'hl2':
            this.getPriceVal = (d) => medianPrice(d);
            break;
        case 'close':
        default:
            this.getPriceVal = (d) => d.close();
    }
    
    //Plot Code
    this.atrMovingAverage = MMA(100);
}
//Kama Code
sumDifferences(data) {
    let result = 0;
    for (let i = 1; i < data.length; i++) {
        result += Math.abs(this.getPriceVal(data[i]) - this.getPriceVal(data[i-1]));
    }
    return result;
}

map(d, i, history) {
    if (!history.prior()) {
        return;
    }
   
    //Plot Code
    const atr = this.atrMovingAverage(trueRange(d, history.prior()));
    
    //KAMA Code
    if (history.back(this.erLength) === undefined) {
        return;
    }
    
    const direction = this.getPriceVal(d) - this.getPriceVal(history.back(this.erLength));
    const vol = this.sumDifferences(history.data.slice(i - this.erLength, i + 1));
    const er = vol !== 0 ? Math.abs(direction / vol) : 0.000001;
    const ct = Math.pow((er * (this.fastSf - this.slowSf)) + this.slowSf, 2);

    if (this.lastKama === undefined) {
        this.lastKama = this.getPriceVal(history.prior());
    }
    
    const result = this.lastKama + (ct * (this.getPriceVal(d) - this.lastKama));
    
    
    //Setup price variables
    const close = d.close();
    const v = d.value();
    const vt = d.volume();
    

    const prior = history.prior();
    
    //Cainer Code. Buy = close > kama and > 34 EMA and previous close not true, Sell opposite
    const c1 = (prior.close() < this.lastKama) || (prior.close() < this.slow) || ((prior.volume() / this.volavg) <= 0.15);
    const c2 = (prior.close() > this.lastKama) || (prior.close() > this.slow) || ((prior.volume() / this.volavg) <= 0.15);
    
    this.slow = this.emaSlow(v);
    this.volavg = this.smaVol(vt);
    
    const c3 = (close > result) && (close > this.slow) && ((vt / this.volavg) > 0.15);
    const c4 = (close < result) && (close < this.slow) && ((vt / this.volavg) > 0.15);
    
    
    this.lastKama = result;
    
    const buy = c1 && c3;
    const sell = c2 && c4;
    
    return {
        buy: buy ? d.low() : undefined,
        sell: sell ? d.high() : undefined,
        atr: atr
    };
}
filter(d, i) {
    return i > Math.max(this.props.fastLength, this.props.slowLength, this.erLength);
}

}
function customPlotter(canvas, indicatorInstance, history) {

for(let i = 1; i < history.data.length; i++) {
    const item = history.get(i);
    
    if (item.buy !== undefined || item.sell !== undefined) {
        
        const props = indicatorInstance.props;
        const prior = history.get(i - 1);
        
        const center = p.x.get(item);
        const left = p.x.between(p.x.get(prior), center, -0.5);
        const right = p.x.between(p.x.get(prior), center, 2.5);
        const height = item.atr / 5;
        
        let point = 0;
        let base = 0;
        let color = 0;
        
        if (item.buy !== undefined) {
            point = item.buy - height * 1.5;
            base = point - height;
            color = props.upColor;
        }
        
        if (item.sell !== undefined) {
            point = item.sell + height * 1.5;
            base = point + height;
            color = props.downColor;
        }

        
        // The triangle path
        const path = p.createPath();
        path.moveTo(left, base);
        path.lineTo(center, point);
        path.lineTo(right, base);
        path.lineTo(left, base);
        path.lineTo(center, point);
        
        // Draw the perimeter
        canvas.drawPath(
            path.end(),
            {
                color: color,
                width: 3,
                opacity: props.opacity / 100.0
            });       

        canvas.drawLine(
            p.offset(center, base - (point - base)),
            p.offset(center, base),
            {
                color: color,
                relativeWidth: 1,
                opacity: props.opacity / 100.0
            });
    }
}

}

module.exports = {
name: “CainerArrows”,
description: “CainerArrows”,
calculator: CainerArrows,
inputType: meta.InputType.BARS,
params: {
priceType: predef.paramSpecs.enum({
high: ‘High’,
low: ‘Low’,
open: ‘Open’,
close: ‘Close’,
hl2: ‘(H+L)/2’
}, ‘close’),
emaLength: predef.paramSpecs.period(34),
fastLength: predef.paramSpecs.period(2),
slowLength: predef.paramSpecs.period(30),
efficiencyRatioLength: predef.paramSpecs.period(10),
upColor: predef.paramSpecs.color(“green”),
downColor: predef.paramSpecs.color(“red”),
opacity: predef.paramSpecs.number(100, 1, 0)
},
plotter: [
predef.plotters.custom(customPlotter)
],
tags: [“Caine”]
};

Is there a reason why it was removed? I have them on a few charts and like the use I have been able to incorporate them into.

Ok, now they have been removed from my charts. What is the deal?

Since it seems to be deleting itself from the charts I had it on I am wondering if someone can explain how to build this indicator again using the code above? Is it copy paste? How do I do this?
Thank you

Somewhere on your computer, create a new file, like my_cainer_arrows.js and paste the code into that file. Save it. Make sure that the file extension is .js. Then in Tradovate, open the Code Explorer and choose File > Import. Navigate to .js file you created and choose it. Once imported, you may need to refresh Tradovate to see it. (Ctrl+R or F5 on Windows should do it.)

If you don’t know how to open the Code Explorer, I made this video a while back that shows you how: Tradovate: Open Code Explorer - YouTube

1 Like

Thank you, I will watch the video also.