Lab 4: StockAgent — Autonomous Financial Market Copilot
Assemble the complete autonomous market screener copilot, integrating MLX local inference, Pydantic tool calling, and live Yahoo Finance scraping.
Say goodbye to expensive commercial financial APIs and rigid stock screeners. Build StockAgent: a 100% local, autonomous financial market screener and stock research copilot that scrapes live Yahoo Finance data, eliminates penny stocks, and solves date hallucination with Temporal Grounding.
Download notebook to follow along: https://github.com/MysteryBytes-Labs/agentic_ai/tree/main/ai_trading_coach_Gemma4
⚠️ MANDATORY FINANCIAL & SOFTWARE ENGINEERING DISCLAIMER:
This tutorial, code repository, and the "StockAgent" application are strictly for EDUCATIONAL, EXPERIMENTAL, AND SOFTWARE ENGINEERING PURPOSES ONLY.
I am a software engineer and AI educator—I am NOT a licensed financial advisor, certified broker, or fiduciary. The outputs generated by Gemma 4 and the autonomous agents shown in this guide DO NOT constitute investment advice, stock recommendations, or financial endorsement. AI models hallucinate, make mathematical errors, and can misinterpret market context. Never execute real-money trades based on autonomous AI outputs or unverified code. Always conduct your own exhaustive due diligence (DYOR) and consult with a licensed financial professional before risking capital.
The Problem: Commercial API Costs & LLM Date Hallucination
Building an automated financial market intelligence system typically faces three formidable roadblocks:
- Astronomical API Subscription Costs: Commercial financial data feeds (Bloomberg, FactSet, premium REST APIs) cost hundreds to thousands of dollars per month with strict rate limits.
- The "Date Hallucination" Trap: Frozen LLM weights lack an internal real-time clock. When presented with market data, pretrained models frequently default to their training cutoff (such as October 2023), outputting stale or fictionalized market contexts.
- The Penny Stock Hazard: Public market screeners frequently flood retail investors with volatile sub-$5 micro-caps vulnerable to illiquidity, wide bid-ask spreads, and algorithmic manipulation.
The Solution: In this series finale, we build StockAgent—a 100% local, zero-subscription financial copilot powered by Google Gemma 4 (12B) and Apple MLX. StockAgent directly scrapes live market tables from Yahoo Finance, enforces an institutional Penny Stock Purge ($\text{Price} \ge $5.00$, $\text{Market Cap} \ge $1.0\text{B}$), and anchors every generation to the live hardware clock via Temporal Grounding.
Traditional Screeners vs. StockAgent
| Feature & Safety Boundary | Traditional Stock Screeners | StockAgent (Local Gemma 4 + Apple MLX) |
|---|---|---|
| Query Flexibility | Hardcoded filter menus & dropdowns | Natural language conversational intelligence |
| Risk Guardrails | Manual ticker checking | Automated penny stock purge ($Price \ge $5$, $Cap \ge $1\text{B}$) |
| Data Ingestion | Paid proprietary vendor APIs | Direct, autonomous web scraping from Yahoo Finance ($0 cost) |
| Decision Synthesis | Raw numerical data dumps | Institutional investment memos with catalysts & stop-losses |
| Temporal Accuracy | Vulnerable to stale LLM date assumptions | Hardware clock anchored (Temporal Grounding) |
| Data Sovereignty | Cloud tracking of investor watchlists | 100% Local & Private analysis on Apple Silicon Metal |
3-Phase Closed-Loop Execution Architecture
StockAgent operates through a deterministic, three-phase autonomous cycle:
┌────────────────────────────────────────────────────────┐
│ User Financial Market Inquiry │
│ "Scrape Yahoo Finance for today's most active stocks │
│ and recommend the 3 most promising opportunities." │
└──────────────────────────┬─────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────┐
│ Phase 1: Structured Intent Analysis (MLX) │
│ Gemma 4 analyzes prompt & outputs StockAgentDecision │
│ specifying market section & Pydantic filter bounds │
└──────────────────────────┬─────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────┐
│ Phase 2: Live Scraping & Penny Stock Purge │
│ BeautifulSoup extracts live HTML market tables. │
│ Applies $5 price and $1B cap filters. │
│ Injects authoritative hardware timestamp anchor. │
└──────────────────────────┬─────────────────────────────┘
│
▼
┌────────────────────────────────────────────────────────┐
│ Phase 3: Executive Research Synthesis │
│ Gemma 4 synthesizes top-3 investment briefs with │
│ technical catalysts, stop-losses & risk disclaimers. │
└────────────────────────────────────────────────────────┘
Step 1: Environment Setup & Apple MLX Initialization
In your terminal or virtual environment:
pip install mlx mlx-vlm pydantic beautifulsoup4 requests gradio ipython
In [lab4_ai_finance_coach.ipynb], import dependencies and map Gemma 4 into Apple Silicon unified memory:
import os
import requests
from datetime import datetime
from bs4 import BeautifulSoup
from pydantic import BaseModel, Field
import mlx.core as mx
from mlx_vlm import load, generate
CURRENT_SYSTEM_DATE = datetime.now().strftime("%B %d, %Y")
print(f"Temporal Grounding Anchor: {CURRENT_SYSTEM_DATE}")
assert mx.metal.is_available(), "Apple Metal GPU acceleration required!"
MODEL_PATH = "AIModels/gemma-4-12B-it-qat-4bit"
model, processor = load(MODEL_PATH)
print("Gemma 4 (12B) loaded into Apple Unified Memory.")
Step 2: Defining Pydantic Safety Guardrails
We define Pydantic schemas that programmatically prevent the model from accepting or recommending high-volatility micro-caps:
from typing import Literal, Optional
class YahooScraperParams(BaseModel):
section: Literal["most-active", "gainers"] = Field(
default="most-active",
description="Yahoo Finance market section to scrape"
)
min_price: float = Field(
default=5.0,
ge=5.0,
description="Mandatory penny stock filter: minimum share price ($5.00)"
)
min_market_cap: float = Field(
default=1_000_000_000.0,
ge=1_000_000_000.0,
description="Mandatory penny stock filter: minimum market cap ($1.0B)"
)
class StockAgentDecision(BaseModel):
reasoning: str = Field(..., description="Deductive rationale explaining the strategy")
tool: Literal["scrape_market", "none"]
scraper_params: Optional[YahooScraperParams] = None
DECISION_SCHEMA = StockAgentDecision.model_json_schema()
Notice the ge=5.0 constraint: Gemma 4 is mathematically prohibited from lowering the price boundary below $5.00!
Step 3: Real-Time Yahoo Finance Web Scraper & Penny Stock Purge
We build a robust scraper with numeric normalizers that strip messy currency symbols and chaotic suffixes (T, B, M):
def parse_num(val_str: str) -> float:
"""Normalizes string representations into clean floats."""
val_str = val_str.replace("$", "").replace(",", "").strip()
multiplier = 1.0
if val_str.endswith("T"):
multiplier = 1e12
val_str = val_str[:-1]
elif val_str.endswith("B"):
multiplier = 1e9
val_str = val_str[:-1]
elif val_str.endswith("M"):
multiplier = 1e6
val_str = val_str[:-1]
try:
return float(val_str) * multiplier
except ValueError:
return 0.0
def scrape_yahoo_finance(params: YahooScraperParams) -> dict:
url = f"https://finance.yahoo.com/{params.section}"
headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Apple Silicon) AppleWebKit/537.36"}
response = requests.get(url, headers=headers, timeout=10)
soup = BeautifulSoup(response.text, "html.parser")
qualified = []
purged = []
# Scrapes rows, normalizes numbers, and applies strict filters:
# If price < params.min_price or cap < params.min_market_cap:
# purged.append(row)
# Else:
# qualified.append(row)
return {
"section": params.section,
"qualified_equities": qualified[:10],
"purged_count": len(purged),
"as_of_date": CURRENT_SYSTEM_DATE
}
Step 4: Assembling the Autonomous Execution Loop (run_stock_agent)
The run_stock_agent function orchestrates all three phases into a closed loop:
import json
def run_stock_agent(user_query: str) -> str:
# Phase 1: Intent Analysis
conversation = [
{
"role": "system",
"content": f"You are StockAgent, an autonomous market screener. Current date is {CURRENT_SYSTEM_DATE}.\n"
f"Output strictly valid JSON matching schema:\n{json.dumps(DECISION_SCHEMA)}"
},
{"role": "user", "content": user_query}
]
formatted = processor.apply_chat_template(conversation, tokenize=False, add_generation_prompt=True)
raw = generate(model, processor, prompt=formatted, max_tokens=256, temp=0.1)
decision = StockAgentDecision.model_validate_json(raw)
# Phase 2: Live Scraping & Penny Stock Purge
if decision.tool == "scrape_market":
params = decision.scraper_params or YahooScraperParams()
market_data = scrape_yahoo_finance(params)
else:
market_data = {"info": "Conceptual query. No market scraping executed."}
# Phase 3: Financial Research Brief Synthesis
synthesis_prompt = (
f"You are a Senior Equity Research Analyst. Current Date: {CURRENT_SYSTEM_DATE}.\n"
f"MANDATORY: Begin with an educational disclaimer reminding users to DYOR.\n"
f"Market Observation: {json.dumps(market_data)}\n"
f"User Inquiry: {user_query}\n"
f"Synthesize the Top 3 opportunities with live prices, market caps, catalysts, and stop-loss levels."
)
formatted_synth = processor.apply_chat_template(
[{"role": "user", "content": synthesis_prompt}],
tokenize=False,
add_generation_prompt=True
)
return generate(model, processor, prompt=formatted_synth, max_tokens=768, temp=0.2)
Step 5: Benchmark Evaluation Across 3 Scenarios
When benchmarked across three realistic market requests:
- Active Market Screener:
The agent autonomously routes tomost-active, scans live quotes, purges sub-$5 penny stocks, and outputs institutional research briefs for leaders like SpaceX, Nvidia, and Nu Holdings. - High-Momentum Gainers:
With tightened boundaries ($Price \ge $10$, $Cap \ge $2\text{B}$), the agent highlights breakout leaders with suggested stop-loss risk buffers. - Conceptual Risk Inquiry:
When asked "Why should trading algorithms strictly avoid penny stocks?", the agent selectstool: "none"and provides an expert breakdown of liquidity traps, bid-ask slippage, and pump-and-dump schemes without firing web scrapers.
Interactive Web App with Gradio (app_gradio.py)
To transform your notebook into a desktop GUI, launch the included app_gradio.py:
python3 app_gradio.py
This launches a real-time web interface running locally on http://127.0.0.1:7860, allowing you to run live stock screens, filter penny stocks, and generate executive investment memos with an interactive dashboard.
Complete Masterclass Series Summary
Congratulations! You have completed the entire Local Agentic AI Masterclass:
| Lab | Milestone | Architecture & Technologies |
|---|---|---|
| Lab 1 | High-Speed Local Inference Engine | Google Gemma 4 (12B), Apple MLX, Metal UMA zero-copy, token streaming |
| Lab 2 | Zero-Hallucination Tool Calling | Pydantic v2 schemas, Google Serper API, dynamic temporal date grounding |
| Lab 3 | Quantitative Valuation Multiples | Active candidate screener, Penny Stock Purge, fair-value P/E engine |
| Lab 4 | Capstone: Autonomous StockAgent | Closed-loop supervisor, Yahoo Finance scraping, Gradio desktop GUI |
💻 Download Full Source Code & Notebooks:
👉 https://github.com/MysteryBytes-Labs/agentic_ai/tree/main/ai_trading_coach_Gemma4