From 3cfacff6859ca6e172fc3f1c20158e49165b16de Mon Sep 17 00:00:00 2001 From: Vlad Obukhanich Date: Sun, 27 Jan 2019 16:33:10 -0500 Subject: [PATCH] Add an Alpha Factor Library Add a library where we store the alpha factors and pipelines we have created or borrowed/adapted from research papers in the past. --- bualpha-factor-and-pipeline-lib.ipynb | 194 ++++++++++++++++++++++++++ 1 file changed, 194 insertions(+) create mode 100644 bualpha-factor-and-pipeline-lib.ipynb diff --git a/bualpha-factor-and-pipeline-lib.ipynb b/bualpha-factor-and-pipeline-lib.ipynb new file mode 100644 index 0000000..b12bc12 --- /dev/null +++ b/bualpha-factor-and-pipeline-lib.ipynb @@ -0,0 +1,194 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# BU Alpha: Factor & Pipeline Library" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## > Alpha Source #1: Buyback Announcements\n", + "### *^based on a strategy proposed by Shahram Amini and Vijay Singal in the \"Are Earnings Predictable? Evidence from Equity Issues and Buyback Announcements\" paper (November 21, 2018)*" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Libraries to import:**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "from quantopian.pipeline import Pipeline\n", + "from quantopian.pipeline.data.eventvestor import BuybackAuthorizations\n", + "\n", + "from quantopian.pipeline.factors.eventvestor import (\n", + " BusinessDaysSinceBuybackAuth,\n", + " BusinessDaysSincePreviousEarnings,\n", + ")\n", + "\n", + "from quantopian.pipeline.data import Fundamentals" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**BB (Buyback) Pipeline defined:**" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def make_BB_pipe(context):\n", + " BB_pipe = Pipeline()\n", + " \n", + " # add BB factors to BB Pipeline\n", + " BB_pipe.add(BuybackAuthorizations.previous_date.latest, \"previous_date\")\n", + " \n", + " BB_pipe.add(BuybackAuthorizations.previous_amount.latest, \"previous_amount\")\n", + " \n", + " BB_pipe.add(BuybackAuthorizations.previous_unit.latest, \"previous_unit\")\n", + "\n", + " BB_pipe.add(BusinessDaysSinceBuybackAuth(), \"business_days_since_buyback\")\n", + "\n", + " BB_pipe.add(BusinessDaysSincePreviousEarnings(), \"business_days_since_earnings\")\n", + "\n", + " # add fundamental factors to BB Pipeline\n", + " BB_pipe.add(Fundamentals.market_cap.latest, \"market_cap\")\n", + " \n", + " BB_pipe.add(Fundamentals.shares_outstanding.latest, \"shares_outstanding\") \n", + " \n", + " # filter out share buybacks of less than 5% of shares outstanding, or dollar buybacks \n", + " # of less than 5% of market cap\n", + " significant_buyback = (BuybackAuthorizations.previous_amount.latest*mil >= BB_min_pcntg*Fundamentals.market_cap.latest) if BuybackAuthorizations.previous_unit.latest == '$M' else (BuybackAuthorizations.previous_amount.latest*mil >= BB_min_pcntg*Fundamentals.shares_outstanding.latest)\n", + " \n", + " # filter out buybacks that occurred less than 2 days prior to the most recent # earnings announcement\n", + " not_recent_buyback = BusinessDaysSinceBuybackAuth() - BusinessDaysSincePreviousEarnings() >= 2\n", + " \n", + " BB_pipe.set_screen(base_universe & significant_buyback & not_recent_buyback)\n", + " \n", + " return BB_pipe" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## > Alpha Source #2: Secondary Equity Offerings (SEOs)\n", + "### *^based on a strategy proposed by Shahram Amini and Vijay Singal in the \"Are Earnings Predictable? Evidence from Equity Issues and Buyback Announcements\" paper (November 21, 2018)*" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**Libraries to import:**" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "from quantopian.pipeline import Pipeline\n", + "from quantopian.pipeline.data.eventvestor import IssueEquityAnnouncements\n", + "\n", + "from quantopian.pipeline.factors.eventvestor import (\n", + " BusinessDaysSinceIssueEquityAnnouncement,\n", + " BusinessDaysSincePreviousEarnings,\n", + ")\n", + "\n", + "from quantopian.pipeline.data import Fundamentals" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "**SEO Pipeline defined:**" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def make_SEO_pipe(context):\n", + " SEO_pipe = Pipeline()\n", + " \n", + " # add SEO factors to SEO Pipeline\n", + " SEO_pipe.add(IssueEquityAnnouncements.announcement_date.latest, \"previous_date\")\n", + " \n", + " SEO_pipe.add(IssueEquityAnnouncements.issue_amount.latest, \"previous_amount\")\n", + " \n", + " SEO_pipe.add(IssueEquityAnnouncements.issue_units.latest, \"previous_unit\")\n", + " \n", + " SEO_pipe.add(BusinessDaysSinceIssueEquityAnnouncement(), \"business_days_since_equity_issuance\")\n", + " \n", + " SEO_pipe.add(BusinessDaysSincePreviousEarnings(), \"business_days_since_earnings\")\n", + " \n", + " # add fundamental factors to SEO Pipeline\n", + " SEO_pipe.add(Fundamentals.market_cap.latest, \"market_cap\")\n", + "\n", + " SEO_pipe.add(Fundamentals.shares_outstanding.latest, \"shares_outstanding\")\n", + " \n", + " # filter out share SEOs of less than 10% of shares outstanding, or dollar SEOs of less \n", + " # than 10% of market cap\n", + " significant_SEO = (IssueEquityAnnouncements.issue_amount.latest*mil >= SEO_min_pcntg*Fundamentals.market_cap.latest) if IssueEquityAnnouncements.issue_units.latest == '$M' else (IssueEquityAnnouncements.issue_amount.latest*mil >= SEO_min_pcntg*Fundamentals.shares_outstanding.latest)\n", + " \n", + " # filter out SEOs that occurred less than 2 days prior to the most recent earnings \n", + " # announcement \n", + " not_recent_SEO = BusinessDaysSinceIssueEquityAnnouncement() - BusinessDaysSincePreviousEarnings() >= 2\n", + " \n", + " SEO_pipe.set_screen(base_universe & significant_SEO & not_recent_SEO)\n", + " \n", + " return SEO_pipe" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}