sell in may – Helping you Master EasyLanguage https://easylanguagemastery.com Helping you Master EasyLanguage Thu, 08 Aug 2024 13:51:18 +0000 en-US hourly 1 https://wordpress.org/?v=7.0 https://easylanguagemastery.com/wp-content/uploads/2019/02/cropped-logo_size_icon_invert.jpg sell in may – Helping you Master EasyLanguage https://easylanguagemastery.com 32 32 Riding the Market Waves: How to Surf Seasonal Trends to Trading Success https://easylanguagemastery.com/market-studies/market-seasonality-study-may-2019/?utm_source=rss&utm_medium=rss&utm_campaign=market-seasonality-study-may-2019 https://easylanguagemastery.com/market-studies/market-seasonality-study-may-2019/#comments Mon, 26 Aug 2024 10:00:00 +0000 http://easylanguagemastery.com/?p=19871

Remember that old Wall Street chestnut, "Sell in May and go away"? Well, grab your favorite beverage and settle in, because we're about to dive into this age-old wisdom and see if it really holds water.

Now, I don't know about you, but I've always been a bit skeptical of these catchy market phrases. They sound great at cocktail parties, but do they actually work? That's exactly what I set out to discover.

In this article, we're going to break down our Market Seasonality Study step by step.

Below is a graph of the market with a "buy" at the start of the strong period and a "sell" at the end of the strong period.

Testing the "Buy in November, Sell in May" Strategy

To evaluate the popular trading concept of buying the S&P in November and selling in May, I set up a test with the following parameters:

  • Market: S&P cash market
  • Time period: 1960 to present
  • Position sizing: Risk-adjusted, with $5,000 risked per trade based on market volatility
  • Transaction costs: Not included (no slippage or commissions accounted for)

The core logic of this strategy can be implemented in EasyLanguage as follows:

CurrentMonth = Month(Date);
If (CurrentMonth = BuyMonth) And (MP = 0) Then
Buy("Buy Month") iShares contracts next bar at market;
If (CurrentMonth = SellMonth) Then
Sell("Sell Month") iShares contracts next bar at market;

This code does the following:

  1. Determines the current month
  2. If it's the buy month (November) and we're not in the market, it enters a long position
  3. If it's the sell month (May), it exits the position

By using this simple logic, we can test whether this well-known market adage holds up over a long period of historical data.

Test Parameters and Assumptions

I decided to test the strategy on the S&P cash index, with data going back to 1960. The following assumptions were made for this test:

  • Starting account size: $100,000
  • Test period: January 1960 through May 2024
  • Position sizing: Full account size used when opening a new position
  • Equity management: P&L not accumulated to the starting equity
  • Transaction costs: No deductions for commissions and slippage
  • Risk management: No stops were used

With these parameters set, we can now input the key months for our seasonality strategy:

  • Buy month: November
  • Sell month: May

Using these inputs, we generated the following equity graph:

Buy November, Sell May

Buy November, Sell May

"Sell in May and Go Away" Strategy Results

The equity curve we generated visually represents the performance of our "Sell in May and Go Away" strategy over the 64-year test period. It allows us to see the long-term trend as well as any significant drawdowns or periods of exceptional growth. And I must say, it sure looks like these months have a long bias - those are some impressive results!

Let's break down the numbers:

  • Total Profit: $4,640,085
  • Max Intra-day Drawdown: $1,403,538
  • Net Profit vs Drawdown Ratio: 3.3

In simpler terms, for every dollar of drawdown, the strategy is making just over three dollars in profit. That's a respectable ratio by most trading standards.

Inverting the Strategy

But here's where it gets really interesting. What would happen if we flipped our strategy on its head? Instead of buying in November and selling in May, what if we did the opposite - buying in May and selling in November?

To find out, I inverted the BuyMonth and SellMonth inputs in our test. Here's the resulting equity curve:

Buy May, Sell November

Buy May, Sell November

Analyzing the Inverted Strategy Results

The inverted equity curve provides a fascinating contrast to our original strategy, allowing us to visually compare the performance of buying during the traditionally "weak" months versus the "strong" months.

Let's break down the performance of this inverted strategy:

  1. 1960-1970: The equity curve consistently declined.
  2. 1970-1978: It bottomed out and began to climb.
  3. 1978-1997: Steady growth, reaching an equity peak in 1997.
  4. 1997-2008: Entered a drawdown period, bottoming in 2008.
  5. 2008-2021: Recovered, reaching new equity highs in 2020 and 2021.

Key metrics for the inverted strategy:

  • Total Profit: $94,148
  • Max Intra-day Drawdown: $92,357
  • Net Profit vs Drawdown Ratio: 1.0

This 1:1 ratio indicates that you must endure a dollar of drawdown for every dollar of profit - a much less attractive risk-reward proposition compared to our original strategy.

Let's focus on the strong season period from November-May moving forward. Can we add a filter to improve the results?

Implementing a Simple Moving Average Filter

To refine our strategy and avoid potentially unfavorable entry and exit points, we're introducing a 30-period simple moving average (SMA) as a short-term trend filter. This addition aims to prevent us from:

  1. Buying immediately into a falling market
  2. Selling immediately into a rising market

Here's how it works:

  • For Selling: If May (our SellMonth) arrives and the market is rising (price above the 30-period SMA), we delay selling until the price closes below the SMA.
  • For Buying: If November (our BuyMonth) arrives, we only buy when the price closes above the SMA.

To implement this in EasyLanguage, we create two flags: BuyFlag and SellFlag. These indicate when the proper conditions for buying or selling are met based on our short-term trend filter.

if (MinorTrendLen > 0) Then 
BuyFlag = Close > Average(Close, MinorTrendLen)
Else
BuyFlag = true;

If (MinorTrendLen > 0) Then
SellFlag = Close < Average(Close, MinorTrendLen)
Else
SellFlag = true;

The MinorTrendLen variable is an input that determines the SMA's look-back period. An additional check allows us to enable or disable the SMA filter:

  • If MinorTrendLen > 0: The SMA filter is active
  • If MinorTrendLen = 0: Both flags are always true, effectively disabling the filter

This flexibility lets us easily compare performance with and without the filter.

Strong Seasonality Trade (November-May) With Filters

Baseline

SMA Filter

Net Profit

$4,640,095

$5,961,005

Profit Factor

4.42

4.81

Total Trades

64

64

Avg.Trade Net Profit

$72,501

$93,140

Annual Rate of Return

9.54%

9.93%

Max Drawdown(Intraday)

$1,403,538

$1,856,564

NP vs Drawdown

3.3

3.2

We increased the net profit, profit factor, average profit per trade, and annual rate of return. There is a slight decline in the NP vs Drawdown ratio, but it's tiny. We can decently pull more profit by applying a simple moving average.

MACD Filter

A standard MACD filter is a well known indicator that may help with timing. I'm going to add a MACD calculation, using the default settings, and only open a new trade when the MACD line is above zero. Likewise, I'm only going to sell when the MACD line is below zero.  Within EasyLanguage we can create a MACD filter  by creating two Boolean flags called MACDBull and MACDBear which will indicate when the proper major market trend is in our favor.

If ( MACD_Filter ) Then
Begin
MyMACD = MACD( Close, FastLength, SlowLength );
MACDAvg = XAverage( MyMACD, MACDLength );
MACDDiff = MyMACD - MACDAvg;
If ( MyMACD crosses over 0 ) Then
Begin
MACDBull = True;
MACDBear = False;
End
Else If ( MyMACD crosses under 0 ) Then
Begin
MACDBull = False;
MACDBear = True;
End;
End
Else Begin
MACDBull = True;
MACDBear = True;
End;

Below are the results with the MACD filter:

Strong Seasonality Trade (November-May) With Filters

Baseline

SMA Filter

MACD Filter

Net Profit

$4,640,095

$5,961,005

$4,685,543

Profit Factor

4.42

4.81

5.35

Total Trades

64

64

63

Avg.Trade Net Profit

$72,501

$93,140

$74,373

Annual Rate of Return

9.54%

9.93%

9.55%

Max Drawdown (Intraday)

$1,403,538

$1,856,564

$1,205,264

NP vs Drawdown

3.3

3.2

3.8

Utilizing the MACD filter and comparing it to our baseline system, we can see we don't make as much more as the simple moving average filter, however, we increased our risk adjusted return with a NP vs DD of 3.8. So, if drawdown is your concern and not just pure profit it looks the MACD filter is slightly better.

RSI Filter

For our final filter I will try the RSI indicator with its default loopback period of 14. Again, like the MACD calculation, I want price moving in our direction so I want the RSI calculation to be above zero when opening a position and below zero when closing a position.

If ( RSI_Filter ) Then
Begin
   RSIBull = RSI(Close, 14 ) > 50;
   RSIBear = RSI(Close, 14 ) < 50;
End
Else Begin
   RSIBull = true;
   RSIBear = true;
End;

Strong Seasonality Trade (November-May) With Filters

Baseline

SMA Filter

MACD Filter

RSI Filter

Net Profit

$4,640,095

$5,961,005

$4,685,543

$4,080,657

Profit Factor

4.42

4.81

5.35

4.24

Total Trades

64

64

63

64

Avg.Trade Net Profit

$72,501

$93,140

$74,373

$63,760

Annual Rate of Return

9.54%

9.93%

9.55%

9.34%

Max Drawdown (Intraday)

$1,403,538

$1,856,564

$1,205,264

$1,291,784

NP vs Drawdown

3.3

3.2

3.8

3.1

Filter Comparison Results

The RSI filter performed worse than both the MACD and SMA filters.

In the end, it appears that applying either an SMA filter or an MACD filter can improve the baseline results. Both filters are relatively simple to implement and were tested for this article using their default values. Of course, this simple study could be expanded much further.

Applying Filters to the Weak Seasonality Period

After performing the different filter tests and selecting the simple moving average filter as the most effective, I began to wonder how our three filters would perform if applied to the weak seasonality period. Below are the performance results.

Weak Seasonality Trade (May-November) With Filters

No Filter

SMA Filter

MACD Filter

RSI Filter

Net Profit

$94,148

$244,406

$221,672

$121,740

Profit Factor

1.42

1.67

1.79

1.52

Total Trades

64

64

63

64

Avg.Trade Net Profit

$1,471

$3,818

$3,518

$1,902

Annual Rate of Return

3.64%

5.03%

4.88%

4.00%

Max Drawdown (Intraday)

$92,357

$128,921

$106,121

$100,544

NP vs Drawdown

1.0

1.7

2.0

1.2

We can see that adding MACD Filter produces the best results in terms risk adjusted return (NP vs Drawdown). The SMA Filter products the best results in terms of net profit. Both provide a radical change when compared to the No Filter situation. 

Conclusion

It certainly appears there is a significant seasonal edge in the S&P market. The trading rules we used above for the S&P cash market could be applied to the SPY and DIA ETF markets. I've tested these ETFs, and they produce very similar results. The S&P futures market also yields comparable outcomes. Interestingly, this approach even seems to work well for some individual stocks.

Keep in mind that this market study did not utilize any market stops. This is not a complete trading system!

Practical Use: Market Regime Filter For Stock Index Markets

With some additional work, an automated trading system could be built from this study. Another application would be to use this study as a filter for other trading systems. I envision using these results as a regime filter for your existing trading systems that trade the stock index markets.

Strong Season Bull/Bear Filter

  • Bull Market = if price is above 30-day SMA
  • Bear Market = if price is at or below 30-day SMA

Weak Season Bull/Bear Filter

  • Bull Market = if MACD is above zero
  • Bear Market = if MACD is at or below zero

This seasonality filter could be applied to both automated trading systems and discretionary trading. While it may not be particularly helpful for intraday trading, it's worth testing in that context as well.

Being aware of these major market cycles can be invaluable in understanding current market conditions and potential future directions. This knowledge can enhance your overall market perspective and potentially improve your trading decisions.

I hope you found this study helpful and that it provides you with new insights for your trading strategies.

]]>
https://easylanguagemastery.com/market-studies/market-seasonality-study-may-2019/feed/ 2
Market Seasonality Study https://easylanguagemastery.com/market-studies/market-seasonality-study/?utm_source=rss&utm_medium=rss&utm_campaign=market-seasonality-study https://easylanguagemastery.com/market-studies/market-seasonality-study/#comments Mon, 05 Nov 2018 11:00:50 +0000 http://systemtradersuccess.com/?p=3616


With October over I thought it would be a good idea to review our Market Seasonality Study.

Back in May of this year, we closed a seasonality trade in anticipation for a traditionally weak period of the stock index markets. That is the months of May, June, July, August, September, and October. So what did the market do during those months?

Below is a graph of the market with a "buy" at the start of the weak period and a "sell" at the end of the weak period.

As you can see, the traditionally weak period took off! Only in the last few weeks did it start giving back some of those gains. The weak period returned a $3,375 (3.4%) gain.

We are now entering a traditionally strong season for the stock index market. This is a well known seasonality period. In this article I would like to take a closer look at the seasonality bias which so many investors and traders talk about. 

Seasonality Bias

First, I would like to test the popular trading idea of buying the S&P in November and selling in May. I will test this on the cash market going back to 1983. The number of shares to buy will be adjusted based upon a fixed amount of risk. In this case, $5,000 is risked per trade based upon the volatility of the market. As this is a simple market study no slippage or commissions were taken into account. The EasyLanguage code looks like this:

CurrentMonth = Month( Date );
 
If ( CurrentMonth = BuyMonth ) And ( MP = 0 ) Then Buy("Buy Month") iShares contracts next bar at market;
 
If ( CurrentMonth = SellMonth ) Then Sell("Sell Month") iShares contracts next bar at market;

Testing Environment

I decided to test the strategy on the S&P cash index going back to 1960. The following assumptions were made:

* Starting account size of  $100,000.
* Dates tested are from 1960 through May 2017.
* The number of shares traded will be based on volatility estimation and risking no more than $5,000 per trade.
* Volatility is estimated with a two times 20-week ATR calculation. This is done to normalize the amount of risk per trade.
* The P&L is not accumulated to the starting equity.
* There are no deductions for commissions and slippage.
* No stops were used.

From here we can plug into the input values the buy month (November) and sell month (May). Doing this we generate the following equity graph:  

It sure looks like these months have a long bias as those are some nice results. What would the equity curve look like if we reverse the BuyMonth and SellMonth? That is, let's buy in May and sell in November. Below is the equity curve for this inverted system.

The early years of 1960 to about 1970 the equity curve went lower and lower. Then it started climbing reaching an equity peak of 1987. During this period, the strategy was producing positive results. That equity peak occurred during 1987 should be familiar. That was the year we had the massive one day market crash on October 19th known as Black Monday. That's when Dow Jones Industrial Average dropped 22% in one day!

 Since that event the behavior of market participants has been altered. This is not unlike the radical market changes which occurred after the 2000 market peek where much of the trending characteristics of the major markets were replaced by mean reversion tendencies. So far the basic seasonality study looks interesting. However, keep in mind that we do not have any stops in place. 

Nor do we have any entry filter that would prevent us from opening a trade during a bear market. If the market is falling strongly when our BuyMonth rolls around we may not wish to purchase right away.

Likewise, we have no exit filter to prevent us from exiting when the market may be on a strong rise during the month of May. It's conceivable that the market may be experiencing a strong bull run when our usual SellMonth of May rolls around.

Simple Moving Average Filter

In order to avoid buying and selling at the wrong times I'm going to introduce a 30-period simple moving average (SMA) to act as a short-term trend filter. This filter will be used to prevent us from immediately buying into a falling market or selling into a rising market. For example, if our SellMonth of May rolls around and the market happens to be rising (trading above the 30-period SMA), we do not sell just yet. We wait until unit price closes below the short-term SMA. The same idea is applied to the buying side, but reversed. We will not go long until price closed above the short-term SMA. Within EasyLanguage we can create a buy/sell confirmation flag called BuyFlag and SellFlag which will indicate when the proper go-long or sell conditions appear based upon our short-term trend filter.

if ( MinorTrendLen > 0 ) Then BuyFlag = Close > Average( Close,  MinorTrendLen )
Else BuyFlag = true;
If ( MinorTrendLen > 0 ) Then SellFlag = Close < Average( Close, MinorTrendLen )
Else SellFlag = true;

The MinorTrendLen variable is actually an input value which holds the look-back period to be used in the SMA calculation. You will notice there is an additional check to see if the look-back period is zero. This is done so we can enable or disable this SMA filter. If you enter zero for the look-back period, the code will always set our BuyFlag and SellFlag to true. This effectively disables our short-term market filter. This is a handy way to enable and disable filters from the system inputs. Below is the performance of both our Baseline system and the system with our SMA filter:

Seasonality Trade

Baseline

SMA Filter

Net Profit

$383,604

$419,965

Profit Factor

5.73

6.22

Total Trades

57

57

%Winners

75%

74%

Avg.Trade Net Profit

$6,730

$7,368

Annual Rate of Return

2.71%

2.83%

Sharpe Ratio

0.15

0.16

Max Drawdown(Intraday)

$36,151

$29,979

RINA Index

145

158

We increased the net profit, profit factor, average profit per trade, annual rate of return, and the expectancy score. The max intraday drawdown fell as well. Overall it looks like the SMA filter adds value.

MACD Filter

A standard MACD filter is a well known indicator that may help with timing. I'm going to add a MACD calculation, using the default settings, and only open a new trade when the MACD line is above zero. Likewise, I'm only going to sell when the MACD line is below zero.  Within EasyLanguage we can create a MACD filter  by creating two Boolean flags called MACDBull and MACDBear which will indicate when the proper major market trend is in our favor.

If ( MACD_Filter ) Then
Begin
MyMACD = MACD( Close, FastLength, SlowLength );
MACDAvg = XAverage( MyMACD, MACDLength );
MACDDiff = MyMACD - MACDAvg;
If ( MyMACD crosses over 0 ) Then
Begin
MACDBull = True;
MACDBear = False;
End
Else If ( MyMACD crosses under 0 ) Then
Begin
MACDBull = False;
MACDBear = True;
End;
End
Else Begin
MACDBull = True;
MACDBear = True;
End;

Below are the results with the MACD filter:

Seasonlity Trade

Baseline

SMA Filter

MACD Filter

Net Profit

$383,604

$419,965

$367,642

Profit Factor

5.73

6.22

4.74

Total Trades

57

57

56

%Winners

75%

74%

71%

Avg.Trade Net Profit

$6,730

$7,368

$6,565

Annual Rate of Return

2.71%

2.83%

2.65%

Sharpe Ratio

0.15

0.16

0.12

Max Drawdown(Intraday)

$36,151

$29,979

$36,151

RINA Index

145

158

111

Utilizing the MACD filter and comparing it to our baseline system, we reduced every so slightly many of the performance metrics. Overall, it does not appear to be better than our SMA filter.

RSI Filter

For our final filter I will try the RSI indicator with its default loopback period of 14. Again, like the MACD calculation, I want price moving in our direction so I want the RSI calculation to be above zero when opening a position and below zero when closing a position.

If ( RSI_Filter ) Then
Begin
   RSIBull = RSI(Close, 14 ) > 50;
   RSIBear = RSI(Close, 14 ) < 50;
End
Else Begin
   RSIBull = true;
   RSIBear = true;
End;

Seasonality Trade

Baseline

SMA Filter

MACD Filter

RSI Filter

Net Profit

$383,604

$419,965

$367,642

$381,850

Profit Factor

5.73

6.22

4.74

5.39

Total Trades

57

57

56

57

%Winners

75%

74%

71%

75%

Avg.Trade Net Profit

$6,730

$7,368

$6,565

$6,699

Annual Rate of Return

2.71%

2.83%

2.65%

2.70%

Sharpe Ratio

0.15

0.16

0.12

0.14

Max Drawdown(Intraday)

$36,151

$29,979

$36,151

$35,052

RINA Index

145

158

111

137

The RSI filter performed better than the MACD filter. Comparing it to the Baseline, we see it's very similar. With the RSI filter the net profit, profit factor and RINA Index are all slightly lower.

In the end it does appear applying a SMA filter or an RSI filter can improve the baseline results. Both filters are rather simple to implement and were tested for this article with their default values. Of course, you could take this simple study much further.

Apply SMA Filter on Weak Seasonality Period?

After performing the different filter tests and choosing the simple moving average filter, I started wondering what it would look like if we applied to the weak seasonality period. Below are the before-and-after equity curves.

Without the simple moving average filter

With the simple moving average filter

It appears the simple moving average filter helps a lot. While we can still see the weak seasonality period equity curve is not nearly as attractive as the strong seasonality period, it did improve to somewhat decent. 

Conclusion

It certainly appears there is a significant seasonal edge to the S&P market. The very trading rules we used above for the S&P cash market could be applied to the SPY and DIA ETF markets. I've tested those ETFs and they produce very similar results. The S&P futures market also produces similar results. It even appears to work well on some stocks.

Keep in mind this market study did not utilize any market stops. How can this study be used? With a little work an automated trading system could be built from this study. Another use would be to apply this study as a filter for trading other systems.

This seasonality filter could be applied to both automated trading systems or even discretionary trading. It may not be much help for intraday trading, but it may be worth testing. Anyway, just being aware of these major market cycles can be helpful in understanding what's going on with today's markets and where they may be going in the near future.

Hope you found this study helpful. 

]]>
https://easylanguagemastery.com/market-studies/market-seasonality-study/feed/ 7