Differences
This shows you the differences between two versions of the page.
| Both sides previous revision Previous revision | |||
| playground:playground [2026/06/15 17:19] – juan | playground:playground [2026/06/24 14:59] (current) – juan | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| ====== PlayGround ====== | ====== PlayGround ====== | ||
| - | ====== T4 Chart API ====== | ||
| - | |||
| - | Our chart API provides data in aggregated or non-aggregated (raw trade) formats. | ||
| - | |||
| - | < | ||
| - | All times are in CST. | ||
| - | </ | ||
| - | |||
| - | The complete API documentation is available via Swagger UI at: | ||
| - | |||
| - | [[https:// | ||
| - | |||
| - | The Swagger documentation provides: | ||
| - | * Complete list of available endpoints | ||
| - | * Request parameters and response formats | ||
| - | * Interactive testing capability | ||
| - | * Authentication requirements | ||
| - | |||
| - | < | ||
| - | **What changed in this revision** \\ | ||
| - | This page has been extended to document the **compact binary response format** (``application/ | ||
| - | * A new top-level section **[[#Binary Response Format (T4Bin / T4BinAggr)]]** describing the on-the-wire envelope, framing, 7-bit/ | ||
| - | * A new top-level section **[[# | ||
| - | * Minor clarifications to the existing **Accept** header tables to cross-reference the binary sections. | ||
| - | |||
| - | See **[[# | ||
| - | </ | ||
| - | |||
| - | ===== 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 ==== | ||
| - | < | ||
| - | |||
| - | ==== Headers ==== | ||
| - | |||
| - | For proper access and response handling, the **GetBarChart** API requires certain HTTP headers to be set in the request. | ||
| - | |||
| - | ^ Header | ||
| - | | Authorization | ||
| - | | Accept | ||
| - | |||
| - | **Examples: | ||
| - | |||
| - | * To authorize the request, include the bearer token: | ||
| - | < | ||
| - | |||
| - | * To receive the response in a compact binary format, set the `Accept` header accordingly: | ||
| - | < | ||
| - | or | ||
| - | < | ||
| - | |||
| - | Setting the `Accept` header is optional, and if it is not included, the API will return the response in a JSON format. | ||
| - | |||
| - | < | ||
| - | The aggregated binary stream is referred to as **T4BinAggr**. Its envelope, framing, and record tags are documented under **[[# | ||
| - | </ | ||
| - | |||
| - | ==== Parameters ==== | ||
| - | ^ Parameter | ||
| - | | **exchangeId** | ||
| - | | **contractId** | ||
| - | | **chartType** | ||
| - | | **barInterval** | ||
| - | | **barPeriod** | ||
| - | | **tradeDateStart** | ||
| - | | **tradeDateEnd** | ||
| - | | marketID | ||
| - | | continuationType | Method of continuation for the chart. Only **Volume** is currently supported. | ||
| - | | resetInterval | ||
| - | | contractMonths | ||
| - | | rolloverThreshold| Rollover threshold (not applicable when **ContinuationType.Volume** is used). | ||
| - | | forwardMonths | ||
| - | |||
| - | ==== 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 | ||
| - | | tradeDate | ||
| - | | time | Time when the bar data starts. | ||
| - | | closeTime | ||
| - | | marketID | ||
| - | | openPrice | ||
| - | | highPrice | ||
| - | | lowPrice | ||
| - | | closePrice | ||
| - | | volume | ||
| - | | volumeAtBid | ||
| - | | volumeAtOffer | ||
| - | | trades | ||
| - | | tradesAtBid | ||
| - | | tradesAtOffer | ||
| - | |||
| - | === MarketDefinitions === | ||
| - | ^ Element | ||
| - | | marketID | ||
| - | | minPriceIncrement | Minimum increment of the market' | ||
| - | | priceCode | ||
| - | | tickValue | ||
| - | | vpt | Additional market-specific information (variable). | ||
| - | |||
| - | === ModeChanges === | ||
| - | ^ Element | ||
| - | | marketID | ||
| - | | tradeDate | ||
| - | | time | Time when the mode change occurred. | ||
| - | | marketMode | ||
| - | |||
| - | === OpenInterests === | ||
| - | ^ Element | ||
| - | | marketID | ||
| - | | tradeDate | ||
| - | | time | Time of the recorded open interest. | ||
| - | | openInterest | ||
| - | |||
| - | === Settlements === | ||
| - | ^ Element | ||
| - | | marketID | ||
| - | | tradeDate | ||
| - | | time | Time when the settlement information was recorded. | ||
| - | | settlementPrice | ||
| - | | isHeld | ||
| - | |||
| - | ==== Example JSON Response ==== | ||
| - | |||
| - | < | ||
| - | { | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | { | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | } | ||
| - | ], | ||
| - | " | ||
| - | { | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | } | ||
| - | ], | ||
| - | " | ||
| - | { | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | }, | ||
| - | // ... additional mode changes ... | ||
| - | ], | ||
| - | " | ||
| - | { | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | }, | ||
| - | // ... additional open interests ... | ||
| - | ], | ||
| - | " | ||
| - | { | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | }, | ||
| - | { | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | } | ||
| - | // ... additional settlements ... | ||
| - | ] | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | ===== 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 ==== | ||
| - | < | ||
| - | |||
| - | ==== Headers ==== | ||
| - | ^ Header | ||
| - | | Authorization | Bearer < | ||
| - | | Accept | ||
| - | |||
| - | ==== Parameters ==== | ||
| - | ^ Parameter | ||
| - | | exchangeId | ||
| - | | contractId | ||
| - | | marketID | ||
| - | | tradeDateStart | ||
| - | | tradeDateEnd | ||
| - | | 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. | ||
| - | |||
| - | < | ||
| - | 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 **[[# | ||
| - | </ | ||
| - | |||
| - | === Response === | ||
| - | ^ Element | ||
| - | | exchangeID | ||
| - | | contractID | ||
| - | | marketID | ||
| - | | requestStatusMessage| Any status messages or errors related to the request. | ||
| - | | tradeDateStart | ||
| - | | tradeDateEnd | ||
| - | | trades | ||
| - | | marketDefinitions | ||
| - | | modeChanges | ||
| - | | openInterests | ||
| - | | settlements | ||
| - | | vwaPs | An array detailing volume-weighted average prices (VWAP). | ||
| - | |||
| - | === Trades === | ||
| - | |||
| - | ^ Element | ||
| - | | marketID | ||
| - | | tradeDate | ||
| - | | time | The specific time when the trade occurred. | ||
| - | | tradePrice | ||
| - | | aggressorSide | ||
| - | |||
| - | === VWAP(s) === | ||
| - | |||
| - | ^ Element | ||
| - | | marketID | ||
| - | | tradeDate | ||
| - | | time | The specific time when the VWAP is calculated. | ||
| - | | vwapPrice | ||
| - | |||
| - | ==== Example JSON Response ==== | ||
| - | |||
| - | < | ||
| - | { | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | { | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | " | ||
| - | }, | ||
| - | ... | ||
| - | ], | ||
| - | " | ||
| - | " | ||
| - | ... | ||
| - | ], | ||
| - | " | ||
| - | ... | ||
| - | ], | ||
| - | " | ||
| - | ... | ||
| - | ], | ||
| - | " | ||
| - | ... | ||
| - | ] | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | 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/ | ||
| - | |||
| - | Two closely-related dialects exist: | ||
| - | |||
| - | ^ Stream | ||
| - | | **T4BinAggr** | ``/ | ||
| - | | **T4Bin** | ||
| - | |||
| - | < | ||
| - | You do **not** need to implement the byte-level format yourself — reference decoders are provided for JavaScript and Python (see **[[# | ||
| - | </ | ||
| - | |||
| - | ==== 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 | ||
| - | | **T4BinAggr** | ``05 01 01 00 00 00`` | length=5, tag=``CTAG_SOF`` (1), version=1 (little-endian int32) | ||
| - | | **T4Bin** | ||
| - | |||
| - | 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**: | ||
| - | |||
| - | < | ||
| - | [ length : 7-bit int ] [ tag : 7-bit int ] [ tag-specific payload ... ] | ||
| - | </ | ||
| - | |||
| - | * **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**: | ||
| - | * **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/ | ||
| - | |||
| - | ==== Value encodings ==== | ||
| - | |||
| - | === 7-bit variable-length integers === | ||
| - | |||
| - | Integers are stored little-endian, | ||
| - | |||
| - | ^ Type ^ Positive encoding ^ Negative encoding | ||
| - | | Signed 32-bit int | 1–5 bytes | always 5 bytes (sign-extended) | ||
| - | | Signed 64-bit long | 1–9 bytes | always 10 bytes (sign-extended) | ||
| - | |||
| - | 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/ | ||
| - | * 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' | ||
| - | |||
| - | ==== 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' | ||
| - | * **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 " | ||
| - | |||
| - | ==== Aggregated tags (T4BinAggr) ==== | ||
| - | |||
| - | Record tags emitted on ``/ | ||
| - | |||
| - | ^ Tag value ^ Constant | ||
| - | | 1 | ``CTAG_SOF`` | ||
| - | | 2 | ``CTAG_MARKET_DEFINITION`` | ||
| - | | 3 | ``CTAG_MARKET_SWITCH`` | ||
| - | | 4 | ``CTAG_TRADEDATE_SWITCH`` | ||
| - | | 10 | ``CTAG_BAR_DELTA`` | ||
| - | | 11 | ``CTAG_BAR`` | ||
| - | | 20 | ``CTAG_MARKET_MODE`` | ||
| - | | 21 | ``CTAG_OPEN_INTEREST`` | ||
| - | | 22 | ``CTAG_SETTLEMENT_PRICE`` | ||
| - | |||
| - | Each decoded ``Bar`` exposes the same fields as the JSON //Bars// array (``TradeDate``, | ||
| - | |||
| - | ==== Non-aggregated tags (T4Bin) ==== | ||
| - | |||
| - | Record tags emitted on ``/ | ||
| - | |||
| - | === Framing / market === | ||
| - | ^ Tag ^ Constant | ||
| - | | 1 | ``CTAG_SOF`` | ||
| - | | 2 | ``CTAG_MARKET_DEFINITION`` | Market parameters for price conversion. | ||
| - | | 7 | ``CTAG_CONSOLIDATED`` | ||
| - | | 8 | ``CTAG_MARKET_SWITCH`` | ||
| - | | 9 | ``CTAG_MARKET_KEY`` | ||
| - | |||
| - | === Trades / ticks === | ||
| - | ^ Tag ^ Constant | ||
| - | | 11 | ``CTAG_TICKDATAPOINT_7BIT`` | ||
| - | | 12 | ``CTAG_TICKDATAPOINT_NEG_7BIT`` | ||
| - | | 17 | ``CTAG_TICKDATAPOINT_ALT_7BIT`` | ||
| - | | 18 | ``CTAG_TICKDATAPOINT_ALT_NEG_7BIT`` | Trade (-tick) with per-order volume list. | | ||
| - | | 60 | ``CTAG_TRADE_PRICE`` | ||
| - | | 61 | ``CTAG_TRADE_PRICE_DEC`` | ||
| - | | 62 | ``CTAG_TRADE_PRICE_ALT`` | ||
| - | | 63 | ``CTAG_TRADE_PRICE_DEC_ALT`` | ||
| - | |||
| - | === Tick-change (TickChange aggregation) === | ||
| - | ^ Tag ^ Constant | ||
| - | | 14 | ``CTAG_TICKCHANGEDATAPOINT_7BIT`` | ||
| - | | 15 | ``CTAG_TICKCHANGEDATAPOINT_NEG_7BIT`` | Bar close-price moves -tick. | ||
| - | | 140 | ``CTAG_PRICE_CHANGE`` | ||
| - | | 141 | ``CTAG_PRICE_CHANGE_DEC`` | ||
| - | |||
| - | === Bars === | ||
| - | ^ Tag ^ Constant | ||
| - | | 21 | ``CTAG_BARDATAPOINT_7BIT_DELTA_LOW`` | ||
| - | | 22 | ``CTAG_BARDATAPOINT_NEG_7BIT_DELTA_LOW`` | OHLCV bar; prices as -tick offsets from bar low. | | ||
| - | | 65 | ``CTAG_BAR_PRICE`` | ||
| - | | 66 | ``CTAG_BAR_PRICE_DEC`` | ||
| - | |||
| - | === Quotes (BBO) === | ||
| - | ^ Tag ^ Constant | ||
| - | | 50 | ``CTAG_QUOTE_7BIT`` | ||
| - | | 51 | ``CTAG_QUOTE_NEG_7BIT`` | ||
| - | | 52 | ``CTAG_QUOTE_VOLUME_DELTA`` | Quote volume-only change. | ||
| - | | 53 | ``CTAG_QUOTE_PRICE`` | ||
| - | | 54 | ``CTAG_QUOTE_PRICE_DEC`` | ||
| - | |||
| - | === TPO (Time Price Opportunity / Market Profile) === | ||
| - | ^ Tag ^ Constant | ||
| - | | 30 | ``CTAG_TPO_START`` | ||
| - | | 31 | ``CTAG_TPO_START_NEGBASE`` | ||
| - | | 32 | ``CTAG_TPO_DATAPOINT`` | ||
| - | | 33 | ``CTAG_TPO_DATAPOINT_OPEN`` | ||
| - | | 34 | ``CTAG_TPO_DATAPOINT_CLOSE`` | ||
| - | | 35 | ``CTAG_TPO_DATAPOINT_OPENCLOSE`` | TPO cell (opening & closing). | ||
| - | | 190 | ``CTAG_TPO_START_PRICE`` | ||
| - | | 191 | ``CTAG_TPO_START_PRICE_DEC`` | ||
| - | | 192 | ``CTAG_TPO_PRICE`` | ||
| - | | 193 | ``CTAG_TPO_OPEN_PRICE`` | ||
| - | | 194 | ``CTAG_TPO_CLOSE_PRICE`` | ||
| - | | 195 | ``CTAG_TPO_OPENCLOSE_PRICE`` | ||
| - | |||
| - | === Market state / session events === | ||
| - | ^ Tag ^ Constant | ||
| - | | 100 | ``CTAG_MARKET_MODE`` | ||
| - | | 101 | ``CTAG_MARKET_SETTLEMENT`` | ||
| - | | 102 | ``CTAG_MARKET_HELD_SETTLEMENT`` | Held settlement price (tick). | ||
| - | | 103 | ``CTAG_MARKET_CLEARED_VOLUME`` | ||
| - | | 104 | ``CTAG_MARKET_OPEN_INTEREST`` | ||
| - | | 105 | ``CTAG_MARKET_VWAP`` | ||
| - | | 106 | ``CTAG_MARKET_RFQ`` | ||
| - | | 107 | ``CTAG_SETTLEMENT_PRICE`` | ||
| - | | 108 | ``CTAG_HELD_SETTLEMENT_PRICE`` | ||
| - | | 109 | ``CTAG_VWAP_PRICE`` | ||
| - | |||
| - | ===== 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/ | ||
| - | |||
| - | [[https:// | ||
| - | |||
| - | ^ Language | ||
| - | | JavaScript | ||
| - | | Python | ||
| - | |||
| - | ==== JavaScript: @t4/ | ||
| - | |||
| - | Requires **Node 18+** (uses global ``fetch``) or any modern browser. The only runtime dependency is **decimal.js**. | ||
| - | |||
| - | === Install === | ||
| - | Clone the [[https:// | ||
| - | |||
| - | <code powershell> | ||
| - | git clone https:// | ||
| - | cd t4-api-tools/ | ||
| - | npm install | ||
| - | </ | ||
| - | |||
| - | === 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 ' | ||
| - | |||
| - | const client = new ChartClient({ token: ' | ||
| - | |||
| - | await client.getBarchartBinary({ | ||
| - | exchangeId: ' | ||
| - | contractId: ' | ||
| - | barInterval: | ||
| - | barPeriod: | ||
| - | tradeDateStart: | ||
| - | tradeDateEnd: | ||
| - | handler: { | ||
| - | onMarketDefinition(def) { /* def.MarketID, | ||
| - | onBar(bar) | ||
| - | onModeChange(marketId, | ||
| - | onSettlement(marketId, | ||
| - | onOpenInterest(marketId, | ||
| - | }, | ||
| - | }); | ||
| - | </ | ||
| - | |||
| - | The handler interface: | ||
| - | |||
| - | ^ Callback | ||
| - | | ``onMarketDefinition(marketDefinition)`` | ||
| - | | ``onBar(bar)`` | ||
| - | | ``onModeChange(marketId, | ||
| - | | ``onSettlement(marketId, | ||
| - | | ``onOpenInterest(marketId, | ||
| - | |||
| - | === 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, | ||
| - | |||
| - | const reader = await client.getTradehistoryBinary({ | ||
| - | exchangeId: ' | ||
| - | contractId: ' | ||
| - | tradeDateStart: | ||
| - | tradeDateEnd: | ||
| - | }); | ||
| - | |||
| - | while (reader.read()) { | ||
| - | const s = reader.state; | ||
| - | switch (s.Change) { | ||
| - | case ChartDataChange.Trade: | ||
| - | console.log(s.LastTimeTicks, | ||
| - | break; | ||
| - | case ChartDataChange.Quote: | ||
| - | console.log(' | ||
| - | break; | ||
| - | case ChartDataChange.Settlement: | ||
| - | console.log(' | ||
| - | break; | ||
| - | // ... MarketMode, OpenInterest, | ||
| - | } | ||
| - | } | ||
| - | </ | ||
| - | |||
| - | === 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, | ||
| - | extractT4BinPayload, | ||
| - | } from ' | ||
| - | |||
| - | // Aggregated: | ||
| - | ChartDataStreamReaderAggr.read(extractT4BinPayload(bytes), | ||
| - | |||
| - | // Non-aggregated: | ||
| - | const reader = new ChartDataStreamReader({ | ||
| - | data: new ByteReader(extractT4BinPayload(bytes)), | ||
| - | tradeDate: new NDateTime(0n), | ||
| - | marketId: ' | ||
| - | dataType: ChartDataType.get(0), | ||
| - | }); | ||
| - | </ | ||
| - | |||
| - | === Browser (no bundler) === | ||
| - | |||
| - | The JSDemo copy ships a ``decoder/ | ||
| - | |||
| - | <code html> | ||
| - | <script type=" | ||
| - | < | ||
| - | window.addEventListener(' | ||
| - | const { ChartDataStreamReaderAggr, | ||
| - | // ... | ||
| - | }); | ||
| - | </ | ||
| - | </ | ||
| - | |||
| - | ==== 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:// | ||
| - | |||
| - | <code powershell> | ||
| - | git clone https:// | ||
| - | cd t4-api-tools/ | ||
| - | pip install -e . # installs from pyproject.toml | ||
| - | </ | ||
| - | |||
| - | === Usage === | ||
| - | |||
| - | <code python> | ||
| - | from t4login.client.chart_client import ChartClient | ||
| - | from t4login.definitions.chartdata.chart_data_change import ChartDataChange | ||
| - | |||
| - | client = ChartClient(token=" | ||
| - | |||
| - | # Aggregated (handler model) | ||
| - | client.get_barchart_binary( | ||
| - | exchange_id=" | ||
| - | trade_date_start=" | ||
| - | handler=my_handler, | ||
| - | ) | ||
| - | |||
| - | # Non-aggregated (state model) | ||
| - | reader = client.get_tradehistory_binary( | ||
| - | exchange_id=" | ||
| - | trade_date_start=" | ||
| - | ) | ||
| - | while reader.read(): | ||
| - | s = reader.state | ||
| - | if s.Change == ChartDataChange.Trade: | ||
| - | print(s.LastTradePrice, | ||
| - | </ | ||
| - | |||
| - | ==== ChartDataState field reference (T4Bin) ==== | ||
| - | |||
| - | Populated by ``ChartDataStreamReader``. Field names are PascalCase for parity across Java/ | ||
| - | |||
| - | ^ Group ^ Fields | ||
| - | | Change | ||
| - | | Trade date | ``TradeDate``, | ||
| - | | Market def. | ``MarketDefined``, | ||
| - | | Last trade | ``LastTradePrice``, | ||
| - | | Bar | ``BarStartTime``, | ||
| - | | TPO | ``TPOStartTime``, | ||
| - | | Quote | ``BidPrice``, | ||
| - | | Session | ||
| - | | RFQ | ``RFQBuySell`` (**[[# | ||
| - | |||
| - | ==== Enumerations ==== | ||
| - | |||
| - | === ChartDataChange === | ||
| - | The ``state.Change`` discriminator after each ``read()``. | ||
| - | |||
| - | ^ Value ^ Name | ||
| - | | 0 | ``NONE`` | ||
| - | | 1 | ``Trade`` | ||
| - | | 2 | ``Quote`` | ||
| - | | 3 | ``MarketMode`` | ||
| - | | 4 | ``Settlement`` | ||
| - | | 5 | ``TradeBar`` | ||
| - | | 6 | ``TradeDate`` | ||
| - | | 7 | ``TPO`` | ||
| - | |||
| - | === MarketMode === | ||
| - | Exchange session lifecycle state (the ``marketMode`` field in JSON, and ``state.Mode`` / ``onModeChange`` in binary). | ||
| - | |||
| - | ^ Value ^ Name | ||
| - | | 0 | ``Undefined`` | ||
| - | | 1 | ``PreOpen`` | ||
| - | | 2 | ``Open`` | ||
| - | | 3 | ``RestrictedOpen`` | | 11 | ``Expired`` | ||
| - | | 4 | ``PreClosed`` | ||
| - | | 5 | ``Closed`` | ||
| - | | 6 | ``Suspended`` | ||
| - | | 7 | ``Halted`` | ||
| - | |||
| - | === 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``, | ||
| - | |||
| - | ===== 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/ | ||
| - | | New section | **Binary Response Format (T4Bin / T4BinAggr)** — envelope/ | ||
| - | | New section | Full **CTAG record-tag tables** for both the aggregated (T4BinAggr) and non-aggregated (T4Bin) dialects. | | ||
| - | | New section | **Decoder Libraries** — JavaScript (``@t4/ | ||
| - | |||
| - | **Source of truth:** the tables above are generated from the decoder source in | ||
| - | ``tools/ | ||
| - | ``tools/ | ||
| - | (``CVAL_T4BIN_VERSION`` / ``CVAL_T4BINAGGR_VERSION``) change, regenerate the tag tables from | ||
| - | ``ChartFormat`` / ``ChartFormatAggr``. | ||
| - | </ | ||
| - | </ | ||