Skip to content

futures.public_liquidates: result shape and timestamp field differ from docs, size sign undocumented #132

Description

@karudo

Docs page: https://www.gate.com/docs/developers/futures/ws/en/#public-liquidate-order-notification

The live futures.public_liquidates feed does not match its documentation in three ways, and the gateio/gatews Python SDK has no channel class for it at all (that repo is archived, so reporting here). All four points are reproducible; raw frames are included below.

Endpoint: wss://fx-ws.gateio.ws/v4/ws/usdt, subscribed by contract name (300 contracts per shard). Frames captured 2026-08-10.

{"time":1786327033,"time_ms":1786327033532,"channel":"futures.public_liquidates","event":"update","result":{"contract":"HEI_USDT","price":"0.13827","time":1786327033531,"size":-23}}
{"time":1786327035,"time_ms":1786327035702,"channel":"futures.public_liquidates","event":"update","result":{"contract":"HEI_USDT","price":"0.13761","time":1786327035701,"size":-9}}
{"time":1786327040,"time_ms":1786327040873,"channel":"futures.public_liquidates","event":"update","result":{"contract":"LAB_USDT","price":"0.11824","time":1786327040872,"size":-9}}

1. result is a bare object, not an array

The docs type result as Array ("Array of objects") and the example shows "result": [{...}]. Every frame observed carries a bare object. A client written to the documented shape breaks on the first message.

2. The timestamp field inside result is time, not time_ms

The parameter table for the notification lists time_ms (Integer, "time_in_milliseconds"). The live object carries time, holding a millisecond value.

Note this is specifically about the result object — the envelope does have time_ms, so the mismatch is easy to miss when skimming. Observed keys:

  • envelope: time, time_ms, channel, event, result
  • result: contract, price, time, size

Whichever side is authoritative, the two disagree today, and a client that reads only the documented name gets undefined on every row.

3. The sign of size is not documented

size is described only as "liquidate order quantity"; the example shows -124 with no explanation of the sign. This is the single most important field in the feed — it decides whether an event is a short being liquidated or a long — and the documentation does not say.

Determined empirically over 1008 events across 184 contracts:

  • size > 0 → short liquidation (forced buy). Price moved +1.58% in the two minutes before the event; only 9% of these events had falling price beforehand (n=387).
  • size < 0 → long liquidation (forced sell). Price moved −1.15% before; 93% had falling price (n=614).

Cross-checked against the exchange's own 5-minute rollup in futures.contract_stats: in five-minute buckets where it reported short liquidations only, 84% of granular volume was positive; where it reported longs only, 10% was.

Please state the convention in the docs so clients do not each have to measure it.

4. The Python SDK has no channel class for futures.public_liquidates

In gateio/gatews, python/gate_ws/futures.py defines FuturesLiquidatesChannel (futures.liquidates, authenticated) but nothing for the public channel, which was added on 2025-02-19 per the WS changelog. Users of the SDK have to bypass it to subscribe.

Aside

futures.liquidates returns authentication required for Channel futures.liquidates when subscribed without credentials, which is correct and expected — noting it only because the two channel names are one word apart and it is easy to reach for the wrong one.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      , 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
       blocks
      (function() {
      function addCopyButtons() {
      document.querySelectorAll('pre code').forEach(function(codeBlock) {
      if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
      codeBlock.parentElement.setAttribute('data-copy-added', 'true');
      var btn = document.createElement('button');
      btn.textContent = 'Copy';
      btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
      btn.onmouseover = function() { this.style.opacity = '1'; };
      btn.onmouseout = function() { this.style.opacity = '0.7'; };
      btn.onclick = function() {
      navigator.clipboard.writeText(codeBlock.textContent).then(function() {
      btn.textContent = 'Copied!';
      setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
      });
      };
      codeBlock.parentElement.style.position = 'relative';
      codeBlock.parentElement.appendChild(btn);
      });
      }
      addCopyButtons();
      // Re-run on dynamic content
      var observer = new MutationObserver(addCopyButtons);
      observer.observe(document.body, { childList: true, subtree: true });
      })();
      }
      } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
      })();
      (function(){
      try {
      var __m = "github.com";
      var __re = new RegExp('^' + "github\\.com" + '
      Issue · GitHub
      Skip to content

      futures.public_liquidates: result shape and timestamp field differ from docs, size sign undocumented #132

      Description

      @karudo

      Docs page: https://www.gate.com/docs/developers/futures/ws/en/#public-liquidate-order-notification

      The live futures.public_liquidates feed does not match its documentation in three ways, and the gateio/gatews Python SDK has no channel class for it at all (that repo is archived, so reporting here). All four points are reproducible; raw frames are included below.

      Endpoint: wss://fx-ws.gateio.ws/v4/ws/usdt, subscribed by contract name (300 contracts per shard). Frames captured 2026-08-10.

      {"time":1786327033,"time_ms":1786327033532,"channel":"futures.public_liquidates","event":"update","result":{"contract":"HEI_USDT","price":"0.13827","time":1786327033531,"size":-23}}
      {"time":1786327035,"time_ms":1786327035702,"channel":"futures.public_liquidates","event":"update","result":{"contract":"HEI_USDT","price":"0.13761","time":1786327035701,"size":-9}}
      {"time":1786327040,"time_ms":1786327040873,"channel":"futures.public_liquidates","event":"update","result":{"contract":"LAB_USDT","price":"0.11824","time":1786327040872,"size":-9}}

      1. result is a bare object, not an array

      The docs type result as Array ("Array of objects") and the example shows "result": [{...}]. Every frame observed carries a bare object. A client written to the documented shape breaks on the first message.

      2. The timestamp field inside result is time, not time_ms

      The parameter table for the notification lists time_ms (Integer, "time_in_milliseconds"). The live object carries time, holding a millisecond value.

      Note this is specifically about the result object — the envelope does have time_ms, so the mismatch is easy to miss when skimming. Observed keys:

      • envelope: time, time_ms, channel, event, result
      • result: contract, price, time, size

      Whichever side is authoritative, the two disagree today, and a client that reads only the documented name gets undefined on every row.

      3. The sign of size is not documented

      size is described only as "liquidate order quantity"; the example shows -124 with no explanation of the sign. This is the single most important field in the feed — it decides whether an event is a short being liquidated or a long — and the documentation does not say.

      Determined empirically over 1008 events across 184 contracts:

      • size > 0 → short liquidation (forced buy). Price moved +1.58% in the two minutes before the event; only 9% of these events had falling price beforehand (n=387).
      • size < 0 → long liquidation (forced sell). Price moved −1.15% before; 93% had falling price (n=614).

      Cross-checked against the exchange's own 5-minute rollup in futures.contract_stats: in five-minute buckets where it reported short liquidations only, 84% of granular volume was positive; where it reported longs only, 10% was.

      Please state the convention in the docs so clients do not each have to measure it.

      4. The Python SDK has no channel class for futures.public_liquidates

      In gateio/gatews, python/gate_ws/futures.py defines FuturesLiquidatesChannel (futures.liquidates, authenticated) but nothing for the public channel, which was added on 2025-02-19 per the WS changelog. Users of the SDK have to bypass it to subscribe.

      Aside

      futures.liquidates returns authentication required for Channel futures.liquidates when subscribed without credentials, which is correct and expected — noting it only because the two channel names are one word apart and it is easy to reach for the wrong one.

      Metadata

      Metadata

      Assignees

      No one assigned

        Labels

        No labels
        No labels

        Projects

        No projects

          Milestone

          No milestone

          Relationships

          None yet

          Development

          No branches or pull requests

          Issue actions

          , 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Issue · GitHub
          Skip to content

          futures.public_liquidates: result shape and timestamp field differ from docs, size sign undocumented #132

          Description

          @karudo

          Docs page: https://www.gate.com/docs/developers/futures/ws/en/#public-liquidate-order-notification

          The live futures.public_liquidates feed does not match its documentation in three ways, and the gateio/gatews Python SDK has no channel class for it at all (that repo is archived, so reporting here). All four points are reproducible; raw frames are included below.

          Endpoint: wss://fx-ws.gateio.ws/v4/ws/usdt, subscribed by contract name (300 contracts per shard). Frames captured 2026-08-10.

          {"time":1786327033,"time_ms":1786327033532,"channel":"futures.public_liquidates","event":"update","result":{"contract":"HEI_USDT","price":"0.13827","time":1786327033531,"size":-23}}
          {"time":1786327035,"time_ms":1786327035702,"channel":"futures.public_liquidates","event":"update","result":{"contract":"HEI_USDT","price":"0.13761","time":1786327035701,"size":-9}}
          {"time":1786327040,"time_ms":1786327040873,"channel":"futures.public_liquidates","event":"update","result":{"contract":"LAB_USDT","price":"0.11824","time":1786327040872,"size":-9}}

          1. result is a bare object, not an array

          The docs type result as Array ("Array of objects") and the example shows "result": [{...}]. Every frame observed carries a bare object. A client written to the documented shape breaks on the first message.

          2. The timestamp field inside result is time, not time_ms

          The parameter table for the notification lists time_ms (Integer, "time_in_milliseconds"). The live object carries time, holding a millisecond value.

          Note this is specifically about the result object — the envelope does have time_ms, so the mismatch is easy to miss when skimming. Observed keys:

          • envelope: time, time_ms, channel, event, result
          • result: contract, price, time, size

          Whichever side is authoritative, the two disagree today, and a client that reads only the documented name gets undefined on every row.

          3. The sign of size is not documented

          size is described only as "liquidate order quantity"; the example shows -124 with no explanation of the sign. This is the single most important field in the feed — it decides whether an event is a short being liquidated or a long — and the documentation does not say.

          Determined empirically over 1008 events across 184 contracts:

          • size > 0 → short liquidation (forced buy). Price moved +1.58% in the two minutes before the event; only 9% of these events had falling price beforehand (n=387).
          • size < 0 → long liquidation (forced sell). Price moved −1.15% before; 93% had falling price (n=614).

          Cross-checked against the exchange's own 5-minute rollup in futures.contract_stats: in five-minute buckets where it reported short liquidations only, 84% of granular volume was positive; where it reported longs only, 10% was.

          Please state the convention in the docs so clients do not each have to measure it.

          4. The Python SDK has no channel class for futures.public_liquidates

          In gateio/gatews, python/gate_ws/futures.py defines FuturesLiquidatesChannel (futures.liquidates, authenticated) but nothing for the public channel, which was added on 2025-02-19 per the WS changelog. Users of the SDK have to bypass it to subscribe.

          Aside

          futures.liquidates returns authentication required for Channel futures.liquidates when subscribed without credentials, which is correct and expected — noting it only because the two channel names are one word apart and it is easy to reach for the wrong one.

          Metadata

          Metadata

          Assignees

          No one assigned

            Labels

            No labels
            No labels

            Projects

            No projects

              Milestone

              No milestone

              Relationships

              None yet

              Development

              No branches or pull requests

              Issue actions

              , 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Issue · GitHub
              Skip to content

              futures.public_liquidates: result shape and timestamp field differ from docs, size sign undocumented #132

              Description

              @karudo

              Docs page: https://www.gate.com/docs/developers/futures/ws/en/#public-liquidate-order-notification

              The live futures.public_liquidates feed does not match its documentation in three ways, and the gateio/gatews Python SDK has no channel class for it at all (that repo is archived, so reporting here). All four points are reproducible; raw frames are included below.

              Endpoint: wss://fx-ws.gateio.ws/v4/ws/usdt, subscribed by contract name (300 contracts per shard). Frames captured 2026-08-10.

              {"time":1786327033,"time_ms":1786327033532,"channel":"futures.public_liquidates","event":"update","result":{"contract":"HEI_USDT","price":"0.13827","time":1786327033531,"size":-23}}
              {"time":1786327035,"time_ms":1786327035702,"channel":"futures.public_liquidates","event":"update","result":{"contract":"HEI_USDT","price":"0.13761","time":1786327035701,"size":-9}}
              {"time":1786327040,"time_ms":1786327040873,"channel":"futures.public_liquidates","event":"update","result":{"contract":"LAB_USDT","price":"0.11824","time":1786327040872,"size":-9}}

              1. result is a bare object, not an array

              The docs type result as Array ("Array of objects") and the example shows "result": [{...}]. Every frame observed carries a bare object. A client written to the documented shape breaks on the first message.

              2. The timestamp field inside result is time, not time_ms

              The parameter table for the notification lists time_ms (Integer, "time_in_milliseconds"). The live object carries time, holding a millisecond value.

              Note this is specifically about the result object — the envelope does have time_ms, so the mismatch is easy to miss when skimming. Observed keys:

              • envelope: time, time_ms, channel, event, result
              • result: contract, price, time, size

              Whichever side is authoritative, the two disagree today, and a client that reads only the documented name gets undefined on every row.

              3. The sign of size is not documented

              size is described only as "liquidate order quantity"; the example shows -124 with no explanation of the sign. This is the single most important field in the feed — it decides whether an event is a short being liquidated or a long — and the documentation does not say.

              Determined empirically over 1008 events across 184 contracts:

              • size > 0 → short liquidation (forced buy). Price moved +1.58% in the two minutes before the event; only 9% of these events had falling price beforehand (n=387).
              • size < 0 → long liquidation (forced sell). Price moved −1.15% before; 93% had falling price (n=614).

              Cross-checked against the exchange's own 5-minute rollup in futures.contract_stats: in five-minute buckets where it reported short liquidations only, 84% of granular volume was positive; where it reported longs only, 10% was.

              Please state the convention in the docs so clients do not each have to measure it.

              4. The Python SDK has no channel class for futures.public_liquidates

              In gateio/gatews, python/gate_ws/futures.py defines FuturesLiquidatesChannel (futures.liquidates, authenticated) but nothing for the public channel, which was added on 2025-02-19 per the WS changelog. Users of the SDK have to bypass it to subscribe.

              Aside

              futures.liquidates returns authentication required for Channel futures.liquidates when subscribed without credentials, which is correct and expected — noting it only because the two channel names are one word apart and it is easy to reach for the wrong one.

              Metadata

              Metadata

              Assignees

              No one assigned

                Labels

                No labels
                No labels

                Projects

                No projects

                  Milestone

                  No milestone

                  Relationships

                  None yet

                  Development

                  No branches or pull requests

                  Issue actions

                  , 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Issue · GitHub
                  Skip to content

                  futures.public_liquidates: result shape and timestamp field differ from docs, size sign undocumented #132

                  Description

                  @karudo

                  Docs page: https://www.gate.com/docs/developers/futures/ws/en/#public-liquidate-order-notification

                  The live futures.public_liquidates feed does not match its documentation in three ways, and the gateio/gatews Python SDK has no channel class for it at all (that repo is archived, so reporting here). All four points are reproducible; raw frames are included below.

                  Endpoint: wss://fx-ws.gateio.ws/v4/ws/usdt, subscribed by contract name (300 contracts per shard). Frames captured 2026-08-10.

                  {"time":1786327033,"time_ms":1786327033532,"channel":"futures.public_liquidates","event":"update","result":{"contract":"HEI_USDT","price":"0.13827","time":1786327033531,"size":-23}}
                  {"time":1786327035,"time_ms":1786327035702,"channel":"futures.public_liquidates","event":"update","result":{"contract":"HEI_USDT","price":"0.13761","time":1786327035701,"size":-9}}
                  {"time":1786327040,"time_ms":1786327040873,"channel":"futures.public_liquidates","event":"update","result":{"contract":"LAB_USDT","price":"0.11824","time":1786327040872,"size":-9}}

                  1. result is a bare object, not an array

                  The docs type result as Array ("Array of objects") and the example shows "result": [{...}]. Every frame observed carries a bare object. A client written to the documented shape breaks on the first message.

                  2. The timestamp field inside result is time, not time_ms

                  The parameter table for the notification lists time_ms (Integer, "time_in_milliseconds"). The live object carries time, holding a millisecond value.

                  Note this is specifically about the result object — the envelope does have time_ms, so the mismatch is easy to miss when skimming. Observed keys:

                  • envelope: time, time_ms, channel, event, result
                  • result: contract, price, time, size

                  Whichever side is authoritative, the two disagree today, and a client that reads only the documented name gets undefined on every row.

                  3. The sign of size is not documented

                  size is described only as "liquidate order quantity"; the example shows -124 with no explanation of the sign. This is the single most important field in the feed — it decides whether an event is a short being liquidated or a long — and the documentation does not say.

                  Determined empirically over 1008 events across 184 contracts:

                  • size > 0 → short liquidation (forced buy). Price moved +1.58% in the two minutes before the event; only 9% of these events had falling price beforehand (n=387).
                  • size < 0 → long liquidation (forced sell). Price moved −1.15% before; 93% had falling price (n=614).

                  Cross-checked against the exchange's own 5-minute rollup in futures.contract_stats: in five-minute buckets where it reported short liquidations only, 84% of granular volume was positive; where it reported longs only, 10% was.

                  Please state the convention in the docs so clients do not each have to measure it.

                  4. The Python SDK has no channel class for futures.public_liquidates

                  In gateio/gatews, python/gate_ws/futures.py defines FuturesLiquidatesChannel (futures.liquidates, authenticated) but nothing for the public channel, which was added on 2025-02-19 per the WS changelog. Users of the SDK have to bypass it to subscribe.

                  Aside

                  futures.liquidates returns authentication required for Channel futures.liquidates when subscribed without credentials, which is correct and expected — noting it only because the two channel names are one word apart and it is easy to reach for the wrong one.

                  Metadata

                  Metadata

                  Assignees

                  No one assigned

                    Labels

                    No labels
                    No labels

                    Projects

                    No projects

                      Milestone

                      No milestone

                      Relationships

                      None yet

                      Development

                      No branches or pull requests

                      Issue actions

                      , 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Issue · GitHub
                      Skip to content

                      futures.public_liquidates: result shape and timestamp field differ from docs, size sign undocumented #132

                      Description

                      @karudo

                      Docs page: https://www.gate.com/docs/developers/futures/ws/en/#public-liquidate-order-notification

                      The live futures.public_liquidates feed does not match its documentation in three ways, and the gateio/gatews Python SDK has no channel class for it at all (that repo is archived, so reporting here). All four points are reproducible; raw frames are included below.

                      Endpoint: wss://fx-ws.gateio.ws/v4/ws/usdt, subscribed by contract name (300 contracts per shard). Frames captured 2026-08-10.

                      {"time":1786327033,"time_ms":1786327033532,"channel":"futures.public_liquidates","event":"update","result":{"contract":"HEI_USDT","price":"0.13827","time":1786327033531,"size":-23}}
                      {"time":1786327035,"time_ms":1786327035702,"channel":"futures.public_liquidates","event":"update","result":{"contract":"HEI_USDT","price":"0.13761","time":1786327035701,"size":-9}}
                      {"time":1786327040,"time_ms":1786327040873,"channel":"futures.public_liquidates","event":"update","result":{"contract":"LAB_USDT","price":"0.11824","time":1786327040872,"size":-9}}

                      1. result is a bare object, not an array

                      The docs type result as Array ("Array of objects") and the example shows "result": [{...}]. Every frame observed carries a bare object. A client written to the documented shape breaks on the first message.

                      2. The timestamp field inside result is time, not time_ms

                      The parameter table for the notification lists time_ms (Integer, "time_in_milliseconds"). The live object carries time, holding a millisecond value.

                      Note this is specifically about the result object — the envelope does have time_ms, so the mismatch is easy to miss when skimming. Observed keys:

                      • envelope: time, time_ms, channel, event, result
                      • result: contract, price, time, size

                      Whichever side is authoritative, the two disagree today, and a client that reads only the documented name gets undefined on every row.

                      3. The sign of size is not documented

                      size is described only as "liquidate order quantity"; the example shows -124 with no explanation of the sign. This is the single most important field in the feed — it decides whether an event is a short being liquidated or a long — and the documentation does not say.

                      Determined empirically over 1008 events across 184 contracts:

                      • size > 0 → short liquidation (forced buy). Price moved +1.58% in the two minutes before the event; only 9% of these events had falling price beforehand (n=387).
                      • size < 0 → long liquidation (forced sell). Price moved −1.15% before; 93% had falling price (n=614).

                      Cross-checked against the exchange's own 5-minute rollup in futures.contract_stats: in five-minute buckets where it reported short liquidations only, 84% of granular volume was positive; where it reported longs only, 10% was.

                      Please state the convention in the docs so clients do not each have to measure it.

                      4. The Python SDK has no channel class for futures.public_liquidates

                      In gateio/gatews, python/gate_ws/futures.py defines FuturesLiquidatesChannel (futures.liquidates, authenticated) but nothing for the public channel, which was added on 2025-02-19 per the WS changelog. Users of the SDK have to bypass it to subscribe.

                      Aside

                      futures.liquidates returns authentication required for Channel futures.liquidates when subscribed without credentials, which is correct and expected — noting it only because the two channel names are one word apart and it is easy to reach for the wrong one.

                      Metadata

                      Metadata

                      Assignees

                      No one assigned

                        Labels

                        No labels
                        No labels

                        Projects

                        No projects

                          Milestone

                          No milestone

                          Relationships

                          None yet

                          Development

                          No branches or pull requests

                          Issue actions

                          , 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Issue · GitHub
                          Skip to content

                          futures.public_liquidates: result shape and timestamp field differ from docs, size sign undocumented #132

                          Description

                          @karudo

                          Docs page: https://www.gate.com/docs/developers/futures/ws/en/#public-liquidate-order-notification

                          The live futures.public_liquidates feed does not match its documentation in three ways, and the gateio/gatews Python SDK has no channel class for it at all (that repo is archived, so reporting here). All four points are reproducible; raw frames are included below.

                          Endpoint: wss://fx-ws.gateio.ws/v4/ws/usdt, subscribed by contract name (300 contracts per shard). Frames captured 2026-08-10.

                          {"time":1786327033,"time_ms":1786327033532,"channel":"futures.public_liquidates","event":"update","result":{"contract":"HEI_USDT","price":"0.13827","time":1786327033531,"size":-23}}
                          {"time":1786327035,"time_ms":1786327035702,"channel":"futures.public_liquidates","event":"update","result":{"contract":"HEI_USDT","price":"0.13761","time":1786327035701,"size":-9}}
                          {"time":1786327040,"time_ms":1786327040873,"channel":"futures.public_liquidates","event":"update","result":{"contract":"LAB_USDT","price":"0.11824","time":1786327040872,"size":-9}}

                          1. result is a bare object, not an array

                          The docs type result as Array ("Array of objects") and the example shows "result": [{...}]. Every frame observed carries a bare object. A client written to the documented shape breaks on the first message.

                          2. The timestamp field inside result is time, not time_ms

                          The parameter table for the notification lists time_ms (Integer, "time_in_milliseconds"). The live object carries time, holding a millisecond value.

                          Note this is specifically about the result object — the envelope does have time_ms, so the mismatch is easy to miss when skimming. Observed keys:

                          • envelope: time, time_ms, channel, event, result
                          • result: contract, price, time, size

                          Whichever side is authoritative, the two disagree today, and a client that reads only the documented name gets undefined on every row.

                          3. The sign of size is not documented

                          size is described only as "liquidate order quantity"; the example shows -124 with no explanation of the sign. This is the single most important field in the feed — it decides whether an event is a short being liquidated or a long — and the documentation does not say.

                          Determined empirically over 1008 events across 184 contracts:

                          • size > 0 → short liquidation (forced buy). Price moved +1.58% in the two minutes before the event; only 9% of these events had falling price beforehand (n=387).
                          • size < 0 → long liquidation (forced sell). Price moved −1.15% before; 93% had falling price (n=614).

                          Cross-checked against the exchange's own 5-minute rollup in futures.contract_stats: in five-minute buckets where it reported short liquidations only, 84% of granular volume was positive; where it reported longs only, 10% was.

                          Please state the convention in the docs so clients do not each have to measure it.

                          4. The Python SDK has no channel class for futures.public_liquidates

                          In gateio/gatews, python/gate_ws/futures.py defines FuturesLiquidatesChannel (futures.liquidates, authenticated) but nothing for the public channel, which was added on 2025-02-19 per the WS changelog. Users of the SDK have to bypass it to subscribe.

                          Aside

                          futures.liquidates returns authentication required for Channel futures.liquidates when subscribed without credentials, which is correct and expected — noting it only because the two channel names are one word apart and it is easy to reach for the wrong one.

                          Metadata

                          Metadata

                          Assignees

                          No one assigned

                            Labels

                            No labels
                            No labels

                            Projects

                            No projects

                              Milestone

                              No milestone

                              Relationships

                              None yet

                              Development

                              No branches or pull requests

                              Issue actions

                              , 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Issue · GitHub
                              Skip to content

                              futures.public_liquidates: result shape and timestamp field differ from docs, size sign undocumented #132

                              Description

                              @karudo

                              Docs page: https://www.gate.com/docs/developers/futures/ws/en/#public-liquidate-order-notification

                              The live futures.public_liquidates feed does not match its documentation in three ways, and the gateio/gatews Python SDK has no channel class for it at all (that repo is archived, so reporting here). All four points are reproducible; raw frames are included below.

                              Endpoint: wss://fx-ws.gateio.ws/v4/ws/usdt, subscribed by contract name (300 contracts per shard). Frames captured 2026-08-10.

                              {"time":1786327033,"time_ms":1786327033532,"channel":"futures.public_liquidates","event":"update","result":{"contract":"HEI_USDT","price":"0.13827","time":1786327033531,"size":-23}}
                              {"time":1786327035,"time_ms":1786327035702,"channel":"futures.public_liquidates","event":"update","result":{"contract":"HEI_USDT","price":"0.13761","time":1786327035701,"size":-9}}
                              {"time":1786327040,"time_ms":1786327040873,"channel":"futures.public_liquidates","event":"update","result":{"contract":"LAB_USDT","price":"0.11824","time":1786327040872,"size":-9}}

                              1. result is a bare object, not an array

                              The docs type result as Array ("Array of objects") and the example shows "result": [{...}]. Every frame observed carries a bare object. A client written to the documented shape breaks on the first message.

                              2. The timestamp field inside result is time, not time_ms

                              The parameter table for the notification lists time_ms (Integer, "time_in_milliseconds"). The live object carries time, holding a millisecond value.

                              Note this is specifically about the result object — the envelope does have time_ms, so the mismatch is easy to miss when skimming. Observed keys:

                              • envelope: time, time_ms, channel, event, result
                              • result: contract, price, time, size

                              Whichever side is authoritative, the two disagree today, and a client that reads only the documented name gets undefined on every row.

                              3. The sign of size is not documented

                              size is described only as "liquidate order quantity"; the example shows -124 with no explanation of the sign. This is the single most important field in the feed — it decides whether an event is a short being liquidated or a long — and the documentation does not say.

                              Determined empirically over 1008 events across 184 contracts:

                              • size > 0 → short liquidation (forced buy). Price moved +1.58% in the two minutes before the event; only 9% of these events had falling price beforehand (n=387).
                              • size < 0 → long liquidation (forced sell). Price moved −1.15% before; 93% had falling price (n=614).

                              Cross-checked against the exchange's own 5-minute rollup in futures.contract_stats: in five-minute buckets where it reported short liquidations only, 84% of granular volume was positive; where it reported longs only, 10% was.

                              Please state the convention in the docs so clients do not each have to measure it.

                              4. The Python SDK has no channel class for futures.public_liquidates

                              In gateio/gatews, python/gate_ws/futures.py defines FuturesLiquidatesChannel (futures.liquidates, authenticated) but nothing for the public channel, which was added on 2025-02-19 per the WS changelog. Users of the SDK have to bypass it to subscribe.

                              Aside

                              futures.liquidates returns authentication required for Channel futures.liquidates when subscribed without credentials, which is correct and expected — noting it only because the two channel names are one word apart and it is easy to reach for the wrong one.

                              Metadata

                              Metadata

                              Assignees

                              No one assigned

                                Labels

                                No labels
                                No labels

                                Projects

                                No projects

                                  Milestone

                                  No milestone

                                  Relationships

                                  None yet

                                  Development

                                  No branches or pull requests

                                  Issue actions