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
6 changes: 3 additions & 3 deletions .github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ body:
- type: markdown
attributes:
value: |
AlgoStream is paper trading only — there is no venue connectivity anywhere
in the project. If you are reporting something about placing real orders,
that code does not exist here.
Execution in AlgoStream is simulated. There is no venue connectivity in
this project today, so if you are reporting something about placing real
orders, that code does not exist here yet.

For security vulnerabilities, do **not** open an issue. Follow
[SECURITY.md](../blob/main/SECURITY.md) instead.
Expand Down
5 changes: 3 additions & 2 deletions .github/ISSUE_TEMPLATE/feature_request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@ body:
- type: markdown
attributes:
value: |
AlgoStream is paper trading only — there is no venue connectivity anywhere
in the project. Proposals that assume live order placement are out of scope.
Execution in AlgoStream is simulated. There is no venue connectivity in
this project today, so proposals that assume live order placement are
out of scope for now.

- type: textarea
id: problem
Expand Down
8 changes: 4 additions & 4 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ First public release.
- **Order and risk management** — routing, sizing, execution-quality measurement, VaR and limits.
- **Monte Carlo, optimization and performance** — path simulation, walk-forward analysis and
return attribution.
- **Live runtime** — a paper-trading runner driving the same strategy code as the backtester
- **Live runtime** — a runner with simulated execution, driving the same strategy code as the backtester
against a live feed, with `test/runtime/test_parity.exe` asserting the two produce identical
results from one fixture.
- **Telemetry and reporting** — metrics, health checks, alerting and report export.
Expand All @@ -36,9 +36,9 @@ First public release.

### Notes

This is paper trading. There is no venue connectivity anywhere in the project — no exchange
credentials, no request signing, no trading endpoint. Fills are simulated against live quotes by
the same engine the backtester uses.
Execution is simulated. There is no venue connectivity in this release: no exchange credentials,
no request signing, no trading endpoint. Fills are simulated against live quotes by the same
engine the backtester uses.

Performance figures are stated in the README alongside the machine and the command that produced
them. Targets that cannot be validated without a venue are marked as such where they appear,
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ lib/ # All library code
├── data_ingestion/ # Exchange connectors and the ingestion supervisor
├── analytics/ pairs/ # Statistics and cointegration
├── strategy/ backtest/ # The strategy contract and the simulator
├── runtime/ # Live paper-trading runner
├── runtime/ # Live runner, simulated execution
└── telemetry/ # Metrics, health, alerting

bin/ # Executables — daemon, keyctl, auditctl, backtest, benchmark
Expand Down
43 changes: 28 additions & 15 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,31 @@

---

> [!NOTE]
> **This is a public portion of a larger private project, published as a reference for people
> learning this domain.** The proprietary side (strategies, their parameters, and the research
> around them) stays private and is not here. What is here is the machinery underneath: an event
> bus, market-data ingestion, cointegration analytics, a fill simulator, a risk gate and a live
> runtime, complete enough to build, test and run end to end.
>
> If you are trying to understand how an algorithmic-trading system is actually put together, and
> where the honest limits of each piece are, that is what this repository is for. Execution is
> simulated at present, and the docs are explicit about which numbers are measured and which
> cannot be until there is a venue behind them.

## Overview

AlgoStream is an event-driven platform for researching statistical-arbitrage strategies: live
market-data ingestion, cointegration and mean-reversion analytics, a backtest engine, and a live
runtime that drives the same strategy code against a real feed.

**It is paper trading.** There is no venue connectivity anywhere in the project — no exchange
**Execution is simulated.** There is no venue connectivity in this repository today: no exchange
credentials, no request signing, no trading endpoint, so nothing here can place a real order. Fills
are simulated against live quotes by the same engine the backtester uses, and
`test/runtime/test_parity.exe` asserts the live runtime and the backtest produce identical results
from one fixture. That equivalence is the claim the project makes; anything about real execution
would need a venue this project does not have.
from one fixture. That equivalence is the claim the project makes today; real execution latency and
fill quality are marked unmeasured wherever they appear, and stay that way until there is a venue
behind them.

### Measured

Expand All @@ -43,7 +56,7 @@ stated offered load; there is no venue leg to include, so this is not an order-e

The other latency benchmark, `event_bus_latency`, saturates the bus on purpose and reports queueing
delay in the tens of milliseconds by construction. Both are real and they answer different
questions — `paced-bench` is the one comparable to a latency target.
questions. `paced-bench` is the one comparable to a latency target.

## Architecture

Expand All @@ -69,7 +82,7 @@ same `Strategy.S` runs under the backtester and the live runtime.
| `montecarlo`, `optimization`, `performance` | Simulation, walk-forward, attribution | [monte carlo](docs/guides/monte_carlo.md) · [optimization](docs/guides/optimization.md) |
| `runtime`, `telemetry`, `reporting` | Live paper runner, metrics, report export | [live runtime](docs/guides/live_runtime.md) · [telemetry](docs/guides/telemetry.md) |

Written in OCaml 5.x — `Domain` for parallelism, `Atomic` for publication, Lwt for I/O. The
Written in OCaml 5.x, using `Domain` for parallelism, `Atomic` for publication and Lwt for I/O. The
numerics are hand-rolled rather than pulled from a linear-algebra dependency; the reasoning is in
the relevant guides.

Expand Down Expand Up @@ -125,7 +138,7 @@ The quickest look at a running system:
make dash
```

Then **http://127.0.0.1:8080/dashboard/** — note the path; `/` is the landing page.
Then **http://127.0.0.1:8080/dashboard/**. Note the path; `/` is the landing page.

No keystore means no credential required, and the listener is loopback-only.

Expand All @@ -141,7 +154,7 @@ dune exec bin/keyctl.exe -- add --label viewer --scopes read
dune exec bin/keyctl.exe -- list
```

Keys land in `$XDG_CONFIG_HOME/algostream/keys.json` (`~/.config/...`), mode `0600` — the daemon
Keys land in `$XDG_CONFIG_HOME/algostream/keys.json` (`~/.config/...`), mode `0600`. The daemon
**refuses to start** if the permissions are wider, rather than warning.

```bash
Expand All @@ -159,7 +172,7 @@ Directly:

```bash
KEY='ask_...'
curl -s localhost:8080/api/health | jq # public — shows auth_required
curl -s localhost:8080/api/health | jq # public; shows auth_required
curl -i localhost:8080/api/telemetry # 401 + WWW-Authenticate
curl -i -XPOST -H "Authorization: Bearer $KEY" localhost:8080/api/strategies/pairs-1/stop
```
Expand All @@ -175,7 +188,7 @@ dune exec bin/auditctl.exe -- verify /tmp/algostream-audit # exit 1 on a break
dune exec bin/auditctl.exe -- head /tmp/algostream-audit
```

`head` prints the **anchor** — copy it somewhere the daemon cannot write. The chain is unkeyed, so
`head` prints the **anchor**. Copy it somewhere the daemon cannot write. The chain is unkeyed, so
anyone who can write the log can recompute it and hand you a file that verifies perfectly. The
[security guide](docs/guides/security.md) shows how to demonstrate that, and what an anchor buys you.

Expand All @@ -189,7 +202,7 @@ make stack-down
```

Scope-gated like every other observation endpoint. Grafana `:3000` (anonymous viewer), Prometheus
`:9090`, Alertmanager `:9093` — all bound to loopback.
`:9090`, Alertmanager `:9093`, all bound to loopback.

## Documentation

Expand Down Expand Up @@ -235,7 +248,7 @@ make k8s-validate
# Performance benchmarks (release profile)
make bench # text output
make bench-json # JSON output for github-action-benchmark
make paced-bench # latency at a stated offered load — the figure to quote
make paced-bench # latency at a stated offered load; the figure to quote
```

## Deployment
Expand All @@ -251,8 +264,8 @@ make stack-up # daemon + Prometheus + Grafana + Alertmanager
make stack-down
```

`Dockerfile` (root) is the release image. `Dockerfile.dev` is a **profiling shell** — passwordless
sudo, `SYS_ADMIN`, `seccomp:unconfined` — which is correct for running `perf` and valgrind and
`Dockerfile` (root) is the release image. `Dockerfile.dev` is a **profiling shell** (passwordless
sudo, `SYS_ADMIN`, `seccomp:unconfined`), which is correct for running `perf` and valgrind and
disqualifying for anything unattended. Never derive one from the other.

A container must bind `0.0.0.0`, since a pod's loopback is unreachable from outside its network
Expand Down Expand Up @@ -286,10 +299,10 @@ not make this a clustered system.

## Contributing

Contributions are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) for the build setup, code style
Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for the build setup, code style
and test expectations. Security issues should go through [SECURITY.md](SECURITY.md) rather than a
public issue.

## License

MIT — see [LICENSE](LICENSE).
MIT. See [LICENSE](LICENSE).
6 changes: 3 additions & 3 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

## Scope

AlgoStream is **paper-trading research infrastructure**. There is no venue connectivity anywhere in
the project — no exchange credentials, no request signing, no trading endpoint — so no vulnerability
here can move funds. What the security model protects is the **control surface and the data**: the
AlgoStream is **research infrastructure with simulated execution**. There is no venue connectivity
in the project today (no exchange credentials, no request signing, no trading endpoint), so no
vulnerability here can currently move funds. What the security model protects is the **control surface and the data**: the
dashboard API can start, pause, stop and reallocate strategies, and it serves live position and P&L
figures.

Expand Down
4 changes: 2 additions & 2 deletions bin/algostream.ml
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ let default_cli () =

let usage () =
print_string
{|algostream — live paper-trading daemon with a monitoring dashboard
{|algostream: live daemon with simulated execution and a monitoring dashboard

Market data (pick one):
--exchange {binance|coinbase|both} live public feeds (default both)
Expand Down Expand Up @@ -445,7 +445,7 @@ let () =
let c = parse_args () in
Logs.set_reporter (Logs.format_reporter ()) ;
Logs.set_level (Some Logs.Info) ;
Printf.printf "algostream — paper trading, no venue connectivity\n%!" ;
Printf.printf "algostream: simulated execution, no venue connectivity\n%!" ;

(* Both tuning knobs must be applied before anything is spawned: [Gc.set] so the Domains inherit
the minor-heap size, and [set_plan] so each Domain can claim a core as it starts. *)
Expand Down
4 changes: 2 additions & 2 deletions docs/architecture/latency_optimization.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,8 @@ leaving them to be discovered:
the p50/p99 figures; the far tail is the major collector, which is stop-the-world across every
Domain. Reporting the maximum as order-path latency would blame the wrong component, and omitting
it would be worse.
- **The venue leg does not exist.** AlgoStream is paper trading — no exchange connectivity, no order
placement, no acknowledgement. This answers the latency target only for the part the project
- **The venue leg does not exist yet.** There is no exchange connectivity, no order placement and
no acknowledgement, so this answers the latency target only for the part the project
controls. Real execution latency is dominated by the network round trip and the venue's matching
engine, neither of which is measurable here.

Expand Down
6 changes: 3 additions & 3 deletions docs/architecture/system_overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

What AlgoStream is made of and how the pieces fit together.

**Scope.** This is paper-trading research infrastructure. There is no venue connectivity anywhere in
the project — no exchange credentials, no request signing, no trading endpoint. Fills are simulated
against live quotes.
**Scope.** This is research infrastructure with simulated execution. There is no venue connectivity
in the project today: no exchange credentials, no request signing, no trading endpoint. Fills are
simulated against live quotes.

## Shape

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/dashboard.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ containing markup therefore cannot become markup.
System health and latency, throughput, per-band queue depth, subsystem status, the portfolio NAV
curve, strategy control, positions, recent fills, and active alerts.

The paper-trading banner sits above all of them and is the most important element on the page.
The simulated-execution banner sits above all of them and is the most important element on the page.

## Known gaps / follow-ups

Expand Down
2 changes: 1 addition & 1 deletion docs/guides/deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ Service serves it, and a promotion and a rollback both complete without the Serv
endpoint. Multi-node is still unproven — see below. Where a number appears — CPU, memory, timeouts —
it is reasoned from the benchmarks rather than measured under production load.

This remains paper trading throughout. There is no venue connectivity in this project.
Execution is simulated throughout. There is no venue connectivity in this project today.

## The release container

Expand Down
6 changes: 3 additions & 3 deletions docs/guides/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

Building AlgoStream, running the tests, and getting a live dashboard in front of you.

**AlgoStream is paper trading.** There is no venue connectivity anywhere in the project — no
credentials, no request signing, no trading endpoint. Every fill is simulated against live quotes.
Nothing in this guide, or anywhere else, will place a real order.
**Execution is simulated.** There is no venue connectivity in this project today: no credentials,
no request signing, no trading endpoint. Every fill is simulated against live quotes. Nothing in
this guide, or anywhere else, will place a real order.

## Prerequisites

Expand Down
4 changes: 2 additions & 2 deletions lib/runtime/instance.ml
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,8 @@ let default_config ~strategy_id ~venue ~initial_capital =
initial_capital;
venue;
slippage = Slippage.Book_walk;
(* Unlike the backtest's [Latency.zero], live paper trading models the venue's real round trip:
an order submitted now is not matchable until the outbound delay has elapsed. *)
(* Unlike the backtest's [Latency.zero], the live runtime models the venue's real round trip: an
order submitted now is not matchable until the outbound delay has elapsed. *)
latency = Latency.of_venue venue ();
cost = Cost_model.default_config venue;
risk_limits = Some Risk_limits.default;
Expand Down
6 changes: 3 additions & 3 deletions site/dashboard/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@
.alert-msg { font-size: 12px; color: #C9C4B8; }
.alert-count { margin-left: auto; font-size: 10px; color: var(--dim); flex: none; }

/* paper-trading banner — the single most important thing on the page */
/* simulated-execution banner, the single most important thing on the page */
.paper {
display: flex; align-items: center; gap: 12px;
padding: 10px 16px;
Expand Down Expand Up @@ -189,9 +189,9 @@
</div>

<div class="paper">
<strong>Paper</strong>
<strong>Simulated</strong>
<span>Every order, fill and P&amp;L figure below is simulated against live quotes. This project has no
venue connectivity — no credentials, no request signing, no trading endpoint.</span>
venue connectivity today: no credentials, no request signing, no trading endpoint.</span>
</div>

<div class="dash">
Expand Down
2 changes: 1 addition & 1 deletion site/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ <h1>
<pre class="ascii-mark">┌─ <span class="dim">benchmark reference · apple silicon · release</span>
│ ingestion 427k ev/s binance parse
│ latency 0.07ms p50 · 0.15ms p99 at 50k ev/s
└─ paper trading · no venue connectivity</pre>
└─ simulated execution · no venue connectivity yet</pre>


<div class="meta-right">
Expand Down
14 changes: 7 additions & 7 deletions test/performance/order_path_latency.ml
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,12 @@
tick observed → strategy decides → risk gate → position sizing → routing → fill admitted
v}

{b The venue leg does not exist.} AlgoStream is paper trading — there is no connectivity to any
exchange, no order placement, no acknowledgement. So this answers the target only for the part
the project actually controls: from market data arriving to an order being handed to the fill
simulator. Real execution latency is dominated by the network round trip and the venue's
matching engine, neither of which is here. Quoting this figure as "order execution latency"
without that sentence would be dishonest, which is why the sentence is in the output.
{b The venue leg does not exist yet.} There is no connectivity to any exchange, no order
placement and no acknowledgement. So this answers the target only for the part the project
actually controls: from market data arriving to an order being handed to the fill simulator.
Real execution latency is dominated by the network round trip and the venue's matching engine,
neither of which is here. Quoting this figure as "order execution latency" without that sentence
would be dishonest, which is why the sentence is in the output.

{1 Method}

Expand Down Expand Up @@ -196,7 +196,7 @@ let main () =
\ is the p50/p99 figures. See docs/architecture/latency_optimization.md on GC.\n"
(ms p999) (ms max_v) ;
print_endline
" scope: market data in → order admitted to the fill simulator. AlgoStream is paper trading,\n\
" scope: market data in → order admitted to the fill simulator. Execution is simulated,\n\
\ so the venue round trip and matching are not included and cannot be measured here." ;

match json_path with
Expand Down
Loading