[Python] Sell in May and Go Away for Straits Times Index

By The Boy Who Procrastinates - May 08, 2020

There is an old financial adage to “sell in May and go away”. According to it, investors are better off divesting their stocks and holding cash in May and wait to reinvest in November. 

This seasonal pattern is based on the premise that the six "summer" months of May through October typically register lower gains than the six "winter" months of November through April.

The theory of selling in May is believed to have originated in England with the continuation to the maxim being "come back on St Legers Day". It refers to the St. Leger's Stakes which was one of the most prestigious horse races held in Doncaster every September. 

To seek respite from the heat, those at the upper echelons of society, who tend to invest in the market, can afford to be away during the summer vacation months. A host of fall events which includes the St. Leger’s Stakes horse race will enticingly lure them back in fall when cooler temperatures arrives.

Hence, the rough summer doldrums for the market has been attributed to plummeting trading volume and increased volatility during summer vacation months and increased investment flows during the winter months.

Now, it is anybody's guess as to how this strategy will fare in 2020But it definitely merits a closer look at whether this inherited market axiom holds water for the Straits Times Index (STI) over the past 20 years. 

The Python step-by-step seasonality analysis will be shared so that we can all learn a little programming at the same time, especially during this Circuit Breaker period. I will be using the Jupyter Notebook which is a free open-source web application. To install any of the package used, one can simply use the command, "pip install package" on their Anaconda Prompt.

Data Extraction for STI

First and foremost, the main component for analysis is the STI price data which we will extract from Yahoo Finance.  

from pandas_datareader import data as pdr
import pandas as pd
import yfinance as yf


# Indicate start and end date
start = '2000-01-01'
end   = '2020-01-01'

# Generate STI price data
STI = pdr.get_data_yahoo('^STI', start, end)['Adj Close']

We define the time frame to be 20 years, starting from 2000 to 2019. The data of interest is the daily adjusted close price of STI. 

Generate STI returns for May

Next, the monthly returns for STI are computed by taking the percentage change between the closing price of the last day of a calendar month and that of the preceding month. 

# Extract STI month-end price data
monthly_STI = STI.groupby(pd.Grouper(freq='M')).tail(1) 

# Generate STI monthly returns
monthly_returns = round(monthly_STI.pct_change()*100,2)

# Filter the STI returns for May
may = []
for date in monthly_returns.index:
    if date.month == 5: 

Subsequently, the monthly returns for May over the 20 years period is filtered and we now have what we need to plot a nice bar chart. 

STI Returns in the Month of May

(Click to enlarge)

Common to popular belief, the largest 30 companies listed on SGX typically turn in lackluster performance on the local bourse in May. 

To address the two outliers, the disappointing decline of 17% for the STI was due to the Dot Com market crash in 2000. On the other hand, the extraordinary STI growth of 21% in May 2009 marks the start of a strong rally contributed by the market recovery from the global financial crisis.

The average returns of STI in May is calculated to be as follows:
  • Over the last 20 years: -1.68%
  • Over the last 10 years: -3.23%
  • Over the last 5 years: -3.35%
It is intriguing to observe that the effect of selling in May seems to be more notable in recent times as evidenced by the progressive decline in returns of STI over the years. Overall, the month of May has not been a good month for the stock market. 

Calculate the number of years with negative STI Returns in the Month of May

To calculate number of years with negative STI returns in May, we can write a simple loop to do so. 

# Set a counter for the number of years with negative STI returns in May
negative_month_count = 0

for year in may:
    if year < 0:
        negative_month_count += 1

The output shows that STI has seen negative returns in May for 13 out of the last 20 years. 

As most of such events turned up during the latter half of the time frame, the percentage of the number of years with negative STI returns in May increases as follows:
  • Over the last 20 years: 65%
  • Over the last 10 years: 80%
  • Over the last 5 years: 80%

STI Performance during 6-month periods from May to Oct and from Nov to Apr

Now to determine if the underperformance of STI in the "summery" six-month period from May to Oct as compared to the "wintery" months stands, we can modify the Python code shared earlier to filter the STI price data for the relevant months. 

# Filter the STI price data for April and October
apr = []
octo = []
for date in monthly_STI.index:
    if date.month == 4: 
    if date.month == 10:

With the data collected, we can now plot the STI returns during the 6-month periods from May to Oct and from Nov to Apr as follows: 

(Click to enlarge)

According to the data presented, there does appear to be some truth to the axiom. The divergence of average returns between the "winter" months and  "summer" months is startling!

Similar to the pattern observed for the May effect, the deviation between the average returns from May to Oct and from Nov to Apr has been increasingly pronounced in recent 5 years, reaching a difference of 12.78%.

(Click to enlarge)

When we break down the returns recorded in the segregated 6-month periods by years, it is noticeable that the trend line for the STI returns from Nov to April has mostly stayed above that from May to Oct. The outcome appears to be fairly 
consistent even in times of crisis such as the 2000 Dot-Com Bubble and the Global Financial Crisis in 2008

Final Thought

As irrational as it may seem, the seasonality effect appears to be enduring and has persisted over time for the local index. Frankly, the result is much more significant than I have expected to uncover.

While not 
initially intended for market-timing reasons, the trends of selling in May seems to have evolved into self-fulfilling prophecies.

All in all, it should be emphasized that past historical data should not be construed as a guarantee for future results. It would be a dangerously misleading approach to assume that the market will always display consistent seasonal pattern, especially when we are witnessing an unprecedented stock market reaction to the COVID-19.

If you do not wish to miss out on any articles, you may consider following the facebook page for timely update. 

Disclaimer: Kindly note that this is not a sponsored post. The Boy who Procrastinates has compiled the information for his own reference, with the hope that it will benefit others as well. It should not be used or construed as an offer to sell, a solicitation of an offer to buy, a recommendation for any security or as professional financial investment advice.

  • Share:

You Might Also Like


  1. Hi TBWP, very good article supported by data, analysis and opinions. Love the programming something I can never do. Actually wanted to write a similar article but not anymore, coz u really already did a fantastic job.

    1. Hi Rolf Suey,

      Thank you for your kind words. I'm glad that you have enjoyed it! We can all learn the programming bit together 🙂

  2. Hi BWP,

    Nice analysis using Python. I am learning it as well but still getting familiar with the basics.
    Where did you learn from?

    Also, I see you invested quite a good sum for someone so young.
    How much % are you invested currently in equities?
    (excluding cpf)


    1. Hi there,

      Glad you have enjoyed it! I have picked up Python from resources found online such as Coursera. Likewise, I have only covered the basic of it and there is still so much room for improvement.

      Ah I wouldn’t say I am young anymore and there are times I wish I had started investing when I was younger. I have not really sit down to look at the percentage breakdown but a ballpark figure probably put me at about 70% invested I think.

    2. I see. did you use python for work or learning just out of interest?

      By the way, i was also looking at Coursera courses. They are not free ,right?
      (other than 7 days trial)

    3. I have mainly picked up Python out of interest and to improve employability as well.

      Hmm if i remember correctly, you have to choose those non-specialization courses and there will be an option to audit the course when you enroll. From there, you should have free access to its resources.