Real-Time Arbitrage
Stream live cross-venue arbitrage returns with the SDK and React hooks
Real-Time Arbitrage
AGG real-time arbitrage streams help prediction market apps find cross-venue price dislocations as
they happen. Use arbReturn to rank matched markets, power trading dashboards, alert users, or feed
agent workflows with live arbitrage signals.
arbReturn is the estimated cross-venue arbitrage return for a matched market — a decimal fraction
(e.g. 0.012 = 1.2%) derived from the best prices across the venues in a matched cluster. It is
available from three places:
- List Venue Events — an
arbReturnembedded in every listing row. Synced by a background job, so it can lag the live books; use it for initial render and sorting, not as a live signal. - Get Midpoints with
bestPrice=true— computed fresh by the pricing engine on every request. The REST source of truth when you need a current value on demand (agents, alerts, one-off checks) without holding a socket open. - WebSocket arb streams — pushes updates as they happen. The right choice for anything that stays on screen.
Two consumption modes:
- Per-market — for a detail view of one or a few markets.
- Feed — a single coalesced subscription for a whole listing, so you don't manage a subscription per visible row.
What you get
arbReturnon venue event and market listings for initial page loads and sorting.- Per-market WebSocket updates for focused detail views.
- A coalesced
arb-feedstream for large lists and dashboards. - SDK helpers (
subscribeArb,subscribeArbFeed) and React hooks (useMarketArb,useArbFeed). - Event-level rollups through
useArbFeed, wherebyEventkeeps the max livearbReturnacross markets in the same event.
The stream is delta-only and last-value-wins — there is no snapshot or sequence number. Load
the initial arbReturn from the REST listing, then layer the stream on top. A market that hasn't
moved since page load simply won't appear in the stream yet, so always fall back to the listing
value. Updates are loss-tolerant. See the WebSocket Protocol
for the wire format and the API Reference for REST
request and response details.
SDK (vanilla JS/TS)
import { createAggClient } from "@agg-build/sdk";
const client = createAggClient({
baseUrl: "https://api.agg.market",
appId: "your-app-id",
wsUrl: "wss://ws.agg.market/ws",
});
const ws = client.createWebSocket();
// Per-market: subscribe returns an unsubscribe function.
const offMarket = ws.subscribeArb("vm_1", (update) => {
// update: { type, marketId, activeVenuesOnly: true, venueEventId, arbReturn, ts }
renderArb(update.marketId, update.arbReturn);
});
// Last value received for a market (or null), e.g. to seed a re-render.
const current = ws.getArb("vm_1");
// Feed: one subscription for the whole listing.
const offFeed = ws.subscribeArbFeed((batch) => {
// batch.activeVenuesOnly === true; entries contain no per-entry venue metadata.
// batch.entries: [{ marketId, venueEventId, arbReturn, ts }, ...]
for (const e of batch.entries) {
updateRow(e.marketId, e.arbReturn);
}
});
// Clean up when done.
offMarket();
offFeed();
The SDK handles ref-counting (multiple subscribers to the same market share one server subscription) and re-subscribes automatically on reconnect.
React (hooks)
One market
import { useMarketArb } from "@agg-build/hooks";
function ArbBadge({ marketId, initialArbReturn }: { marketId: string; initialArbReturn: number }) {
const { arbReturn, isLive } = useMarketArb(marketId);
// Fall back to the listing value until the first live update arrives.
const value = arbReturn ?? initialArbReturn;
return (
<span>
{(value * 100).toFixed(2)}%{isLive ? " ●" : ""}
</span>
);
}
A listing (feed)
useArbFeed maintains a live byMarket map and a derived byEvent map (the max arbReturn
across the markets of each venueEventId), so you can render either market-level or event-level
arbitrage live.
import { useArbFeed } from "@agg-build/hooks";
function EventList({ events }: { events: VenueEvent[] }) {
const { byEvent } = useArbFeed();
return (
<ul>
{events.map((event) => {
// Live value if the feed has sent one for this event, else the listing value.
const arb = byEvent.get(event.id) ?? event.arbReturn ?? 0;
return (
<li key={event.id}>
{event.title} — {(arb * 100).toFixed(2)}%
</li>
);
})}
</ul>
);
}
Initial value: the feed only carries markets whose value has changed, so a freshly loaded
row may not be in byMarket/byEvent yet. Always resolve with feedValue ?? restValue — read
arbReturn from your listing response as the fallback.
Sort stability: if you sort a listing by arbReturn, re-sorting on every flush makes rows
jump. Prefer updating values in place and re-sorting only on an explicit user action or the next
listing refetch.
FAQ
What is prediction market arbitrage?
Prediction market arbitrage is a cross-venue price dislocation where matched markets imply a positive return if the relevant outcomes can be bought or hedged at the displayed prices. AGG calculates this signal on matched market clusters so apps can spot opportunities across venues without building their own matching and price-comparison layer.
What does arbReturn mean?
arbReturn is the estimated arbitrage return expressed as a decimal fraction. For example,
0.012 means an estimated 1.2% cross-venue return for that matched market based on the best prices
AGG sees in the cluster. Use it as a ranking, alerting, or trading signal, and render it as a
percentage in user-facing views.
Is arbReturn guaranteed execution?
No. arbReturn is a real-time market signal, not a guaranteed fill or guaranteed profit. Execution
can still depend on venue availability, liquidity, routeability, fees, stale prices, slippage, and
order timing. Before placing trades, check the relevant market and outcome routeability fields and
use AGG's routing and execution APIs for executable quotes.
Should I use REST or WebSocket data?
Use the venue-event listing to load the initial page, filters, and fallback arbReturn values, then
use WebSocket data to keep visible markets live. The WebSocket stream is delta-only, so it does not
replace the listing response.
If you need a fresh value over REST — for example an agent or alerting job that polls rather than
holding a socket — call GET /midpoints?bestPrice=true
with the market ids you care about. Its arbReturn is computed by the pricing engine at request
time, unlike the listing value, which a background sync can leave stale.
For request schemas and parameters, use the List Venue Events API reference; for live message shapes, use the WebSocket Protocol.