Advanced Indicator Techniques
Advanced patterns for building sophisticated indicators in CodeLab.
Multi-Plot Indicators
Plot 3 or more lines with different visual properties.
typescript
// ADX with +DI and -DI (simplified)
const adxVal = this.adx(14);
const emaFast = this.ema('close', 9);
const emaSlow = this.ema('close', 21);
const emaTrend = this.ema('close', 50);
plot('Fast', emaFast, { color: color.cyan, width: 2, overlay: true });
plot('Slow', emaSlow, { color: color.orange, width: 1, overlay: true });
plot('Trend', emaTrend, { color: color.purple, width: 1, overlay: true });Dynamic Per-Bar Coloring
2-Color Pattern (Bullish/Bearish)
typescript
const val = this.ema('close', 20);
const prev = this.bar > 0 ? this.getPlot('EMA', 1) : val;
plotColor('EMA', val,
[color.green, color.red],
val > prev ? 0 : 1,
{ width: 2 }
);4-Color Histogram (MACD Style)
Position + direction creates 4 visual states:
typescript
const m = this.macd('close', 12, 26, 9);
const hist = m.histogram;
const prevHist = this.bar > 0
? this.getPlot('MACD', 1) - this.getPlot('Signal', 1)
: 0;
let histColor;
if (hist >= 0) {
histColor = hist > prevHist ? '#16a34a' : '#86efac'; // strong/weak bullish
} else {
histColor = hist < prevHist ? '#dc2626' : '#fca5a5'; // strong/weak bearish
}
plotHistogram('Histogram', hist, { color: histColor });Gradient Coloring (Multiple Levels)
typescript
const rsiVal = this.rsi('close', 14);
const colors = ['#16a34a', '#86efac', '#6b7280', '#fca5a5', '#dc2626'];
const idx = rsiVal > 80 ? 4 : rsiVal > 60 ? 3 : rsiVal > 40 ? 2 : rsiVal > 20 ? 1 : 0;
plotColor('RSI', rsiVal, colors, idx, { width: 2 });Signal Markers
Mark specific conditions with shapes on the chart.
typescript
// Buy/sell arrow signals
const fast = this.ema('close', 9);
const slow = this.ema('close', 21);
plot('Fast', fast); plot('Slow', slow);
if (this.bar > 0) {
const pf = this.getPlot('Fast', 1);
const ps = this.getPlot('Slow', 1);
if (this.crossOver(fast, slow, pf, ps)) {
plotShape('Buy', true, {
shape: 'triangleup',
location: 'belowbar',
color: color.green,
size: 'small',
text: 'BUY'
});
}
if (this.crossUnder(fast, slow, pf, ps)) {
plotShape('Sell', true, {
shape: 'triangledown',
location: 'abovebar',
color: color.red,
size: 'small',
text: 'SELL'
});
}
}Complex State Management
Tracking Trend Direction
typescript
calculate() {
const st = this.supertrend(10, 3);
// Store current direction in state
this.setState('direction', st.direction);
// Access previous direction
if (this.bar > 0) {
const prevDir = this.getState('direction');
if (st.direction === 1 && prevDir === -1) {
this.log('Trend flipped BULLISH at', this.close);
}
}
}Counting Consecutive Events
typescript
calculate() {
const up = this.close > this.open;
if (this.isFirstBar) {
this.setState('streak', up ? 1 : -1);
} else {
const prev = this.getState('streak');
if (up) {
this.setState('streak', prev > 0 ? prev + 1 : 1);
} else {
this.setState('streak', prev < 0 ? prev - 1 : -1);
}
}
const streak = this.getState('streak');
plotHistogram('Streak', streak, {
color: streak > 0 ? color.green : color.red
});
}Combining Multiple Indicators
Build composite indicators that combine trend, momentum, and volume signals.
typescript
import { Script, input, plotHistogram, plot, hline, color } from '@chartlabs/script-sdk';
export default class CompositeSignal extends Script {
adxLen = input.number('ADX Period', 14, { min: 1, max: 50 });
rsiLen = input.number('RSI Period', 14, { min: 1, max: 50 });
calculate() {
// Trend filter
const adxVal = this.adx(this.adxLen);
const trending = adxVal > 25;
// Momentum
const rsiVal = this.rsi('close', this.rsiLen);
const bullMomentum = rsiVal > 50;
// Volume
const mfiVal = this.mfi(14);
const volumeConfirm = mfiVal > 50;
// Composite score
let score = 0;
if (trending) score += bullMomentum ? 1 : -1;
if (volumeConfirm) score += 1;
else score -= 1;
plotHistogram('Signal', score, {
color: score > 0 ? color.green : score < 0 ? color.red : color.gray
});
plot('ADX', adxVal, { color: color.purple });
hline('Trend Threshold', 25, { color: color.gray, style: 'dashed' });
}
}Squeeze Momentum Pattern
Detect when Bollinger Bands are inside Keltner Channel (squeeze), then plot momentum direction.
typescript
import { Script, input, plotColor, color } from '@chartlabs/script-sdk';
export default class SqueezeMomentum extends Script {
bbLen = input.number('BB Length', 20, { min: 2, max: 200 });
bbMult = input.number('BB Mult', 2.0, { min: 0.5, max: 5, step: 0.5 });
kcMult = input.number('KC Mult', 1.5, { min: 0.5, max: 5, step: 0.5 });
calculate() {
const bb = this.bbands('close', this.bbLen, this.bbMult);
// Keltner Channel
const kcMid = this.ema('close', this.bbLen);
const atrVal = this.atr(this.bbLen);
const kcUpper = kcMid + atrVal * this.kcMult;
const kcLower = kcMid - atrVal * this.kcMult;
// Squeeze detection
const squeeze = bb.lower > kcLower && bb.upper < kcUpper;
// Momentum using linear regression
const momentum = this.linreg('close', this.bbLen) - this.sma('close', this.bbLen);
// 4 states: squeeze on/off x momentum up/down
plotColor('Squeeze', momentum,
[color.green, color.red, color.cyan, color.magenta],
squeeze
? (momentum > 0 ? 2 : 3) // squeeze: cyan/magenta
: (momentum > 0 ? 0 : 1), // no squeeze: green/red
{ width: 3 }
);
}
}Background and Bar Coloring
Highlight Zones
typescript
const rsiVal = this.rsi('close', 14);
// Color background in extreme zones
if (rsiVal > 80) bgcolor('#ef444415'); // very light red
if (rsiVal < 20) bgcolor('#22c55e15'); // very light greenColor Bars by Trend
typescript
const st = this.supertrend(10, 3);
barcolor(st.direction === 1 ? color.green : color.red);
