# Trying to import a custom indicator. Keep getting Syntax Error

**URL:** <https://community.tradovate.com/t/trying-to-import-a-custom-indicator-keep-getting-syntax-error/12653>\
**Category:** Custom Indicators\
**Created:** [May 24, 2026, 6:36pm UTC](https://community.tradovate.com/t/trying-to-import-a-custom-indicator-keep-getting-syntax-error/12653 "2026-05-24T18:36:42Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ark13](https://avatars.discourse-cdn.com/v4/letter/a/b19c9b/32.png) [@Ark13](https://community.tradovate.com/u/Ark13)\
**Post date:** [May 24, 2026, 6:36pm UTC](https://community.tradovate.com/t/trying-to-import-a-custom-indicator-keep-getting-syntax-error/12653/1 "2026-05-24T18:36:42Z")

</div>

I have been trying for hours to import this custom indicator and i can not figure out what im doing wrong. Below you will find my script and the error I keep getting. Please can someone help!?

Syntax Errors

MyIndicator.js (447:1): Unexpected token (447:1)

// Precision Market Entropy Heatmap with Zones  
// Originally by LuxAlgo (Pine Script v6)  
// Licensed under CC BY-NC-SA 4.0 — [Deed - Attribution-NonCommercial-ShareAlike 4.0 International - Creative Commons](https://creativecommons.org/licenses/by-nc-sa/4.0/)  
// Ported for Tradovate custom indicator format

// ---------------------------------------------------------------------------  
// Settings — edit these values to configure the indicator  
// ---------------------------------------------------------------------------  
var ROWS = 50; // Number of price rows per session profile  
var MAX\_SESSIONS = 10; // How many past sessions to show  
var SHOW\_DEV\_POC = true; // Show developing POC line  
var EXTEND\_POCS = true; // Extend POC lines to current bar  
var HEATMAP\_ALPHA = 0.30; // Heatmap cell opacity (0 = invisible, 1 = solid)

// Heatmap gradient colours [R, G, B]  
var COLOR\_LOW = [0, 0, 51]; // #000033 dark blue  
var COLOR\_MID = [0, 255, 136]; // #00ff88 green  
var COLOR\_HIGH = [255, 255, 0]; // #ffff00 yellow  
var COLOR\_BULL = [8, 153, 129]; // #089981 teal (POC below price)  
var COLOR\_BEAR = [242, 54, 69]; // #f23645 red (POC above price)  
var COLOR\_DEV = [255, 255, 255]; // #ffffff white (developing POC)

// ---------------------------------------------------------------------------  
// Colour helpers  
// ---------------------------------------------------------------------------  
function lerpColor(t, c0, c1) {  
return [  
Math.round(c0[0] + (c1[0] - c0[0]) \* t),  
Math.round(c0[1] + (c1[1] - c0[1]) \* t),  
Math.round(c0[2] + (c1[2] - c0[2]) \* t)  
];  
}

function toRgba(rgb, alpha) {  
return ‘rgba(’ + rgb[0] + ‘,’ + rgb[1] + ‘,’ + rgb[2] + ‘,’ + alpha.toFixed(3) + ‘)’;  
}

function rowColor(intensity) {  
var rgb;  
if (intensity \> 0.5) {  
rgb = lerpColor((intensity - 0.5) \* 2, COLOR\_MID, COLOR\_HIGH);  
} else {  
rgb = lerpColor(intensity \* 2, COLOR\_LOW, COLOR\_MID);  
}  
return toRgba(rgb, HEATMAP\_ALPHA);  
}

function pocColor(pocPrice, closePrice) {  
if (pocPrice \< closePrice) {  
return toRgba(COLOR\_BULL, 1.0);  
}  
return toRgba(COLOR\_BEAR, 1.0);  
}

// ---------------------------------------------------------------------------  
// Volume formatting  
// ---------------------------------------------------------------------------  
function fmtVol(v) {  
if (v \>= 1000000000) { return (v / 1000000000).toFixed(2) + ‘B’; }  
if (v \>= 1000000) { return (v / 1000000).toFixed(2) + ‘M’; }  
if (v \>= 1000) { return (v / 1000).toFixed(2) + ‘K’; }  
return v.toFixed(2);  
}

// ---------------------------------------------------------------------------  
// Build a volume profile for one session from an array of bars  
// Each bar: { open, high, low, close, volume, timestamp }  
// ---------------------------------------------------------------------------  
function buildProfile(bars, sessionStartTime) {  
var i, j, d, sHigh, sLow, rowSize;  
var isBull, idxH, idxL, span, vSplit;  
var maxVol, peakIdx, pocPriceMin, pocPriceMax, pocPrice;  
var rowVolumes, rowBullVol, rowBearVol, rows, intensity;

```auto
// 1. Find session high / low
sHigh = -Infinity;
sLow = Infinity;
for (i = 0; i < bars.length; i++) {
    d = bars[i];
    if (d.high > sHigh) { sHigh = d.high; }
    if (d.low < sLow) { sLow = d.low; }
}

if (!isFinite(sHigh) || !isFinite(sLow) || sHigh <= sLow) {
    return emptyProfile(sessionStartTime);
}

rowSize = (sHigh - sLow) / ROWS;

// 2. Accumulate volume into rows
rowVolumes = [];
rowBullVol = [];
rowBearVol = [];
for (i = 0; i < ROWS; i++) {
    rowVolumes.push(0);
    rowBullVol.push(0);
    rowBearVol.push(0);
}

for (i = 0; i < bars.length; i++) {
    d = bars[i];
    if (d.high == null || d.low == null || d.volume == null) { continue; }

    isBull = d.close >= d.open;
    idxH = Math.min(ROWS - 1, Math.max(0, Math.floor((d.high - sLow) / rowSize)));
    idxL = Math.min(ROWS - 1, Math.max(0, Math.floor((d.low - sLow) / rowSize)));
    span = idxH - idxL + 1;

    for (j = idxL; j <= idxH; j++) {
        vSplit = d.volume / span;
        rowVolumes[j] += vSplit;
        if (isBull) {
            rowBullVol[j] += vSplit;
        } else {
            rowBearVol[j] += vSplit;
        }
    }
}

// 3. Find POC (highest volume row)
maxVol = 0;
peakIdx = 0;
for (i = 0; i < ROWS; i++) {
    if (rowVolumes[i] > maxVol) {
        maxVol = rowVolumes[i];
        peakIdx = i;
    }
}

pocPriceMin = sLow + peakIdx * rowSize;
pocPriceMax = pocPriceMin + rowSize;
pocPrice = pocPriceMin + rowSize / 2;

// 4. Build row data array
rows = [];
for (i = 0; i < ROWS; i++) {
    intensity = maxVol > 0 ? rowVolumes[i] / maxVol : 0;
    rows.push({
        volume: rowVolumes[i],
        bullVol: rowBullVol[i],
        bearVol: rowBearVol[i],
        priceMin: sLow + i * rowSize,
        priceMax: sLow + (i + 1) * rowSize,
        intensity: intensity,
        color: rowColor(intensity)
    });
}

return {
    startTime: sessionStartTime,
    sessionHigh: sHigh,
    sessionLow: sLow,
    pocPrice: pocPrice,
    pocPriceMin: pocPriceMin,
    pocPriceMax: pocPriceMax,
    peakVolume: maxVol,
    peakBullVol: rowBullVol[peakIdx],
    peakBearVol: rowBearVol[peakIdx],
    rows: rows
};

```

}

function emptyProfile(startTime) {  
var i, rows;  
rows = ;  
for (i = 0; i \< ROWS; i++) {  
rows.push({  
volume: 0, bullVol: 0, bearVol: 0,  
priceMin: NaN, priceMax: NaN,  
intensity: 0, color: toRgba(COLOR\_LOW, HEATMAP\_ALPHA)  
});  
}  
return {  
startTime: startTime,  
sessionHigh: NaN,  
sessionLow: NaN,  
pocPrice: NaN,  
pocPriceMin: NaN,  
pocPriceMax: NaN,  
peakVolume: 0,  
peakBullVol: 0,  
peakBearVol: 0,  
rows: rows  
};  
}

// ---------------------------------------------------------------------------  
// Label text for a profile block  
// ---------------------------------------------------------------------------  
function profileLabel(profile, nowMs) {  
var daysAgo, bPerc, sPerc, domTxt, volTxt;  
daysAgo = Math.floor((nowMs - profile.startTime) / 86400000);  
bPerc = profile.peakVolume \> 0 ? (profile.peakBullVol / profile.peakVolume) \* 100 : 0;  
sPerc = profile.peakVolume \> 0 ? (profile.peakBearVol / profile.peakVolume) \* 100 : 0;  
domTxt = bPerc \>= sPerc  
? Math.round(bPerc) + ‘% B’  
: Math.round(sPerc) + ‘% S’;  
volTxt = ‘Vol: ’ + fmtVol(profile.peakVolume) + ’ (’ + domTxt + ‘)’;

```auto
if (daysAgo === 0) {
    return 'Current Profile | ' + volTxt;
}
return daysAgo + ' Days | ' + volTxt;

```

}

// ---------------------------------------------------------------------------  
// State — session accumulator  
// ---------------------------------------------------------------------------  
var sessionBars = ;  
var completedBlocks = ;  
var activeBlock = null;  
var lastSessionDay = null;

// ---------------------------------------------------------------------------  
// Tradovate indicator entry point  
// Called on every bar update by the platform  
//  
// bar: { open, high, low, close, volume, timestamp (ms) }  
// draw: Tradovate drawing API { line, rect, text, … }  
// ---------------------------------------------------------------------------  
function map(bar, draw) {  
var barDay = new Date(bar.timestamp).toDateString();  
var isNewSession = (lastSessionDay !== null && barDay !== lastSessionDay);

```auto
// On new session boundary, finalise the previous session
if (isNewSession && sessionBars.length > 0) {
    var finishedBlock = buildProfile(sessionBars, sessionBars[0].timestamp);
    completedBlocks.push(finishedBlock);

    // Trim to max sessions
    while (completedBlocks.length > MAX_SESSIONS) {
        completedBlocks.shift();
    }

    sessionBars = [];
    activeBlock = null;
}

lastSessionDay = barDay;
sessionBars.push(bar);

// Build the live (developing) profile for the current session
activeBlock = buildProfile(sessionBars, sessionBars[0].timestamp);

// -----------------------------------------------------------------------
// Rendering — draw all profiles
// -----------------------------------------------------------------------
var allBlocks = completedBlocks.concat(activeBlock ? [activeBlock] : []);
var nowMs = bar.timestamp;
var closePrice = bar.close;

for (var b = 0; b < allBlocks.length; b++) {
    var block = allBlocks[b];
    if (!block || isNaN(block.pocPrice)) { continue; }

    var isActive = (b === allBlocks.length - 1);
    var pCol = pocColor(block.pocPrice, closePrice);

    // --- Heatmap rows ---
    for (var r = 0; r < block.rows.length; r++) {
        var row = block.rows[r];
        if (isNaN(row.priceMin)) { continue; }

        draw.rect({
            x: block.startTime,
            y: row.priceMax,
            width: isActive ? (nowMs - block.startTime) : null,
            height: row.priceMax - row.priceMin,
            fill: row.color,
            stroke: 'transparent'
        });
    }

    // --- POC zone (highlighted band) ---
    draw.rect({
        x: block.startTime,
        y: block.pocPriceMax,
        width: EXTEND_POCS || isActive ? (nowMs - block.startTime) : null,
        height: block.pocPriceMax - block.pocPriceMin,
        fill: pCol.replace('1.000', '0.200'),
        stroke: pCol.replace('1.000', '0.700')
    });

    // --- POC midline ---
    draw.line({
        x1: block.startTime,
        y1: block.pocPrice,
        x2: nowMs,
        y2: block.pocPrice,
        color: pCol,
        style: 'dashed',
        width: 1
    });

    // --- POC label ---
    draw.text({
        x: nowMs,
        y: block.pocPrice,
        text: profileLabel(block, nowMs),
        color: pCol,
        size: 10
    });

    // --- Developing POC dot (active session only) ---
    if (isActive && SHOW_DEV_POC) {
        draw.line({
            x1: block.startTime,
            y1: block.pocPrice,
            x2: nowMs,
            y2: block.pocPrice,
            color: toRgba(COLOR_DEV, 0.9),
            style: 'solid',
            width: 2
        });
    }
}

```

}

// ---------------------------------------------------------------------------  
// Tradovate indicator descriptor  
// This tells the platform the name, inputs, and entry function  
// ---------------------------------------------------------------------------  
var indicatorDescriptor = {  
name: ‘Precision Market Entropy Heatmap’,  
description: ‘Volume profile heatmap with POC zones per session. Port of LuxAlgo Pine Script.’,  
calculator: map,  
inputs: [  
{ name: ‘rows’, type: ‘number’, defaultValue: 50, title: ‘Profile Rows’ },  
{ name: ‘maxSessions’, type: ‘number’, defaultValue: 10, title: ‘Max Sessions’ },  
{ name: ‘showDevPoc’, type: ‘boolean’, defaultValue: true, title: ‘Show Developing POC’ },  
{ name: ‘extendPocs’, type: ‘boolean’, defaultValue: true, title: ‘Extend POCs’ }  
],  
plots:   
};

module.exports = {name:‘my indicator13’, description: ‘My Indicator13’, calculator: MyIndicator, tags:[“\> My Indicators”]

---

<div class="post-metadata">

**Author:** ![tikidave](https://sea1.discourse-cdn.com/flex015/user_avatar/community.tradovate.com/tikidave/32/2889_2.png) [@tikidave](https://community.tradovate.com/u/tikidave)\
**Post date:** [May 26, 2026, 3:29am UTC](https://community.tradovate.com/t/trying-to-import-a-custom-indicator-keep-getting-syntax-error/12653/2 "2026-05-26T03:29:59Z")

</div>

I hate to be the bearer of bad news but this does not look like Tradovate indicator code – as mentioned in a previous thread, I recommend starting with a working indicator that’s similar and tweak it slowly – most LLMs will not create solid Tradovate code out of the gates, they just guess poorly.
