Oracle3
Oracle3: 예측시장 거래 엔진·MCP 서버
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기메이커가 쓴 소개는 위의 한 줄이 전부입니다. 더 자세한 내용은 저장소 README에서 읽을 수 있습니다. 저장소 README ↗
README 전체를 불러오는 중입니다.
README 전문 보기 ↗Build a swing trading entry rule, backtest it honestly, and compare exit strategies on identical entries. A $0/month portfolio project, built in about ten days by directing AI coding agents.
Live demo · 52/52 acceptance criteria green · no sign up
Not investment advice. The public demo runs on a generated market, not real prices, and the generated market has a planted edge, so any strategy will look good on it. Nothing here is a recommendation to buy or sell anything.
🎬 Demo GIF pending. Until then, the live demo is the real thing and the demo script below is the two minute tour.
Most backtesting tools let you tune an entry rule until the equity curve looks good, which is how you end up with a strategy that fits the past and nothing else. This one is built around three things that make it harder to fool yourself:
Plus the boring honesty: expectancy per bar held next to plain expectancy, MAE and MFE guides from in sample winners only, distinct entry weeks as the real sample size rather than trade count, and an assumptions header on every result stating the fill model, slippage and cooldown.
rsi(14) < 75, and watch the URL and the JSON panel update as you type.DEMO-INDEX with the in sample and out of sample split marked, and the trade list filtered to
exit_reason = delisted.flowchart LR
subgraph Presentation
W["apps/web<br/>Next.js, static export<br/>Vercel"]
A["services/api<br/>FastAPI, ~320 lines<br/>Lambda container"]
end
subgraph Application
U["engine.api<br/>scan, backtest"]
end
subgraph Domain
D["engine/<br/>indicators · rules · exits<br/>sim · baseline · metrics"]
end
subgraph Infrastructure
I["engine/data, engine/synthetic<br/>engine/live<br/>Parquet, Alpaca"]
end
W -->|"typed OpenAPI client"| A
A --> U
U --> D
U --> I
I --> D
Every arrow points inward, and nothing points back out: the domain knows nothing about the API, the web app, Parquet or Alpaca.
Clean Architecture, with the dependency rule enforced by a test rather than a convention:
engine/tests/test_engine_boundary.py fails the build if
the domain imports FastAPI, Starlette or uvicorn. The API is ~320 lines because every decision
lives inward of it; routers assemble responses and nothing else.
Exit precedence lives in exactly one function, step(position, bar), and "never special case an
exit outside it" is an enforced invariant. Both the portfolio day loop and the per trade exit lab
loop call it, so the two modes cannot disagree about what an exit does.
Read more: spec 0001 (stack) · all 10 specs · ADR digest, 17 decisions tracked to outcomes · agent log: how it was built
| Why | ||
|---|---|---|
| TypeScript (strict) on Node 24, Next.js App Router | static export | No server needed, so Vercel Hobby hosts it free |
| Tailwind + shadcn/ui, TanStack Query/Table, Lightweight Charts | Tables and charts are most of the UI | |
| Python 3.12 (uv), FastAPI + Pydantic v2 | Lambda container, ap-southeast-1 | Pydantic models are the contract, and generate the TypeScript client |
| Polars (indicators and rules), NumPy and plain Python loops (simulator) | Deliberately not Numba or vectorbt. Profiling decided this, not taste — see ADR-006 and 016 | |
| No database, no auth, no background jobs | 10 to 20 MB of Parquet ships inside the image. State lives in the URL | |
pnpm + uv monorepo, one Makefile | make ci runs everything CI runs |
Things it deliberately does not have: accounts, saved rules, alerts, watchlists, OR groups in rules, intraday data, fundamentals, short selling, parameter sweeps, walk forward, Monte Carlo, or hosted real data. Those are listed as non goals, not oversights.
| Piece | How it is free |
|---|---|
| Web app | Vercel Hobby, static export, deployed from Git |
| API | AWS Lambda always free tier. 2,048 MB, 30 s timeout, x86_64, one container image |
| Image registry | ECR, images tagged with the commit SHA |
| Data | No database. Synthetic Parquet is built into the image |
| CI/CD | GitHub Actions, free on a public repo. Deploys use OIDC, so no AWS keys are stored |
| Staying awake | One /api/v1/health call a week, so the image does not go Inactive and spoil the first visit after a quiet spell. Not a warm up ping — the web app does that itself on page load |
| Guard rails | A $1 budget alarm and a throttle alarm, both by email |
Measured cold start for a visitor hitting an idle function: 2.66 s (warm: 0.07 s). The first
call right after a deploy is slower and different, 9 to 14 s, because Lambda optimises each new
image once; infra/README.md §6 keeps the two numbers apart so neither gets quoted as the other.
All of these point the same way: results look better than reality.
Therefore every finding here is a hypothesis. Confidence would need delisted inclusive data, walk forward testing, and a paper traded forward test. The research note states its own confidence level and names which of these limits bite it.
data/live/ on one machine and never published. The API
refuses to start in live mode anywhere but 127.0.0.1, and refuses on Lambda or in CI whatever
the binding says.research/ folder; only synthetic notes are
published.data/ and research/ are gitignored.make setup # install from lockfiles (pnpm --frozen-lockfile, uv sync --frozen)
make hooks # once per clone: install the pre-commit hooks
make data # generate the seed 42 synthetic market into data/synthetic (gitignored)
make dev # API on 127.0.0.1:8000 + web on :3000
make ci # every check CI runs, in one command
Live mode, local only, needs Alpaca keys in your environment or a local .env:
make load-live # Alpaca daily bars into data/live (gitignored)
make dev-live # the same app against your live data, on 127.0.0.1 only
| Suite | What it is |
|---|---|
26 oracle tests (tests/oracle/) | Owner written correctness tests, protected by a pre commit guard and a CI label so no agent can edit them. They define correct behaviour for every exit type, loop parity, look ahead and MAE/MFE, and they were written before the engine |
141 acceptance tests (tests/acceptance/) | Written from the criteria and contracts only. All 52 MUST criteria are required and green; test_traceability.py fails the build if the gate and the traceability matrix disagree |
| 710 Python tests, ~450 web tests | Unit tests beside their packages, plus Vitest for the UI |
Golden references (tests/golden/) | Naive loop implementations that the fast paths are checked against |
make test · make test-acceptance · make test-oracle · make lint · make typecheck
The GIF above is the one artifact that needs a human. Record the six steps of the demo script
against make dev on the seed 42 market, at 375 px wide (every page is checked to work there), and
save it to docs/assets/demo.gif. Keep it under about 10 MB so it loads on this page, and make
sure the synthetic banner is legible in the first frame — it is the first thing the GIF has to say.
A learning and portfolio project with one real user, never sold. Why there is no monetisation.