Skip to Main Content

Guppy Moving Averages

This code shows how to generate multiple related moving averages in a single script to generate a 'guppy' visualization with many moving averages moving at once.

Guppy Moving Averages
describe_indicator('Guppy Multiple MA', 'price', { shortName: 'GMMA' });
 
const fastLength1 = input('Fast 1', 3, { min: 2, max: 199 });
const fastLength2 = input('Fast 2', 5, { min: 2, max: 199 });
const fastLength3 = input('Fast 3', 8, { min: 2, max: 199 });
const fastLength4 = input('Fast 4', 10, { min: 2, max: 199 });
const fastLength5 = input('Fast 5', 12, { min: 2, max: 199 });
const fastLength6 = input('Fast 6', 15, { min: 2, max: 199 });
 
const slowLength1 = input('Slow 1', 30, { min: 2, max: 199 });
const slowLength2 = input('Slow 2', 35, { min: 2, max: 199 });
const slowLength3 = input('Slow 3', 40, { min: 2, max: 199 });
const slowLength4 = input('Slow 4', 45, { min: 2, max: 199 });
const slowLength5 = input('Slow 5', 50, { min: 2, max: 199 });
const slowLength6 = input('Slow 6', 60, { min: 2, max: 199 });
 
 
const maType = input('MA type', 'sma', constants.ma_types);
const priceSource = input('Price source', 'close', constants.price_source_options);
 
input('Offset', 0, { min: -50, max: 50 });
 
// get a reference to the MA math, according to user's choice in maType input
const computeMA = indicators[maType];
// get a reference to the corresponding price data (open, high, close e.tc.), as per user's choice
const price = prices[priceSource];
 
const fastMa1 = computeMA(price, fastLength1);
const fastMa2 = computeMA(price, fastLength2);
const fastMa3 = computeMA(price, fastLength3);
const fastMa4 = computeMA(price, fastLength4);
const fastMa5 = computeMA(price, fastLength5);
const fastMa6 = computeMA(price, fastLength6);
 
const slowMa1 = computeMA(price, slowLength1);
const slowMa2 = computeMA(price, slowLength2);
const slowMa3 = computeMA(price, slowLength3);
const slowMa4 = computeMA(price, slowLength4);
const slowMa5 = computeMA(price, slowLength5);
const slowMa6 = computeMA(price, slowLength6);
 
paint(fastMa1, 'Fast 1', '#2ca599');
paint(fastMa2, 'Fast 2', '#2ca599');
paint(fastMa3, 'Fast 3', '#2ca599');
paint(fastMa4, 'Fast 4', '#2ca599');
paint(fastMa5, 'Fast 5', '#2ca599');
paint(fastMa6, 'Fast 6', '#2ca599');
 
paint(slowMa1, 'Slow 1', '#ee5451');
paint(slowMa2, 'Slow 2', '#ee5451');
paint(slowMa3, 'Slow 3', '#ee5451');
paint(slowMa4, 'Slow 4', '#ee5451');
paint(slowMa5, 'Slow 5', '#ee5451');
paint(slowMa6, 'Slow 6', '#ee5451');
 
// To fill the area between the highest and lowest of slow and fast MAs,
// we need to define the lines with the highest and lowest values per candle
const slowMin = series_of(null);
const slowMax = series_of(null);
const fastMin = series_of(null);
const fastMax = series_of(null);
 
for (let candleIndex = 2; candleIndex < price.length; candleIndex++) {
	// Find minimum and maximum values if all MA values are defined
	if (
		slowMa1[candleIndex] !== null &&
		slowMa2[candleIndex] !== null &&
		slowMa3[candleIndex] !== null &&
		slowMa4[candleIndex] !== null &&
		slowMa5[candleIndex] !== null &&
		slowMa6[candleIndex] !== null
	) {
		slowMin[candleIndex] = Math.min(
			slowMa1[candleIndex],
			slowMa2[candleIndex],
			slowMa3[candleIndex],
			slowMa4[candleIndex],
			slowMa5[candleIndex],
			slowMa6[candleIndex]
		);
 
		slowMax[candleIndex] = Math.max(
			slowMa1[candleIndex],
			slowMa2[candleIndex],
			slowMa3[candleIndex],
			slowMa4[candleIndex],
			slowMa5[candleIndex],
			slowMa6[candleIndex]
		);
	}
 
	if (
		fastMa1[candleIndex] !== null &&
		fastMa2[candleIndex] !== null &&
		fastMa3[candleIndex] !== null &&
		fastMa4[candleIndex] !== null &&
		fastMa5[candleIndex] !== null &&
		fastMa6[candleIndex] !== null
	) {
		fastMin[candleIndex] = Math.min(
			fastMa1[candleIndex],
			fastMa2[candleIndex],
			fastMa3[candleIndex],
			fastMa4[candleIndex],
			fastMa5[candleIndex],
			fastMa6[candleIndex]
		);
 
		fastMax[candleIndex] = Math.max(
			fastMa1[candleIndex],
			fastMa2[candleIndex],
			fastMa3[candleIndex],
			fastMa4[candleIndex],
			fastMa5[candleIndex],
			fastMa6[candleIndex]
		);
	}
}
 
fill(
	paint(slowMin, { hidden: true }),
	paint(slowMax, { hidden: true }),
	'#ffb2b0'
);
 
fill(
	paint(fastMin, { hidden: true }),
	paint(fastMax, { hidden: true }),
	'#9fe2dc'
);