Mid-Month Payday S&P500 Strategy
Log in to collectOnsite backtest IDE
Quant Buffet native backtest IDEEdit and run Quant Buffet Python for Mid-Month Payday S&P500 Strategy in the browser. Results update live with equity, drawdown, and metrics charts. Allowed: backtest.data, backtest.engine, backtest.metrics, numpy, pandas. Define ASSETS and make_on_day(prices). Shortcut: Ctrl+Enter. API docs →
Quant Buffet syntax cheat sheet (copy / insert)
Paste these fragments into the editor. The sandbox rejects QuantConnect, os, and network libraries.
from __future__ import annotations
import numpy as np
import pandas as pd
from backtest.data import load_daily_prices
from backtest.engine import EngineConfig, PortfolioEngine
from backtest.metrics import compute_metricsASSETS = ["SPY", "QQQ", "TLT", "GLD", "BIL"]def make_on_day(prices: pd.DataFrame):
cols = [c for c in ASSETS if c in prices.columns]
sma = prices[cols].rolling(200, min_periods=200).mean()
state = {"last": None}
def on_day(engine: PortfolioEngine, dt: pd.Timestamp) -> None:
if sma.loc[dt].isna().all():
return
key = (dt.year, dt.month)
if state["last"] == key:
return
state["last"] = key
long = [
s for s in cols
if pd.notna(prices.at[dt, s]) and pd.notna(sma.at[dt, s])
and prices.at[dt, s] > sma.at[dt, s]
]
weights = {} if not long else {s: 1.0 / len(long) for s in long}
engine.set_target_weights(dt, weights)
ready = sma.dropna(how="all").index.min() if sma.notna().any().any() else None
return on_day, readyengine.set_target_weights(dt, {"SPY": 0.60, "BIL": 0.40})Live backtest performance
Export to your platform
Transform Quant Buffet lab code (ASSETS + make_on_day / PortfolioEngine) into native classes for a third-party IDE — then copy and paste.
# Generated from Quant Buffet → QuantConnect LEAN
# Strategy: Mid-Month Payday S&P500 Strategy
# Detected pattern: Custom / hybrid
# Source uses Quant Buffet lab APIs (ASSETS + make_on_day / PortfolioEngine).
# Review fees, data, and risk before live trading — educational export only.
from AlgorithmImports import *
class QuantBuffetExport(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2010, 1, 1)
self.SetCash(100000)
tickers = ["SPY", "TLT", "GLD", "BIL"]
self.symbols = []
for t in tickers:
if "-" in t: # crypto proxy e.g. BTC-USD
self.symbols.append(self.AddCrypto(t.replace("-USD", ""), Resolution.Daily).Symbol)
else:
self.symbols.append(self.AddEquity(t, Resolution.Daily).Symbol)
self.Schedule.On(
self.DateRules.MonthStart(self.symbols[0]),
self.TimeRules.AfterMarketOpen(self.symbols[0], 30),
self.Rebalance,
)
# Logic: Custom Quant Buffet logic — adapt the signal block to match your lab on_day().
def Rebalance(self):
# Pattern: custom — Custom Quant Buffet logic — adapt the signal block to match your lab on_day().
# Default: equal-weight. Port your make_on_day weights here via SetHoldings.
w = 1.0 / len(self.symbols) if self.symbols else 0.0
for symbol in self.symbols:
self.SetHoldings(symbol, w)
Exported code uses the platform’s native classes and libraries. Install dependencies in your third-party IDE, then run. Validate before live trading.
Academic paper
Aixin Ma; William R. Pratt
- Oklahoma City University
- ?Oklahoma City University - Meinders School of Business
https://papers.ssrn.com/sol3/papers.cfm?abstract_id=3257064


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.
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.