
“The investment universe consists of the S&P500 index. Simply, buy and hold the index during the 16th day in the month during each month of the year.”
ASSET CLASS: CFDs, ETFs, futures | REGION: United States | FREQUENCY: Daily | MARKET:
equities | KEYWORD: Payday
I. STRATEGY IN A NUTSHELL
The investment universe consists of the S&P500 index. Simply, buy and hold the index during the 16th day in the month during each month of the year.
II. ECONOMIC RATIONALE
The reason for the functionality is probably deeply connected with paychecks. Employees get paid at the end of the month, and many of them either automatically invest a portion of their paycheck in the market through retirement contributions or are encouraged to do so by having a surplus of funds with the new paycheck. However, many companies pay their employees twice a month, on the 15th and at the end of the month. Therefore, building on that the pay-day effect holds true for the turn-of-the-month days, there should be a clear pattern in the middle of the month as well as at the end of the month since employees do make retirement contributions with every paycheck. Results confirm that abnormal returns indeed exist in the middle of the month. According to the research, the 16th of the month is not only the 3rd best day in the month overall, but has moved up in the ranks monotonically every decade since the 1950s, until the most recent decade, the 2010s. Although more and more firms are paying wages on a bi-weekly basis, the highest average hourly earnings are distributed semi-monthly followed by monthly distribution, which favours this strategy, and therefore, this effect should not diminish. Another possible reason for the functionality is that, because the other pay-days have been extensively discussed in the literature, practitioners have been trying to take advantage of the anomaly and market efficiency has caught up, reducing the magnitude of the anomaly. Therefore, this novel anomaly has a strong performance if we compare it with the other days, and mainly, it is not traded-off, at least not yet.
III. SOURCE PAPER
Payday Anomaly [Click to Open PDF]
- Aixin (James) Ma, Oklahoma City University – Meinders School of Business
- William R. Pratt, Oklahoma City University
<Abstract>
Abnormal returns have been found on days near the turn of the calendar months. Previous studies have linked the phenomenon to month-end paychecks, of which a sizable proportion goes into employees’ retirement accounts and is then automatically invested in the market. Since many institutions adopt a semi-monthly pay schedule, we test the hypothesis that the market should exhibit detectable mid-month abnormal movement. Our results indicate that the 16th day of the month statistically and economically outperforms all other calendar days except the 1st and 2nd. As more and more institutions transition into bi-weekly pay schedule, however, the mid-month payday anomaly becomes less prominent.


IV. BACKTEST PERFORMANCE
| Annualised Return | 2.57% |
| Volatility | 4.31% |
| Beta | 0.056 |
| Sharpe Ratio | -0.3 |
| Sortino Ratio | -0.077 |
| Maximum Drawdown | 12.1% |
| Win Rate | 57% |
V. FULL PYTHON CODE
from dateutil.relativedelta import relativedelta
from AlgoLib import *
class PayDayAnomaly(XXX):
def Initialize(self):
self.SetStartDate(2000, 1, 1)
self.SetCash(100000)
self.market: Symbol = self.AddEquity('SPY', Resolution.Minute).Symbol
self.liquidate_next_day: bool = False
self.Schedule.On(self.DateRules.EveryDay(self.market), self.TimeRules.BeforeMarketClose(self.market, 1), self.Purchase)
def Purchase(self) -> None:
alg_time = self.Time
paydate = self.PaydayDate(alg_time)
if alg_time.date() == paydate:
self.SetHoldings(self.market, 1)
self.liquidate_next_day = True
if self.liquidate_next_day:
self.liquidate_next_day = False
return
if self.Portfolio[self.market].IsLong:
self.Liquidate(self.market)
def PaydayDate(self, date_time):
payday = date(date_time.year, date_time.month, 1) + relativedelta(day=15)
if payday.weekday() == 5: # Is saturday.
payday = payday - timedelta(days=1)
elif payday.weekday() == 6: # Is sunday.
payday = payday - timedelta(days=2)
return payday