Oracle3
Open-source trading engine and MCP server for prediction markets. Fee-aware no-arbitrage trading across related contracts, live on Kalshi, Polymarket and Solana or on paper.
Local-first equity research where the LLM never produces a number. Questions compile to a typed plan of Python metrics; the model only narrates results it did not compute, and every claim is re-verifi
FinancePython · TypeScriptGitHub @karanmjpintoOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
Local-first equity research where the LLM never produces a number. Questions compile to a typed plan of Python metrics; the model only narrates results it did not compute, and every claim is re-verified against a frozen snapshot.
Taken from the repository README
Loading the full README. The saved excerpt is shown below.
Local-first equity research where the language model never produces a number.
-orange.svg)
To make AI-generated investment research checkable.
The goal is not a smarter model. It is a harness around the model good enough that its
output can be checked, repeated and argued with — so when an answer is wrong you can see
which part was wrong, and fix the method rather than the number.
Four commitments follow from that. They are enforced in code, not asserted in a
document, and they are what to hold this project to:Read the full README ↗Local-first equity research where the language model never produces a number.
Live landing page · Architecture · Contributing
To make AI-generated investment research checkable.
The goal is not a smarter model. It is a harness around the model good enough that its output can be checked, repeated and argued with — so when an answer is wrong you can see which part was wrong, and fix the method rather than the number.
Four commitments follow from that. They are enforced in code, not asserted in a document, and they are what to hold this project to:
unverifiable — the one thing worse than an unchecked number is an unchecked number
wearing a tick.The intended user is one person doing their own research who wants to disagree with a machine on the evidence — not a system that decides for them.
Most AI research tools hand a language model a pile of financial data and ask for a verdict. That makes every figure in the answer a token prediction — the P/E ratio, the drawdown, the conviction score. The output reads perfectly plausibly whether or not the arithmetic happened, and you cannot tell which from the prose.
This project compiles the question into a typed program, computes every figure in plain Python, and lets the model write only over results it did not produce.
flowchart LR
Q([Question]) --> P[Planner]
P --> D[Typed plan]
D --> E[Executor]
E --> N[Narrator]
N --> H[Harness]
H --> R([Recorded run])
P -.- Pn["picks metrics from a fixed<br/>catalog — never sees a value"]
E -.- En["plain Python computes<br/>every number"]
N -.- Nn["writes prose over computed<br/>results, no arithmetic"]
H -.- Hn["re-checks every numeric claim<br/>against the snapshot"]
The model appears twice, in two narrow roles. A planner chooses what to measure
from a fixed catalog and is shown no values. A narrator is shown only computed
values, under an explicit no-arithmetic rule. When the plan computes a conviction
score it overwrites whatever the narrator wrote, and says so in
harness_overrides.
Then a deterministic pass re-reads the finished thesis, extracts each numeric claim,
and compares it against the snapshot. Claims it cannot map are reported
unverifiable — never as passing.
| Numbers you can check | Every figure traces to a registered Python metric, not to the model. |
| Runs you can replay | Each analysis stores its snapshot, prompts, model parameters and output. Re-run it later against the same frozen data. |
| Drift you can see | runs/compare sets nondeterminism_detected when identical inputs reach different conclusions — the signal that an eval built on them would be measuring noise. |
| Sources you can trace | Providers disagree on split adjustment, fiscal alignment and currency. Every fetch records who answered, whether it was cached, and how the payload verified. |
| No API keys | Ollama serves the model locally, market data comes from keyless providers by default, and the book is a SQLite file you own. |
Prerequisites: uv, Node 20+, and Ollama.
git clone https://github.com/karanmjpinto/mjresearch.git
cd mjresearch/ai-hedge-fund
ollama pull qwen3:30b
cp .env.example .env
./start.sh
start.sh brings up the API on :8000 and the UI on :5173, waits for the API
before opening the browser, and stops both on Ctrl-C. It warns rather than fails
if Ollama is down — everything except AI research still works.
Then open http://localhost:5173.
cd ai-hedge-fund
cp .env.example .env # set OLLAMA_MODEL to a name from `ollama list`
uv sync --extra dev
uv run uvicorn hedge_fund.api.main:app --reload # :8000
cd frontend && npm install && npm run dev # :5173
Run a second instance beside one that is already bound — the UI proxy follows the API port automatically:
./start.sh --api-port 8010 --ui-port 5174
Both instances share ./data/fund.db, so two backends at once write to the same book.
One-off data check from the terminal:
uv run check-data AAPL
qwen3:30b is a mixture-of-experts model — ~30B total parameters but only ~3B active
per token, so it reasons far better than a small dense model at comparable speed.
Smaller models tend to write theses that cite none of the computed values. The harness
catches that and flags narrative_grounded: false, but a capable model avoids it in
the first place.
Prefer a hosted API? uv sync --extra openai, then set LLM_PROVIDER=openai,
OPENAI_API_KEY and LLM_MODEL.
POST /api/research/plan compiles a question into a DAG
of deterministic metrics, executes it, then narrates over the results. Node values
are content-addressed, so re-running an edited plan recomputes only what changed.suspect_convergence rather than reading as confirmation — the failure mode being
managed is agreement, not disagreement.uv sync --extra sentiment is installed; degrades to enabled: false otherwise../data/fund.db — trades, cash, splits, dividends, manual edits.SEC_USER_AGENT.When an analysis comes out wrong, the durable lesson is usually the method, not the
number. POST /api/methodology stores a portable correction that later runs apply.
Notes containing prices, amounts or scores are rejected — a stored number would be
replayed onto runs where it is no longer true. GET /api/methodology/applicable shows
exactly what would enter a prompt right now, and each run records which notes shaped it.
The whole stack is exposed as an MCP server with thirteen tools — research_ticker,
plan_research, list_metrics, get_market_data, get_sec_filings, get_peers,
run_backtest_tool, optimize_portfolio, describe_research_graph, list_runs,
get_run, compare_runs, teach_methodology.
{
"mcpServers": {
"mjresearch": {
"command": "uv",
"args": ["run", "hedge-fund-mcp"],
"cwd": "/absolute/path/to/mjresearch/ai-hedge-fund"
}
}
}
Restart the client, then ask it to "research NVDA with the committee" or "run a golden cross backtest on AAPL for 3 years" and it will invoke the tools directly.
This section carries the same weight as the one above it. A research tool that oversells its certainty is worse than one that states plainly what it cannot do.
LLM_TEMPERATURE=0.0,
LLM_SEED=7) and every input is recorded, but providers do not guarantee identical
output. Moving arithmetic out of the model narrows this — it does not eliminate it.The published site at karanmjpinto.github.io/mjresearch is the landing page only. The backend is deliberately not hosted: the API has no authentication and full write access to the portfolio, so putting it on the public internet would expose the book and its trade endpoints to anyone with the URL. The model is local too, so a hosted instance would have no AI research regardless.
App routes on the published site show the commands to run it locally. Everything real — portfolio, data, model — stays on your machine.
Railway deployment instructions live in ai-hedge-fund/README.md.
.
├── ai-hedge-fund/ # the application
│ ├── src/hedge_fund/ # FastAPI backend, agents, quant, data, MCP server
│ ├── frontend/ # React + Vite + Tailwind UI
│ ├── tests/ # pytest suite
│ ├── docs/architecture.md # full design document
│ └── README.md # operational detail: env vars, API reference, Railway
├── .github/workflows/ # CI, GitHub Pages deploy
└── LICENSE
Full API reference, the complete environment-variable table, and deployment detail are
in ai-hedge-fund/README.md. The design rationale is in
ai-hedge-fund/docs/architecture.md.
cd ai-hedge-fund
uv run pytest -q # 304 tests
CI runs Ruff, pytest, a frontend build, and a design review on every push and PR.
Issues and pull requests are welcome — see CONTRIBUTING.md for the development setup and what makes a change easy to merge. Security reports go through SECURITY.md, not the public tracker.
The investor-persona and committee/portfolio-manager ideas are inspired by the
educational multi-agent design in virattt/ai-hedge-fund
(MIT). This is an independent codebase, not a fork; the system prompts are original text.
See ai-hedge-fund/third_party/ATTRIBUTION.md
for the full attribution.
MIT © karanmjpinto