adona-robot — données de marché à la capacité

Un flux forex en direct par WebSocket

L'achat et la vente en direct, et les bougies à leur clôture, pour 46 paires de devises et 5 métaux, sur un seul WebSocket ouvert depuis votre serveur ou directement depuis un navigateur.

Se connecter
Votre serveur échange la clé d'API contre un jeton valable 12 heures. Avec le jeton, POST /v1/ws-ticket donne un ticket à usage unique, proposé comme second sous-protocole à côté de adona.data.v1, jamais dans l'URL. Une trame subscribe nomme ensuite les canaux.
Les canaux
quote:SYMBOLE pour l'achat et la vente en direct, candle:SYMBOLE:UNITÉ pour les bougies à leur clôture, sur S1, M1, M5, M15, H1, H4, D1. Jusqu'à 64 canaux par trame subscribe. À l'abonnement, chaque canal de bougies envoie d'abord ses bougies récentes, facturées en tranches comme une page REST : chaque reconnexion les paie à nouveau.
Les connexions
Un palier payant ne refuse jamais une connexion : le pic mensuel de connexions simultanées fixe le palier de la facture suivante. L'essai permet 3 connexions simultanées. Une fermeture avec le code 1008 et une raison, comme une clé révoquée ou un essai terminé, est une réponse : ne vous reconnectez pas en boucle dessus. Les autres fermetures sont passagères : reconnectez-vous après une pause.
Ce que cela coûte
Vendu à la capacité, dès CHF 500 par mois. La redistribution est permise sur chaque palier : un symbole que vos connexions suivent en direct plus de 80 % de ses heures d'ouverture dans le mois ajoute CHF 150 à la facture, en plus du palier.

Faits à la date du 03.10.2026.

Le code : le flux en direct, en JavaScript

stream.mjs
// Node 22+: live quotes and closed bars on one WebSocket. ADONA_API_KEY=... node stream.mjs
// In a browser the WebSocket part is the same; the token comes from your server, never the key.
const API = "https://api.adona-robot.com";
const STREAM = "wss://api.adona-robot.com/v1/stream";

async function post(path, bearer, body) {
  const response = await fetch(`${API}${path}`, {
    method: "POST",
    headers: { Authorization: `Bearer ${bearer}`, "Content-Type": "application/json" },
    body: body === undefined ? undefined : JSON.stringify(body),
  });
  if (!response.ok) throw new Error(`refused: ${response.status} ${await response.text()}`);
  return response.json();
}

// your server exchanges the key for a token
const { access_token: token } = await post("/v1/tokens", process.env.ADONA_API_KEY, { end_user_id: "u-42" });
// a single-use ticket, offered as the second subprotocol, never in the URL
const { ticket } = await post("/v1/ws-ticket", token);

const ws = new WebSocket(STREAM, ["adona.data.v1", `ticket.${ticket}`]);
ws.onopen = () =>
  ws.send(JSON.stringify({ type: "subscribe", request_id: "sub", payload: { channels: ["quote:EURUSD", "candle:EURUSD:M1"] } }));
ws.onmessage = (event) => {
  const { type, payload } = JSON.parse(event.data);
  if (type === "quote.update" || type === "quote.snapshot") console.log(type, payload.symbol, payload.bid, payload.ask);
  else if (type === "candle.snapshot") console.log(type, payload.channel, payload.candles.length, "bars");
  else if (type === "candle.bar") console.log(type, payload.symbol, payload.tf, payload.ts, payload.c); // short keys
  else console.log(type, payload);
};
// 1008 with a reason (revoked, trial ended) is an answer: do not reconnect in a loop on it
ws.onclose = (event) => console.log("closed", event.code, event.reason);

Premiers pas : de la clé au flux en direct, étape par étape

Ouvrir un compte

Guides liés

Paires et métaux