Generated banner for Earnings Recap
Generated logo for Earnings Recap

Earnings Recap

Alex YangCommunityCreated by Alex Yang

  • Skill
  • Content generator
  • Data and AI
  • MIT
  • No issues found

From the author

Analyze a company's most recent (or a specified past) earnings report from Yahoo Finance data (yfinance): actual vs estimated EPS, surprise size, revenue and margin trends, and the stock's price reaction. Use this skill whenever the user asks how earnings went — beat or miss, earnings surprise, quarterly results, the post-earnings move, or an earnings call recap — including casual references to a past report such as "AMZN reported last night" or "how did they do". For an upcoming report, use earnings-preview.
— the description by Alex Yang

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

The earnings-recap skill provides a structured analysis of a company's recent earnings performance. By leveraging the yfinance library, it retrieves historical earnings data, financial statements, and price history to synthesize a comprehensive report. It calculates key metrics such as EPS surprises, revenue trends, and profit margins, while also measuring the stock's price reaction to the announcement. This skill is designed to help users quickly understand the outcome of a quarterly report, providing a factual summary of the beat or miss and the subsequent market sentiment.

What it does

  • Fetches actual vs. estimated EPS and calculates the surprise percentage.
  • Analyzes quarterly revenue, gross margins, and operating margins.
  • Determines the stock's price reaction based on the earnings announcement timing.
  • Compares the recent price move against historical earnings-day volatility.
  • Provides context using recent news and current financial information.
  • Summarizes the overall financial trajectory and analyst sentiment.

When to use it

  • When a user asks about the results of a company's most recent earnings report.
  • To investigate whether a company beat or missed analyst expectations.
  • To understand how the market reacted to a specific quarterly announcement.
  • When reviewing the financial performance trends of a company over recent quarters.

Advantages

  • Automates the collection of disparate financial data points into a single summary.
  • Provides objective, data-driven insights into earnings surprises and price reactions.
  • Helps contextualize current performance against historical trends.
  • Saves time by programmatically identifying the correct reaction window for earnings announcements.

Usage examples

“How did Apple do in their latest earnings report?”
The agent retrieves AAPL's latest earnings data, compares the reported EPS to estimates, calculates the revenue growth, and reports the stock's price reaction.
“Did Microsoft beat earnings expectations last quarter?”
The agent identifies the most recent quarterly report for MSFT, extracts the EPS surprise data, and provides a summary of the beat or miss.

Install

  1. Download the skill as a ZIP:

    https://mp-staging.autogineer.com/agent-skills/himself65/earnings-recap/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip earnings-recap.zip -d .agents/skills

Documentation by Alex Yang

Earnings Recap Skill

If your host has not already executed the shell probes below (for example, in Codex), run the commands inside the ! wrappers with its shell tool before choosing a setup path. Use the actual output; if shell access is unavailable, report that limitation.

Generates a post-earnings analysis using Yahoo Finance data via yfinance. Covers the actual vs estimated numbers, surprise magnitude, stock price reaction, and financial context — a complete picture of what happened.

Important: Data is for research and educational purposes only. Not financial advice. yfinance is not affiliated with Yahoo, Inc.


Step 1: Ensure yfinance Is Available

Current environment status:

!`python3 -c "exec('try:\n import yfinance\n print(\'yfinance \' + yfinance.__version__ + \' installed\')\nexcept Exception:\n print(\'YFINANCE_NOT_INSTALLED\')')"`

If YFINANCE_NOT_INSTALLED, install it:

import subprocess, sys
subprocess.check_call([sys.executable, "-m", "pip", "install", "-q", "yfinance"])

If already installed, skip to the next step.


Step 2: Identify the Ticker and Gather Data

Extract the ticker from the user's request. Fetch all relevant post-earnings data in one script.

import yfinance as yf
import pandas as pd

ticker = yf.Ticker("AAPL")  # replace with actual ticker

# --- Earnings results ---
earnings_dates = ticker.get_earnings_dates(limit=12)  # report timestamps, newest first
earnings_hist = ticker.earnings_history               # last 4 quarters, indexed by fiscal quarter-end, oldest first

# --- Financial statements (about five quarters, newest first) ---
quarterly_income = ticker.quarterly_income_stmt
quarterly_cashflow = ticker.quarterly_cashflow
quarterly_balance = ticker.quarterly_balance_sheet

# --- Context ---
info = ticker.info
news = ticker.news
recommendations = ticker.recommendations
What to extract
Data SourceKey FieldsPurpose
get_earnings_dates()Earnings Date, EPS Estimate, Reported EPS, Surprise(%)Which report, when, and the beat/miss
earnings_historyepsEstimate, epsActual, epsDifference, surprisePercentLast four quarters' results by fiscal quarter
quarterly_income_stmtTotalRevenue, GrossProfit, OperatingIncome, NetIncome, BasicEPSActual financials
history()Daily closes around each reportStock price reaction
infocurrentPrice, marketCap, forwardPECurrent context
newsRecent headlinesEarnings-related news

Step 3: Find the Report and Measure the Reaction

earnings_history is indexed by fiscal quarter-end, not by announcement date, so take report timing from get_earnings_dates(): the most recent report is the newest row with a Reported EPS. Its timestamp (US Eastern) sets the reaction window: at or after 16:00 means the company reported after the close; anything earlier means before the open or, occasionally, during the session. If the user asked about a specific quarter, use that row instead.

def earnings_reaction(ticker, report_ts):
    """% move from the last close before the report to the first close after it."""
    daily = ticker.history(start=(report_ts - pd.Timedelta(days=10)).date(),
                           end=(report_ts + pd.Timedelta(days=10)).date())
    closes = daily["Close"]
    days = closes.index.date
    d = report_ts.date()
    if report_ts.hour >= 16:  # reported after the close: report-day close -> next close
        pre, post = closes[days <= d], closes[days > d]
    else:                     # before the open or intraday: prior close -> report-day close
        pre, post = closes[days < d], closes[days >= d]
    if pre.empty or post.empty:
        return None           # the reaction session hasn't closed yet
    return (post.iloc[0] / pre.iloc[-1] - 1) * 100

reported = earnings_dates[earnings_dates["Reported EPS"].notna()]
latest_ts = reported.index[0]
reaction_pct = earnings_reaction(ticker, latest_ts)

# Typical earnings-day move over the prior four reports
prior_moves = [earnings_reaction(ticker, ts) for ts in reported.index[1:5]]
avg_abs_move = pd.Series([abs(m) for m in prior_moves if m is not None]).mean()

If reaction_pct is None, the report came after the most recent close; say the regular-session reaction is still pending (an intraday history(..., prepost=True) call shows the after-hours move if the user wants it).


Step 4: Build the Earnings Recap

Cover these areas, leading with the result:

  1. Headline result — EPS actual vs estimate with the surprise %, revenue with year-over-year growth, and the stock's reaction.

  2. Estimates vs actuals — EPS estimate, actual, and surprise ($ and %) for the quarter in question.

  3. Quarterly trends — revenue, gross margin, operating margin, and EPS for the recent quarters, with margins computed from the statements (gross profit / revenue, operating income / revenue). yfinance usually returns about five quarters, so year-over-year growth is available for the latest quarter only (column 0 vs column 4); show sequential change for the others rather than inventing a comparison.

  4. Price reaction — the move in the reaction session, how it compares with the stock's average absolute earnings move over the prior four reports, and whether the stock has since held, given back, or extended the move.

  5. What changed — margin direction vs the prior quarter, any shift in the revenue growth trajectory, how this surprise compares with the company's usual pattern, and current analyst sentiment if available.


Step 5: Respond to the User

Open with the headline — which quarter, when it was reported, the beat or miss, revenue growth, and the reaction — then the supporting tables. Say what matters: whether this was a meaningful beat or a low bar cleared, and whether the trend is improving or deteriorating. Keep it factual and leave out investment recommendations.

Include the caveats that apply: Yahoo Finance data doesn't capture everything from the call (guidance, segment detail), revenue is compared year over year from the statements rather than against a revenue consensus, the price reaction can reflect a broader market move that day, and this is not financial advice.


Reference Files

  • references/api_reference.md — Detailed yfinance API reference for earnings history and financial statement methods

Read the reference file when you need exact method signatures or to handle edge cases in the financial data.

Files

references/api_reference.md

Earnings Recap — yfinance API Reference

Detailed reference for the yfinance methods used by the earnings-recap skill.


Earnings History

ticker.earnings_history

Returns a DataFrame with the last 4 quarters of actual vs estimated earnings:

Columns:

  • epsEstimate — consensus EPS estimate at the time of reporting

  • epsActual — reported EPS

  • epsDifference — actual minus estimate

  • surprisePercent — surprise as a percentage (decimal form: 0.037 = 3.7%)

Index (quarter) is the fiscal quarter-end date, sorted oldest first — the latest quarter is the last row. It is not the announcement date, so don't use it for the price-reaction window.


Earnings Dates

ticker.get_earnings_dates(limit=12)

Returns a DataFrame indexed by Earnings Date — tz-aware announcement timestamps (America/New_York), newest first, including the next scheduled report.

Columns: EPS Estimate, Reported EPS, Surprise(%) (already in percent, e.g. 6.74).

Usage for recap: the most recent report is the first row with a non-null Reported EPS. The timestamp's time of day (US Eastern) gives the reaction window — at or after 16:00 means the company reported after the close (reaction = report-day close → next session's close); anything earlier means before the open, or occasionally during the session (reaction = prior close → report-day close).


Quarterly Financial Statements

Income Statement
ticker.quarterly_income_stmt

Returns a DataFrame with financial line items as rows and quarter-end dates as columns (most recent first).

Key rows for earnings recap:

  • Total Revenue — top-line revenue

  • Cost Of Revenue — COGS

  • Gross Profit — revenue minus COGS

  • Operating Income — EBIT

  • Net Income — bottom line

  • Basic EPS — earnings per share (basic)

  • Diluted EPS — earnings per share (diluted)

  • EBITDA — if available

Margin calculations:

gross_margin = df.loc['Gross Profit'] / df.loc['Total Revenue']
operating_margin = df.loc['Operating Income'] / df.loc['Total Revenue']
net_margin = df.loc['Net Income'] / df.loc['Total Revenue']

YoY Growth:

# Columns are ordered most-recent-first; yfinance usually returns about five quarters
# Column 0 = latest quarter, column 4 = same quarter last year (if present)
revenue = df.loc['Total Revenue']
yoy_growth = (revenue.iloc[0] - revenue.iloc[4]) / abs(revenue.iloc[4]) if len(revenue) > 4 else None

Note: Column indexing depends on how many quarters are returned. Typically 4-5 quarters are available.

Cash Flow Statement
ticker.quarterly_cashflow

Key rows:

  • Operating Cash Flow — cash from operations

  • Capital Expenditure — capex

  • Free Cash Flow — OCF minus capex

Balance Sheet
ticker.quarterly_balance_sheet

Key rows:

  • Total Assets

  • Total Debt

  • Cash And Cash Equivalents

  • Total Stockholders Equity


Historical Prices

# Around a report timestamp from get_earnings_dates() (not an earnings_history index value)
from datetime import timedelta
hist = ticker.history(
    start=(earnings_date - timedelta(days=10)).date(),
    end=(earnings_date + timedelta(days=10)).date()
)

Returns DataFrame with: Open, High, Low, Close, Volume.

Price reaction calculation tips:

  • After-hours reporters: compare prior day's Close to next day's Open (gap) and next day's Close (full reaction)

  • Before-market reporters: compare prior day's Close to same day's Close

  • The biggest single-day |%change| near the earnings date is usually the reaction day

  • Volume spike confirms the reaction day


Company Info

ticker.info

Key fields for context:

  • shortName — company name

  • sector, industry

  • marketCap

  • currentPrice, previousClose

  • forwardPE, trailingPE

  • fiftyTwoWeekHigh, fiftyTwoWeekLow


News

ticker.news

Returns a list of dicts:

  • title — headline

  • link — URL

  • publisher — source name

  • providerPublishTime — unix timestamp

Filter for recent news around the earnings date for earnings-related headlines.


Recommendations

ticker.recommendations

Returns a DataFrame with columns: strongBuy, buy, hold, sell, strongSell.

Use the most recent row to show current analyst sentiment distribution. Compare to the prior period to detect any post-earnings sentiment shifts.


Error Handling

try:
    hist = ticker.earnings_history
    if hist is None or (hasattr(hist, 'empty') and hist.empty):
        print("No earnings history — ticker may not have reported recently")
except Exception as e:
    print(f"Error: {e}")

Common issues:

  • No earnings history: Company hasn't reported yet, or it's an ETF/fund

  • Missing financial statement rows: Not all companies report the same line items; check with .loc and handle KeyError

  • Quarterly alignment: Q-end dates in financial statements don't always align perfectly with calendar quarters; use the dates as-is from yfinance

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs Python

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Created by
Alex Yang
Publisher
Alex Yang (Community)
Source
himself65/finance-skills · plugins/market-analysis/skills/earnings-recap · commit a085078
Licence
MIT License (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Alex Yang.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download earnings-recap.zip