$npx -y skills add himself65/finance-skills --skill earnings-recapGenerate a post-earnings analysis for any stock using Yahoo Finance data. Use when the user wants to review what happened after earnings, understand beat/miss results, see stock reaction, or get an earnings recap. Triggers: "AAPL earnings recap", "how did TSLA earnings go", "MSFT
| 1 | # Earnings Recap Skill |
| 2 | |
| 3 | Generates a post-earnings analysis using Yahoo Finance data via [yfinance](https://github.com/ranaroussi/yfinance). Covers the actual vs estimated numbers, surprise magnitude, stock price reaction, and financial context — a complete picture of what happened. |
| 4 | |
| 5 | **Important**: Data is for research and educational purposes only. Not financial advice. yfinance is not affiliated with Yahoo, Inc. |
| 6 | |
| 7 | --- |
| 8 | |
| 9 | ## Step 1: Ensure yfinance Is Available |
| 10 | |
| 11 | **Current environment status:** |
| 12 | |
| 13 | ``` |
| 14 | !`python3 -c "import yfinance; print('yfinance ' + yfinance.__version__ + ' installed')" 2>/dev/null || echo "YFINANCE_NOT_INSTALLED"` |
| 15 | ``` |
| 16 | |
| 17 | If `YFINANCE_NOT_INSTALLED`, install it: |
| 18 | |
| 19 | ```python |
| 20 | import subprocess, sys |
| 21 | subprocess.check_call([sys.executable, "-m", "pip", "install", "-q", "yfinance"]) |
| 22 | ``` |
| 23 | |
| 24 | If already installed, skip to the next step. |
| 25 | |
| 26 | --- |
| 27 | |
| 28 | ## Step 2: Identify the Ticker and Gather Data |
| 29 | |
| 30 | Extract the ticker from the user's request. Fetch all relevant post-earnings data in one script. |
| 31 | |
| 32 | ```python |
| 33 | import yfinance as yf |
| 34 | import pandas as pd |
| 35 | from datetime import datetime, timedelta |
| 36 | |
| 37 | ticker = yf.Ticker("AAPL") # replace with actual ticker |
| 38 | |
| 39 | # --- Earnings result --- |
| 40 | earnings_hist = ticker.earnings_history |
| 41 | |
| 42 | # --- Financial statements --- |
| 43 | quarterly_income = ticker.quarterly_income_stmt |
| 44 | quarterly_cashflow = ticker.quarterly_cashflow |
| 45 | quarterly_balance = ticker.quarterly_balance_sheet |
| 46 | |
| 47 | # --- Price reaction --- |
| 48 | # Get ~30 days of history to capture the reaction window |
| 49 | hist = ticker.history(period="1mo") |
| 50 | |
| 51 | # --- Context --- |
| 52 | info = ticker.info |
| 53 | news = ticker.news |
| 54 | recommendations = ticker.recommendations |
| 55 | ``` |
| 56 | |
| 57 | ### What to extract |
| 58 | |
| 59 | | Data Source | Key Fields | Purpose | |
| 60 | |---|---|---| |
| 61 | | `earnings_history` | epsEstimate, epsActual, epsDifference, surprisePercent | Beat/miss result | |
| 62 | | `quarterly_income_stmt` | TotalRevenue, GrossProfit, OperatingIncome, NetIncome, BasicEPS | Actual financials | |
| 63 | | `history()` | Close prices around earnings date | Stock price reaction | |
| 64 | | `info` | currentPrice, marketCap, forwardPE | Current context | |
| 65 | | `news` | Recent headlines | Earnings-related news | |
| 66 | |
| 67 | --- |
| 68 | |
| 69 | ## Step 3: Determine the Most Recent Earnings |
| 70 | |
| 71 | The most recent earnings result is the first row (most recent date) in `earnings_history`. Use its date to: |
| 72 | |
| 73 | 1. **Identify the earnings date** for the price reaction analysis |
| 74 | 2. **Match to the corresponding quarter** in the financial statements |
| 75 | 3. **Calculate stock price reaction** — compare the close before earnings to the next trading day's close (or open, depending on whether earnings were before/after market) |
| 76 | |
| 77 | ### Price reaction calculation |
| 78 | |
| 79 | ```python |
| 80 | import numpy as np |
| 81 | |
| 82 | # Find the earnings date from earnings_history index |
| 83 | earnings_date = earnings_hist.index[0] # most recent |
| 84 | |
| 85 | # Get daily prices around the earnings date |
| 86 | hist_extended = ticker.history(start=earnings_date - timedelta(days=5), |
| 87 | end=earnings_date + timedelta(days=5)) |
| 88 | |
| 89 | # The reaction is typically measured as: |
| 90 | # - Close on the last trading day before earnings -> Close on the first trading day after |
| 91 | # Be careful with before/after market reports |
| 92 | if len(hist_extended) >= 2: |
| 93 | pre_price = hist_extended['Close'].iloc[0] |
| 94 | post_price = hist_extended['Close'].iloc[-1] |
| 95 | reaction_pct = ((post_price - pre_price) / pre_price) * 100 |
| 96 | ``` |
| 97 | |
| 98 | **Note**: The exact reaction window depends on when the company reported (before market open vs after close). The price data will reflect this — look for the biggest gap between consecutive closes near the earnings date. |
| 99 | |
| 100 | --- |
| 101 | |
| 102 | ## Step 4: Build the Earnings Recap |
| 103 | |
| 104 | ### Section 1: Headline Result |
| 105 | |
| 106 | Lead with the key numbers: |
| 107 | - **EPS**: Actual vs. Estimate, beat/miss by how much, surprise % |
| 108 | - **Revenue**: Actual vs. prior year (from quarterly_income_stmt TotalRevenue) |
| 109 | - **Stock reaction**: % move on earnings day |
| 110 | |
| 111 | Example: "AAPL beat Q3 EPS estimates by 3.7% ($1.40 actual vs $1.35 expected). Revenue grew 5.4% YoY to $94.3B. The stock rose +2.1% on the report." |
| 112 | |
| 113 | ### Section 2: Earnings vs. Estimates Detail |
| 114 | |
| 115 | | Metric | Estimate | Actual | Surprise | |
| 116 | |---|---|---|---| |
| 117 | | EPS | $1.35 | $1.40 | +$0.05 (+3.7%) | |
| 118 | |
| 119 | If the user asked about a specific quar |