playground:playground

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

playground:playground [2024/08/05 06:28] – created - external edit 127.0.0.1playground:playground [2026/06/15 17:19] (current) juan
Line 1: Line 1:
 ====== PlayGround ====== ====== PlayGround ======
 +====== T4 Chart API ======
 +
 +Our chart API provides data in aggregated or non-aggregated (raw trade) formats.
 +
 +<bootnote>
 +All times are in CST.
 +</bootnote>
 +
 +The complete API documentation is available via Swagger UI at:
 +
 +[[https://api-sim.t4login.com/chart/swagger/index.html|T4 Chart API Documentation]]
 +
 +The Swagger documentation provides:
 +  * Complete list of available endpoints
 +  * Request parameters and response formats
 +  * Interactive testing capability
 +  * Authentication requirements
 +
 +<bootnote info>
 +**What changed in this revision** \\
 +This page has been extended to document the **compact binary response format** (``application/octet-stream`` / ``application/t4``) and the **open-source decoder libraries** that consume it. The original JSON documentation below is unchanged; the new material is additive:
 +  * A new top-level section **[[#Binary Response Format (T4Bin / T4BinAggr)]]** describing the on-the-wire envelope, framing, 7-bit/decimal value encodings, price & time conventions, and the full record-tag (CTAG) tables.
 +  * A new top-level section **[[#Decoder Libraries]]** documenting the JavaScript (``@t4/chart-decoder``) and Python (``t4login``) reference decoders, including the streaming handler interface, the ``ChartDataState`` field reference, and the ``ChartDataChange`` / ``MarketMode`` / ``BidOffer`` enumerations.
 +  * Minor clarifications to the existing **Accept** header tables to cross-reference the binary sections.
 +
 +See **[[#Revision Notes / Changelog]]** at the bottom for the detailed list.
 +</bootnote>
 +
 +===== Aggregated Chart Data =====
 +
 +==== Overview ====
 +The **GetBarChart** API retrieves bar chart data for a specified trading instrument over a given date range. This API supports various chart types and bar intervals, tailored for detailed data analysis in financial contexts.
 +
 +==== API Endpoint ====
 +<code>GET https://api-sim.t4login.com/chart/barchart</code>
 +
 +==== Headers ====
 +
 +For proper access and response handling, the **GetBarChart** API requires certain HTTP headers to be set in the request.
 +
 +^ Header           ^ Value                                                   ^ Description                                                                             ^
 +| Authorization    | Bearer <token>                                          | **Required**. A valid bearer token to authenticate the request.                         |
 +| Accept           | application/json, text/csv, application/octet-stream, application/t4               | **Optional**. Specifies the response format the client can handle. If omitted, the API returns JSON. Use text/csv to request CSV, or application/octet-stream / application/t4 to request the compact binary format (see **[[#Binary Response Format (T4Bin / T4BinAggr)]]**). |
 +
 +**Examples:**
 +
 +  * To authorize the request, include the bearer token:
 +    <code>Authorization: Bearer YOUR_ACCESS_TOKEN</code>
 +
 +  * To receive the response in a compact binary format, set the `Accept` header accordingly:
 +    <code>Accept: application/octet-stream</code>
 +    or
 +    <code>Accept: application/t4</code>
 +
 +Setting the `Accept` header is optional, and if it is not included, the API will return the response in a JSON format.
 +
 +<bootnote>
 +The aggregated binary stream is referred to as **T4BinAggr**. Its envelope, framing, and record tags are documented under **[[#Aggregated tags (T4BinAggr)]]**, and a ready-made decoder is described under **[[#Decoder Libraries]]**.
 +</bootnote>
 +
 +==== Parameters ====
 +^ Parameter        ^ Description                                                                                       ^
 +| **exchangeId**       | **Required**. Identifier for the exchange.                                                        |
 +| **contractId**       | **Required**. Identifier for the contract.                                                        |
 +| **chartType**        | **Required**. Type of chart to compute. Currently, only **Bar** type is supported.              |
 +| **barInterval**      | **Required**. Interval at which bars are aggregated. Possible values:\\ • **Tick**: Bars aggregated based on trade count.\\ • **TickRange**: Bars aggregated based on price range.\\ • **Volume**: Bars aggregated based on number of contracts traded.\\ • **Second**: Bars aggregated into multiples of seconds.\\ • **Minute**: Bars aggregated into multiples of minutes.\\ • **Hour**: Bars aggregated into multiples of hours.\\ • **Day**: Bars aggregated into multiples of days.\\ • **Week**: Bars aggregated into multiples of weeks. |
 +| **barPeriod**        | **Required**. Period for the bars.                                                                |
 +| **tradeDateStart**   | **Required**. Start date for the trade data.                                                      |
 +| **tradeDateEnd**     | **Required**. End date for the trade data.                                                        |
 +| marketID         | Market ID (optional). Can be omitted when using ContinuationType.                                 |
 +| continuationType | Method of continuation for the chart. Only **Volume** is currently supported.                      |
 +| resetInterval    | Interval at which bar computations reset (not applicable when ContinuationType.Volume is used). \\ Defaults to **TradingDay**. Other possible values:\\ • **None**: No reset interval.\\ • **TradingWeek**: Reset on the trading week boundary.\\ • **ExpiryChange**: Reset on an expiry change. |
 +| contractMonths   | Contract months to include (not applicable when **ContinuationType.Volume** is used).             |
 +| rolloverThreshold| Rollover threshold (not applicable when **ContinuationType.Volume** is used).                      |
 +| forwardMonths    | Forward months (not applicable when **ContinuationType.Volume** is used).                         |
 +
 +==== Response ====
 +
 +The response from the **GetBarChart** API is a JSON object containing detailed information about the bar chart data. Below is the structure of the response along with a description of each element:
 +
 +=== Bars ===
 +^ Element         ^ Description                                      ^
 +| tradeDate       | Date of the trade.                               |
 +| time            | Time when the bar data starts.                   |
 +| closeTime       | Time when the bar data ends.                     |
 +| marketID        | Identifier for the market.                       |
 +| openPrice       | Opening price for this bar.                      |
 +| highPrice       | Highest price in this bar.                       |
 +| lowPrice        | Lowest price in this bar.                        |
 +| closePrice      | Closing price for this bar.                      |
 +| volume          | Total volume of trades in this bar.              |
 +| volumeAtBid     | Volume of trades at the bid price.               |
 +| volumeAtOffer   | Volume of trades at the offer price.             |
 +| trades          | Total number of trades in this bar.              |
 +| tradesAtBid     | Number of trades at the bid price.               |
 +| tradesAtOffer   | Number of trades at the offer price.             |
 +
 +=== MarketDefinitions ===
 +^ Element           ^ Description                                              ^
 +| marketID          | Identifier for the market.                               |
 +| minPriceIncrement | Minimum increment of the market's price.                 |
 +| priceCode         | Code related to the pricing of the market.               |
 +| tickValue         | Value of each tick in the market's pricing.              |
 +| vpt               | Additional market-specific information (variable).       |
 +
 +=== ModeChanges ===
 +^ Element         ^ Description                                ^
 +| marketID        | Identifier for the market.                 |
 +| tradeDate       | Date of the trade.                         |
 +| time            | Time when the mode change occurred.        |
 +| marketMode      | The mode of the market at the given time.  |
 +
 +=== OpenInterests ===
 +^ Element         ^ Description                                ^
 +| marketID        | Identifier for the market.                 |
 +| tradeDate       | Date of the trade.                         |
 +| time            | Time of the recorded open interest.        |
 +| openInterest    | The amount of open interest.               |
 +
 +=== Settlements ===
 +^ Element           ^ Description                                           ^
 +| marketID          | Identifier for the market.                            |
 +| tradeDate         | Date of the trade.                                    |
 +| time              | Time when the settlement information was recorded.    |
 +| settlementPrice   | Price at which the trade was settled.                 |
 +| isHeld            | Indicates if the settlement was held (boolean).       |
 +
 +==== Example JSON Response ====
 +
 +<code>
 +{
 +    "tradeDateStart": "2024-01-08T00:00:00",
 +    "tradeDateEnd": "2024-01-08T00:00:00",
 +    "activeMarket": "XCME_Eq ES (H24)",
 +    "bars": [
 +        {
 +            "tradeDate": "2024-01-08T00:00:00",
 +            "time": "2024-01-08T00:00:00",
 +            "closeTime": "2024-01-08T15:59:59.5853624",
 +            "marketID": "XCME_Eq ES (H24)",
 +            "openPrice": "473575",
 +            "highPrice": "480325",
 +            "lowPrice": "471525",
 +            "closePrice": "479800",
 +            "volume": 1339989,
 +            "volumeAtBid": 665050,
 +            "volumeAtOffer": 674939,
 +            "trades": 320624,
 +            "tradesAtBid": 152333,
 +            "tradesAtOffer": 168291
 +        }
 +    ],
 +    "marketDefinitions": [
 +        {
 +            "marketID": "XCME_Eq ES (H24)",
 +            "minPriceIncrement": "25",
 +            "priceCode": "",
 +            "tickValue": 12.5,
 +            "vpt": ""
 +        }
 +    ],
 +    "modeChanges": [
 +        {
 +            "marketID": "XCME_Eq ES (H24)",
 +            "tradeDate": "2024-01-08T00:00:00",
 +            "time": "2024-01-07T08:04:27.7736882",
 +            "marketMode": 5
 +        },
 +        // ... additional mode changes ...
 +    ],
 +    "openInterests": [
 +        {
 +            "marketID": "XCME_Eq ES (H24)",
 +            "tradeDate": "2024-01-08T00:00:00",
 +            "time": "2024-01-07T12:43:16.8256856",
 +            "openInterest": 2211632
 +        },
 +        // ... additional open interests ...
 +    ],
 +    "settlements": [
 +        {
 +            "marketID": "XCME_Eq ES (H24)",
 +            "tradeDate": "2024-01-08T00:00:00",
 +            "time": "2024-01-05T16:38:39.9345143",
 +            "settlementPrice": "473475"
 +        },
 +        {
 +            "marketID": "XCME_Eq ES (H24)",
 +            "tradeDate": "2024-01-08T00:00:00",
 +            "time": "2024-01-08T15:01:01.4810068",
 +            "isHeld": true
 +        }
 +        // ... additional settlements ...
 +    ]
 +}
 +</code>
 +
 +===== Non-Aggregated Chart Data (Trade History) =====
 +
 +==== Overview ====
 +The **GetTradeHistory** API retrieves historical trade data for a specified trading instrument within a given date and time range. This API allows for querying trade data based on the trade date or specific start and end timestamps.
 +
 +==== API Endpoint ====
 +<code>GET https://api-sim.t4login.com/chart/tradehistory</code>
 +
 +==== Headers ====
 +^ Header        ^ Value                                                      ^ Description                                                                             ^
 +| Authorization | Bearer <token>                                             | **Required**. A valid bearer token to authenticate the request.                         |
 +| Accept        | application/octet-stream, application/t4                   | **Optional**. Specifies the content type that the client can handle. Use this header to request a compact binary format response (see **[[#Binary Response Format (T4Bin / T4BinAggr)]]**). If omitted, the default response format is JSON. |
 +
 +==== Parameters ====
 +^ Parameter        ^ Description                                                                                       ^
 +| exchangeId       | **Required**. Identifier for the exchange.                                                        |
 +| contractId       | **Required**. Identifier for the contract.                                                        |
 +| marketID         | Market ID (optional).                                                                            |
 +| tradeDateStart   | The start date for the trade history based on trade dates (optional).                            |
 +| tradeDateEnd     | The end date for the trade history based on trade dates (optional).                              |
 +| start            | The calendar start date and time for the request in CST (optional).                              |
 +| end              | The calendar end date and time for the request in CST (optional).                                |
 +| since            | Filters data to only include trades after the specified date and time (optional).                |
 +
 +**Note:** Pass either **tradeDateStart** and **tradeDateEnd** OR **start** and **end**. Including both will result in an error. Use **since** to further filter data to only include trades after the specified date and time.
 +
 +<bootnote>
 +The non-aggregated binary stream is referred to as **T4Bin**. Unlike the JSON response (which materialises the entire payload into arrays), the binary stream is a **delta-encoded event log**: each record carries only the change from the previous one, so it must be decoded sequentially. See **[[#Non-aggregated tags (T4Bin)]]** and **[[#Decoder Libraries]]**.
 +</bootnote>
 +
 +=== Response ===
 +^ Element            ^ Description                                                                                                  ^
 +| exchangeID         | Identifier for the exchange.                                                                                  |
 +| contractID         | Identifier for the contract.                                                                                  |
 +| marketID           | Identifier for the market.                                                                                    |
 +| requestStatusMessage| Any status messages or errors related to the request.                                                          |
 +| tradeDateStart     | The starting date of the trade data.                                                                          |
 +| tradeDateEnd       | The ending date of the trade data.                                                                            |
 +| trades             | An array of trade objects, each detailing individual trades.                                                  |
 +| marketDefinitions  | An array of market definition objects, detailing market-specific information.                                |
 +| modeChanges        | An array of mode change objects, each showing changes in the market mode.                                    |
 +| openInterests      | An array containing information about open interests.                                                        |
 +| settlements        | An array detailing settlement information, including prices.                                                 |
 +| vwaPs              | An array detailing volume-weighted average prices (VWAP).                                                    |
 +
 +=== Trades ===
 +
 +^ Element        ^ Description                                                         ^
 +| marketID       | Identifier for the market.                                          |
 +| tradeDate      | The date of the trade as per trade date convention.                |
 +| time           | The specific time when the trade occurred.                         |
 +| tradePrice     | The price at which the trade was executed.                         |
 +| aggressorSide  | Indicates the side of the aggressor of the trade. 1 for buyer, -1 for seller. |
 +
 +=== VWAP(s) ===
 +
 +^ Element    ^ Description                                                         ^
 +| marketID   | Identifier for the market.                                          |
 +| tradeDate  | The date of the trade as per trade date convention.                |
 +| time       | The specific time when the VWAP is calculated.                     |
 +| vwapPrice  | The volume-weighted average price for the trades up to the specified time. |
 +
 +==== Example JSON Response ====
 +
 +<code>
 +{
 +    "exchangeID": "CME_E",
 +    "contractID": "YM",
 +    "marketID": "XCME_E YM (H24)",
 +    "requestStatusMessage": "",
 +    "tradeDateStart": "2024-01-08T00:00:00",
 +    "tradeDateEnd": "2024-01-08T00:00:00",
 +    "trades": [
 +        {
 +            "marketID": "XCME_E YM (H24)",
 +            "tradeDate": "2024-01-08T00:00:00",
 +            "time": "2024-01-07T17:00:00",
 +            "tradePrice": "37674",
 +            "aggressorSide": 1
 +        },
 +        ...
 +    ],
 +    "marketDefinitions": [],
 +    "modeChanges": [
 +        ...
 +    ],
 +    "openInterests": [
 +        ...
 +    ],
 +    "settlements": [
 +        ...
 +    ],
 +    "vwaPs": [
 +        ...
 +    ]
 +}
 +</code>
 +
 +The response is structured as a JSON object with various elements containing detailed trade data and related information for the specified contract and exchange within the requested time frame.
 +
 +===== Binary Response Format (T4Bin / T4BinAggr) =====
 +
 +When the **Accept** header requests ``application/octet-stream`` or ``application/t4``, the chart endpoints return a **compact binary stream** instead of JSON. The binary format is typically an order of magnitude smaller than the equivalent JSON and is the recommended transport for large date ranges or high-resolution (tick / quote) history.
 +
 +Two closely-related dialects exist:
 +
 +^ Stream        ^ Endpoint                ^ Aggregation              ^ Decoder entry point                ^
 +| **T4BinAggr** | ``/chart/barchart``     | Pre-aggregated OHLCV bars | ``ChartDataStreamReaderAggr``      |
 +| **T4Bin**     | ``/chart/tradehistory`` | Raw, delta-encoded events | ``ChartDataStreamReader``          |
 +
 +<bootnote tip>
 +You do **not** need to implement the byte-level format yourself — reference decoders are provided for JavaScript and Python (see **[[#Decoder Libraries]]**). This section documents the wire format for completeness and for anyone porting the decoder to another language.
 +</bootnote>
 +
 +==== Envelope & payload extraction ====
 +
 +The HTTP body may contain a small amount of framing before the actual T4Bin payload. The payload begins at a **Start-Of-Format (SOF)** record whose first bytes form a recognisable signature. A decoder should scan for the first matching signature and treat everything from that offset onward as the stream.
 +
 +^ Stream        ^ SOF signature (hex)        ^ Meaning                                                            ^
 +| **T4BinAggr** | ``05 01 01 00 00 00``      | length=5, tag=``CTAG_SOF`` (1), version=1 (little-endian int32)     |
 +| **T4Bin**     | ``0D 01 01 00 00 00``      | length=13, tag=``CTAG_SOF`` (1), version=1 (little-endian int32)    |
 +
 +If a non-empty response contains neither signature, the body is almost certainly an error message or an unexpected format and should be treated as a hard error rather than decoded.
 +
 +==== Record framing ====
 +
 +Both dialects are a flat sequence of **length-prefixed records**:
 +
 +<code>
 +[ length : 7-bit int ] [ tag : 7-bit int ] [ tag-specific payload ... ]
 +</code>
 +
 +  * **length** — the number of bytes in the record //after// the length prefix itself (i.e. tag + payload). A decoder reads ``length``, resets a byte counter, reads the tag and payload, then skips any unconsumed trailing bytes so that exactly ``length`` bytes are consumed. This makes the format **forward-compatible**: unknown tags and extra trailing fields in known tags are skipped safely.
 +  * **tag** — one of the ``CTAG_*`` constants in the tables below. The tag namespaces are **separate** for the two dialects (e.g. tag ``11`` means ``CTAG_BAR`` in T4BinAggr but ``CTAG_TICKDATAPOINT_7BIT`` in T4Bin).
 +  * A record with ``length == 0`` is a no-op padding/keepalive and is ignored.
 +
 +==== Value encodings ====
 +
 +=== 7-bit variable-length integers ===
 +
 +Integers are stored little-endian, 7 bits per byte, with the high bit (``0x80``) used as a continuation flag.
 +
 +^ Type                ^ Positive encoding ^ Negative encoding                 ^ Decoder result type        ^
 +| Signed 32-bit int   | 1–5 bytes         | always 5 bytes (sign-extended)    | JS ``number`` / Py ``int`` |
 +| Signed 64-bit long  | 1–9 bytes         | always 10 bytes (sign-extended)   | JS ``BigInt`` / Py ``int`` |
 +
 +64-bit values (notably **tick timestamps**) must be decoded with a wide integer type. The JavaScript decoder uses ``BigInt`` throughout to avoid loss of precision above ``2^53``.
 +
 +=== Decimal encoding (96-bit unscaled) ===
 +
 +Prices and tick values use a .NET ``decimal``-compatible layout: a single **header byte** (2 bits per chunk, 4 chunks) followed by up to four 7-bit-encoded magnitudes.
 +
 +  * Chunks (MSB→LSB in the header): ``lo``, ``mid``, ``hi`` (the 96-bit unscaled integer split into three 32-bit words) and a ``sign/scale`` chunk.
 +  * Per-chunk 2-bit tag: ``0x00`` = zero (no magnitude bytes follow), ``0x01`` = positive, ``0x02`` = negative, ``0x03`` = the ``Int32.MinValue`` sentinel (no magnitude bytes follow).
 +  * In the sign/scale chunk: **bit 31** set ⇒ value is negative; **bits 16–23** hold the decimal **scale** (number of fractional digits).
 +  * Final value = ``(±) unscaled / 10^scale``.
 +
 +The reference decoders represent decimals with arbitrary-precision libraries (**decimal.js** at scale 18 in JavaScript, ``decimal.Decimal`` in Python) so that round-tripping matches Java ``BigDecimal`` exactly.
 +
 +=== Nullable price (decodePriceN) ===
 +
 +Some fields (e.g. a market's minimum cabinet price) are nullable: a single header byte is read first; if bit 0 is **clear** the value is ``null`` and no further bytes follow, otherwise a decimal (above) follows.
 +
 +==== Price & time conventions ====
 +
 +  * **Prices** are exposed as a ``Price`` type — a decimal quantized to **scale 18** with **HALF_EVEN** rounding. Many tick records encode a price as a //tick increment// relative to a running value; the decoder converts these to absolute prices via the market's denominator / minimum-price-increment / VPT. The JSON ``openPrice`` etc. fields (which are integer-tick strings such as ``"473575"``) correspond to the decoded ``Price`` after conversion.
 +  * **Timestamps** are .NET-style **ticks**: 1 tick = 100 ns since ``0001-01-01 00:00:00``. The decoder wraps these in an ``NDateTime`` type. As with the JSON API, **all times are CST**.
 +  * Many time fields are **delta-encoded** against the previous record. A decoded "delta" larger than a threshold (~ year 1900 in ticks, ``599266080000000000``) is interpreted as an **absolute** tick value rather than a delta — a decoder must apply this rule to reconstruct timestamps correctly.
 +
 +==== Aggregated tags (T4BinAggr) ====
 +
 +Record tags emitted on ``/chart/barchart`` with a binary ``Accept`` header. Format version constant ``CVAL_T4BINAGGR_VERSION = 1``.
 +
 +^ Tag value ^ Constant                    ^ Purpose                                                                 ^
 +| 1         | ``CTAG_SOF``                | Start of format; carries the little-endian int32 version. Resets state. |
 +| 2         | ``CTAG_MARKET_DEFINITION``  | Market parameters: id, numerator, denominator, price code, tick value, VPT, min-cabinet price. |
 +| 3         | ``CTAG_MARKET_SWITCH``      | Switch the active market id for subsequent records.                     |
 +| 4         | ``CTAG_TRADEDATE_SWITCH``   | Switch the active trade date (7-bit datetime).                          |
 +| 10        | ``CTAG_BAR_DELTA``          | An OHLCV bar with prices encoded as tick increments relative to the bar low. |
 +| 11        | ``CTAG_BAR``                | An OHLCV bar with absolute decimal-encoded prices.                      |
 +| 20        | ``CTAG_MARKET_MODE``        | Market mode change (see **[[#MarketMode]]**).                           |
 +| 21        | ``CTAG_OPEN_INTEREST``      | Open-interest sample.                                                   |
 +| 22        | ``CTAG_SETTLEMENT_PRICE``   | Settlement price + ``held`` boolean.                                    |
 +
 +Each decoded ``Bar`` exposes the same fields as the JSON //Bars// array (``TradeDate``, ``Time``, ``CloseTime``, ``MarketID``, ``OpenPrice``, ``HighPrice``, ``LowPrice``, ``ClosePrice``, ``Volume``, ``VolumeAtBid``, ``VolumeAtOffer``, ``Trades``, ``TradesAtBid``, ``TradesAtOffer``), with PascalCase names for parity with the Java/Python sources.
 +
 +==== Non-aggregated tags (T4Bin) ====
 +
 +Record tags emitted on ``/chart/tradehistory`` with a binary ``Accept`` header. Format version constant ``CVAL_T4BIN_VERSION = 1``. Each record updates the decoder's ``ChartDataState`` and sets ``state.Change`` to the corresponding **[[#ChartDataChange]]** value.
 +
 +=== Framing / market ===
 +^ Tag ^ Constant                   ^ Purpose                                                        ^
 +| 1   | ``CTAG_SOF``               | Start of format (+ optional version and trade date). Resets state. |
 +| 2   | ``CTAG_MARKET_DEFINITION`` | Market parameters for price conversion.                        |
 +| 7   | ``CTAG_CONSOLIDATED``      | Marks the stream as a consolidated (multi-market) feed.        |
 +| 8   | ``CTAG_MARKET_SWITCH``     | Switch active market by previously-registered key.             |
 +| 9   | ``CTAG_MARKET_KEY``        | Register a market key → market id mapping.                     |
 +
 +=== Trades / ticks ===
 +^ Tag ^ Constant                            ^ Purpose                                                  ^
 +| 11  | ``CTAG_TICKDATAPOINT_7BIT``         | Trade; price as +tick increment.                         |
 +| 12  | ``CTAG_TICKDATAPOINT_NEG_7BIT``     | Trade; price as -tick increment.                         |
 +| 17  | ``CTAG_TICKDATAPOINT_ALT_7BIT``     | Trade (+tick) with per-order volume list.                |
 +| 18  | ``CTAG_TICKDATAPOINT_ALT_NEG_7BIT`` | Trade (-tick) with per-order volume list.                |
 +| 60  | ``CTAG_TRADE_PRICE``                | Trade; price as decimal increment (cumulative).          |
 +| 61  | ``CTAG_TRADE_PRICE_DEC``            | Trade; price as absolute decimal increment.              |
 +| 62  | ``CTAG_TRADE_PRICE_ALT``            | As 60, with per-order volume list.                       |
 +| 63  | ``CTAG_TRADE_PRICE_DEC_ALT``        | As 61, with per-order volume list.                       |
 +
 +=== Tick-change (TickChange aggregation) ===
 +^ Tag ^ Constant                              ^ Purpose                                  ^
 +| 14  | ``CTAG_TICKCHANGEDATAPOINT_7BIT``     | Bar close-price moves +tick.             |
 +| 15  | ``CTAG_TICKCHANGEDATAPOINT_NEG_7BIT`` | Bar close-price moves -tick.             |
 +| 140 | ``CTAG_PRICE_CHANGE``                 | Bar close-price moves by decimal increment. |
 +| 141 | ``CTAG_PRICE_CHANGE_DEC``             | Bar close-price set to absolute decimal. |
 +
 +=== Bars ===
 +^ Tag ^ Constant                              ^ Purpose                                            ^
 +| 21  | ``CTAG_BARDATAPOINT_7BIT_DELTA_LOW``  | OHLCV bar; prices as +tick offsets from bar low.   |
 +| 22  | ``CTAG_BARDATAPOINT_NEG_7BIT_DELTA_LOW`` | OHLCV bar; prices as -tick offsets from bar low. |
 +| 65  | ``CTAG_BAR_PRICE``                    | OHLCV bar; decimal increments from running low.    |
 +| 66  | ``CTAG_BAR_PRICE_DEC``                | OHLCV bar; absolute decimal prices.                |
 +
 +=== Quotes (BBO) ===
 +^ Tag ^ Constant                    ^ Purpose                                          ^
 +| 50  | ``CTAG_QUOTE_7BIT``         | Bid/offer quote; bid as +tick increment.         |
 +| 51  | ``CTAG_QUOTE_NEG_7BIT``     | Bid/offer quote; bid as -tick increment.         |
 +| 52  | ``CTAG_QUOTE_VOLUME_DELTA`` | Quote volume-only change.                        |
 +| 53  | ``CTAG_QUOTE_PRICE``        | Quote; bid as cumulative decimal increment.      |
 +| 54  | ``CTAG_QUOTE_PRICE_DEC``    | Quote; bid as absolute decimal.                  |
 +
 +=== TPO (Time Price Opportunity / Market Profile) ===
 +^ Tag ^ Constant                       ^ Purpose                                   ^
 +| 30  | ``CTAG_TPO_START``             | TPO row start; base price +tick.          |
 +| 31  | ``CTAG_TPO_START_NEGBASE``     | TPO row start; base price -tick.          |
 +| 32  | ``CTAG_TPO_DATAPOINT``         | TPO cell.                                 |
 +| 33  | ``CTAG_TPO_DATAPOINT_OPEN``    | TPO cell (opening).                       |
 +| 34  | ``CTAG_TPO_DATAPOINT_CLOSE``   | TPO cell (closing).                       |
 +| 35  | ``CTAG_TPO_DATAPOINT_OPENCLOSE`` | TPO cell (opening & closing).           |
 +| 190 | ``CTAG_TPO_START_PRICE``       | TPO row start; cumulative decimal base.   |
 +| 191 | ``CTAG_TPO_START_PRICE_DEC``   | TPO row start; absolute decimal base.     |
 +| 192 | ``CTAG_TPO_PRICE``             | TPO cell; decimal price.                  |
 +| 193 | ``CTAG_TPO_OPEN_PRICE``        | TPO cell (opening); decimal price.        |
 +| 194 | ``CTAG_TPO_CLOSE_PRICE``       | TPO cell (closing); decimal price.        |
 +| 195 | ``CTAG_TPO_OPENCLOSE_PRICE``   | TPO cell (open & close); decimal price.   |
 +
 +=== Market state / session events ===
 +^ Tag ^ Constant                        ^ Purpose                                         ^
 +| 100 | ``CTAG_MARKET_MODE``            | Market mode change (see **[[#MarketMode]]**).   |
 +| 101 | ``CTAG_MARKET_SETTLEMENT``      | Settlement price (tick).                        |
 +| 102 | ``CTAG_MARKET_HELD_SETTLEMENT`` | Held settlement price (tick).                   |
 +| 103 | ``CTAG_MARKET_CLEARED_VOLUME``  | Cleared volume.                                 |
 +| 104 | ``CTAG_MARKET_OPEN_INTEREST``   | Open interest.                                  |
 +| 105 | ``CTAG_MARKET_VWAP``            | VWAP (tick).                                    |
 +| 106 | ``CTAG_MARKET_RFQ``             | Request-for-quote (side + volume).              |
 +| 107 | ``CTAG_SETTLEMENT_PRICE``       | Settlement price (decimal increment).           |
 +| 108 | ``CTAG_HELD_SETTLEMENT_PRICE``  | Held settlement price (decimal increment).      |
 +| 109 | ``CTAG_VWAP_PRICE``             | VWAP (decimal increment).                       |
 +
 +===== Decoder Libraries =====
 +
 +Open-source reference decoders are maintained alongside this API so you do not have to implement the binary format by hand. Both libraries are line-for-line ports of the original Java ``com.t4login`` chart-data reader and are validated against each other and against the CSV/JSON output.
 +
 +All of the tools below live in the public **CTS-Futures/t4-api-tools** repository:
 +
 +[[https://github.com/CTS-Futures/t4-api-tools/tree/main/tools|https://github.com/CTS-Futures/t4-api-tools/tree/main/tools]]
 +
 +^ Language    ^ Package / module                ^ Location in the repo                                  ^
 +| JavaScript  | ``@t4/chart-decoder`` (ES modules) | ``tools/JavaScript/t4-javascript-api/`` (and a browser copy under ``tools/JavaScript/JSDemo/decoder/``) |
 +| Python      | ``t4login``                     | ``tools/Python/t4-pythonConversion-api/src/t4login/``         |
 +
 +==== JavaScript: @t4/chart-decoder ====
 +
 +Requires **Node 18+** (uses global ``fetch``) or any modern browser. The only runtime dependency is **decimal.js**.
 +
 +=== Install ===
 +Clone the [[https://github.com/CTS-Futures/t4-api-tools/tree/main/tools|t4-api-tools]] repository, then install dependencies:
 +
 +<code powershell>
 +git clone https://github.com/CTS-Futures/t4-api-tools.git
 +cd t4-api-tools/tools/JavaScript/t4-javascript-api
 +npm install
 +</code>
 +
 +=== Aggregated barchart (push / handler model) ===
 +
 +``ChartDataStreamReaderAggr`` decodes the whole stream and dispatches each record to a handler. Any subset of callbacks may be supplied; missing callbacks are skipped.
 +
 +<code javascript>
 +import { ChartClient } from '@t4/chart-decoder';
 +
 +const client = new ChartClient({ token: 'YOUR_ACCESS_TOKEN' });
 +
 +await client.getBarchartBinary({
 +  exchangeId: 'CME_Eq',
 +  contractId: 'ESM6',
 +  barInterval: 'Minute',
 +  barPeriod:   1,
 +  tradeDateStart: '2026-05-01',
 +  tradeDateEnd:   '2026-05-02',
 +  handler: {
 +    onMarketDefinition(def) { /* def.MarketID, def.TickValue, ... */ },
 +    onBar(bar)              { console.log(bar.Time.toString(), bar.ClosePrice.toString()); },
 +    onModeChange(marketId, tradeDate, time, mode) { /* ... */ },
 +    onSettlement(marketId, tradeDate, time, price, held) { /* ... */ },
 +    onOpenInterest(marketId, tradeDate, time, oi) { /* ... */ },
 +  },
 +});
 +</code>
 +
 +The handler interface:
 +
 +^ Callback                                                            ^ Emitted for tag(s)                ^
 +| ``onMarketDefinition(marketDefinition)``                            | ``CTAG_MARKET_DEFINITION``        |
 +| ``onBar(bar)``                                                      | ``CTAG_BAR``, ``CTAG_BAR_DELTA``  |
 +| ``onModeChange(marketId, tradeDate, time, mode)``                   | ``CTAG_MARKET_MODE``              |
 +| ``onSettlement(marketId, tradeDate, time, settlementPrice, held)``  | ``CTAG_SETTLEMENT_PRICE``         |
 +| ``onOpenInterest(marketId, tradeDate, time, openInterest)``         | ``CTAG_OPEN_INTEREST``            |
 +
 +=== Non-aggregated trade history (pull / state model) ===
 +
 +``ChartDataStreamReader`` is a sequential cursor. Each ``read()`` consumes one record and mutates the public ``reader.state`` object; ``read()`` returns ``false`` at end-of-stream. Branch on ``state.Change``:
 +
 +<code javascript>
 +import { ChartClient, ChartDataChange } from '@t4/chart-decoder';
 +
 +const reader = await client.getTradehistoryBinary({
 +  exchangeId: 'CME_E',
 +  contractId: 'YM',
 +  tradeDateStart: '2024-01-08',
 +  tradeDateEnd:   '2024-01-08',
 +});
 +
 +while (reader.read()) {
 +  const s = reader.state;
 +  switch (s.Change) {
 +    case ChartDataChange.Trade:
 +      console.log(s.LastTimeTicks, s.LastTradePrice.toString(), s.TradeVolume, s.AtBidOrOffer);
 +      break;
 +    case ChartDataChange.Quote:
 +      console.log('BBO', s.BidPrice.toString(), s.OfferPrice.toString());
 +      break;
 +    case ChartDataChange.Settlement:
 +      console.log('settle', s.SettlementPrice?.toString());
 +      break;
 +    // ... MarketMode, OpenInterest, VWAP, TPO, TradeBar, TickChange, RFQ ...
 +  }
 +}
 +</code>
 +
 +=== Lower-level / advanced usage ===
 +
 +You can also decode bytes you already have (e.g. from a saved file) without the HTTP client:
 +
 +<code javascript>
 +import {
 +  ByteReader, NDateTime, ChartDataType,
 +  ChartDataStreamReader, ChartDataStreamReaderAggr,
 +  extractT4BinPayload,
 +} from '@t4/chart-decoder';
 +
 +// Aggregated:
 +ChartDataStreamReaderAggr.read(extractT4BinPayload(bytes), handler);
 +
 +// Non-aggregated:
 +const reader = new ChartDataStreamReader({
 +  data: new ByteReader(extractT4BinPayload(bytes)),
 +  tradeDate: new NDateTime(0n),
 +  marketId: 'XCME_E YM (H24)',
 +  dataType: ChartDataType.get(0), // Tick
 +});
 +</code>
 +
 +=== Browser (no bundler) ===
 +
 +The JSDemo copy ships a ``decoder/loader.js`` ES-module entry point that publishes the decoder on ``window.T4ChartDecoder`` and fires a ``t4-decoder-ready`` event, so classic ``<script>`` code can use it without an ``import`` statement:
 +
 +<code html>
 +<script type="module" src="decoder/loader.js"></script>
 +<script>
 +  window.addEventListener('t4-decoder-ready', (e) => {
 +    const { ChartDataStreamReaderAggr, extractT4BinPayload } = e.detail;
 +    // ...
 +  });
 +</script>
 +</code>
 +
 +==== Python: t4login ====
 +
 +The Python package mirrors the JavaScript API one-to-one (same class names, same field names). It is the original conversion the JavaScript port was derived from.
 +
 +=== Install ===
 +Clone the [[https://github.com/CTS-Futures/t4-api-tools/tree/main/tools|t4-api-tools]] repository, then install dependencies:
 +
 +<code powershell>
 +git clone https://github.com/CTS-Futures/t4-api-tools.git
 +cd t4-api-tools/tools/Python/t4-pythonConversion-api
 +pip install -e .                  # installs from pyproject.toml
 +</code>
 +
 +=== Usage ===
 +
 +<code python>
 +from t4login.client.chart_client import ChartClient
 +from t4login.definitions.chartdata.chart_data_change import ChartDataChange
 +
 +client = ChartClient(token="YOUR_ACCESS_TOKEN")
 +
 +# Aggregated (handler model)
 +client.get_barchart_binary(
 +    exchange_id="CME_Eq", contract_id="ESM6",
 +    trade_date_start="2026-05-01", trade_date_end="2026-05-02",
 +    handler=my_handler,
 +)
 +
 +# Non-aggregated (state model)
 +reader = client.get_tradehistory_binary(
 +    exchange_id="CME_E", contract_id="YM",
 +    trade_date_start="2024-01-08", trade_date_end="2024-01-08",
 +)
 +while reader.read():
 +    s = reader.state
 +    if s.Change == ChartDataChange.Trade:
 +        print(s.LastTradePrice, s.TradeVolume)
 +</code>
 +
 +==== ChartDataState field reference (T4Bin) ====
 +
 +Populated by ``ChartDataStreamReader``. Field names are PascalCase for parity across Java/Python/JS. Prices are ``Price`` objects (call ``.toString()`` / Python ``str()``); 64-bit tick times are ``BigInt`` in JS.
 +
 +^ Group        ^ Fields                                                                                                   ^
 +| Change       | ``Change`` (a **[[#ChartDataChange]]** value)                                                             |
 +| Trade date   | ``TradeDate``, ``TradeDateTicks``                                                                         |
 +| Market def.  | ``MarketDefined``, ``MarketID``, ``Numerator``, ``Denominator``, ``PriceCode``, ``TickValue``, ``VPT``, ``MinCabPrice``, ``MinPriceIncrement``, ``PointValue`` |
 +| Last trade   | ``LastTradePrice``, ``TradeVolume``, ``LastTTV``, ``LastTimeTicks``, ``AtBidOrOffer`` (**[[#BidOffer]]**), ``DueToSpread``, ``OrderVolumes`` |
 +| Bar          | ``BarStartTime``, ``BarCloseTime``, ``BarOpenPrice``, ``BarHighPrice``, ``BarLowPrice``, ``BarClosePrice``, ``BarVolume``, ``BarBidVolume``, ``BarOfferVolume``, ``BarTrades``, ``BarTradesAtBid``, ``BarTradesAtOffer`` |
 +| TPO          | ``TPOStartTime``, ``TPOBasePrice``, ``TPOPrice``, ``TPOVolume``, ``TPOVolumeAtBid``, ``TPOVolumeAtOffer``, ``TPOIsOpening``, ``TPOIsClosing`` |
 +| Quote        | ``BidPrice``, ``BidRealVolume``, ``BidImpliedVolume``, ``OfferPrice``, ``OfferRealVolume``, ``OfferImpliedVolume`` |
 +| Session      | ``Mode`` (**[[#MarketMode]]**), ``SettlementPrice``, ``SettlementHeldPrice``, ``ClearedVolume``, ``OpenInterest``, ``VWAP_Price`` |
 +| RFQ          | ``RFQBuySell`` (**[[#BidOffer]]**), ``RFQVolume``                                                         |
 +
 +==== Enumerations ====
 +
 +=== ChartDataChange ===
 +The ``state.Change`` discriminator after each ``read()``.
 +
 +^ Value ^ Name               ^ Value ^ Name              ^
 +| 0     | ``NONE``           | 8     | ``TickChange``    |
 +| 1     | ``Trade``        |   | 9     | ``RFQ``           |
 +| 2     | ``Quote``        |   | 10    | ``HeldSettlement``|
 +| 3     | ``MarketMode``     | 11    | ``ClearedVolume`` |
 +| 4     | ``Settlement``     | 12    | ``OpenInterest``  |
 +| 5     | ``TradeBar``       | 13    | ``VWAP``          |
 +| 6     | ``TradeDate``    |   | 14    | ``MarketSwitch``  |
 +| 7     | ``TPO``          |   | 15    | ``MarketDefinition`` |
 +
 +=== MarketMode ===
 +Exchange session lifecycle state (the ``marketMode`` field in JSON, and ``state.Mode`` / ``onModeChange`` in binary).
 +
 +^ Value ^ Name               ^ Value ^ Name             ^
 +| 0     | ``Undefined``    |   | 8     | ``Failed``       |
 +| 1     | ``PreOpen``      |   | 9     | ``PreCross``     |
 +| 2     | ``Open``           | 10    | ``Cross``        |
 +| 3     | ``RestrictedOpen`` |  | 11    | ``Expired``      |
 +| 4     | ``PreClosed``    |   | 12    | ``Rejected``     |
 +| 5     | ``Closed``         | 13    | ``Unavailable``  |
 +| 6     | ``Suspended``    |   | 14    | ``NoPermission`` |
 +| 7     | ``Halted``         | 15    | ``TrialExpired`` |
 +
 +=== BidOffer ===
 +Which side of the market a trade/RFQ executed against (mirrors the JSON ``aggressorSide``).
 +
 +^ Value ^ Name          ^
 +| 1     | ``Bid``       |
 +| 0     | ``Undefined`` |
 +| -1    | ``Offer``     |
 +
 +==== Numeric correctness ====
 +
 +  * 64-bit ticks / 7-bit-long values use **BigInt** (JS) / native ``int`` (Python).
 +  * 96-bit unscaled decimals use **decimal.js** at scale 18 with ``ROUND_HALF_EVEN`` (JS) / ``decimal.Decimal`` (Python), matching Java ``BigDecimal``.
 +  * Field naming preserves Java/Python PascalCase on ``ChartDataState``, ``Bar``, and ``MarketDefinition`` for 1:1 parity across all three implementations.
 +
 +===== Revision Notes / Changelog =====
 +
 +This revision adds documentation for the binary transport and the reference decoders. Nothing in the original JSON documentation was removed or semantically altered.
 +
 +^ Area ^ Change ^
 +| Accept headers (both endpoints) | Clarified that ``application/octet-stream`` / ``application/t4`` return the compact binary format and cross-linked to the new sections. |
 +| New section | **Binary Response Format (T4Bin / T4BinAggr)** — envelope/SOF extraction, length-prefixed record framing, 7-bit int/long and 96-bit decimal encodings, nullable price, and price/time (CST tick) conventions. |
 +| New section | Full **CTAG record-tag tables** for both the aggregated (T4BinAggr) and non-aggregated (T4Bin) dialects. |
 +| New section | **Decoder Libraries** — JavaScript (``@t4/chart-decoder``) and Python (``t4login``) usage, the aggregated handler interface, the non-aggregated state-cursor model, browser loader, the ``ChartDataState`` field reference, and the ``ChartDataChange`` / ``MarketMode`` / ``BidOffer`` enumerations. |
 +
 +**Source of truth:** the tables above are generated from the decoder source in
 +``tools/JavaScript/t4-javascript-api/src`` (mirror under ``tools/JavaScript/JSDemo/decoder``) and
 +``tools/Python/t4-pythonConversion-api/src/t4login``. If the format version constants
 +(``CVAL_T4BIN_VERSION`` / ``CVAL_T4BINAGGR_VERSION``) change, regenerate the tag tables from
 +``ChartFormat`` / ``ChartFormatAggr``.
 +</content>
 +</invoke>
  
  • playground/playground.1722839287.txt.gz
  • Last modified: 2024/08/05 06:28
  • by 127.0.0.1