# Revisiting The January Effect

## Introduction

In this article, we review the infamous January effect which proposes that stocks’ prices increase from December to January is the highest. We illustrate the causes of the January effect, and present a simple trading strategy to profit from this calendar effect. The project is shared on my online repository https://github.com/DinodC/january-effect.

We start off by importing packages

```import numpy as np
import pandas as pd
import pickle
```

## Pull Data

In this section, we collect S&P consittuents’ historical data from a previous project https://quant-trading.blog/2019/06/24/backtesting-a-trading-strategy-part-2/.

```keys = ['sp500',
'sp400',
'sp600']
```

Initialize close

```close = {}
```

Pull data

```for i in keys:
with open(i + '_data.pickle', 'rb') as f:

# Update close prices data
close[i] = data.close

f.close()
```

Inspect close prices of S&P 500 Index

```close['sp500'].head()
```

5 rows × 505 columns

```close['sp500'].tail()
```

5 rows × 505 columns

```close['sp500'].describe()
```

8 rows × 505 columns

```close['sp500'].shape
```
```(1258, 505)
```

## The January Effect

A calendar effect is an economic or stock market behavior which is related to the calendar such as the day of the week or the month of the year. The most popular is the January effect which suggests that stock prices’ increase from December to January is the highest. The January effect was first observed by Sydney Wachtel in 1942, but seems to have lost its effect in recent years.

## Explanations Of The January Effect:

Possible explanations of the January effect include:

1. Tax-loss harvesting (or saving):
Tax-loss harvesting allows investors to save taxes on realized gains using their unrealized losses. In detail, investors sell the the losing stocks of their portfolio to generate losses. Investors’ taxes are reduced as the gains and losses are netted out.
2. Window dressing:
Window dressing enables investors to improve the appearance of the portfolios which they manage. In detail, investors buy (sell) winning (losing) stocks to enhance portfolio appearance. Investors’ portfolios has a better image as they now contain high-flying stocks.
3. Bonus:
Bonus (end-of-year) allows investors to purchase stocks at the beginning of the year. In detail, investors buying stocks in January will push the stock prices up. Investors’ bonus fuels price increase from December to January.

## A Trading Strategy To Profit From The January Effect

A possible trading strategy to profit from the January effect is the following:

2. Sell the winning stocks of December.

We backtest the strategy using the different investment universes:

1. S&P 500 Index composed of large capitalization stocks
2. S&P 400 Index comprised of medium capitalization stocks
3. S&P 600 Index composed of small capitalization stocks

Assume transaction cost (one-way)

```tc_one_way = 0.0005
```

Initialize the strategy’s returns

```returns = {}
```

Backtesting the strategy

```for i in keys:
# Create today series
today = pd.Series(close[i].index)

# Create months and years series
months = pd.Series(close[i].index.month)
years = pd.Series(close[i].index.year)

# Create next day of the month and next day of the year
next_day_month = months.shift(periods=-1)
next_day_year = years.shift(periods=-1)

# Last day of December

# Last day of Jan

# Ensure that last day of January is after last day of December
assert (last_day_jan.values > last_day_dec.values).any(), 'Assertion violated'

# End of year indices
# Last item is not eoy
eoy = eoy[:-1]

# Check that eoy dates match last day of December dates
assert (last_day_dec.values==eoy.values).any(), 'Assertion violated'

# Calculate annual returns (from December of previous year to December of current year)

# Retrieve last day of January close prices

# Retrieve last day of December close prices
# Modify the index of clost_last_day_dec
close_last_day_dec.index = close_last_day_jan.index

# Calculate January returns (from December of previous year to January of current year)
january_returns = (close_last_day_jan - close_last_day_dec) / close_last_day_dec

for j in range(1, annual_returns.shape[0]-1):
# Create a mask for stocks with returns != NaN

# Sort stocks as per annual returns
sort_tickers = annual_returns[has_data].iloc[j, :].sort_values().index

# Set the number of stocks to long (short)
top_n = round(len(has_data) / 10)

# List of stocks to long and short
longs = sort_tickers[:top_n]
shorts = sort_tickers[-top_n:]

# Calculate returns from the last day of December to the last day of January
long_returns = (january_returns.iloc[j][longs]).mean()
short_returns = (january_returns.iloc[j][shorts]).mean()
portfolio_returns = 0.5 * (long_returns - short_returns) - 2 * tc_one_way

# Update portfolio returns
returns[i] = portfolio_returns
```

## Backtesting Results

In this section, we present the backtesting results of the trading strategy.

```pd.DataFrame(returns,
index=['returns'],
columns=keys)
```

Remarks:

1. The trading strategy generated positive returns under all investment universes.
2. The trading strategy produced the highest (lowest) returns using small (large) capitalization stocks.
3. Note that higher spreads are usually attached to small-cap stocks which could reduce the trading strategy’s returns.

## Conclusion

In this article, we reviewed the well-known January effect, and proposed a trading strategy to profit from it. The trading strategy buys (sells) the losing (winning) stocks in December, and awaits reversal in January. The trading strategy generates the most (least) returns when using small (large) capitalization stocks.