Introduction

Retailers typically see an increase in sales volume leading into a holiday. The increase in sales can be from shoppers taking advantage of holiday sales or spending extra cash to buy gifts for friends and family. In this research post, we analyze trading opportunities for Amazon around Black Friday and Prime Day.

Background

Black Friday is the day following Thanksgiving Day in the United States, which is celebrated on the fourth Thursday of November. Prime Day is an annual shopping event hosted on Amazon. Both of these holidays feature large discounts for Amazon members, which typically increases the amount of attention Amazon receives from the market.

Research

To investigate if there are any trading opportunities surrounding these holidays, we created a notebook in the Research Environment. We started by gathering the daily returns of Amazon and the S&P 500 leading into each holiday. From the sets of daily returns, we calculated the median price path 10 days before Black Friday and Prime Day for each asset. The following image shows the median price paths for Black Friday:

AD_4nXfnDbftUkQlL-MKoLjLacxHeS0_g6lPbi1crYggs0lIWXeulYGbEkk-HQ1JD7qOhgJ2Qm1jj1hR_iVYhV4UBUtc3IM_c1hyuHIs1lZehm6J6ATvLB6s_HUglob34o6VyyojZF73NemYBYzX60oJ8Ja4WL_l?key=cG3zABNf9xoHuZLEXR4sLw

The following image shows the median price paths for Prime Day:

AD_4nXcX6ZzwOdbDz0vZQAEq8Y45laaJpIL0FT_Gtec-2U2iYXozsoRaZKG8K-PMG_UAQUiVt1OOV_g8k9zqDxwcL9zHRRN5yonEiWmtohD6cSEMf8qZwhfilR9tIKjaHnYAJ7JB0rd9fAkXMSqXSrRYvBFbWn-I?key=cG3zABNf9xoHuZLEXR4sLw

As shown in the visuals above, AMZN typically outperforms SPY leading into each type of holiday. However, to determine if the median AMZN performance during these periods is statistically significant, we ran some one-sample t-tests. The null hypothesis of these tests is that the mean 2-week return leading into the holiday equals the usual 2-week return of the asset. The p-value of both tests was below 0.01, so we rejected the null hypothesis.

Strategy Implementation

To implement this strategy, we start by defining the dates of every Black Friday and Prime Day.

_black_fridays = [
    datetime(1998, 11, 27),
    datetime(1999, 11, 26),
    datetime(2000, 11, 24),
    # ...
]

_prime_days = [
    datetime(2015, 7, 15),
    datetime(2016, 7, 12),
    datetime(2017, 7, 11),
    # ...
]

Next, in the initialize method, we add the AMZN and SPY Equities.

amzn = self.add_equity('AMZN')
spy = self.add_equity('SPY')

Lastly, we iterate through each holiday and create Scheduled Events to rotate the portfolio between AMZN and SPY. We hold AMZN 14 calendar days before the holiday and then go back to holding SPY after the holiday.

for holidays in [self._black_fridays, self._prime_days]:
    for holiday in holidays:
        # Hold AMZN before the holiday.
        self.schedule.on(
            self.date_rules.on(spy.exchange.hours.get_next_market_close(holiday - timedelta(14), False)), 
            self.time_rules.before_market_close(spy.symbol, 1), 
            lambda: self.set_holdings([PortfolioTarget(amzn.symbol, 1)], True)
        )
        # Hold SPY after the holiday.
        self.schedule.on(
            self.date_rules.on(spy.exchange.hours.get_next_market_close(holiday + timedelta(1), False)), 
            self.time_rules.before_market_close(spy.symbol, 1), 
            lambda: self.set_holdings([PortfolioTarget(spy.symbol, 1)], True)
        )

Other Monetization Methods

The underlying signal can be monetized with other investment vehicles, like Equity Options, to improve the strategy's performance. As a Black Friday or Prime Day sales event approaches, we open AMZN Option positions to capture the pre-holiday rally and then close the position when the holiday has passed.

Equity Option contract premiums increase when the volatility of the underlying Equity increases. To capture the premium and gain exposure to AMZN, we can sell at-the-money or out-of-the-money put Option contracts that expire after the holiday. To adjust the algorithm so that it trades Options, we start by changing the data normalization mode for AMZN to raw and adding a member to track the Option contract Symbol.

self._amzn = self.add_equity('AMZN', data_normalization_mode=DataNormalizationMode.RAW)
self._contract_symbol = None

Next, we adjust the Scheduled Events to trade Options instead of AMZN Equity.

# Sell an AMZN put contract before the holiday.
self.schedule.on(
    self.date_rules.on(self._spy.exchange.hours.get_next_market_close(holiday - timedelta(self._holding_period), False)), 
    self.time_rules.before_market_close(self._spy.symbol, 1), 
    self._sell_put
)
# Liquidate the put contract after the holiday.
self.schedule.on(
    self.date_rules.on(self._spy.exchange.hours.get_next_market_close(holiday + timedelta(1), False)), 
    self.time_rules.before_market_close(self._spy.symbol, 1), 
    lambda: self.liquidate(self._contract_symbol) if self._contract_symbol else None
)

We define the _sell_put method to select the contract, add it to the algorithm, and then sell it.

def _sell_put(self):
    chain = self.option_chain(self._amzn.symbol).data_frame
    if chain.empty:
        return
    expiry_threshold = self._amzn.exchange.hours.get_next_market_close(self.time + timedelta(self._holding_period), False)
    expiry = chain[chain.expiry > expiry_threshold].expiry.min()
    self._contract_symbol = chain[
        (chain.expiry == expiry) &
        (chain.right == OptionRight.PUT) &
        (chain.strike <= chain.underlyinglastprice)
    ].sort_values('openinterest').index[-1]
    self.add_option_contract(self._contract_symbol)
    self.set_holdings(self._contract_symbol, -0.2)

To ensure that we can add the contract and trade it during the same time step, we set a security initializer that seeds the price of each contract we add to the algorithm.

self.set_security_initializer(BrokerageModelSecurityInitializer(self.brokerage_model, FuncSecuritySeeder(self.get_last_known_prices)))

The last step is to add an on_data method that liquidates the underlying AMZN position if the Option buyer ever exercises their contract.

def on_data(self, data):
    if self._amzn.holdings.invested:
        self.liquidate(self._amzn.symbol)
        self._contract_symbol = None

Alternatively, to hold SPY while trading the AMZN put Options, we just need to add two extra lines to the on_data method.

def on_data(self, data):
    if not self._spy.holdings.invested:
        self.set_holdings(self._spy.symbol, 1)
    if self._amzn.holdings.invested:
        self.liquidate(self._amzn.symbol)
        self._contract_symbol = None

Results

Let's review the performance of each monetization method.

Version 1: Rotating Between AMZN and SPY Equities

This version of the strategy rotates between AMZN and SPY. We backtested this version from 1998 to 2024. The results show that the strategy achieves a 0.51 Sharpe ratio. In contrast, buying and holding the SPY achieves a 0.303 Sharpe ratio. Therefore, the strategy outperforms the benchmark. 

To test the robustness of the strategy, we ran an optimization job. We varied the number of calendar days that the algorithm held AMZN shares before each holiday. We tested 3 calendar days to 31 calendar days in steps of one day. Of the 29 strategy variants, 29/29 (100%) outperformed buying and holding the SPY.

AD_4nXcNJflw6o9M1d04RJqDQZuJTAJYulH2Vu9RJw8CQHn1s_2VQUmbFhWunYQyhhWCbSehCBTEwJnC9LOsRL3k0H8NoC6SRGIcCoQFPiVNeaYmHRA28HQISRIdADgJ1OxqYrIvpWahRsyW2sUlOO8CEECMkuf6?key=cG3zABNf9xoHuZLEXR4sLw

Version 2: Collecting Put Option Premiums

This version of the strategy sells AMZN put Option contracts before each Black Friday and Prime Day. We backtested this version from 2012 to 2024, which is the longest period of time our Options dataset supports. The strategy produces a 100% win rate. It generates a profit every Black Friday and Prime Day.

Version 3: Holding SPY + Collecting Put Option Premiums

This version of the strategy is the same as Version 2, but it also buys and holds SPY. We also backtested this version from 2012 to 2024. The results show that the strategy achieves a 0.722 Sharpe ratio. In contrast, buying and holding the SPY over the same time period without trading AMZN put Options results in a 0.657 Sharpe ratio. Therefore, this monetization method of the strategy signal also outperforms the benchmark.