Name: Towards AI Legal Name: Towards AI, Inc. Description: Towards AI is the world's leading artificial intelligence (AI) and technology publication. Read by thought-leaders and decision-makers around the world. Phone Number: +1-650-246-9381 Email: pub@towardsai.net
228 Park Avenue South New York, NY 10003 United States
Website: Publisher: https://towardsai.net/#publisher Diversity Policy: https://towardsai.net/about Ethics Policy: https://towardsai.net/about Masthead: https://towardsai.net/about
Name: Towards AI Legal Name: Towards AI, Inc. Description: Towards AI is the world's leading artificial intelligence (AI) and technology publication. Founders: Roberto Iriondo, , Job Title: Co-founder and Advisor Works for: Towards AI, Inc. Follow Roberto: X, LinkedIn, GitHub, Google Scholar, Towards AI Profile, Medium, ML@CMU, FreeCodeCamp, Crunchbase, Bloomberg, Roberto Iriondo, Generative AI Lab, Generative AI Lab VeloxTrend Ultrarix Capital Partners Denis Piffaretti, Job Title: Co-founder Works for: Towards AI, Inc. Louie Peters, Job Title: Co-founder Works for: Towards AI, Inc. Louis-François Bouchard, Job Title: Co-founder Works for: Towards AI, Inc. Cover:
Towards AI Cover
Logo:
Towards AI Logo
Areas Served: Worldwide Alternate Name: Towards AI, Inc. Alternate Name: Towards AI Co. Alternate Name: towards ai Alternate Name: towardsai Alternate Name: towards.ai Alternate Name: tai Alternate Name: toward ai Alternate Name: toward.ai Alternate Name: Towards AI, Inc. Alternate Name: towardsai.net Alternate Name: pub.towardsai.net
5 stars – based on 497 reviews

Frequently Used, Contextual References

TODO: Remember to copy unique IDs whenever it needs used. i.e., URL: 304b2e42315e

Resources

Our 15 AI experts built the most comprehensive, practical, 90+ lesson courses to master AI Engineering - we have pathways for any experience at Towards AI Academy. Cohorts still open - use COHORT10 for 10% off.

Publication

Building Financial Reports With FinGPT and Claude 3.7 Sonnet
Latest   Machine Learning

Building Financial Reports With FinGPT and Claude 3.7 Sonnet

Author(s): Michalzarnecki

Originally published on Towards AI.

Building Financial Reports With FinGPT and Claude 3.7 Sonnet
Financial report generated for GameStop Corporation using approach end-to-end approach described in this article

Introduction

Large Language Models (LLMs) are powerful tools for generating summaries and analyses of source documents. Modern LLMs can even grasp nuances of financial jargon and concepts, understanding abstractions like stock valuations and liquidity ratios. However, keeping an LLM up-to-date with the latest financial data is challenging — retraining a model frequently to capture rapid market changes would demand enormous computational resources. Even the best reasoning model would struggle to stay current with real-time financial news if it relied solely on its training data.

The solution is to use model with good reasoning in financial area and augment it with fresh financial knowledge from reliable sources. In this article, we will walk through creating a Python-based pipeline (built on the open-source FinGPT framework) that generates a polished PDF report describing a company’s financial condition using up-to-date data. I leverage FinGPT for data processing and Anthropic’s Claude 3.7 Sonnet (via AWS Bedrock) for analysis and text generation.
All the code presented in this article can be found in GitHub repository forked from FinGPT framework.

Financial LLMs

The finance domain has its own terminology — terms like balance sheet assets/liabilities, liquidity ratio, P/E ratio, and EPS are commonplace. General-purpose LLMs can stumble on such domain-specific jargon or might hallucinate figures. Specialized financial LLMs like BllombergGPT and FinGPT are trained (or fine-tuned) on curated, finance‑specific text which helps them produce more accurate financial analysis. By focusing on financial corpora, these models reduce hallucinations and improve their ability to reason about financial ratios and concepts. In other words, a domain-specific model is less likely to confuse an income statement with a cash flow statement, and more likely to accurately discuss metrics like debt-to-equity or liquidity ratios.

The FinGPT Project

FinGPT is an open-source LLM-based framework tailored for finance. It’s essentially a collection of tools and components aimed at financial data analysis. Key parts of FinGPT include:

  • Financial LLMs — A finance-domain dedicated model (the FinGPT model on HuggingFacemedium.com) is provided, and the framework also allows plugging in other popular LLMs (GPT-4, LLaMa, Mistral, Claude, Gemini, Qwen, etc.) for the analysis.
  • Data Pipelines — Connectors and utilities to fetch data from financial news, SEC filings, price feeds, and other sources.
  • Adapters & LoRA Checkpoints — Lightweight fine-tuning components to adapt general models to the finance domain.
  • Task-Oriented Notebooks — Examples and workflows for specific use cases like sentiment-driven trading, and (relevant to this article) financial report analysis.
FinGPT framework from https://github.com/AI4Finance-Foundation/FinGPT/blob/master/figs/FinGPT_framework_20240301.png

In essence, FinGPT provides an end-to-end pipeline specialized for financial use-cases, filling a similar niche that a general framework like LangChain might fill for broader applications, but with finance-specific tools and knowledge built-in.

Source documents

To analyze a company’s financial condition, we primarily need three key documents from its annual report (Form 10-K):

  • Balance Sheet: Provides a snapshot of the company’s assets, liabilities, and equity at the end of the fiscal year, reflecting financial stability and capital structure.
conclusions related to company financial condition from balance sheet document
https://finance.yahoo.com/quote/GME/balance-sheet/
  • Income Statement: Details profitability over the fiscal year, listing revenues, expenses, and net income, which shows how well the company performed in terms of profit.
https://finance.yahoo.com/quote/GME/financials/
  • Cash Flow Statement: Tracks the actual cash inflows and outflows, , crucial for understanding liquidity and cash management.
https://finance.yahoo.com/quote/GME/cash-flow/

In addition, annual reports contain qualitative sections like the Management’s Discussion & Analysis (MD&A), where management explains the financial results and outlook. While our pipeline will also retrieve the MD&A text for completeness, our primary focus will be on the three financial statements above, which provide the quantitative foundation for analysis.

Application Overview

To get familiar with FinGPT framework and automate the creation of a financial reports, I’ve created fork on top of FinGPT. This custom FinGPT fork replaces OpenAI/GPT-4 calls with Anthropic’s Claude 3.7 Sonnet model (accessed via AWS Bedrock) and adjusts the prompting to have the model include actual figures from the statements verbatim in its output. By having Claude including the numbers from the source data directly in the analysis, it becomes much easier for us (and auditors) to verify accuracy by cross-checking those figures. In short, by using Claude’s advanced reasoning to generate the narrative we also make sure it’s grounded in the real numbers from the reports.

Application Architecture

Key components of the solution include:

  • SEC-API: Fetching annual reports (10-K forms) directly from the SEC’s EDGAR database.
  • Yahoo Finance API – for obtaining current and historical stock market data (share prices, market cap, etc.) to enrich the report with market context.
  • FinGPT: Processing and structuring raw financial data with the flow and prompts proposed in attached Jupyter notebook.
  • AWS Bedrock (Claude 3.7): for analyzing the structured data and generating precise textual commentary. Claude 3.7 is used here because of its strong reasoning abilities and an “extended thinking” mode that allows step-by-step, deterministic reasoning — ideal for calculating financial ratios like current ratio or debt-to-equity without error.
  • Reportlab PDF Builder: for assembling the final report as a polished PDF document with formatted text and charts.

High‑level architecture:

SEC API ──► 10‑K HTML/JSON ┌──────────────┐
Yahoo ► Market data ─────────► │ FinGPT │──┐
│ (data prep) │ │ pandas DF
└──────────────┘ │

Claude 3.7 via Bedrock
(analysis & narratives)


reportlab (layout) → PDF

Diving in the application code

The workflow for generating the financial report involves:

  1. Fetching and parsing raw data from SEC filings and Yahoo Finance.
  2. Structuring data into pandas DataFrames using FinGPT.
  3. Generating insightful textual analysis via Claude 3.7.
  4. Creating visually appealing and structured PDFs using Reportlab.

The SEC API provides the 10-K filing content, and Yahoo (or FinancialModelingPrep) provides market data. FinGPT then prepares this raw data (e.g., parsing tables into DataFrames). Claude 3.7, accessed through AWS Bedrock, takes the prepared data and produces analysis text. Finally, ReportLab formats the analysis and any visuals into a PDF report.

Prerequisites

  • Python 3.11 (the runtime environment for script/notebook).
  • AWS Bedrock — Specifically, an Anthropic Claude 3.7 Sonnet endpoint enabled in a supported region. Make sure your AWS IAM permissions allow invoking Bedrock models, and that you have Claude 3.7 enabled in the Bedrock Model Catalog for your region.
  • sec‑api — sign up for a free API key on the SEC-API site link to access SEC EDGAR filings (specifically, we’ll use it to fetch 10-K reports)
  • Jupyter Notebook or similar — The code can be run in a Jupyter notebook for convenience (DataSpell, VS Code, or any Python environment will work).

With these prerequisites satisfied, you can proceed to set up the project and run the analysis.

Step 1. Quick setup

First, clone the FinGPT repository fork and install the required dependencies:

git clone https://github.com/mzarnecki/FinGPT.git
cd FinGPT
pip install -r requirements.txt

Before running any code, create a local .env file (in the project’s root directory) to store your configuration secrets:

aws_access_key_id = YOUR_AWS_ACCESS_KEY_ID 
aws_secret_access_key = YOUR_AWS_SECRET_ACCESS_KEY
sec_api_key = YOUR_SECAPI_KEY

Replace YOUR_AWS_ACCESS_KEY_ID/YOUR_AWS_SECRET_ACCESS_KEY with your AWS credentials and YOUR_SECAPI_KEY with the key from SEC-API. These will be loaded by our script to authenticate with AWS Bedrock and SEC-API.

Step 2. Fetching Data with SEC-API and Yahoo Finance

With the environment set up, we can retrieve the latest financial filings and market data for our target company. In the code, you’ll specify a stock ticker symbol (for example, ticker_symbol = "TSLA" for Tesla) and use that to query data sources.

Fetching the 10-K filing from the SEC: We use the sec-api Python client to search the SEC’s EDGAR database for the latest annual report (Form 10-K) for the given ticker. The SEC-API provides a convenient query interface to find filings and then fetch their content. For example, the function below searches for the most recent 10-K and downloads its full text:

from sec_api import QueryApi, ExtractorApi

def get_10k_filing(ticker, api_key):
"""Fetch the latest 10-K filing for a given ticker."""

# Set up the SEC API client
client = SecApiClient(api_key)

# Search for the latest 10-K filing
query = {
"query": {
"query_string": {
"query": f"ticker:{ticker} AND formType:\"10-K\""
}
},
"from": "0",
"size": "1",
"sort": [{"filedAt": {"order": "desc"}}]
}

search_response = client.get_filings(query)

if not search_response['filings']:
raise ValueError(f"No 10-K filings found for {ticker}")

# Get the accession number from the search results
accession_number = search_response['filings'][0]['accessionNumber']

# Download the full text filing
filing_text = client.get_filing(accession_number)

return filing_text

In this snippet, we use the SEC-API client to retrieve the latest 10-K filing for the specified ticker. The query finds the most recent filing of type “10-K”, then we download the filing’s content (as HTML or text). The result filing_text will contain the entire annual report (often hundreds of pages long in HTML form).

In addition to the filing, we gather current market data to provide context in the report. Using Yahoo’s finance data (via the yfinance Python library), we can get information like recent stock prices, historical price trends, and valuation metrics. For example, we might retrieve the stock’s price history for the past year and the current market capitalization. This data can later be used to generate charts or to cite the stock’s performance relative to its financial results.

import yfinance as yf

stock = yf.Ticker('TSLA')
historical_data = stock.history(period="5y")
print(historical_data)
data from yfinance Python library using Yahoo finance API

By the end of this step, we have the raw textual content of the latest 10-K filing, along with supplementary market data for our company of interest.

Step 3. Processing Financial Statements

The 10-K filing text is lengthy and contains much more than just the financial statements. The next step is to extract the specific sections we care about — namely the Balance Sheet, Income Statement and Cash Flow Statement.

One approach is to use simple regex pattern matching on the filing text to isolate these sections. For example, if the filing is HTML or plain text, we can search for headings like “CONSOLIDATED BALANCE SHEET” and grab everything until the next section heading. Regular expressions are handy for this kind of extraction:

def extract_financial_statements(filing_text):
"""Extract key financial statements from the 10-K filing."""

# Extract Balance Sheet
balance_sheet_pattern = r"(?i)CONSOLIDATED BALANCE SHEETS?(.*?)(?=CONSOLIDATED STATEMENTS OF OPERATIONS|CONSOLIDATED STATEMENTS OF INCOME|$)"
balance_sheet_match = re.search(balance_sheet_pattern, filing_text, re.DOTALL)
balance_sheet = balance_sheet_match.group(1) if balance_sheet_match else ""

# Extract Income Statement
income_stmt_pattern = r"(?i)CONSOLIDATED STATEMENTS OF OPERATIONS(.*?)(?=CONSOLIDATED STATEMENTS OF COMPREHENSIVE|CONSOLIDATED BALANCE SHEETS|$)"
income_stmt_match = re.search(income_stmt_pattern, filing_text, re.DOTALL)
income_statement = income_stmt_match.group(1) if income_stmt_match else ""

# Extract Cash Flow Statement
cash_flow_pattern = r"(?i)CONSOLIDATED STATEMENTS OF CASH FLOWS(.*?)(?=NOTES TO CONSOLIDATED|$)"
cash_flow_match = re.search(cash_flow_pattern, filing_text, re.DOTALL)
cash_flow = cash_flow_match.group(1) if cash_flow_match else ""

# Extract MD&A Section
mda_pattern = r"(?i)ITEM\s*[7]\.\s*MANAGEMENT'S DISCUSSION AND ANALYSIS(.*?)(?=ITEM\s*[7A]|ITEM\s*[8]|$)"
mda_match = re.search(mda_pattern, filing_text, re.DOTALL)
mda = mda_match.group(1) if mda_match else ""

return {
'balance_sheet': balance_sheet,
'income_statement': income_statement,
'cash_flow': cash_flow,
'mda': mda
}

In this code, we define regex patterns for each section header and pull out the content that follows. For example, the balance sheet pattern looks for the phrase “Consolidated Balance Sheet” (case-insensitive) and captures everything until it hits “Consolidated Statements of Operations” (or end-of-file), which marks where the income statement section begins. Similarly, we isolate the Income Statement and Cash Flows sections. We also attempt to grab the MD&A (Management’s Discussion & Analysis) section by looking for “Item 7. Management’s Discussion and Analysis” up until “Item 7A” or “Item 8” (the next sections in a 10-K).

After running this function on the filing text, we get a dictionary sections with keys 'balance_sheet', 'income_statement', 'cash_flow', and 'mda'. Each of these contains the raw text (often HTML-formatted) of the respective section. For our analysis, the first three are most important, but having the MD&A text is a nice bonus (one could potentially feed it into the language model as well if needed for additional context).

Step 4. Shape the raw numbers

The extracted financial statement sections are still unstructured text (or HTML). To analyze numbers (like computing ratios or comparing year-over-year figures), it’s much easier to work with structured data. This is where FinGPT’s utilities come into play: FinGPT includes helper functions to parse and clean financial tables from filings. These functions can strip out units (like “M” for millions), handle missing values, and convert the HTML tables into pandas DataFrames.

parse_xbrl_to_df leverages FinGPT’s utilities to convert the raw HTML of each statement into a tidy pandas.DataFrame:

from fingpt.fin_reports import parse_xbrl_to_df
bs_df, is_df, cf_df = parse_xbrl_to_df(sections)Pyth

After this step, bs_df, is_df, and cf_df are pandas DataFrames containing the Balance Sheet, Income Statement, and Cash Flow statement data, respectively, in a structured form. Typically, the rows would be line items (e.g., “Total Current Assets”, “Net Income”, “Net Cash from Operating Activities”) and the columns might be the years (e.g., 2020, 2021, 2022) depending on how the filing presents the data. Now we have machine-readable numbers to feed into our analysis.

Step 5: Generating Analysis with Claude 3.7 via Bedrock

With clean financial data in hand, the next step is to have the language model analyze it. I use AWS Bedrock to access Claude 3.7 Sonnet. AWS Bedrock is a service that allows developers to call various foundation models (from providers like Anthropic, AI21, Stability, etc.) via a unified API. We have configured our AWS credentials in the .env and enabled Claude 3.7 in our account, so we can now programmatically invoke the model.

Why Claude 3.7? Claude 3.7 Sonnet is one of the most advanced LLMs available, known for its hybrid reasoning ability (combining chain-of-thought and self-consistency techniques). In practical terms, Claude can be instructed to perform step-by-step reasoning (“extended thinking”), which is very useful for financial analysis — it can do calculations or logical comparisons explicitly, reducing errors in things like ratio computation. It also has a large context window, meaning it can handle our financial statements (even if lengthy) plus additional data in one go.

Here’s set up of the Bedrock client and define a helper to call Claude:

### Generative AI with large language models available on AWS
def generate(prompt: str) -> str:
boto3_bedrock = boto3.client(
'bedrock-runtime',
aws_access_key_id=aws_access_key_id,
aws_secret_access_key=aws_secret_access_key,
region_name="eu-central-1"
)

body = json.dumps({
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 300,
"top_k": 250,
"stop_sequences": [],
"temperature": 0.1,
"top_p": 0.999,
"messages": [
{
"role": "user",
"content": [
{
"type": "text",
"text": prompt
}
]
}
]
})

# modelId is in Bedrock cross-region Inference section (https://eu-central-1.console.aws.amazon.com/bedrock/home?region=eu-central-1#/inference-profiles)
modelId = 'arn:aws:bedrock:eu-central-1:695938443023:inference-profile/eu.anthropic.claude-3-7-sonnet-20250219-v1:0'
contentType = 'application/json'
accept = 'application/json'
response = boto3_bedrock.invoke_model(body=body, modelId=modelId, accept=accept, contentType=contentType)
response_body = json.loads(response.get('body').read())

return response_body['content'][0]['text']

In the code above, we use Boto3 (AWS’s SDK for Python) to create a Bedrock runtime client. The modelId for Claude 3.7 Sonnet is specified, along with an antrophic version. We send our prompt in the body as a conversation with a single user message (since we’re using Claude in a single-turn question-answer fashion here).

Before calling Claude, we need to craft the prompt that we send to Claude. This prompt will include instructions or questions about the financial data. In our project, we followed the FinGPT notebook’s approach of using a system role prompt (to prime the model as an “Expert Financial Analyst”) and then separate prompts for each section of analysis (balance sheet analysis, income statement analysis, cash flow analysis, etc.). We’ll detail these prompts in the next section. For now, understand that for each analysis we will generate a text prompt that includes relevant data (or references to it) and asks Claude to produce an analysis paragraph.

(When using Bedrock, ensure that the region you specify supports the model you want (Claude 3.7 is available in select regions like us-east-1). Also, note that Bedrock usage will incur costs per invocation/token, though for our use-case the cost is relatively low given we only generate a few thousand tokens per report.)

Step 6: Assembling the PDF with ReportLab

Once Claude has generated the analysis text for each section, the final step is to compile everything into a well-formatted PDF report. We use ReportLab, a powerful Python library for PDF generation, to handle this. ReportLab allows precise control over document layout — we can add headings, paragraphs of text, images (for charts), spacers, tables, etc.

In the code, analysis outputs are taken (which we have stored in a dictionary, e.g., analysis_dict = { "Balance Sheet Analysis": bs_text, "Income Statement Analysis": is_text, ... }), and then PDF is created like so:

from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet

# Prepare PDF document
doc = SimpleDocTemplate(f"projects/{ticker_symbol}/{ticker_symbol}_report.pdf", pagesize=letter)
styles = getSampleStyleSheet()
story = []

# Add each section's analysis to the PDF story
for title, content in analysis_dict.items():
# Add section heading
story.append(Paragraph(f"<b>{title}</b>", styles['Heading2']))
# Convert markdown to HTML and add as paragraph text
story.append(Paragraph(markdown2html(content), styles['BodyText']))
story.append(Spacer(1, 12)) # add a bit of space after each section

doc.build(story)

Let’s break down what this does:

  • Create a SimpleDocTemplate for the PDF, specifying the output file path (in a projects/{ticker}/{ticker}_report.pdf directory) and page size (letter in this case, i.e., 8.5×11 inches)medium.commedium.com.
  • Get a sample stylesheet for consistent text styling.
  • Iterate over each section of our analysis. For each section (Balance Sheet Analysis, Income Statement Analysis, etc.), we add a heading (Heading2 style, bold) and then the content as a paragraph (BodyText style).
  • The content generated by Claude might contain some Markdown (for example, bullet points or italics) or at least plain text that we want to ensure is rendered with proper formatting. We use a helper markdown2html to convert any Markdown syntax in the content into HTML, which ReportLab’s Paragraph can understand (ReportLab’s Paragraph can take a subset of HTML for formatting).
  • Add a spacer (12 points of vertical space) after each section to keep the layout clean.
  • Finally, build the PDF with doc.build(story), which assembles all the elements into the final document.

In addition to the narrative text, thereport includes some visual elements. The code (in the FinGPT notebook) also generates charts for the “Share Performance” and “PE & EPS” sections mentioned in the outline of the report. This was done using matplotlib to plot the stock’s historical price and to illustrate the Price-to-Earnings ratio over time, for example. The generated charts are saved and then likely inserted into the PDF (possibly by adding an Image flowable from ReportLab). The specifics of that code aren’t shown here, but keep in mind that beyond textual analysis, adding such visual context can greatly enhance the usefulness of the report.

After this step, we have a complete PDF file created in the projects/{ticker}/ directory. Each section of analysis from Claude is included, and any charts or extra visuals have been appended. Now it’s time to run it and see the result.

Step 7: Run the Pipeline

Everything is set — data fetching, processing, analysis, and report assembly. To generate a report, we just need to specify our target company ticker and execute the pipeline.

In the Jupyter notebook, set for example:

ticker_symbol = "TSLA" # e.g., Tesla; or use "MSFT", "NVDA", "GME", etc.

…and then Run All cells. The code will fetch Tesla’s latest 10-K, parse the statements, query Claude 3.7 for analysis, and build the PDF. After a short wait, a fresh PDF will appear at projects/TSLA/TSLA_report.pdf.

You can repeat this process for any other stock ticker. For instance, if you change ticker_symbol = "GME" and rerun, you’ll get a report for GameStop Corp., and so on. Each run uses the same pipeline, so as long as the data is available, you can quickly generate reports for different companies.

Performance: In terms of speed, this automated pipeline is quite efficient. In our tests, the longest step was the Claude model inference — each Claude call took on the order of a few seconds. Since we call it four times (for three statements + one summary), the total model time was around ~12 seconds. Fetching data from SEC and Yahoo is relatively quick (a couple of seconds), and PDF generation is almost instantaneous. So overall, generating a full report typically completes in well under a minute. This shows that an LLM-powered analysis can be done in a short time with relatively low computational cost.

Next, let’s discuss the prompts we used for Claude in more detail, as they are key to guiding the model to produce the analysis we want.

Prompts from FinGPT

To get meaningful outputs from the LLM, carefully designing the prompts is crucial. The FinGPT project’s financial report analysis notebook provides a baseline set of prompts: one system prompt to establish the AI’s role, and four section prompts (one each for analyzing the Balance Sheet, Income Statement, Cash Flow, and a final summarization). We adapted these prompts slightly to fit Claude 3.7 and to emphasize clarity and numerical accuracy.

By adjusting the prompts to set expectations for output length and by instructing the model to incorporate direct figures from the data, we obtain concise, informative, and easy-to-verify results. In practice, this means we ask Claude to include the actual numbers (from the statements) in its explanations — so if it says “current ratio improved,” it will also say “current assets were $X and current liabilities $Y”. This makes it simple to trace every claim back to the source.

Below, we show the prompts used. We introduce a variable max_words_paragraph to control the length of each response (to avoid overly long answers), and in the balance sheet prompt, we opted to have the model analyze the last 3 years of data (instead of just the last year) to provide a longer-term perspective.

System prompt

"""
Role: Expert Investor
Department: Finance
Primary Responsibility: Generation of Customized Financial Analysis Reports

Role Description:
As an Expert Investor within the finance domain, your expertise is harnessed
to develop bespoke Financial Analysis Reports that cater to specific client
requirements. This role demands a deep dive into financial statements and
market data to unearth insights regarding a company's financial performance
and stability. Engaging directly with clients to gather essential information
and continuously refining the report with their feedback ensures the final
product precisely meets their needs and expectations.

Key Objectives:

Analytical Precision: Employ meticulous analytical prowess to interpret
financial data, identifying underlying trends and anomalies.
Effective Communication: Simplify and effectively convey complex financial
narratives, making them accessible and actionable to non-specialist audiences.
Client Focus: Dynamically tailor reports in response to client feedback,
ensuring the final analysis aligns with their strategic objectives.
Adherence to Excellence: Maintain the highest standards of quality and
integrity in report generation, following established benchmarks for
analytical rigor.
Performance Indicators:
The efficacy of the Financial Analysis Report is measured by its utility in
providing clear, actionable insights. This encompasses aiding corporate
decision-making, pinpointing areas for operational enhancement, and offering
a lucid evaluation of the company's financial health. Success is ultimately reflected in the report's contribution to informed investment decisions and strategic planning.
Supply numbers:
When write some conclusions add direct numbers coming from source report
confirming it.
"""

This system prompt primes Claude to act as an “Expert Financial Analyst”. It sets the tone and instructs on priorities: be precise, communicate clearly, focus on the client’s needs, and include numbers as evidence. The last line in bold explicitly tells the model to supply numbers in its output — this is critical for our use-case to ensure verifiability. By providing such a detailed system role description, we give the model a persona and clear guidelines to follow throughout the session.

Balanace sheet analysis prompt

f"Delve into a detailed scrutiny of the company's balance sheet for
previous 3 fiscal years showed in source data, pinpointing the structure
of assets, liabilities, and shareholders' equity to decode the firm's
financial stability and operational efficiency. Focus on evaluating the
liquidity through current assets versus current liabilities, the solvency
via long-term debt ratios, and the equity position to gauge long-term
investment potential. Contrast these metrics with previous years' data to
highlight financial trends, improvements, or deteriorations. Finalize with
a strategic assessment of the company's financial leverage, asset management,
and capital structure, providing insights into its fiscal health and future
prospects in a single paragraph.Generate limited output to less than
{max_words_paragraph} words. Add a separate paragraph for each of 3 years."

This prompt asks Claude to delve into the balance sheet. We explicitly mention analyzing the past 3 years, which means the data we feed should include three years of balance sheet figures (ensuring our DataFrame or text has multiple years). The prompt guides the model on what to discuss: liquidity (current assets vs. liabilities), solvency (debt levels vs equity), equity position, and trends over the years. We also tell it to produce the output in a structured way (a separate paragraph for each year’s analysis) and to keep each paragraph under a word limit. The instruction to include actual figures means the model should pull numbers like “current assets of $X and current liabilities of $Y” directly from the data given to it.

(By examining multiple years, the model can say, for instance, “The current ratio improved from 1.2 in 2021 to 1.5 in 2022 as current assets grew from $5.0B to $5.8B while current liabilities stayed around $3.9B,” which provides a concrete, checkable insight. This is far more useful than a generic statement like “liquidity improved,” and that’s exactly what our prompt aims to achieve.)

Cashflow analysis prompt

f"Dive into a comprehensive evaluation of the company's cash flow for the
latest fiscal year, focusing on cash inflows and outflows across operating,
investing, and financing activities. Examine the operational cash flow to
assess the core business profitability, scrutinize investing activities for
insights into capital expenditures and investments, and review financing
activities to understand debt, equity movements, and dividend policies.
Compare these cash movements to prior periods to discern trends,
sustainability, and liquidity risks. Conclude with an informed analysis
of the company's cash management effectiveness, liquidity position, and
potential for future growth or financial challenges in a single paragraph.
Generate limited output to less than {max_words_paragraph} words."

This prompt is for analyzing the cash flow statement. It asks the model to look at how the company’s cash is coming in and going out in the latest year, touching on each component: operating activities (which ideally should be positive and healthy), investing activities (often negative due to investments or capital spending), and financing activities (could be positive or negative depending on borrowing, stock buybacks, dividends, etc.). We also encourage a comparison to prior periods (to spot trends like “operating cash flow increased by 20% over last year”). And as always, we limit length and instruct to use actual dollar figures from the statement.

Income statement prompt

f"Embark on a thorough analysis of the company's income statement for the
current fiscal year, focusing on revenue streams, cost of goods sold,
operating expenses, and net income to discern the operational performance
and profitability. Examine the gross profit margin to understand the cost
efficiency, operating margin for operational effectiveness, and net profit
margin to assess overall profitability. Compare these financial metrics
against historical data to identify growth patterns, profitability trends,
and operational challenges. Conclude with a strategic overview of the
company's financial health, offering insights into revenue growth
sustainability and potential areas for cost optimization and profit
maximization in a single paragraph. Generate limited output to less than
{max_words_paragraph} words."

This prompt covers the income statement. It guides the model to comment on different levels of profit (gross vs operating vs net) and the efficiency at each stage. By asking for margins, we ensure the model will likely compute (or at least state) percentages like gross margin = gross profit / revenue. We tell it to check year-on-year trends for growth. The model should output something like “Revenues were $10M (up 5% from $9.5M last year), with a gross profit of $4M (40% gross margin), operating income $1M (10% operating margin), and net income $0.8M (8% net margin). This indicates… etc.” — again, including the concrete numbers.

Summarization Prompt

After getting the individual analyses, we also have the model produce an overall summary. The summarization prompt takes the outputs of the previous analyses as inputs (we effectively feed the model its own answers for BS, IS, CF), and asks it to synthesize them into a coherent conclusion:

f"Income statement analysis: {income_stmt_analysis}, \
Balance sheet analysis: {balance_sheet_analysis}, \
Cash flow analysis: {cash_flow_analysis}, \
Synthesize the findings from the in-depth analysis of the income statement,
balance sheet, and cash flow for the latest fiscal year. Highlight the core
insights regarding the company's operational performance, financial stability,
and cash management efficiency. Discuss the interrelations between revenue
growth, cost management strategies, and their impact on profitability as
revealed by the income statement. Incorporate the balance sheet's insights
on financial structure, liquidity, and solvency to provide a comprehensive
view of the company's financial health. Merge these with the cash flow
analysis to illustrate the company's liquidity position, investment
activities, and financing strategies. Conclude with a holistic assessment
of the company's fiscal health, identifying strengths, potential risks,
and strategic opportunities for growth and stability. Offer recommendations
to address identified challenges and capitalize on the opportunities to
enhance shareholder value in a single paragraph. Generate limited output
to less than {max_words_paragraph} words."

Here, {income_statement_analysis}, {balance_sheet_analysis}, and {cash_flow_analysis} would be placeholders that we fill with the actual text generated by Claude for each section. This prompt essentially says: “Given all those details, now summarize the overall financial situation.”

The summary should be a single well-rounded paragraph. We explicitly caution the model to integrate key numbers — meaning if the revenue was $X or debt was $Y, those should appear — but not to just copy-paste entire sentences from the earlier analysis.

By designing the prompts in this modular way (one per section plus a summary), we make the task easier for the model and also get a nicely organized output that’s easy to assemble into a report.

Note: We found that including explicit instructions to use numbers and keeping an eye on output length results in descriptive yet focused analysis. If the model outputs text that’s too long or too vague, you can tweak the max_words_paragraph or adjust wording in prompts (e.g., ask for bullet points versus paragraph, if desired). Prompt engineering is iterative – feel free to experiment with these templates to suit your needs.

Generated financial report

Balance Sheet Analysis

Evaluates liquidity, leverage, and capital structure to assess financial stability. Metrics like current ratio and debt-to-equity are highlighted.

Generated Balance Sheet analysis paragraph

This section evaluates the company’s liquidity, leverage, and capital structure to assess financial stability. It highlights metrics like the current ratio (current assets vs. current liabilities) to gauge short-term liquidity, and the debt-to-equity ratio to examine long-term solvency. The model’s generated paragraph includes specific figures, for example: it might note the dollar values of current assets and liabilities for each year and point out that the current ratio improved from, say, 1.2 to 1.5 over the last three years, indicating better liquidity. It could also mention how total liabilities changed relative to equity, commenting on whether the company’s leverage is increasing or decreasing.

(In our GameStop example, the AI output highlighted an increase in cash assets and a reduction in debt in the latest year, referencing the actual values from the balance sheet to support the claim that the company’s financial position had improved.)

Income Statement Analysis

Focuses on profitability metrics including margins, revenue trends, and EPS, offering insights into operational efficiency and market positioning.

Generated Income Statement analysis paragraph

Cash Flow Statement Analysis

Emphasizes cash management, highlighting operating, investing, and financing cash flows to demonstrate financial health.

Generated Cashflow analysis paragraph

Summarization and Insights

A concise executive summary is generated, integrating the detailed analysis into actionable insights suitable for executive reviews and strategic decision-making.

Generated Summarization paragraph

Share Performance

Historical stock performance analysis contextualizes the company’s financial results relative to market performance.

Generated Share Performance chart

PE & EPS

Key valuation metrics like Price-to-Earnings (PE) ratio and Earnings Per Share (EPS) provide critical context for investors.

Generated PE & EPS chart

Complete generated PDF report can be downloaded from this link.

Conclusion

With FinGPT and Claude 3.7, generating sophisticated financial analyses becomes fast, efficient, and cost-effective. The structured process ensures accuracy and clarity, providing actionable financial insights quickly. The combination of FinGPT’s financial analysis capabilities with Claude 3.7’s advanced language understanding creates a powerful tool for automated financial report analysis. This implementation demonstrates how AI can assist financial professionals in processing and interpreting complex financial documents, saving time and potentially uncovering insights that might be missed in manual analysis.

As language models continue to improve, we can expect even more sophisticated financial analysis tools that further augment human decision-making in the financial sector.

Try It Yourself

All code samples presented in this article can be found in repository: mzarnecki/FinGPT. Full FinGPT repository can be found on https://github.com/AI4Finance-Foundation/FinGPT.

If you want to experiment with this yourself, you can:

  1. Clone the repository medium.com and install the requirements.
  2. Configure your environment by creating the .env file with your AWS and SEC-API credentials (as shown earlier in Step 1).
  3. Enable Claude 3.7 on AWS Bedrock in your AWS account (and ensure you have the necessary permissions).
  4. Run the Jupyter Notebook (financial_reports_analysis_with_AI_AWS_bedrock.ipynb) provided in the repo. Set the ticker_symbol to a company of your choice.
  5. Execute the notebook to generate your own financial report PDF for that company.

Feel free to modify the prompts or code to suit different use cases — for example, try adding another section for ratio analysis (like calculating and commenting on the current ratio, quick ratio, debt-to-equity over years) or incorporate additional data such as sector averages for comparison.

By exploring the repository and running the analysis, you can gain hands-on experience with FinGPT and Claude, and see how AI can augment financial analysis work. The process is highly customizable: you can plug in other LLMs (if you have access to GPT-4 or a local LLaMa model, for instance) or extend the data pipeline to include quarterly reports (10-Qs) or other filings.

Caveats

LLMs are language models, not Bloomberg terminals. Always cross‑check critical figures. For valuation sections (DCF, comparables) Claude’s reasoning is great, but you must feed it fresh symbol‑level market data.

Performance

Financial report generation performance insights

The calculations for same number of tokens can differ for various models and change over time, but anyway this summary shows that LLM-based application for financial analysis can run in very short time with relatively small costs. The longest part 12s was spent on model inference and needs to be repeated 4 times.

Resources to understand the financial report

proposed in base notebook from FinGPT:

  1. income statement: https://online.hbs.edu/blog/post/income-statement-analysis
  2. balance sheet: https://online.hbs.edu/blog/post/how-to-read-a-balance-sheet
  3. cash flow statement: https://online.hbs.edu/blog/post/how-to-read-a-cash-flow-statement
  4. Annual report: https://online.hbs.edu/blog/post/how-to-read-an-annual-report

Reportlab PDF library

With tools like reportlab building reach PDF reports in Python becomes easy and well structurized. Reportlab library offers many preconfigured document elements and nice builder-oriented programming interface.
Going through rich collection of reportlab components is beyond the scope of this article, although you can go through chapters in their nice documentation starting from https://docs.reportlab.com/reportlab/userguide/ch1_intro/.

By following along with this article, you should be able to build and customize a financial report generator that leverages the latest AI technologies. We improved the clarity and reliability of the outputs by combining domain-specific data processing with careful prompt design for a state-of-the-art LLM. The end result is a tool that can save time and provide valuable insights — a testament to how AI can augment professional workflows when applied thoughtfully. Happy analyzing!

Join thousands of data leaders on the AI newsletter. Join over 80,000 subscribers and keep up to date with the latest developments in AI. From research to projects and ideas. If you are building an AI startup, an AI-related product, or a service, we invite you to consider becoming a sponsor.

Published via Towards AI


Take our 90+ lesson From Beginner to Advanced LLM Developer Certification: From choosing a project to deploying a working product this is the most comprehensive and practical LLM course out there!

Towards AI has published Building LLMs for Production—our 470+ page guide to mastering LLMs with practical projects and expert insights!


Discover Your Dream AI Career at Towards AI Jobs

Towards AI has built a jobs board tailored specifically to Machine Learning and Data Science Jobs and Skills. Our software searches for live AI jobs each hour, labels and categorises them and makes them easily searchable. Explore over 40,000 live jobs today with Towards AI Jobs!

Note: Content contains the views of the contributing authors and not Towards AI.