Seasonality Moving Average

A custom indicator created by TrendSpider Team on TrendSpider. You can import this custom indicator into your TrendSpider account. Don't have TrendSpider? Create an account first, then import the custom indicator.

Chart featuring the Seasonality Moving Average indicator

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.

Source code

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');