DEV Community

shashank ms
shashank ms

Posted on

Practical Guide to Using LLM in Finance

Introduction

We will build an earnings transcript analyzer that turns unstructured call text into structured investment signals. It extracts financial metrics, scores management sentiment, and flags forward-looking risks. This is for developers and analysts who want to automate equity research without surprise token bills.

What you'll need

Step 1: Instantiate the Oxlo.ai client

I always verify the endpoint before building logic. This snippet creates the client, hits the Oxlo.ai OpenAI-compatible API, and confirms the connection with Llama 3.3 70B.

from openai import OpenAI
import os

client = OpenAI(
    base_url="https://api.oxlo.ai/v1",
    api_key=os.environ.get("OXLO_API_KEY", "YOUR_OXLO_API_KEY")
)

response = client.chat.completions.create(
    model="llama-3.3-70b",
    messages=[{"role": "user", "content": "Say 'connected'"}],
)

assert "connected" in response.choices[0].message.content.lower()
print("Oxlo.ai client ready")

Step 2: Lock in the system prompt

The system prompt is the only guardrail we need. It forces the model to behave like a sell-side analyst and output strict JSON.

SYSTEM_PROMPT = """You are a senior equity research analyst. Read the earnings call transcript and return a JSON object with these keys:

- ticker: string
- quarter: string
- revenue_growth_commentary: string, max 30 words
- margin_trend: one of ["expanding", "stable", "contracting"]
- management_sentiment: integer 1-10
- guidance_change: one of ["raised", "unchanged", "lowered", "no guidance"]
- top_risks: array of strings, max 3 items

Rules:
- Output ONLY valid JSON.
- Do not include markdown code fences.
- If a metric is not mentioned, use null."""

Step 3: Extract structured signals with JSON mode

We pass the transcript and the system prompt to Llama 3.3 70B. JSON mode guarantees parseable output, so downstream code stays simple.

import json

def extract_signals(transcript):
    response = client.chat.completions.create(
        model="llama-3.3-70b",
        messages=[
            {"role": "system", "content": SYSTEM_PROMPT},
            {"role": "user", "content": transcript},
        ],
        response_format={"type": "json_object"},
        temperature=0.1,
    )
    raw = response.choices[0].message.content
    return json.loads(raw)

Step 4: Layer in deep reasoning for risk

Raw extraction is useful, but interpretation matters. We feed the structured JSON into DeepSeek V3.2 to generate a forward-looking risk paragraph and an investment stance.

def reason_risk(signals):
    prompt = f"""Given the following structured signals from an earnings call:
{json.dumps(signals, indent=2)}

Write a 2-sentence forward-looking risk assessment and pick an investment stance from: Bullish, Neutral, or Bearish.

Return ONLY JSON with keys: risk_assessment, stance."""
    
    response = client.chat.completions.create(
        model="deepseek-v3.2",
        messages=[
            {"role": "system", "content": "You are a cautious portfolio manager. Be concise."},
            {"role": "user", "content": prompt},
        ],
        response_format={"type": "json_object"},
        temperature=0.2,
    )
    return json.loads(response.choices[0].message.content)

Step 5: Wire the CLI agent together

This orchestrator reads a local text file, runs extraction, then reasoning, and prints a merged report. You can pipe any transcript through it.

def analyze_earnings(file_path):
    with open(file_path, "r", encoding="utf-8") as f:
        transcript = f.read()
    
    print("Extracting signals...")
    signals = extract_signals(transcript)
    
    print("Running risk reasoning...")
    risk = reason_risk(signals)
    
    report = {
        "ticker": signals.get("ticker"),
        "quarter": signals.get("quarter"),
        "margin_trend": signals.get("margin_trend"),
        "management_sentiment": signals.get("management_sentiment"),
        "guidance_change": signals.get("guidance_change"),
        "top_risks": signals.get("top_risks"),
        "risk_assessment": risk.get("risk_assessment"),
        "stance": risk.get("stance"),
    }
    
    print(json.dumps(report, indent=2))
    return report

if __name__ == "__main__":
    analyze_earnings("transcript.txt")

Run it

Create a file named transcript.txt with this sample text:

Good afternoon and welcome to the Q3 2024 call for ACME Corp.
Revenue grew 12% year over year driven by cloud adoption.
Gross margins contracted slightly due to supply chain headwinds.
Management raised full year guidance and sounded optimistic about Q4.
Key risks include currency fluctuation and competitive pricing pressure.

Then execute the script. You should see output similar to this:

{
  "ticker": "ACME",
  "quarter": "Q3 2024",
  "margin_trend": "contracting",
  "management_sentiment": 8,
  "guidance_change": "raised",
  "top_risks": [
    "currency fluctuation",
    "competitive pricing pressure"
  ],
  "risk_assessment": "Margin contraction paired with FX headwinds could offset revenue momentum in the near term.",
  "stance": "Neutral"
}

Next steps

Try batch processing an entire folder of transcripts by wrapping analyze_earnings in a loop over pathlib.Path("transcripts/").glob("*.txt"). If you need to analyze slide decks or charts, swap the reasoning layer to Kimi K2.6 and pass base64 images through the same Oxlo.ai client.

Because Oxlo.ai uses flat per-request pricing, long transcripts or full 10-K filings do not inflate your bill the way token-based providers do. See the exact rates at https://oxlo.ai/pricing.

Top comments (0)