@blackcube/xgate-sdk 0.22.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +344 -24
- package/dist/index.cjs +875 -155
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +452 -5
- package/dist/index.d.ts +452 -5
- package/dist/index.js +873 -156
- package/dist/index.js.map +1 -1
- package/package.json +10 -10
package/dist/index.d.cts
CHANGED
|
@@ -312,6 +312,120 @@ declare class WsCandlesService {
|
|
|
312
312
|
private quoteOf;
|
|
313
313
|
}
|
|
314
314
|
|
|
315
|
+
/**
|
|
316
|
+
* LE FLUX DE BOUGIES D'UNE VENUE — porté de
|
|
317
|
+
* `Blips/server/src/candles/services/internal/dex-candles-stream.service.ts`, où il tourne en
|
|
318
|
+
* production. Même surface, mêmes garanties ; seul le type de bougie change (celui d'XGate).
|
|
319
|
+
*
|
|
320
|
+
* **UNE INSTANCE PAR VENUE, DONC UNE SOCKET PAR VENUE.** La façade est mémoïsée (`instance()`) et
|
|
321
|
+
* `ws()` n'est appelé qu'une fois, hors de la boucle : les N souscriptions partagent la même
|
|
322
|
+
* connexion. Créer la façade à chaque souscription ouvrirait une socket par marché — 200 marchés
|
|
323
|
+
* suivis, 200 sockets, quand hyperliquid n'en accepte que 10 par IP.
|
|
324
|
+
*
|
|
325
|
+
* **UNE SOUSCRIPTION PAR MARCHÉ, et non `subscribeAllCandles`.** Ce dernier ne coûte qu'un
|
|
326
|
+
* abonnement, mais il est bâti sur un flux de prix agrégé : mesuré le 2026-08-02, il rend un prix
|
|
327
|
+
* MILIEU (40 % des valeurs sur un demi-tick contre 8 % au REST) et AUCUN volume (`"v":"0"` sur les
|
|
328
|
+
* six dex). Le canal `candle` par marché rend la vraie bougie de trades, avec son volume.
|
|
329
|
+
*
|
|
330
|
+
* **LE SYMBOLE VIENT DU MESSAGE**, jamais de la souscription. Les SDK hyperliquid et pacifica
|
|
331
|
+
* livraient tout le canal à tous les abonnés jusqu'à la 0.15.0 — trois souscriptions recevaient le
|
|
332
|
+
* même flux. C'est corrigé, mais la règle reste : on lit ce que le wire déclare, on ne suppose pas.
|
|
333
|
+
*/
|
|
334
|
+
declare class CandlesStreamService {
|
|
335
|
+
readonly xex: XgateEx;
|
|
336
|
+
/** Le marché écouté. Le comptant n'est servi que par binance et bybit. */
|
|
337
|
+
readonly kind: MarketKind;
|
|
338
|
+
private readonly logger;
|
|
339
|
+
private source;
|
|
340
|
+
private readonly unsubscribes;
|
|
341
|
+
/** Le plafond de souscriptions documenté par la venue, ou `null` si personne ne l'a publié. */
|
|
342
|
+
readonly maxSubscriptions: number | null;
|
|
343
|
+
constructor(xex: XgateEx,
|
|
344
|
+
/** Le marché écouté. Le comptant n'est servi que par binance et bybit. */
|
|
345
|
+
kind?: MarketKind);
|
|
346
|
+
/**
|
|
347
|
+
* Ouvre le flux sur une LISTE de marchés, sur une seule socket.
|
|
348
|
+
*
|
|
349
|
+
* **UNE ERREUR DE FLUX COUPE TOUT, PUIS LÈVE.** Elle n'arrive pas à la souscription : mesuré le
|
|
350
|
+
* 2026-08-07, la venue accepte un symbole inconnu sans broncher, puis ferme la connexion en le
|
|
351
|
+
* découvrant. Le SDK reconnecte, elle referme — cinq cycles en douze secondes, et sur une socket
|
|
352
|
+
* partagée **tous** les marchés valides cessent de recevoir, en silence.
|
|
353
|
+
*
|
|
354
|
+
* On refuse cette boucle : à la première erreur, les souscriptions sont coupées, l'incident est
|
|
355
|
+
* journalisé en `error`, et l'exception part. Un flux à moitié mort qui se tait coûte plus cher
|
|
356
|
+
* qu'un arrêt franc — on ne découvre le premier qu'en constatant l'absence de données.
|
|
357
|
+
*
|
|
358
|
+
* ⚠️ L'exception naît dans un rappel de socket : elle ne remonte pas à l'appelant de `start()`,
|
|
359
|
+
* elle sort en erreur non capturée. C'est délibéré — elle doit être impossible à ignorer.
|
|
360
|
+
*
|
|
361
|
+
* **binance et bybit ne remontent pas encore leurs erreurs** : leur client gère la fermeture en
|
|
362
|
+
* interne sans l'exposer. Sur ces deux venues, la boucle silencieuse reste possible.
|
|
363
|
+
*/
|
|
364
|
+
start(symbolsXex: string[], interval: Timeframe, onCandle: (candle: ICandle) => void): void;
|
|
365
|
+
/** Coupe tout. Un désabonnement qui échoue ne doit pas empêcher les autres de se fermer. */
|
|
366
|
+
stop(): void;
|
|
367
|
+
/** Le nombre de souscriptions ouvertes. La liste des désabonnements EST le compteur. */
|
|
368
|
+
subscriptionCount(): number;
|
|
369
|
+
/**
|
|
370
|
+
* Le client temps réel, sur le bon marché.
|
|
371
|
+
*
|
|
372
|
+
* Les deux contrats ne signent pas `ws()` pareil, et c'est voulu : côté comptant le marché est
|
|
373
|
+
* **obligatoire** (`ws('spot')`), parce que les façades ouvrent du perpétuel par défaut — un
|
|
374
|
+
* `ws()` nu y diffuserait des prix de perpétuel à qui croit écouter le comptant.
|
|
375
|
+
*/
|
|
376
|
+
private wire;
|
|
377
|
+
/** La façade de la venue, créée une seule fois : c'est elle qui porte la socket partagée. */
|
|
378
|
+
private instance;
|
|
379
|
+
/** Voir `CandlesService.quoteOf` : la cotation se déduit du symbole natif, faute d'être publiée. */
|
|
380
|
+
private quoteOf;
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* LA FAÇADE : un flux par venue, et un seul.
|
|
384
|
+
*
|
|
385
|
+
* Blips instancie `DexCandlesStreamService` une fois par venue et garde la référence. XGate offre
|
|
386
|
+
* la même chose sans que l'appelant ait à tenir cette table : `of(xex)` rend **toujours la même
|
|
387
|
+
* instance** pour une venue et un marché donnés — donc toujours la même socket.
|
|
388
|
+
*
|
|
389
|
+
* Demander deux fois `of(hyperliquid)` et souscrire 100 marchés à chaque fois ouvre **une** socket
|
|
390
|
+
* avec 200 souscriptions, pas deux sockets. C'est exactement ce qui manquait.
|
|
391
|
+
*/
|
|
392
|
+
declare class CandlesStreamRegistry {
|
|
393
|
+
private readonly streams;
|
|
394
|
+
/** Le flux d'une venue, créé au premier appel puis réutilisé. */
|
|
395
|
+
of(xex: XgateEx, kind?: MarketKind): CandlesStreamService;
|
|
396
|
+
/** Coupe tous les flux ouverts, toutes venues confondues. */
|
|
397
|
+
stopAll(): void;
|
|
398
|
+
/** Ce qui est ouvert, par venue — pour surveiller sans avoir à tenir de compteur soi-même. */
|
|
399
|
+
counts(): Record<string, number>;
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* LES PLAFONDS DE SOUSCRIPTION, PAR VENUE — uniquement ceux qu'une documentation officielle donne.
|
|
404
|
+
*
|
|
405
|
+
* Repris de `Blips/server/src/candles/services/internal/dex-candles-stream.service.ts`, où ils ont
|
|
406
|
+
* été établis puis vérifiés en réel.
|
|
407
|
+
*
|
|
408
|
+
* **aster**, section « Websocket Market Streams » : « A single connection can listen to a maximum
|
|
409
|
+
* of 200 streams », et « A connection that goes beyond the limit will be disconnected; IPs that are
|
|
410
|
+
* repeatedly disconnected may be banned ». Vérifié le 2026-08-03 sur `fstream.asterdex.com` : 200
|
|
411
|
+
* tiennent, 300 tuent la connexion.
|
|
412
|
+
* <https://github.com/asterdex/api-docs/blob/master/V3(Recommended)/EN/aster-finance-futures-api-v3.md>
|
|
413
|
+
*
|
|
414
|
+
* **hyperliquid** : 1 000 souscriptions et 10 connexions par IP.
|
|
415
|
+
*
|
|
416
|
+
* **Une venue ABSENTE de cette table n'a pas de plafond DOCUMENTÉ** — ce qui n'est pas la même
|
|
417
|
+
* chose que « pas de plafond ». On ne devine aucun chiffre : le jour où l'une d'elles s'en
|
|
418
|
+
* approche, on lit sa documentation et on l'ajoute.
|
|
419
|
+
*/
|
|
420
|
+
declare const WS_SUBSCRIPTION_LIMITS: Partial<Record<XgateEx, number>>;
|
|
421
|
+
/**
|
|
422
|
+
* Le plafond documenté d'une venue, ou `undefined` si personne ne l'a publié.
|
|
423
|
+
*
|
|
424
|
+
* Rendre `Infinity` par défaut serait un mensonge commode : l'absence de plafond connu n'est pas
|
|
425
|
+
* une garantie d'illimité.
|
|
426
|
+
*/
|
|
427
|
+
declare function subscriptionLimitOf(xex: XgateEx): number | undefined;
|
|
428
|
+
|
|
315
429
|
/**
|
|
316
430
|
* UNE COTATION, TELLE QU'XGATE LA REND — quelle que soit la venue d'où elle vient.
|
|
317
431
|
*
|
|
@@ -433,10 +547,13 @@ declare class SpotCatalogService {
|
|
|
433
547
|
* comptant, sans que rien ne le signale. Deux marchés, deux services ; l'appelant choisit
|
|
434
548
|
* explicitement ce qu'il interroge.
|
|
435
549
|
*
|
|
436
|
-
* La différence n'est pas cosmétique : le perpétuel porte un funding et
|
|
437
|
-
*
|
|
438
|
-
*
|
|
439
|
-
*
|
|
550
|
+
* La différence n'est pas cosmétique : **le perpétuel porte un funding et s'écarte du comptant**.
|
|
551
|
+
* C'est cet écart que certaines stratégies exploitent — le confondre le rendrait invisible.
|
|
552
|
+
*
|
|
553
|
+
* En revanche, les échelles de cotation ne posent aucun problème entre les deux marchés :
|
|
554
|
+
* `SATSUSDT` (×1) et `10000SATSUSDT` (×10000) sont **deux paires distinctes**, chacune portant son
|
|
555
|
+
* `multiplier` au catalogue. Une bougie appartient à une paire, identifiée par `xex` +
|
|
556
|
+
* `symbolXex` + `kind` : il n'y a rien à réconcilier.
|
|
440
557
|
*
|
|
441
558
|
* **Aucune agrégation ici**, contrairement au perpétuel : binance et bybit servent nativement tous
|
|
442
559
|
* les intervalles de `1m` à `1w`. Le jour où une venue comptant en manquerait un, ce serait à
|
|
@@ -463,6 +580,70 @@ declare class SpotCandlesService {
|
|
|
463
580
|
candlesOf(xexes: XgateEx[], query: ICandlesQuery): Promise<ICandle[]>;
|
|
464
581
|
}
|
|
465
582
|
|
|
583
|
+
/**
|
|
584
|
+
* LES PRIX DU **COMPTANT** — binance et bybit.
|
|
585
|
+
*
|
|
586
|
+
* Séparé de `PricesService` comme le catalogue et les bougies le sont : deux marchés, deux
|
|
587
|
+
* services. Ici la raison est encore plus directe qu'ailleurs — **un prix comptant et un prix
|
|
588
|
+
* perpétuel ne sont pas le même nombre**. Le perpétuel porte un funding et s'écarte du comptant ;
|
|
589
|
+
* c'est justement cet écart que certaines stratégies exploitent, et le confondre le rendrait
|
|
590
|
+
* invisible.
|
|
591
|
+
*
|
|
592
|
+
* **La moitié des champs sont `null` au comptant, et c'est correct** : `mark`, `oracle`, `funding`
|
|
593
|
+
* et `openInterest` n'existent que pour un perpétuel. Le comptant renseigne `bid`, `ask`, `last`,
|
|
594
|
+
* `volume24h` — ce qui est mesuré, pas ce qui est dérivé d'un contrat.
|
|
595
|
+
*/
|
|
596
|
+
declare class SpotPricesService {
|
|
597
|
+
private readonly logger;
|
|
598
|
+
/** Les venues dont XGate sert les prix comptant. */
|
|
599
|
+
venues(): readonly XgateEx[];
|
|
600
|
+
/**
|
|
601
|
+
* Les prix comptant d'une ou plusieurs venues, en une seule liste.
|
|
602
|
+
*
|
|
603
|
+
* Même politique d'échec que partout : seule, une venue en échec fait échouer l'appel ; parmi
|
|
604
|
+
* d'autres, elle est journalisée et ignorée. Chaque prix porte son `xex`.
|
|
605
|
+
*/
|
|
606
|
+
prices(...xexes: XgateEx[]): Promise<IPrice[]>;
|
|
607
|
+
/** Les prix comptant d'UNE venue, traduits vers {@link IPrice}. */
|
|
608
|
+
private pricesOf;
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* LES BOUGIES DU **COMPTANT** EN TEMPS RÉEL — binance et bybit.
|
|
613
|
+
*
|
|
614
|
+
* Le pendant de `WsCandlesService`, sur l'autre marché. La séparation n'est pas une symétrie
|
|
615
|
+
* décorative : les façades exposent `ws(kind = 'perp')`, donc **un `ws()` nu ouvre un flux de
|
|
616
|
+
* perpétuels**. Un service unique qui aurait oublié de passer le marché aurait diffusé des prix
|
|
617
|
+
* de perpétuel à qui croyait écouter le comptant — deux séries voisines, jamais égales, et rien
|
|
618
|
+
* pour le signaler.
|
|
619
|
+
*
|
|
620
|
+
* Le contrat {@link IXexSpotSource} exige donc `ws('spot')` explicitement, sans valeur par défaut.
|
|
621
|
+
*/
|
|
622
|
+
declare class SpotWsCandlesService {
|
|
623
|
+
private readonly logger;
|
|
624
|
+
/** Les venues dont XGate diffuse le comptant en temps réel. */
|
|
625
|
+
venues(): readonly XgateEx[];
|
|
626
|
+
/**
|
|
627
|
+
* Souscrit aux bougies **comptant** d'un marché. Rend la fonction de désabonnement.
|
|
628
|
+
*
|
|
629
|
+
* Le handler reçoit une bougie à la fois, au format unifié ; la bougie en cours est repoussée à
|
|
630
|
+
* chaque mise à jour tant qu'elle n'est pas close.
|
|
631
|
+
*/
|
|
632
|
+
subscribe(xex: XgateEx, query: {
|
|
633
|
+
symbol: string;
|
|
634
|
+
interval: Timeframe;
|
|
635
|
+
}, handler: (candle: ICandle) => void): Unsubscribe;
|
|
636
|
+
/**
|
|
637
|
+
* Souscrit au MÊME marché comptant chez plusieurs venues, avec un seul handler.
|
|
638
|
+
*
|
|
639
|
+
* Chaque bougie porte son `xex`. La fonction rendue coupe tous les flux d'un coup.
|
|
640
|
+
*/
|
|
641
|
+
subscribeAll(xexes: XgateEx[], query: {
|
|
642
|
+
symbol: string;
|
|
643
|
+
interval: Timeframe;
|
|
644
|
+
}, handler: (candle: ICandle) => void): Unsubscribe;
|
|
645
|
+
}
|
|
646
|
+
|
|
466
647
|
/** Une paire, telle qu'un SDK de venue la rend. */
|
|
467
648
|
interface IXexPair {
|
|
468
649
|
name: string;
|
|
@@ -555,6 +736,18 @@ interface IXexSpotSource {
|
|
|
555
736
|
}): Promise<IXexCandle[]>;
|
|
556
737
|
getPrices?(): Promise<IXexPrice[]>;
|
|
557
738
|
};
|
|
739
|
+
/**
|
|
740
|
+
* Le temps réel du COMPTANT. **`kind` est obligatoire ici**, contrairement aux façades qui le
|
|
741
|
+
* rendent optionnel : leur défaut est `'perp'`, et un `ws()` nu ouvre donc un flux de perpétuels
|
|
742
|
+
* en croyant écouter le comptant — deux marchés dont les prix diffèrent, sans que rien ne le
|
|
743
|
+
* signale.
|
|
744
|
+
*/
|
|
745
|
+
ws(kind: 'spot'): {
|
|
746
|
+
subscribeCandles(query: {
|
|
747
|
+
name: string;
|
|
748
|
+
interval: string;
|
|
749
|
+
}, handler: (candle: IXexCandle) => void): () => void;
|
|
750
|
+
};
|
|
558
751
|
}
|
|
559
752
|
/**
|
|
560
753
|
* De quoi lire UN compte chez une venue.
|
|
@@ -935,6 +1128,69 @@ interface IPosition {
|
|
|
935
1128
|
margin: string | null;
|
|
936
1129
|
xtras?: Record<string, unknown>;
|
|
937
1130
|
}
|
|
1131
|
+
/**
|
|
1132
|
+
* UNE TRANSACTION PUBLIQUE — celles de tout le monde sur un marché, pas les siennes.
|
|
1133
|
+
*
|
|
1134
|
+
* À ne pas confondre avec {@link ITrade}, qui est une exécution **du compte**. Celle-ci n'a ni
|
|
1135
|
+
* frais, ni PnL, ni identifiant d'ordre : on ne voit que ce que le marché montre.
|
|
1136
|
+
*/
|
|
1137
|
+
interface IPublicTrade {
|
|
1138
|
+
xex: XgateEx;
|
|
1139
|
+
symbolXex: string;
|
|
1140
|
+
price: string;
|
|
1141
|
+
size: string;
|
|
1142
|
+
/** Sens de l'AGRESSEUR : `buy` = quelqu'un a pris l'offre. */
|
|
1143
|
+
side: Side;
|
|
1144
|
+
tradedAt: Date;
|
|
1145
|
+
xtras?: Record<string, unknown>;
|
|
1146
|
+
}
|
|
1147
|
+
/**
|
|
1148
|
+
* L'ÉTAT D'UN COMPTE — ce que toutes les venues disent, sous des noms différents.
|
|
1149
|
+
*
|
|
1150
|
+
* Les formes natives ne se ressemblent pas : hyperliquid range son équité sous
|
|
1151
|
+
* `marginSummary.accountValue`, pacifica sous `accountEquity`, aster sous `totalMarginBalance`.
|
|
1152
|
+
* **Mais les concepts, eux, sont les mêmes** — c'est exactement ce qu'XGate existe pour normaliser.
|
|
1153
|
+
*
|
|
1154
|
+
* `xtras` conserve la forme native complète : ce qui est propre à une venue n'est pas perdu, il
|
|
1155
|
+
* n'est simplement pas promu au rang de contrat.
|
|
1156
|
+
*/
|
|
1157
|
+
interface IAccountState {
|
|
1158
|
+
xex: XgateEx;
|
|
1159
|
+
/** Valeur totale du compte, PnL latent compris. */
|
|
1160
|
+
equity: string;
|
|
1161
|
+
/** Ce qui reste mobilisable — pour ouvrir ou retirer. `null` si la venue ne le publie pas. */
|
|
1162
|
+
available: string | null;
|
|
1163
|
+
/** Marge immobilisée par les positions et ordres en cours. */
|
|
1164
|
+
marginUsed: string | null;
|
|
1165
|
+
/** Marge de maintenance : sous ce seuil, la liquidation menace. */
|
|
1166
|
+
maintenanceMargin: string | null;
|
|
1167
|
+
/**
|
|
1168
|
+
* PnL non réalisé des positions ouvertes.
|
|
1169
|
+
*
|
|
1170
|
+
* **Seule aster le publie au niveau du compte.** hyperliquid et pacifica ne l'exposent pas là —
|
|
1171
|
+
* il se lit alors sur les positions (`IPosition.unrealizedPnl`), qui le portent toutes. On rend
|
|
1172
|
+
* `null` plutôt que de le reconstituer : une somme calculée ici passerait pour une donnée de la
|
|
1173
|
+
* venue.
|
|
1174
|
+
*/
|
|
1175
|
+
unrealizedPnl: string | null;
|
|
1176
|
+
/** L'état natif COMPLET, tel que la venue le publie. */
|
|
1177
|
+
xtras?: Record<string, unknown>;
|
|
1178
|
+
}
|
|
1179
|
+
/**
|
|
1180
|
+
* UN FUNDING PAYÉ — ce qui a réellement été prélevé ou reçu sur une position.
|
|
1181
|
+
*
|
|
1182
|
+
* À ne pas confondre avec le taux courant d'`IPrice.funding`, qui annonce ce qui *sera* payé. Un
|
|
1183
|
+
* calcul de résultat qui ignore ce qui l'a été surestime toute position tenue longtemps.
|
|
1184
|
+
*/
|
|
1185
|
+
interface IFundingPaid {
|
|
1186
|
+
xex: XgateEx;
|
|
1187
|
+
symbolXex: string;
|
|
1188
|
+
/** Le taux appliqué, en fraction. */
|
|
1189
|
+
rate: string;
|
|
1190
|
+
/** Moment où il a été prélevé. */
|
|
1191
|
+
appliedAt: Date;
|
|
1192
|
+
xtras?: Record<string, unknown>;
|
|
1193
|
+
}
|
|
938
1194
|
/** UNE EXÉCUTION du compte — ce qui a réellement été rempli, par opposition à ce qui a été demandé. */
|
|
939
1195
|
interface ITrade {
|
|
940
1196
|
xex: XgateEx;
|
|
@@ -1061,6 +1317,18 @@ declare class TradingService {
|
|
|
1061
1317
|
* conditionnels. Le SDK de la venue s'en charge ; xgate fournit des niveaux justes.
|
|
1062
1318
|
*/
|
|
1063
1319
|
openWithProtection(access: ITradingAccess, input: IEntryWithProtection): Promise<IOrder[]>;
|
|
1320
|
+
/**
|
|
1321
|
+
* CE QUE LA VENUE A RÉELLEMENT FAIT, après une réponse perdue.
|
|
1322
|
+
*
|
|
1323
|
+
* Un timeout ne dit pas « rien n'a été créé » : mesuré sur aster, deux exécutions identiques ont
|
|
1324
|
+
* produit deux sous-ensembles différents — une fois le stop et un take-profit, une fois l'entrée
|
|
1325
|
+
* seule. La seule vérité est au carnet, donc on va l'y chercher.
|
|
1326
|
+
*
|
|
1327
|
+
* **Lève si la position est nue** : une entrée remplie sans stop est exactement ce que ce service
|
|
1328
|
+
* existe pour empêcher, et le silence serait pire que l'erreur. L'appelant doit savoir qu'il a une
|
|
1329
|
+
* position à protéger, tout de suite.
|
|
1330
|
+
*/
|
|
1331
|
+
private etatApres;
|
|
1064
1332
|
/** Les positions ouvertes d'un compte. */
|
|
1065
1333
|
positions(access: ITradingAccess, symbolXex?: string): Promise<IPosition[]>;
|
|
1066
1334
|
/** Les ordres encore au carnet. */
|
|
@@ -1109,10 +1377,120 @@ declare class TradingService {
|
|
|
1109
1377
|
* take-profits partiels, celui-là est la clôture.
|
|
1110
1378
|
*/
|
|
1111
1379
|
exitPrice(access: ITradingAccess, symbolXex: string, direction: Direction, openedAt: Date): Promise<string | null>;
|
|
1380
|
+
/**
|
|
1381
|
+
* L'HISTORIQUE DES ORDRES du compte — ce qui a été soumis, rempli, annulé ou expiré.
|
|
1382
|
+
*
|
|
1383
|
+
* À distinguer de {@link trades} : un ordre est une **intention**, une exécution est un **fait**.
|
|
1384
|
+
* Un ordre `filled` peut avoir été rempli en plusieurs fois, à des prix différents.
|
|
1385
|
+
*
|
|
1386
|
+
* Servi par les huit venues qui tradent.
|
|
1387
|
+
*/
|
|
1388
|
+
orderHistory(access: ITradingAccess, symbolXex?: string): Promise<IOrder[]>;
|
|
1389
|
+
/**
|
|
1390
|
+
* L'ÉTAT DU COMPTE — équité, disponible, marge immobilisée, marge de maintenance, PnL latent.
|
|
1391
|
+
*
|
|
1392
|
+
* Les venues rangent ces valeurs sous des noms qui n'ont rien à voir : `marginSummary.accountValue`
|
|
1393
|
+
* chez hyperliquid, `accountEquity` chez pacifica, `totalMarginBalance` chez aster — **mais elles
|
|
1394
|
+
* disent la même chose**. La forme native complète reste dans `xtras`, rien n'est perdu.
|
|
1395
|
+
*
|
|
1396
|
+
* **blofin ne l'expose pas** et lève ; les sept autres le servent.
|
|
1397
|
+
*/
|
|
1398
|
+
accountInfo(access: ITradingAccess): Promise<IAccountState>;
|
|
1399
|
+
/**
|
|
1400
|
+
* RÈGLE LE LEVIER d'une paire, avant d'ouvrir.
|
|
1401
|
+
*
|
|
1402
|
+
* Le levier détermine la marge immobilisée, donc la taille tenable : le changer après l'ouverture
|
|
1403
|
+
* ne rejoue pas la position déjà prise. C'est un réglage préalable, pas un ajustement.
|
|
1404
|
+
*
|
|
1405
|
+
* **bullet ne l'expose pas** — son levier se fixe au compte, pas à la position — et lève.
|
|
1406
|
+
*/
|
|
1407
|
+
setLeverage(access: ITradingAccess, symbolXex: string, leverage: number): Promise<void>;
|
|
1408
|
+
/**
|
|
1409
|
+
* CHOISIT LE MODE DE MARGE d'une paire : **isolée** ou **croisée**.
|
|
1410
|
+
*
|
|
1411
|
+
* En **croisée**, tout le solde du compte garantit la position : elle tient plus longtemps, mais
|
|
1412
|
+
* une liquidation emporte l'ensemble. En **isolée**, seule la marge affectée est en jeu : la perte
|
|
1413
|
+
* est bornée à ce montant, la liquidation arrive plus tôt.
|
|
1414
|
+
*
|
|
1415
|
+
* **À régler AVANT d'ouvrir.** Changer le mode d'une position vivante est refusé par la plupart
|
|
1416
|
+
* des venues, et là où c'est accepté, cela redistribue la garantie sous les pieds de la position.
|
|
1417
|
+
*
|
|
1418
|
+
* Servi par les trois venues de référence.
|
|
1419
|
+
*/
|
|
1420
|
+
setMarginMode(access: ITradingAccess, symbolXex: string, isolated: boolean): Promise<void>;
|
|
1421
|
+
/**
|
|
1422
|
+
* AJOUTE DE LA MARGE à une position isolée — pour éloigner le prix de liquidation.
|
|
1423
|
+
*
|
|
1424
|
+
* C'est le geste qui sauve une position sous pression sans la réduire : on renforce la garantie
|
|
1425
|
+
* plutôt que de couper. **N'a de sens qu'en marge isolée** ; en croisée, tout le solde garantit
|
|
1426
|
+
* déjà la position et il n'y a rien à ajouter.
|
|
1427
|
+
*
|
|
1428
|
+
* Servi par les trois venues de référence.
|
|
1429
|
+
*/
|
|
1430
|
+
addMargin(access: ITradingAccess, symbolXex: string, amount: string): Promise<void>;
|
|
1431
|
+
/**
|
|
1432
|
+
* RETIRE DE LA MARGE d'une position isolée — pour libérer du capital.
|
|
1433
|
+
*
|
|
1434
|
+
* L'inverse d'{@link addMargin} : la garantie diminue, donc le prix de liquidation **se rapproche**.
|
|
1435
|
+
* La venue refuse ce qui mettrait la position sous son seuil de maintenance.
|
|
1436
|
+
*
|
|
1437
|
+
* ⚠️ **pacifica ne l'expose pas** et lève : chez elle, la marge s'ajoute mais ne se retire pas.
|
|
1438
|
+
* Fermer partiellement la position libère alors le capital.
|
|
1439
|
+
*/
|
|
1440
|
+
removeMargin(access: ITradingAccess, symbolXex: string, amount: string): Promise<void>;
|
|
1441
|
+
/**
|
|
1442
|
+
* L'HISTORIQUE DU FUNDING **PAYÉ** sur une paire — ce qui a réellement été prélevé ou reçu.
|
|
1443
|
+
*
|
|
1444
|
+
* À ne pas confondre avec le taux courant, que rend `PricesService` : celui-ci annonce ce qui
|
|
1445
|
+
* *sera* payé, celui-là dit ce qui *l'a été*. Un backtest qui ignore le funding réel surestime le
|
|
1446
|
+
* résultat d'une position tenue longtemps.
|
|
1447
|
+
*
|
|
1448
|
+
* Servi par les huit venues qui tradent.
|
|
1449
|
+
*/
|
|
1450
|
+
fundingHistory(access: ITradingAccess, symbolXex: string, range?: {
|
|
1451
|
+
startTime?: Date;
|
|
1452
|
+
endTime?: Date;
|
|
1453
|
+
limit?: number;
|
|
1454
|
+
}): Promise<IFundingPaid[]>;
|
|
1455
|
+
/**
|
|
1456
|
+
* UN IDENTIFIANT APPLICATIF pour un ordre, **au format que la venue accepte**.
|
|
1457
|
+
*
|
|
1458
|
+
* C'est lui qui relie un ordre à la décision qui l'a produit : la venue le rend tel quel dans
|
|
1459
|
+
* `IOrder.clientId`, ce qui permet de retrouver son origine sans tenir de table de correspondance.
|
|
1460
|
+
*
|
|
1461
|
+
* **hyperliquid exige un hexadécimal préfixé `0x`** (128 bits) là où les autres acceptent un UUID
|
|
1462
|
+
* ordinaire. Passer le mauvais format fait rejeter l'ordre — d'où cette méthode plutôt qu'un
|
|
1463
|
+
* `randomUUID()` chez l'appelant.
|
|
1464
|
+
*/
|
|
1465
|
+
newClientOrderId(xex: XgateEx): string;
|
|
1466
|
+
/**
|
|
1467
|
+
* LE COUPE-CIRCUIT : annule TOUS les ordres d'une paire, d'un geste.
|
|
1468
|
+
*
|
|
1469
|
+
* À réserver aux situations où l'on veut reprendre la main sans discuter — un état incohérent, un
|
|
1470
|
+
* arrêt d'urgence, une reprise après incident. Annuler un par un laisse une fenêtre pendant
|
|
1471
|
+
* laquelle certains ordres vivent encore.
|
|
1472
|
+
*
|
|
1473
|
+
* ⚠️ **Cela retire aussi les PROTECTIONS.** Stops et take-profits sont des ordres comme les
|
|
1474
|
+
* autres : une position ouverte se retrouve **nue** après ce geste. À n'employer que si la
|
|
1475
|
+
* position est fermée, ou si l'on repose une protection immédiatement — jamais pour « faire le
|
|
1476
|
+
* ménage » sur une position vivante.
|
|
1477
|
+
*
|
|
1478
|
+
* Rend le nombre d'ordres annulés quand la venue le publie, `null` sinon.
|
|
1479
|
+
*/
|
|
1480
|
+
cancelAll(access: ITradingAccess, symbolXex: string): Promise<number | null>;
|
|
1112
1481
|
/** Annule un ordre par son identifiant de venue. */
|
|
1113
1482
|
cancel(access: ITradingAccess, symbolXex: string, orderId: string): Promise<void>;
|
|
1114
1483
|
/** Le scope `perp()` de la venue, typé au plus près de ce que le contrat commun garantit. */
|
|
1115
1484
|
private perpOf;
|
|
1485
|
+
/**
|
|
1486
|
+
* L'état natif d'une venue → {@link IAccountState}.
|
|
1487
|
+
*
|
|
1488
|
+
* Une lecture EXPLICITE par venue plutôt qu'un parcours à l'aveugle : les noms ne se devinent pas,
|
|
1489
|
+
* et prendre le premier champ qui ressemble à une équité produirait un chiffre faux sans que rien
|
|
1490
|
+
* ne le signale. `null` là où la venue ne publie pas la valeur — pas `0`, qui se lirait comme
|
|
1491
|
+
* « rien » alors que personne n'a rien dit.
|
|
1492
|
+
*/
|
|
1493
|
+
private toAccountState;
|
|
1116
1494
|
/**
|
|
1117
1495
|
* Le statut de la venue, VALIDÉ — jamais casté. Une venue qui inventerait un statut rendrait sinon
|
|
1118
1496
|
* une valeur absente de tous les `switch` en aval, et personne ne la rattraperait.
|
|
@@ -1121,6 +1499,75 @@ declare class TradingService {
|
|
|
1121
1499
|
private toOrder;
|
|
1122
1500
|
}
|
|
1123
1501
|
|
|
1502
|
+
/**
|
|
1503
|
+
* LE FLUX DES EXÉCUTIONS DU COMPTE — savoir ce qui s'est rempli, à l'instant où ça se remplit.
|
|
1504
|
+
*
|
|
1505
|
+
* **C'est la seule façon de connaître son état exact.** Sans lui, on interroge en boucle et on
|
|
1506
|
+
* apprend un remplissage avec le retard du sondage : entre-temps, un take-profit partiel a pu
|
|
1507
|
+
* modifier la taille de la position, et toute décision prise sur l'ancienne valeur est fausse.
|
|
1508
|
+
*
|
|
1509
|
+
* Le flux ne dit pas ce qu'on a **demandé** mais ce qui a été **obtenu** : un ordre annoncé `filled`
|
|
1510
|
+
* peut l'avoir été en plusieurs fois, à des prix différents. Chaque exécution porte son prix réel.
|
|
1511
|
+
*
|
|
1512
|
+
* **ON NE TRANSMET QUE CE QUI ARRIVE APRÈS L'OUVERTURE DU FLUX.** Les venues rejouent leur
|
|
1513
|
+
* historique à la souscription : mesuré le 2026-08-09 sur hyperliquid, 30 exécutions arrivent dans
|
|
1514
|
+
* les six premières secondes, **toutes antérieures** à l'abonnement, la plus ancienne de plus de
|
|
1515
|
+
* deux jours. Sans filtre, chaque reconnexion rejouerait deux jours de trades — et un consommateur
|
|
1516
|
+
* qui compte les remplissages compterait deux fois les mêmes.
|
|
1517
|
+
*
|
|
1518
|
+
* Le filtre se fait sur `filledAt` contre l'instant d'abonnement. Un flux dit le **présent** ;
|
|
1519
|
+
* l'historique se lit avec `TradingService.trades()`, qui est fait pour ça.
|
|
1520
|
+
*
|
|
1521
|
+
* **blofin est la seule venue qui ne l'expose pas** ; elle lève. Les sept autres le servent.
|
|
1522
|
+
*/
|
|
1523
|
+
declare class WsTradesService {
|
|
1524
|
+
private readonly logger;
|
|
1525
|
+
/**
|
|
1526
|
+
* S'abonne aux exécutions d'un compte. Rend la fonction de désabonnement.
|
|
1527
|
+
*
|
|
1528
|
+
* Le handler reçoit **une exécution à la fois**, au format unifié, et **uniquement celles
|
|
1529
|
+
* survenues après l'abonnement** — le rejeu d'historique de la venue est écarté.
|
|
1530
|
+
*/
|
|
1531
|
+
subscribe(access: ITradingAccess, handler: (trade: ITrade) => void): Unsubscribe;
|
|
1532
|
+
/**
|
|
1533
|
+
* S'abonne aux exécutions de PLUSIEURS comptes, avec un seul handler.
|
|
1534
|
+
*
|
|
1535
|
+
* Chaque exécution porte son `xex` : l'appelant sait toujours de quelle venue elle vient. La
|
|
1536
|
+
* fonction rendue coupe tous les flux d'un coup — sinon il faudrait en garder N et n'en oublier
|
|
1537
|
+
* aucun.
|
|
1538
|
+
*
|
|
1539
|
+
* Une venue qui refuse est journalisée et ignorée : le reste des comptes doit continuer d'être
|
|
1540
|
+
* suivi. Sur un seul accès, l'échec est celui de l'appel.
|
|
1541
|
+
*/
|
|
1542
|
+
subscribeAll(accesses: ITradingAccess[], handler: (trade: ITrade) => void): Unsubscribe;
|
|
1543
|
+
/**
|
|
1544
|
+
* S'abonne aux ORDRES du compte — leur naissance, leur remplissage, leur mort.
|
|
1545
|
+
*
|
|
1546
|
+
* À distinguer des exécutions : un ordre est une **intention** dont on suit le cycle de vie
|
|
1547
|
+
* (`open` → `partiallyFilled` → `filled`, ou `canceled`), une exécution est un **fait** ponctuel.
|
|
1548
|
+
* Pour savoir qu'un stop vient de se déclencher, c'est ici qu'il faut écouter ; pour savoir à quel
|
|
1549
|
+
* prix, c'est {@link subscribe}.
|
|
1550
|
+
*
|
|
1551
|
+
* **Même règle que pour les exécutions** : seuls les ordres postérieurs à l'abonnement sont
|
|
1552
|
+
* transmis, le rejeu d'historique est écarté.
|
|
1553
|
+
*/
|
|
1554
|
+
subscribeOrders(access: ITradingAccess, handler: (order: IOrder) => void): Unsubscribe;
|
|
1555
|
+
/**
|
|
1556
|
+
* S'abonne aux TRANSACTIONS PUBLIQUES d'un marché — celles de tout le monde, pas les siennes.
|
|
1557
|
+
*
|
|
1558
|
+
* C'est le flux qui dit ce qui se négocie réellement : prix, taille, sens agresseur. Il sert à
|
|
1559
|
+
* mesurer l'activité d'une paire, pas à suivre son compte — pour cela, {@link subscribe}.
|
|
1560
|
+
*
|
|
1561
|
+
* **Aucun filtre temporel ici** : un trade public est daté de son exécution et arrive en direct,
|
|
1562
|
+
* il n'y a pas d'historique rejoué à écarter.
|
|
1563
|
+
*/
|
|
1564
|
+
subscribePublicTrades(access: ITradingAccess, symbolXex: string, handler: (trade: IPublicTrade) => void): Unsubscribe;
|
|
1565
|
+
/** Le client temps réel d'un compte, avec ses souscriptions signées. */
|
|
1566
|
+
private wsOf;
|
|
1567
|
+
private toOrder;
|
|
1568
|
+
private toTrade;
|
|
1569
|
+
}
|
|
1570
|
+
|
|
1124
1571
|
/** La venue sert-elle cet intervalle de première main ? */
|
|
1125
1572
|
declare function servesNatively(xex: XgateEx, interval: Timeframe): boolean;
|
|
1126
1573
|
/**
|
|
@@ -1204,4 +1651,4 @@ declare function expiryOf(xtras?: Record<string, unknown>): Date | undefined;
|
|
|
1204
1651
|
*/
|
|
1205
1652
|
declare function isDated(xtras?: Record<string, unknown>): boolean;
|
|
1206
1653
|
|
|
1207
|
-
export { CandlesService, CatalogService, type Direction, type IBalance, type ICandle, type ICandlesQuery, type IEntryWithProtection, type IEquityPoint, type IMoveStop, type IMovement, type IOrder, type IPair, type IPosition, type IPrice, type IProtection, type IProtectionInput, type IProtectionLeg, type ITrade, type ITradingAccess, type IWalletAccess, type IXexAccess, type IXexSpotSource, type MarketKind, type MovementKind, type MovementStatus, ORDER_STATUSES, type OrderStatus, type OrderType, PricesService, SPOT_XEXES, type Side, SpotCandlesService, SpotCatalogService, TIMEFRAME_MINUTES, type TimeInForce, Timeframe, TradingService, type Unsubscribe, WALLET_XEXES, WalletService, WsCandlesService, XGATE_EXCHANGES, XgateEx, XgateModule, buildLevels, buildProtection, canonicalFromBase, canonicalFromXex, expiryOf, isDated, multiplierFromXex, roundPrice, roundToStep, servesNatively, servesSpot, sourceFor, timeframeMs };
|
|
1654
|
+
export { CandlesService, CandlesStreamRegistry, CandlesStreamService, CatalogService, type Direction, type IAccountState, type IBalance, type ICandle, type ICandlesQuery, type IEntryWithProtection, type IEquityPoint, type IFundingPaid, type IMoveStop, type IMovement, type IOrder, type IPair, type IPosition, type IPrice, type IProtection, type IProtectionInput, type IProtectionLeg, type IPublicTrade, type ITrade, type ITradingAccess, type IWalletAccess, type IXexAccess, type IXexSpotSource, type MarketKind, type MovementKind, type MovementStatus, ORDER_STATUSES, type OrderStatus, type OrderType, PricesService, SPOT_XEXES, type Side, SpotCandlesService, SpotCatalogService, SpotPricesService, SpotWsCandlesService, TIMEFRAME_MINUTES, type TimeInForce, Timeframe, TradingService, type Unsubscribe, WALLET_XEXES, WS_SUBSCRIPTION_LIMITS, WalletService, WsCandlesService, WsTradesService, XGATE_EXCHANGES, XgateEx, XgateModule, buildLevels, buildProtection, canonicalFromBase, canonicalFromXex, expiryOf, isDated, multiplierFromXex, roundPrice, roundToStep, servesNatively, servesSpot, sourceFor, subscriptionLimitOf, timeframeMs };
|