Seasonality
All plugins

Plugin libraryStatistics

Plugin

Seasonality

How the instrument did in past months, weekdays, turns of the month or hours like the current one: mean return, hit rate, count and t-statistic.

IndicatorNo networkDesktop onlyv1.0.0

About

Some markets are said to do better in some months, on some weekdays, around the turn of the month or at some hours. This indicator measures that on the run's own data as it goes: for the bucket the current bar is in (this calendar month, this weekday, turn of the month or not, this hour), the number of earlier periods in it, their mean return, the share that went up, and a t-statistic.

Only finished periods count. One observation is the close to close return of one finished hour, day or month; the period the current bar is in has not finished and is left out, so the bar never feeds the number it reads and a backtest cannot see ahead. Each figure therefore grows with the history: early in a run there is little to go on.

Be careful with what it says. A pattern found by looking at twelve months or seven weekdays is often luck, mean, hit_rate and t_stat stay None until a bucket has min_count observations, and the t-statistic assumes independent returns, which market returns rarely are. A t-statistic around 2 from a dozen observations is weak evidence.

Parameters

NameTypeDefaultRange or optionsDescription
bychoice"weekday"month, weekday, turn_of_month, hourWhat makes periods alike. The turn of the month is the last weekday of a month and the first three weekdays of the next, by the calendar (holidays ignored).
tztext"UTC"The clock days, hours and months are counted on. A time zone name (IANA), like Europe/Berlin or America/New_York.
min_countint10min 2, max 1000Observations a bucket needs before mean, hit_rate and t_stat appear.

Use it in a strategy

pythonsea = ctx.plugin_indicator("seasonality", "seasonality", {"by": "weekday", "min_count": 20})
if sea is not None and sea.t_stat is not None:
    if sea.t_stat > 2.0 and sea.hit_rate > 0.55:
        ctx.signal("LONG")
    elif sea.t_stat < 0:
        ctx.signal("EXIT")

The indicator library has this as seasonality: ctx.ind("seasonality", by="weekday", zone="utc", min_count=10) reads it on the clock of UTC, London, New York, Tokyo or Sydney, with the turn of the month as bucket 1 and the rest as 0, and the chart, Blocks, Rust and the Rust core have it too. This template stays as an example of a plugin indicator; only it takes any time zone.

What it provides

value, meanValueThe mean close to close return of the finished periods in the current bucket, as a fraction (0.001 is 0.1 %); None below min_count.
countValueHow many finished periods of the current bucket came before this bar; 0 when none.
hit_rateValueThe share of those periods with a return above zero, 0 to 1; None below min_count.
t_statValuemean / (sample standard deviation / sqrt(count)); None below min_count or when every return was the same.
bucketValueThe current bucket: month 1 to 12, weekday 0 (Monday) to 6, "turn" or "rest", hour 0 to 23.

Limits

  • It needs history: a month bucket gains one observation a year. Load enough data before the part of the run you judge, or results early in the run rest on almost nothing.
  • Returns are close to close between periods that had bars, so the first hour or day after a weekend includes the weekend gap. With forex data on UTC days the few Sunday evening hours form a day of their own.
  • The hour grouping needs bars of an hour or shorter. Nothing here says a pattern will continue; it describes the past of this data only.
  • A plugin indicator is not drawn on the chart and is not available in Blocks, Pine, Rust or C#; it runs on the run's own instrument only.
OrionQuant