This moving average indicator is colored to reflect weekly seasonality win rate percentage. During weeks when the win rate is below 25%, the moving average is bright red. Red denotes a weekly win rate between 25-50%. Green denotes a win rate between 51-74%. Bright Green denotes a weekly win rate of 75% or greater.
This indicator had been implemented by TrendSpider Team in JavaScript on TrendSpider. Check out the developer documentation to learn more about JS on TrendSpider.
describe_indicator('Seasonality Moving Average');
const maLength = input.number('MA Length', 20, { min: 1 });
const maType = input.select('MA Type', 'sma', constants.ma_types);
const computeMA = indicators[maType];
const ma = computeMA(close, maLength);
// Import the moment library
const moment = library('moment-timezone');
// Fetch weekly seasonality data
const seasonalityData = await request.seasonality(current.ticker, 'week_of_year', 'change');
assert(!seasonalityData.error, `Error fetching seasonality data: ${seasonalityData.error}`);
// Calculate win rate percentage for each week
const weeklyWinRates = seasonalityData.categories.map(week => {
const weekData = seasonalityData.dataByCategory[week];
const winCount = weekData.filter(d => d.value > 0).length;
return (winCount / weekData.length) * 100;
});
// Input for color thresholds
const highThreshold = input.number('High Win Rate Threshold', 75, { min: 0, max: 100 });
const mediumThreshold = input.number('Medium Win Rate Threshold', 51, { min: 0, max: 100 });
const lowThreshold = input.number('Low Win Rate Threshold', 25, { min: 0, max: 100 });
// Input for colors
const highColor = input.color('High Win Rate Color', '#00FF00');
const mediumColor = input.color('Medium Win Rate Color', '#008000');
const lowColor = input.color('Low Win Rate Color', '#FF0000');
const veryLowColor = input.color('Very Low Win Rate Color', '#FF00FF');
// Function to get color based on win rate
const getColor = (winRate) => {
if (winRate >= highThreshold) return highColor;
if (winRate >= mediumThreshold) return mediumColor;
if (winRate >= lowThreshold) return lowColor;
return veryLowColor;
};
// Map each candle to its corresponding week and color
const myColor = for_every(time, (_t) => {
const weekOfYear = moment(_t * 1000).week() - 1; // Moment weeks are 1-indexed
const winRate = weeklyWinRates[weekOfYear];
return getColor(winRate);
});
paint(ma, { name: 'MA', color: myColor });
// Add a comment explaining the color coding
paint_label_at_line(
paint(series_of(null), { hidden: true }),
close.length - 1,
`MA Color Legend:
≥${highThreshold}%: ${highColor}
${mediumThreshold}-${highThreshold-1}%: ${mediumColor}
${lowThreshold}-${mediumThreshold-1}%: ${lowColor}
<${lowThreshold}%: ${veryLowColor}`,
{ vertical_align: 'top' }
);
// Register signals for strategy tester and scanner
register_signal(for_every(time, (_t, _p, index) => {
const weekOfYear = moment(_t * 1000).week() - 1;
const winRate = weeklyWinRates[weekOfYear];
return winRate >= highThreshold;
}), 'High Win Rate');
register_signal(for_every(time, (_t, _p, index) => {
const weekOfYear = moment(_t * 1000).week() - 1;
const winRate = weeklyWinRates[weekOfYear];
return winRate >= mediumThreshold && winRate < highThreshold;
}), 'Medium Win Rate');
register_signal(for_every(time, (_t, _p, index) => {
const weekOfYear = moment(_t * 1000).week() - 1;
const winRate = weeklyWinRates[weekOfYear];
return winRate >= lowThreshold && winRate < mediumThreshold;
}), 'Low Win Rate');
register_signal(for_every(time, (_t, _p, index) => {
const weekOfYear = moment(_t * 1000).week() - 1;
const winRate = weeklyWinRates[weekOfYear];
return winRate < lowThreshold;
}), 'Very Low Win Rate');