Seasonality
Calculate the seasonality of every ticker’s returns: the average return per calendar month (from monthly returns) or per day of the week (from daily returns), with the median, the hit rate (the share of positive returns), the t-statistic of the average and the number of observations. Well-known examples are the January effect and the “sell in May” pattern. A pattern needs many years and a t-statistic well above 2 before it says much, and even then it can fade once it is widely traded on.
A monthly return runs from one month’s last close to the next, so a final month that is not complete yet (an end date before that month’s last business day, as with the default end date of today) is left out rather than averaged as a full month. The Benchmark is included as a ticker, so its seasonality is there to compare with; a Portfolio is left out.
For more information, see the following paper:
- Heston, S.L. and Sadka, R. (2008). “Seasonality in the Cross-Section of Stock Returns.” Journal of Financial Economics, 87(2), 418-445.
Also known as: seasonality, monthly seasonality, day of the week effect, January effect, calendar anomalies.
Seasonality in Python or via the MCP
Install the Finance Toolkit with:
pip install financetoolkit -U
Then call get_seasonality as shown below.
from financetoolkit import Toolkit
toolkit = Toolkit(
["AAPL", "MSFT"],
api_key="FINANCIAL_MODELING_PREP_KEY",
start_date="2000-01-01",
end_date="2025-12-31",
)
seasonality = toolkit.technicals.get_seasonality()
seasonality.xs("AAPL", level=1, axis="columns")
Or, after setting up the Finance Toolkit MCP, ask:
What were Apple's average and median return, hit rate and t-statistic for each calendar month from 2000 to 2025?
Which returns:
| Month | Average Return | Median Return | Hit Rate | t-Statistic | Observations |
|---|---|---|---|---|---|
| January | 0.0239 | 0.0477 | 0.6 | 0.8733 | 25 |
| February | 0.0139 | 0.0245 | 0.5385 | 0.7962 | 26 |
| March | 0.0486 | 0.0529 | 0.6538 | 2.6472 | 26 |
| April | 0.028 | 0.0057 | 0.5769 | 1.5009 | 26 |
| May | 0.018 | 0.0457 | 0.5769 | 0.7223 | 26 |
| June | 0.0171 | 0.0096 | 0.5385 | 0.8119 | 26 |
| July | 0.0523 | 0.0501 | 0.7692 | 2.7965 | 26 |
| August | 0.0501 | 0.0466 | 0.6538 | 3.2948 | 26 |
| September | -0.0252 | -0.0128 | 0.4231 | -0.8129 | 26 |
| October | 0.0529 | 0.0616 | 0.7308 | 2.4423 | 26 |
| November | 0.0306 | 0.0334 | 0.5769 | 1.4177 | 26 |
| December | -0.0061 | 0.0112 | 0.5385 | -0.4179 | 26 |
Parameters
get_seasonality accepts the following parameters.
| Parameter | Type | Description | Example |
|---|---|---|---|
frequency | str | “month” (per calendar month) or “weekday” (per day of the week). Defaults to “month”. | 2 |
close_column | str | The name of the column containing the close prices. Defaults to “Adj Close”. | "Close" |
rounding | int | None | The number of decimals to round the results to. Defaults to None, which uses the rounding of the Toolkit. | 2 |