Skip to content

Repository files navigation

PSX Portfolio Agent

PSX Portfolio Agent

Autonomous AI-powered investment intelligence for the Pakistan Stock Exchange

Python FastAPI React Gemini Docker Cloud Run


Built for the AISeekho 2026 — Google Antigravity Hackathon · Challenge 1: Autonomous Content-to-Action Agent


Demo License Tests


What It Does

PSX Portfolio Agent is a fully autonomous, end-to-end agentic system that scrapes live market data from the Pakistan Stock Exchange, reads financial news from Pakistan's top sources, extracts and cross-validates investment signals, resolves contradictions using weighted arbitration, and produces a fully justified, risk-adjusted portfolio — all in a single API call.

The agent does not rely on static rules. Every portfolio is reasoned from scratch by Gemini, grounded in real-time data scraped minutes before.


Architecture

┌─────────────────────────────────────────────────────────────────┐
│                       React Frontend                            │
│         Vite · Tailwind CSS · Framer Motion · Axios             │
└──────────────────────────┬──────────────────────────────────────┘
                           │  REST  /api/v1
┌──────────────────────────▼──────────────────────────────────────┐
│                    FastAPI REST API                             │
│         /health · /portfolio/run · /market/snapshot · /news     │
└──────────────────────────┬──────────────────────────────────────┘
                           │
                  ActionChain (5 Steps)
                           │
         ┌─────────────────┼──────────────────────┐
         ▼                 ▼                       ▼
   PSXScraper        NewsScraper          SignalExtractor
   KSE-100 Index     Dawn Business        + ContradictionDetector
   Equities Board    ARY Business
   (Playwright)      Geo Business
         │                 │                       │
         └─────────────────┴───────────────────────┘
                           │
                      GeminiAgent
                  (gemini-3-flash-preview)
                           │
                   PortfolioBuilder
                  PKR amounts · Shares
                  Stop-loss · Sharpe
                           │
                    Portfolio (JSON)

The 5-Step Action Chain

Step Action Description
1 Scrape Market Data Fetches KSE-100 index, all-share prices, and volumes from PSX using Playwright for JS-rendered pages
2 Scrape News Concurrently scrapes Dawn Business, ARY Business, and Geo Business; extracts ticker mentions via regex
3 Extract Signals Price momentum × volume surge → market signals; keyword sentiment scoring → news signals
4 Resolve Conflicts Detects bullish_vs_bearish, source_disagreement, confidence_spread; resolves via weighted arbitration
5 Construct Portfolio Gemini reasons over signals + conflicts → structured JSON → typed Portfolio with PKR allocation, share counts, stop-losses, and Sharpe ratio

Tech Stack

Backend

Python FastAPI Pydantic Playwright BeautifulSoup Redis structlog

AI

Google Gemini Tenacity diskcache

Frontend

React Vite Tailwind CSS Framer Motion Axios

Infrastructure

Docker Google Cloud Run Cloud Build


Quick Start

Prerequisites

1. Clone & install

git clone https://github.com/muhammadwali0/psx-portfolio-agent.git
cd psx-portfolio-agent
python -m venv .venv && source .venv/bin/activate
make install-dev

2. Configure

cp .env.example .env
# Add your GOOGLE_API_KEY to .env

3. Run

# Backend only
make run

# Backend + Frontend together
make run-all
Service URL
API http://localhost:8080
Swagger UI http://localhost:8080/docs
Frontend http://localhost:5173

API Reference

POST /api/v1/portfolio/run

Triggers the full 5-step agent pipeline. Returns 202 Accepted immediately with a run_id for polling.

{
  "capital_pkr": 1000000,
  "max_positions": 5,
  "risk_preference": "medium",
  "tickers_filter": []
}

GET /api/v1/portfolio/{run_id}

Poll for completion. Status transitions: pending → in_progress → completed | failed

GET /api/v1/market/snapshot

Live PSX market snapshot — no pipeline required.

GET /api/v1/news?limit=30

Latest articles from Dawn Business, ARY Business, and Geo Business.

GET /api/v1/signals/{run_id}

Returns { signals: [...], conflicts: [...] } for a completed run.


Environment Variables

Variable Required Default Description
GOOGLE_API_KEY Gemini API key
GEMINI_MODEL gemini-3-flash-preview Model ID
ENVIRONMENT development development | staging | production
PORT 8080 Server port (Cloud Run injects this)
PORTFOLIO_CAPITAL_PKR 1000000 Default capital in PKR
PORTFOLIO_MAX_POSITIONS 5 Max stocks in portfolio
RISK_FREE_RATE 0.21 SBP policy rate for Sharpe calculation
REDIS_URL Optional Redis for persistent run store

Testing

All tests are fully offline — scrapers and Gemini are mocked. No API key or network required.

make test        # Full suite
make test-cov    # With HTML coverage report
make test-fast   # Stop on first failure
tests/
├── test_api.py               # FastAPI endpoint integration tests
├── test_chain.py             # ActionChain orchestrator tests
├── test_detector.py          # ContradictionDetector unit tests
├── test_portfolio_builder.py # PortfolioBuilder unit tests
├── test_psx_scraper.py       # PSXScraper HTML parsing tests
└── test_signals.py           # SignalExtractor unit tests

Deployment

Docker

make docker-build
make docker-run

Google Cloud Run (one command)

make deploy

CI/CD via Cloud Build

gcloud builds submit --config cloudbuild.yaml \
  --substitutions _REGION=us-central1,_REPO=psx-agent,_SERVICE=psx-portfolio-agent

The cloudbuild.yaml pipeline builds the Docker image, pushes to Artifact Registry, and deploys to Cloud Run with secrets injected from Secret Manager.


Code Quality

make lint       # ruff
make fmt        # black + ruff --fix
make typecheck  # mypy

Project Structure

psx-portfolio-agent/
├── app/
│   ├── agent/gemini_agent.py     # Gemini reasoning engine
│   ├── api/routes.py             # FastAPI endpoints
│   ├── portfolio/builder.py      # Portfolio construction
│   ├── scrapers/
│   │   ├── base.py               # Async base with retry
│   │   ├── psx_scraper.py        # PSX market data (Playwright)
│   │   └── news_scraper.py       # Dawn / ARY / Geo
│   ├── signals/
│   │   ├── extractor.py          # Signal generation
│   │   └── detector.py           # Contradiction detection
│   ├── chain.py                  # 5-step orchestrator
│   ├── config.py                 # Pydantic settings
│   ├── models.py                 # Domain models
│   └── store.py                  # Run store (memory / Redis)
├── frontend/                     # React + Vite frontend
├── tests/                        # Offline test suite
├── Dockerfile
├── cloudbuild.yaml
└── Makefile

License

MIT — see LICENSE


Built with ❤️ in Karachi for AISeekho 2026 — Google Antigravity Hackathon

GitHub Stars

About

Agentic AI system that ingests PSX market data and financial news, resolves conflicting signals, and constructs a justified investment portfolio with simulated execution.

Topics

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages