EventVestor: Mergers and Acquisitions

In this notebook, we'll take a look at EventVestor's Mergers and Acquisitions dataset, available on the Quantopian Store. This dataset spans January 01, 2007 through the current day.

Notebook Contents

There are two ways to access the data and you'll find both of them listed below. Just click on the section you'd like to read through.

  • Interactive overview: This is only available on Research and uses blaze to give you access to large amounts of data. Recommended for exploration and plotting.
  • Pipeline overview: Data is made available through pipeline which is available on both the Research & Backtesting environment. Recommended for custom factor development and moving back & forth between research/backtesting.

Free samples and limits

One key caveat: we limit the number of results returned from any given expression to 10,000 to protect against runaway memory usage. To be clear, you have access to all the data server side. We are limiting the size of the responses back from Blaze.

There is a free version of this dataset as well as a paid one. The free sample includes data until 2 months prior to the current date.

To access the most up-to-date values for this data set for trading a live algorithm (as with other partner sets), you need to purchase acess to the full set.

With preamble in place, let's get started:

Interactive Overview

Accessing the data with Blaze and Interactive on Research

Partner datasets are available on Quantopian Research through an API service known as Blaze. Blaze provides the Quantopian user with a convenient interface to access very large datasets, in an interactive, generic manner.

Blaze provides an important function for accessing these datasets. Some of these sets are many millions of records. Bringing that data directly into Quantopian Research directly just is not viable. So Blaze allows us to provide a simple querying interface and shift the burden over to the server side.

It is common to use Blaze to reduce your dataset in size, convert it over to Pandas and then to use Pandas for further computation, manipulation and visualization.

Helpful links:

Once you've limited the size of your Blaze object, you can convert it to a Pandas DataFrames using:

from odo import odo
odo(expr, pandas.DataFrame)

To see how this data can be used in your algorithm, search for the Pipeline Overview section of this notebook or head straight to Pipeline Overview


In [1]:
# import the dataset
from quantopian.interactive.data.eventvestor import mergers_and_acquisitions_free as dataset

# or if you want to import the free dataset, use:
#from quantopian.data.eventvestor import buyback_auth_free

# import data operations
from odo import odo
# import other libraries we will use
import pandas as pd
import matplotlib.pyplot as plt

In [2]:
# Let's use blaze to understand the data a bit using Blaze dshape()
dataset.dshape


Out[2]:
dshape("""var * {
  event_id: float64,
  mna_type: ?string,
  trade_date: ?datetime,
  symbol: string,
  event_type: ?string,
  event_headline: ?string,
  news_type: ?string,
  firm_type: ?string,
  payment_mode: ?string,
  target_type: ?string,
  is_crossboarder: ?string,
  deal_amount: float64,
  deal_currency: ?string,
  related_ticker: ?string,
  related_entity: ?string,
  event_rating: float64,
  price_pershare: float64,
  premium_pct: float64,
  sid: int64,
  asof_date: datetime,
  timestamp: datetime
  }""")

In [3]:
# And how many rows are there?
# N.B. we're using a Blaze function to do this, not len()
dataset.count()


Out[3]:
16875

In [4]:
dataset.asof_date.min()


Out[4]:
Timestamp('2007-01-01 00:00:00')

In [5]:
# Let's see what the data looks like. We'll grab the first three rows.
dataset[:3]


Out[5]:
event_id mna_type trade_date symbol event_type event_headline news_type firm_type payment_mode target_type is_crossboarder deal_amount deal_currency related_ticker related_entity event_rating price_pershare premium_pct sid asof_date timestamp
0 148664 Acquisition 2007-01-03 FCS M&A Announcement Fairchild Semiconductor to Acquire System Gene... Announcement Acquirer Mixed Offer Public Cross Border 200 $M None System General Corporatio 1 0 0 20486 2007-01-01 2007-01-02
1 132422 Acquisition 2007-01-03 NUE M&A Announcement Nucor to Acquire Harris Steel Group for $1B Announcement Acquirer Cash Offer Public Cross Border 1070 $M None Harris Steel Group 1 0 0 5488 2007-01-02 2007-01-03
2 134823 Acquisition 2007-01-03 BNI M&A Announcement Burlington Northern Unit Acquires Pro-Am Trans... Announcement Acquirer None Private National 0 None None Pro-Am Transportation Ser 1 0 0 995 2007-01-02 2007-01-03

In [6]:
dataset.is_crossboarder.distinct()


Out[6]:
is_crossboarder
0 None
1 National
2 Other
3 Cross Border

Let's go over the columns:

  • event_id: the unique identifier for this buyback authorization.
  • asof_date: EventVestor's timestamp of event capture.
  • trade_date: for event announcements made before trading ends, trade_date is the same as event_date. For announcements issued after market close, trade_date is next market open day.
  • symbol: stock ticker symbol of the affected company.
  • event_type: this should always be Buyback.
  • event_headline: a short description of the event.
  • timestamp: this is our timestamp on when we registered the data.
  • sid: the equity's unique identifier. Use this instead of the symbol.
  • news_type: the type of news - Announcement, Close, Proposal, Termination, Rumor, Rejection, None
  • firm_type: either Target or Acquirer
  • payment_mode: the type of offer made - Mixed Offer, Cash Offer, Other, Stock Offer, None
  • target_type: Public, Private, PE Holding, VC Funded, None
  • is_crossboarder: None, National, Other, Cross Border
  • deal_amount, deal_currency: the amount of the deal and its corresponding currency
  • related_ticker: if present, this indicates the ticker being acquired or that is acquiring
  • price_pershare, premium_pct: the price per share and the premium paid

We've done much of the data processing for you. Fields like timestamp and sid are standardized across all our Store Datasets, so the datasets are easy to combine. We have standardized the sid across all our equity databases.

We can select columns and rows with ease. Below, we'll fetch all entries for Microsoft. We're really only interested in the buyback amount, the units, and the date, so we'll display only those columns.


In [7]:
# get the sid for MSFT
symbols('MSFT')


Out[7]:
Equity(5061, symbol=u'MSFT', asset_name=u'MICROSOFT CORP', exchange=u'NASDAQ', start_date=Timestamp('2002-01-01 00:00:00+0000', tz='UTC'), end_date=Timestamp('2016-09-06 00:00:00+0000', tz='UTC'), first_traded=None, auto_close_date=Timestamp('2016-09-09 00:00:00+0000', tz='UTC'), exchange_full=u'NASDAQ GLOBAL SELECT MARKET')

In [8]:
# knowing that the MSFT sid is 5061:
msft = dataset[dataset.sid==5061]
msft[:5]


Out[8]:
event_id mna_type trade_date symbol event_type event_headline news_type firm_type payment_mode target_type is_crossboarder deal_amount deal_currency related_ticker related_entity event_rating price_pershare premium_pct sid asof_date timestamp
0 78373 Acquisition 2007-05-25 MSFT M&A Announcement Microsoft to Acquire aQuantive for $6B Announcement Acquirer Cash Offer Public National 6000 $M AQNT None 1 0.00 0 5061 2007-05-24 2007-05-25
1 78370 None 2007-08-13 MSFT M&A Announcement Microsoft Completes Acquisition of aQuantive, ... Close None None None None 0 None None None 1 0.00 0 5061 2007-08-13 2007-08-14
2 125294 Acquisition 2007-11-12 MSFT M&A Announcement Microsoft Intends to Acquire Musiwave Announcement Acquirer Cash Offer Private Cross Border 0 None None Musiwave SA 1 0.00 0 5061 2007-11-12 2007-11-13
3 134224 None 2007-12-12 MSFT M&A Announcement Microsoft Completes Acquisition of UK based Mu... Close None None None None 0 None None Multimap 1 0.00 0 5061 2007-12-12 2007-12-13
4 137589 Acquisition 2008-01-08 MSFT M&A Announcement Microsoft to Acquire Norway's Fast Search for ... Announcement Acquirer Cash Offer Public Cross Border 1200 $M FAST Fast Search & Transfer AS 1 3.54 42 5061 2008-01-08 2008-01-09

Pipeline Overview

Accessing the data in your algorithms & research

The only method for accessing partner data within algorithms running on Quantopian is via the pipeline API.

There are a few factors available using the M&A dataset through Pipeline. They allow you to identify securities that are the current target of an acquisition. You can also view the payment mode used in the offer as well as the number of business days since the offer was made.


In [9]:
# Import necessary Pipeline modules
from quantopian.pipeline import Pipeline
from quantopian.research import run_pipeline
from quantopian.pipeline.factors import AverageDollarVolume

Filtering out ANNOUNCED targets

The following code below shows you how to filter out targets of acquisitions.


In [11]:
from quantopian.pipeline.classifiers.eventvestor import (
    AnnouncedAcqTargetType,
    ProposedAcqTargetType,
)
from quantopian.pipeline.factors.eventvestor import (
    BusinessDaysSinceAnnouncedAcquisition,
    BusinessDaysSinceProposedAcquisition
)
from quantopian.pipeline.filters.eventvestor import (
    IsAnnouncedAcqTarget
)

from quantopian.pipeline import Pipeline
from quantopian.research import run_pipeline
    
def screen_ma_targets_by_type(target_type='cash'):
    """
    target_type:
        (string) Available options are 'cash', 'stock', 'mixed', 'all'.
        This will filter all offers of type target_type.
    """
    if target_type == 'all':
        return (~IsAnnouncedAcqTarget())
    else:
        if target_type == 'cash':
            filter_offer = 'Cash Offer'
        elif target_type == 'stock':
            filter_offer = 'Stock Offer'
        elif target_type == 'mixed':
            filter_offer = 'Mixed Offer'
        return (~AnnouncedAcqTargetType().eq(filter_offer))
    
def screen_ma_targets_by_days(days=200):
    """
    days:
        (int) Filters out securities that have had an announcement
        less than X days. So if days is 200, all securities
        that have had an announcement less than 200 days ago will be
        filtered out.
    """
    b_days = BusinessDaysSinceAnnouncedAcquisition()
    return ((b_days > days) | b_days.isnull())

pipe = Pipeline(
    columns={
            'AnnouncedAcqTargetType': AnnouncedAcqTargetType(),
            'BusinessDays': BusinessDaysSinceAnnouncedAcquisition()
            },
    screen=(screen_ma_targets_by_days(60) &
            screen_ma_targets_by_type(target_type='stock'))
)

output = run_pipeline(pipe, start_date='2016-07-28', end_date='2016-07-28')

Filtering out PROPOSED targets

If you'd also like to filter out proposed targets, please view below


In [12]:
"""
Similar functions for M&A Proposals (different from Announcements)
"""

def screen_ma_proposal_targets_by_type(target_type='cash'):
    """
    target_type:
        (string) Available options are 'cash', 'stock', 'mixed', 'all'.
        This will filter all offers of type target_type.
    """
    if target_type == 'all':
        return (ProposedAcqTargetType().isnull() &
                BusinessDaysSinceProposedAcquisition().isnull())
    if target_type == 'cash':
        filter_offer = 'Cash Offer'
    elif target_type == 'stock':
        filter_offer = 'Stock Offer'
    elif target_type == 'mixed':
        filter_offer = 'Mixed Offer'
    return (~ProposedAcqTargetType().eq(filter_offer))
    
def screen_ma_proposal_targets_by_days(days=200):
    """
    days:
        (int) Filters out securities that have had an announcement
        less than X days. So if days is 200, all securities
        that have had an announcement less than 200 days ago will be
        filtered out.
    """
    b_days = BusinessDaysSinceProposedAcquisition()
    return ((b_days > days) | b_days.isnull())