Using basic Pandas to tell when to enter and exit an investment
Disclaimer: This does not constitute any form of investment advice so please use this methodology at your own risk.
For this analysis, we hope to observe some form of seasonal trend within a stock market and come up with a simple strategy to take advantage of this trend. A basic level of Python (more specifically Pandas) is used to manipulate the data. As this is supposedly a simple strategy, there will not be usage of statistical analysis or predictive techniques (these can and will be covered in the future).
Here, we will be looking at the Singapore stock market. A common barometer of the Singapore economy would be the Straits Times Index (STI), which tracks the performance of 30 stocks listed on the Singapore Exchange (SGX)
We cannot exactly buy a unit of the STI, but we can gain exposure to it. One method is to use an exchange-traded fund (ETF), and in this case, I will be using the SPDR Straits Times Index ETF (ES3.SI). This ETF aims to replicate the performance of the STI and is available to trade over various brokers.
Here’s the adjusted close prices of ES3 from 1st Jan 2008 to 1st Jan 2018:
Adjusted close prices of ES3 from 1st Jan 2008 to 1st Jan 2018
Adjusted close price data is used to omit the effects of corporate actions such as dividends, stock splits etc. and will be a more accurate representation of stock price movements.
We suppose that there are specific months that tend to give better returns than others. We will compute the arithmetic average of the log-returns of the different months (aggregated across the time period).
For example, when considering January, we look at the daily returns of January 2008, January 2009 … January 2018 and calculate the arithmetic mean across these values.
This is how the daily log returns of ES3 look like:
Log returns of ES3 from 1st Jan 2008 to 1st Jan 2018
One of the reasons for using log returns is because of the general assumption that stock returns follow a lognormal distribution.
Below is a summary of the arithmetic mean of the daily log-returns of each month from 1st Jan 2008 to 1st Jan 2018 (1 corresponding to January and 12 corresponding to December):
Name: Daily Returns, dtype: float64
It is observed that these are the months that have had a mean daily positive return over this period:
Therefore, we will buy the maximum amount of ES3 at the start of March and sell off all our holdings at the start of June for every year (same applies for the other months in the list).
For the next sections, we will define 2 portfolios:
- The Default Portfolio: A buy-and-hold portfolio where the full amount of capital is used to purchase the maximum number of shares of ES3 at the start of the period
- The Strategic Portfolio: A portfolio that buys the maximum number of shares of ES3 on the first trading day of a “good month” and exit on the first trading day of a “bad month”
The simulations were conducted with a starting capital of 10,000 SGD. Some assumptions include:
- No transaction costs (bid-ask spreads, commissions, etc.)
- Fractional shares are allowed
A simulation ran over the period 1st Jan 2008 to 1st Jan 2018 yielded the following portfolio values:
Portfolio values from 1st Jan 2008 to 1st Jan 2018
Based on the table, the Default Portfolio achieved an annualised return of -1.8%, while the Strategic Portfolio achieved an annualised return of 10.1%. A visualisation of the portfolio values is shown below.
Portfolio values of the Default Portfolio vs Strategic Portfolio from 1st Jan 2008 to 1st Jan 2018
Naturally, we would expect better performance for the Strategic Portfolio given that the “good months” and “bad months” were determined based on this very same set of data.
Therefore, we shall apply our observations on the period 1st Jan 2018 to 1st May 2021. Note that any observations we made so far were independent of this time period.
Portfolio values from 1st Jan 2018 to 1st May 2021
The Default Portfolio achieved an annualised return of -3.5%, while the Strategic Portfolio achieved an annualised return of -3.0%.
Portfolio values of the Default Portfolio vs Strategic Portfolio from 1st Jan 2018 to 1st May 2021
Well, the simulation results show that the Strategic Portfolio outperformed the Default Portfolio just by a small margin.
It was seen that in both cases, the Strategic Portfolio did better than the Default Portfolio. However, note that in the test case, depending on your investment capital, the improvement over the Default Portfolio may be offset by transaction costs.
The Strategic Portfolio did well for the most of 2018, but it did not avoid the negative impact due to COVID-19, and it missed the sharp recovery in late 2020. Missing the sharp recovery has allowed the Default Portfolio to close up much of the gap.
- Simple to implement with basic Python and does not require any complex analytics (it was done with just a simple df.groupby operation)
- Maximum of 12 transactions per year, which is rather reasonable
- Strategy can be implemented for other stocks which may fit the pattern better
- Removes emotion from the investment process and avoids rash decisions
- Being in and out of the market would mean potentially avoiding large drawdowns due to sudden adverse events (eg. COVID-19 outbreak)
- A very naive strategy with results that may be attributed more to luck than backed by statistical evidence
- Discretises time periods into exact months, where in fact (if such patterns exist), time periods can range from any number of days
- Potentially missing sudden gains due to being out of the market
- Assumption that the economic conditions within a year are similar across years, but it may not be true due to factors such as technology, regulations, policies, etc.
Just because the strategy is simple does not mean that it is useless. Making some modifications could make the model more viable. Here are some ideas:
- Multi regime model: If returns were observed to be mostly seasonal, we could have a model that switches between using a seasonal strategy and another for abnormal changes (which could be detected using statistical tests or even machine learning)
- Irregular time periods model: Seasonal returns do not necessarily need to be discretised by months, it could be 15 days, 93 days or maybe even periods that are not of constant length within the year
- Sector rotation model: Seasonal trends differ across industries and this strategy provides an alternative to leaving your cash to “rest” during certain months of the year
I believe that returns are seasonal (just like economic cycles). Within the course of the year, there are several events that can contribute to these cycles, such as earning dates, budget announcements or even festivities. These events impact certain industries (and companies) more so than others. This is why hypotheses such as the January Effect exists.
The January Effect is a perceived seasonal increase in stock prices due to reasons such as tax-loss harvesting (selling investments at a loss to offset capital gains tax, does not apply to all countries) and even investor psychology.
If we were to establish the existence of such patterns, it would probably apply to a handful of stocks. Nonetheless, this would be a good start to building up a stronger strategy.