Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
QuantConnect
GitHub Repository: QuantConnect/Research
Path: blob/master/Topical/20200601_airlinebuybacks_research.ipynb
994 views
Kernel: Python 3

In response to COVID-19's impact, the airline industry negotiated for $25bn+ in federal bailout funds in Spring 2020. News reports contrasted the bailout, which will ultimately be funded by taxpayers, with the money airlines spent on share buybacks in the last few years.

This research notebook examines airline buybacks compared to Free Cash Flow and Operating Cash Flow for airlines in the last 5 years. While existing news reports have shared figures on the relationship between buybacks and the bailout for the airline industry, this notebook hopes to provide a granular view of the history of buybacks for each airline.

Using SmartInsider and Morningstar fundamentals data, we see that buybacks are a portion of free cash flow but less of operating cash flow. We encourage you to dig into the data for yourself and come to your conclusion on how preventable the airline bailout was, and what should be done going forward.

from QuantConnect.Data.Custom.SmartInsider import * import pandas as pd from datetime import datetime, timedelta qb = QuantBook()
# Assets to analyze usa_airlines = ["AAL", "ALGT", "ALK", "DAL", "HA", "JBLU", "LUV", "SAVE", "SKYW", "UAL"]
# Extract buybacks transactions history, per day, per ticker for the last 5 years usa_airline_transactions = [] for airline in usa_airlines: # Add usa_airlines equity since SmartInsiderIntention custom data requires an existing equity Symbol air = qb.AddEquity(airline, Resolution.Daily).Symbol air_transaction = qb.AddData(SmartInsiderTransaction, air).Symbol transactions_history = qb.History(SmartInsiderTransaction, air_transaction, timedelta(days=1827)) usa_airline_transactions.append(transactions_history)
# Concat lists of dataframes into one dataframe airline_df = pd.concat(usa_airline_transactions, sort=False) airline_df = airline_df[["usdvalue", "buybackdate", "tickersymbol"]] airline_df.head()
# Reset from multiindex to single index of airline tickers airline_df = airline_df.set_index('tickersymbol')
# Get the sum of hopeful words per day for all tickers totals_df = airline_df.groupby(level=0, axis=0).sum() totals_df
# Manually map 2020 airline bailout data to dataframe (source: https://www.forbes.com/sites/willhorton1/2020/04/15/how-the-us-is-distributing-airline-bailout-funds-in-covid-19-relief-deal/#14bea03163a1) bailouts = {"AAL":5810000000, "ALGT": 0, "ALK": 992000000, "DAL": 5400000000, "HA": 0, "JBLU": 936000000, "LUV": 3200000000, "SAVE": 0, "SKYW": 0, "UAL": 6000000000} totals_df['bailout'] = totals_df.index.map(bailouts) totals_df
# Plot the total of the buybacks for each airline over five years next to the 2020 bailout dollar amount import plotly.graph_objects as go tickers = totals_df.index.values.tolist() buybacks_usd = totals_df[['usdvalue']].values.tolist() buybacks_usd = [item for sublist in buybacks_usd for item in sublist] bailout = totals_df[['bailout']].values.tolist() bailout = [item for sublist in bailout for item in sublist] fig = go.Figure(data=[ go.Bar(name='Buybacks Over Last 5 Years', x=tickers, y=buybacks_usd, marker_color = 'rgb(138, 185, 211)'), go.Bar(name='2020 Bailout', x=tickers, y=bailout, marker_color = 'rgb(237, 193, 218)') ]) # Change the bar mode fig.layout = {'barmode':'group', 'title':'A Side-by-Side of Airline Buybacks & 2020 Airline Bailout', 'plot_bgcolor' : 'rgb(248, 247, 247)'} fig.show()
# Percentage of buybacks over five years compared to the 2020 bailout import plotly.graph_objects as go tickers = totals_df.index.values.tolist() # Transform into percentage from absolute numbers totals_df['total'] = totals_df['bailout'] totals_df['buyback_pct_bailout'] = (totals_df['usdvalue']/ totals_df['total']).round(2) buybacks_pct = totals_df[['buyback_pct_bailout']].values.tolist() buybacks_pct = [item for sublist in buybacks_pct for item in sublist] fig = go.Figure(data=[ go.Bar(name='Buybacks', x=tickers, y=buybacks_pct, marker_color = 'rgb(138, 185, 211)') ]) fig.layout = {'barmode':'group', 'title':'Buybacks Over 5 Years as a Percentage of 2020 Bailout', 'plot_bgcolor' : 'rgb(248, 247, 247)', 'yaxis': { 'tickformat': ',.0%', 'range': [0,3]}} fig.show()
# Buyback dollar values over the last 5 years by airline import plotly.express as px df = airline_df fig = px.scatter(df, x='buybackdate', y='usdvalue', range_x=['2018-05-14', '2020-05-16'], color=df.index) fig.layout = {'plot_bgcolor' : 'rgb(248, 247, 247)', 'title':'Buybacks Across 5 Years'} fig.show()
# Calculate Free Cash Flow and Operating Cash Flow over the last 5 years # FCFPerShare = Free Cash Flow / Average Diluted Shares Outstanding # CFOPerShare = Cash Flow from Operations / Average Diluted Shares Outstanding # Reqest fundamentals history number of shares diluted_average_shares = qb.GetFundamental(usa_airlines, "EarningReports.DilutedAverageShares.TwelveMonths", datetime(2015, 5, 18), datetime.now()) # Reqest fundamentals history Free Cash Flow per share fcf_per_share = qb.GetFundamental(usa_airlines, "ValuationRatios.FCFPerShare", datetime(2015, 5, 18), datetime.now()) # Calculate total Free Cash Flow dollar value fcf_df = diluted_average_shares.mul(fcf_per_share) # Reqest fundamentals history for Operating Cash Flow per share ocf_per_share = qb.GetFundamental(usa_airlines, "ValuationRatios.CFOPerShare", datetime(2015, 5, 18), datetime.now()) # Calculate total Operating Cash Flow dollar value ocf_df = diluted_average_shares.mul(ocf_per_share)
# Prepare Free Cash Flow and Operating Cash Flow data for cumulative sum over 5 years # The diluted_average_shares represented data from 12 months, so data is new per year # However data is delivered repeatedly per day, so there are duplicates that we need to drop years = ['2015-05-18', '2016-05-18', '2017-05-18', '2018-05-18', '2019-05-18', '2020-05-15'] fcf_df = fcf_df[fcf_df.index.isin(years)] ocf_df = ocf_df[ocf_df.index.isin(years)] fcf_df
totals_df['ocf_sum'] = ocf_df.sum(axis=0) totals_df['buyback_pct_ocf'] = totals_df['usdvalue']/totals_df['ocf_sum'] totals_df['fcf_sum'] = fcf_df.sum(axis=0) totals_df['buyback_pct_fcf'] = totals_df['usdvalue'] /totals_df['fcf_sum'] totals_df
# Plot 5 year Free Cash Flow and Operating Cash Flow per airline import plotly.graph_objects as go tickers = totals_df.index.values.tolist() fcf = totals_df[['fcf_sum']].values.tolist() fcf = [item for sublist in fcf for item in sublist] ocf = totals_df[['ocf_sum']].values.tolist() ocf = [item for sublist in ocf for item in sublist] fig = go.Figure(data=[ go.Bar(name='Free Cash Flow', x=tickers, y=fcf, marker_color = 'rgb(138, 185, 211)'), go.Bar(name='Operating Cash Flow', x=tickers, y=ocf, marker_color = 'rgb(237, 193, 218)') ]) fig.layout = {'barmode':'group', 'title':'Five Year Cumulative FCF, OCF', 'plot_bgcolor' : 'rgb(248, 247, 247)'} fig.show()
# Plot last five year buybacks per airline as a percentage of both Free Cash Flow and Operating Cash Flow import plotly.graph_objects as go tickers = totals_df.index.values.tolist() buybacks_pct_fcf = totals_df[['buyback_pct_fcf']].values.tolist() buybacks_pct_fcf = [item for sublist in buybacks_pct_fcf for item in sublist] buybacks_pct_ocf = totals_df[['buyback_pct_ocf']].values.tolist() buybacks_pct_ocf = [item for sublist in buybacks_pct_ocf for item in sublist] fig = go.Figure(data=[ go.Bar(name='Buybacks as a percentage of FCF', x=tickers, y=buybacks_pct_fcf, marker_color = 'rgb(138, 185, 211)'), go.Bar(name='Buybacks as a percentage of OCF', x=tickers, y=buybacks_pct_ocf, marker_color = 'rgb(237, 193, 218)') ]) fig.layout = {'barmode':'group', 'title':'Ratio of BuyBacks to Sum of FCF and Sum of OCF Since 2016', 'plot_bgcolor' : 'rgb(248, 247, 247)', 'yaxis': { 'tickformat': ',.0%', 'range': [-5,2]}} fig.show()