Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 3

Handling Corporate Actions in Historical Data

Recommended resources

Welcome back! In our last lesson, we focused on the crucial process of ensuring data integrity by cleaning and aligning our historical price data. We now have a time series that is free of gaps and correctly aligned to the market's clock. However, there's one more critical transformation our data must undergo before it can be used for reliable backtesting. The prices themselves need to be adjusted.

This lesson tackles how to adjust historical price data for corporate actions like stock splits and dividends. If you were to plot the raw, historical price of a stock over many years, you would see large, sudden jumps and drops that weren't caused by market activity. These are artifacts of corporate actions, and failing to correct for them will introduce significant errors into your strategy's performance calculations, leading to flawed and unreliable backtest results. Our goal is to create a smooth, continuous price series that accurately reflects the total return an investor would have experienced.

The Problem with Raw Price Data

Imagine your strategy sees a stock price drop 75% in a single day. It would almost certainly trigger a sell signal. But what if that "drop" was actually a 4-for-1 stock split? The company's value didn't change, and as a shareholder, your total investment value remained the same; you just own four times as many shares at a quarter of the price. The raw price chart, however, tells a dangerously misleading story.

Corporate actions are events initiated by a company that affect its securities. For our purposes, the two most important are:

  1. Stock Splits: The company changes the number of shares outstanding, which proportionally changes the price per share.
  2. Dividends: The company distributes a portion of its profits to shareholders in cash.

Both events change the stock's price on the chart without reflecting a true change in the company's underlying value or an investor's total wealth. Let's see how to correct for each.


Adjusting for Stock Splits

A stock split changes the number of a company's shares without changing its market capitalization. For instance, in a 2-for-1 split, every shareholder gets an additional share for each one they own, and the stock price is halved. The total value of their holding is unchanged.

This chart of VXX shows a massive price gap. This was not a market crash but the result of a 4-for-1 reverse stock split. A backtesting model using unadjusted data would incorrectly interpret this as a catastrophic price drop.

To create a continuous price series, we must adjust all historical prices prior to the split to be comparable to the post-split prices. The QuantStart article "Understanding Equities Data" provides a clear explanation of this.

Understanding Equities Data

This article explains the concept of the "adjusted close" and details how corporate actions like stock splits and dividends affect the price series.

Please read the following two sections: The Effect of Stock Splits: This introduces the concept of a forward split. Continue reading through the explanation of forward vs. reverse splits and the example of Apple's stock splits to understand the motivation and impact. Calculating Stock Split Adjustments: This section provides the core formula. For an N-for-M split, the price adjustment factor is \frac{M}{N}. Pay close attention to how this factor is applied to all prices prior to the split's effective date. The volume adjustment is also mentioned, which uses the inverse factor.

As the article explains, the adjustment is straightforward. For a 2-for-1 split, the factor is . You multiply all historical open, high, low, and close prices before the split date by 0.5. For a 4-for-1 reverse split like the one in the VXX chart, it's an M-for-N split (1-for-4), so the factor is . You would multiply all prior historical prices by 4 to bring them in line with the new, higher price level.


Adjusting for Dividends

Dividends are more subtle but just as important. When a company pays a dividend, it is transferring cash from its accounts to its shareholders. This means the company is now worth less by the total amount of the dividend paid. On the ex-dividend date (the first day the stock trades without the right to receive the upcoming dividend), the stock price will typically drop by approximately the dividend amount.

This table for Reliance Industries Limited shows a dividend payment of 9.00 on August 21, 2023. Notice the "Close" and "Adj Close" columns. While the closing price dropped from 2,520 to 2,516.95 the next day, the adjusted close accounts for the dividend payment to create a more accurate representation of return.

A naive backtest would see this price drop as a capital loss. However, the shareholder's total wealth didn't change—the loss in stock value was offset by the cash received. To correctly model historical returns, we must adjust for this.

A simple subtraction of the dividend from all prior prices is incorrect and can lead to nonsensical results like negative prices over long periods. The correct method, used by professional data providers, involves applying a multiplicative factor. The blog post "Analyzing intraday and overnight stock returns with pandas" provides an excellent, code-centric walkthrough of this exact process.

Analyzing intraday and overnight stock returns with pandas

This article provides a deep dive into the correct, industry-standard method for adjusting prices for dividends, complete with a vectorized Python implementation.

Read the section "Actually calculating dividends". This section is critical. It first explains why a naive subtraction approach is wrong. Then, it details the standardized CRSP method: Calculate the factor: On each dividend's ex-date, the factor is calculated as \text{factor} = 1 - (\frac{\text{dividend}}{\text{price}}), where price is the closing price on the day before the ex-date. Apply the factor: This factor is applied to all historical prices prior to this ex-date. Accumulate factors: For dates in the distant past, multiple dividend adjustment factors are multiplied together (cumprod in Pandas) to create a single cumulative factor. The author provides clear Pandas code for a vectorized implementation, which aligns perfectly with the need to process large datasets efficiently.

The key takeaway is that both splits and dividends are handled by applying a cumulative product of adjustment factors backwards in time. This ensures that the adjusted price series represents the total return of the investment, which is the only valid basis for testing a trading strategy.


The Practical Solution: Let Your Data Provider Do the Work

Understanding the theory is vital for diagnosing data issues. However, when building your system, you rarely need to perform these calculations yourself. Your proficiency in Python can be leveraged by using libraries that handle this automatically.

Most reputable financial data providers offer both raw prices and adjusted prices. The yfinance library for Python makes accessing this incredibly simple.

The following short clip from QuantInsti demonstrates the easiest way to get fully adjusted data.

Get Stock Market Data using Python - Everything you should know!

This video explains the difference between close and adjusted close and shows the parameter needed to get fully adjusted data in Python.

Watch from the explanation of adjusted close prices. The key is the auto_adjust=True parameter in the yfinance.download() function. Setting this to True tells the library to download data where not only the 'Close' price but all OHLC columns have been correctly adjusted for both splits and dividends.

When you use auto_adjust=True, yfinance returns a DataFrame with the OHLCV data already adjusted using the standardized methods we've just discussed. It also removes the Dividends and Stock Splits columns, as their effects are already baked into the prices.

For backtesting the logic of a strategy, you should always use this fully adjusted price series.


Conclusion

In this lesson, we completed the final, critical step of data preparation: adjusting for corporate actions. An unadjusted price series is deceptive and will doom any backtest to failure.

Here are the key takeaways:

  • Corporate actions like stock splits and dividends create artificial price jumps in raw historical data.
  • Stock splits are corrected by multiplying all prior prices by a ratio factor (e.g., 0.5 for a 2-for-1 split).
  • Dividends are corrected by applying a cumulative multiplicative factor, calculated as , backwards in time.
  • The goal of adjustment is to create a continuous total return series, which is the only valid foundation for backtesting strategy performance.
  • In practice, you can use a library like yfinance with the auto_adjust=True setting to automatically receive a fully adjusted and clean dataset.

We now have a pristine, research-ready price series. It is clean, time-aligned, and correctly adjusted. With this solid foundation, we can finally begin calculating meaningful metrics. In our next lesson, we will use this data to measure one of the most fundamental concepts in finance: historical and rolling volatility.