Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 60 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

[![CI](https://github.com/OnePunchMonk/AgentQuant/actions/workflows/ci.yml/badge.svg)](https://github.com/OnePunchMonk/AgentQuant/actions)
![Python](https://img.shields.io/badge/python-3.10%2B-blue)
![Tests](https://img.shields.io/badge/tests-55%20passed-brightgreen)
![Tests](https://img.shields.io/badge/tests-63%20passed-brightgreen)

---

Expand All @@ -18,6 +18,8 @@ AgentQuant is a regime-adaptive research platform that runs a real **ReAct agent
4. **Reflects** on results and retries if Sharpe is below the configured threshold (up to `max_iterations` times).
5. **Stores** the best result to SQLite memory so future runs can recall what worked in similar regimes.

Every completed run now emits a screenshot-friendly **regime card** and a transparent candidate table with pass/watch/reject verdicts, Sharpe, Calmar, Sortino, max drawdown, and bootstrapped Sharpe p5.

---

## Platform Preview
Expand Down Expand Up @@ -54,6 +56,20 @@ analyze ──► hypothesize ──► backtest ──► reflect
store → SQLite memory
```

### Multi-Agent Swarm

The optional swarm mode runs the same research loop through specialized agents:

```mermaid
flowchart LR
M["Memory Agent<br/>learned patterns"] --> R["Regime Analyst<br/>market context"]
R --> S["Strategy Specialists<br/>momentum, mean reversion, volatility"]
S --> C["Critic Agent<br/>reject invalid or duplicate candidates"]
C --> B["Backtest Coordinator<br/>multi-window validation"]
B --> M
B --> O["Regime card + comparison table"]
```

### Key Components

| Module | What it does |
Expand All @@ -63,7 +79,11 @@ analyze ──► hypothesize ──► backtest ──► reflect
| `src/agent/base_planner.py` | `BasePlanner` ABC with Gemini / OpenAI / Fallback |
| `src/agent/context_builder.py` | `RegimeContext` dataclass with VIX percentile, multi-horizon momentum |
| `src/agent/parameter_grid.py` | Canonical grids per strategy; regime-aware prior selection |
| `src/agent/memory_layer.py` | Agentic memory layer that turns SQLite history into strategy patterns |
| `src/agent/reporting.py` | Regime card, comparison table, and pass/watch/reject verdicts |
| `src/agent/trace.py` | Live trace event stream for the ReAct loop |
| `src/agent/strategy_memory.py` | SQLite cross-session memory |
| `src/agent/swarm/` | Memory Agent, Regime Analyst, Specialists, Critic, and Backtest Coordinator |
| `src/research/alpha_store.py` | SQLite memory for accepted, watchlisted, and rejected alpha candidates |
| `src/research/nla_memory.py` | Explicit NLA-style narrative memory and `nla-gemma4` JSONL ingestion |
| `src/research/workspace.py` | Experiment registry, robustness summaries, and research memo generation |
Expand All @@ -79,23 +99,36 @@ analyze ──► hypothesize ──► backtest ──► reflect

---

### Experimental Agent Swarm Branch
### Visible Agent Loop

Run with a live terminal trace to watch the agent move through hypothesis, backtest, reflection, retry, and memory storage:

```bash
agentquant run --ticker SPY --trace
```

Run the multi-agent architecture from main:

The `agent-swarm-method` branch explores a multi-agent version of AgentQuant. It decomposes the research loop into specialized agents:
```bash
agentquant run --ticker SPY --swarm --strategies momentum mean_reversion volatility
```

- **Memory Agent** retrieves and stores strategy patterns across runs.
- **Regime Analyst** builds the market/macro context used by downstream agents.
- **Strategy Specialists** generate proposals for momentum, mean reversion, volatility, and trend-following approaches.
- **Critic Agent** pre-screens proposals before expensive backtests.
- **Backtest Coordinator** validates approved proposals across multiple time windows and ranks by robustness.
Browse accumulated strategy memory:

That branch is intentionally experimental and sits alongside the main ReAct pipeline. To inspect it:
```bash
agentquant memory
agentquant memory --regime LowVol-Bull --patterns
agentquant memory --export markdown
```

Render the latest stored one-page regime card:

```bash
git checkout agent-swarm-method
pytest tests/test_swarm.py -v
agentquant regime-card
```

The Colab quick demo is in `notebooks/agentquant_colab_spy.ipynb`. It runs a full SPY loop in three cells and works with or without a Gemini API key.

---

## Quick Start
Expand All @@ -120,7 +153,13 @@ cp .env.example .env
# 5. Run the agent
python -m src.agent.runner

# 6. Run the dashboard
# Or use the CLI
agentquant run --ticker SPY --trace

# 6. Browse memory
agentquant memory --patterns

# 7. Run the dashboard
python run_app.py
```

Expand All @@ -135,7 +174,7 @@ pip install -e ".[dev]"
pytest tests/ -v
```

**55 tests passing** across:
**63 tests passing** across:
- `test_config.py` — Pydantic validation
- `test_data_ingest.py` — live ticker fetch and cache range coverage
- `test_metrics.py` — Sharpe, drawdown, Calmar, Sortino
Expand All @@ -147,6 +186,9 @@ pytest tests/ -v
- `test_alpha_store.py` — alpha memory persistence and retrieval
- `test_nla_memory.py` — explicit NLA memory and JSONL ingestion
- `test_research_workspace.py` — experiment registry summaries and memos
- `test_memory_layer.py` — agentic memory pattern extraction and markdown export
- `test_reporting_cli.py` — regime card, verdicts, and CLI parsing
- `test_swarm.py` — synthetic-data smoke tests for the multi-agent swarm

---

Expand All @@ -159,9 +201,13 @@ AgentQuant/
│ │ ├── agent_graph.py # ReAct agent loop (analyze→hypothesize→backtest→reflect→store)
│ │ ├── base_planner.py # LLM abstraction: Gemini / OpenAI / Fallback
│ │ ├── context_builder.py # RegimeContext dataclass + builder
│ │ ├── memory_layer.py # Agentic memory pattern extraction
│ │ ├── parameter_grid.py # Canonical parameter grids per strategy
│ │ ├── proposal_generator.py # LLM → Grid → Random fallback chain
│ │ ├── reporting.py # Regime card + comparison table renderers
│ │ ├── strategy_memory.py # SQLite cross-session memory
│ │ ├── swarm/ # Multi-agent Memory/Regime/Critic/Backtest agents
│ │ ├── trace.py # Live trace events
│ │ ├── tools.py # Tool-calling interface for LangGraph
│ │ └── runner.py # Main entry point
│ ├── data/
Expand Down Expand Up @@ -193,7 +239,7 @@ AgentQuant/
├── experiments/
│ ├── results_store.py # SQLite experiment tracking
│ └── walk_forward.py # Walk-forward validation
├── tests/ # 55 tests
├── tests/ # 63 tests
├── docs/ # Documentation
├── config.yaml # Project configuration
├── .env.example # Environment template
Expand Down
72 changes: 72 additions & 0 deletions notebooks/agentquant_colab_spy.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
{
"nbformat": 4,
"nbformat_minor": 5,
"metadata": {
"colab": {
"name": "AgentQuant SPY demo"
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# AgentQuant SPY demo\n",
"\n",
"Three-cell Colab path: install AgentQuant, optionally set a Gemini key, and run a full SPY agent loop with a trace, regime card, and candidate comparison table."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"!pip -q install \"git+https://github.com/OnePunchMonk/agentquant.git\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import os\n",
"from getpass import getpass\n",
"\n",
"key = getpass(\"Gemini API key (leave blank to use grid-search fallback): \")\n",
"if key:\n",
" os.environ[\"GOOGLE_API_KEY\"] = key\n",
"else:\n",
" os.environ.pop(\"GOOGLE_API_KEY\", None)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"from src.agent.agent_graph import run_agent\n",
"from src.agent.reporting import render_comparison_table, render_regime_card\n",
"from src.agent.trace import TraceRecorder\n",
"from src.data.ingest import fetch_ohlcv_data\n",
"\n",
"data = fetch_ohlcv_data(ticker=\"SPY\")\n",
"data.update(fetch_ohlcv_data(ticker=\"^VIX\"))\n",
"state = run_agent(data, strategy_type=\"momentum\", asset=\"SPY\", max_iterations=2, trace=TraceRecorder(live=True))\n",
"\n",
"print(render_regime_card(state))\n",
"print()\n",
"print(render_comparison_table(state.get(\"results\", [])))"
]
}
]
}
4 changes: 4 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ dependencies = [
"matplotlib>=3.8",
"pyarrow>=16.0",
"tabulate>=0.9",
"rich>=13.7",
"statsmodels>=0.14",
"requests>=2.31",
]
Expand Down Expand Up @@ -54,6 +55,7 @@ dev = [

[project.scripts]
run-agent = "src.agent.runner:main"
agentquant = "src.cli:main"

[tool.pytest.ini_options]
pythonpath = ["."]
Expand All @@ -63,6 +65,8 @@ addopts = "-v --tb=short"
[tool.ruff]
line-length = 100
target-version = "py310"

[tool.ruff.lint]
select = ["E", "F", "W", "I"]
ignore = ["E501"]

Expand Down
Loading
Loading