From 6ed6bc9758e1b96b91781724ee740d33441871be Mon Sep 17 00:00:00 2001 From: Sebastian Lerner Date: Sat, 22 Aug 2026 13:57:27 -0400 Subject: [PATCH 01/19] Add beta Futures data streams page Documents the generic front/second/third-month feed rotation methodology for the new commodities futures product (gold, silver, WTI oil, natural gas). Avoids exchange names and proprietary contract symbology per licensing guidance. Co-Authored-By: Claude Sonnet 5 --- src/config/sidebar.ts | 4 + src/content/data-streams/llms-full.txt | 106 ++++++++++++++++ .../data-streams/rwa-streams/futures.mdx | 117 ++++++++++++++++++ 3 files changed, 227 insertions(+) create mode 100644 src/content/data-streams/rwa-streams/futures.mdx diff --git a/src/config/sidebar.ts b/src/config/sidebar.ts index 731b7b1e338..a810fef123d 100644 --- a/src/config/sidebar.ts +++ b/src/config/sidebar.ts @@ -1275,6 +1275,10 @@ export const SIDEBAR: Partial> = { title: "APAC Equities", url: "data-streams/rwa-streams/apac-equities", }, + { + title: "Futures", + url: "data-streams/rwa-streams/futures", + }, ], }, { diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index 868945c8e77..ff2d73e0f74 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -6518,6 +6518,112 @@ For inquiries related to a data outage, contact Chainlink Labs at [data_support@ --- +# Futures +Source: https://docs.chain.link/data-streams/rwa-streams/futures + + + +Futures streams provide price data for exchange-traded futures contracts. These streams enable onchain protocols to build markets around futures price exposure. At launch, coverage is limited to commodities — energy and precious metals — described below. + +Because futures contracts expire, Data Streams does not publish one feed per contract. Instead, each instrument is represented by three **generic** feeds that always track the current front, second, and third contract. This is explained in [Rotation methodology](#rotation-methodology) below. + +Developers are responsible for choosing the appropriate feed and ensuring that the operation and performance of their choice matches expectations. For more information, see the [Developer Responsibilities](/data-streams/developer-responsibilities) guidance. + +## Coverage + +At launch, Futures streams are available for the following commodities. Additional commodities and asset classes may be added based on demand. + +| Commodity | Generic feeds | +| ----------- | ------------------------------------------------ | +| Gold | Front-month, second-month, and third-month feeds | +| Silver | Front-month, second-month, and third-month feeds | +| Oil (WTI) | Front-month, second-month, and third-month feeds | +| Natural Gas | Front-month, second-month, and third-month feeds | + +## Naming and price representation + +Feed names use the plain instrument name only (for example, "WTI," "Gold," "Natural Gas"). Chainlink does not use any exchange's proprietary contract ticker in its feed or stream identifiers. + +Contract specifications — contract size, tick size, quotation units, and similar terms — can vary between exchanges for the same underlying instrument. Chainlink does not publish these specifications, since they belong to the exchange where a given contract is listed. If your application needs exact contract specifications, consult that exchange's own public product documentation directly. + +## Rotation methodology + +Unlike spot instruments, futures contracts have a finite life. For example, a given month's Natural Gas contract trades for a limited window and then expires. If Data Streams published a dedicated feed per contract, integrators would need to re-point their integration to a new feed every time a contract expired. + +To avoid this, each instrument is represented by three static, non-expiring **generic feeds** that always represent the near-term forward curve of eligible contracts: + +| Generic feed | Meaning | +| --------------------- | ---------------------------------------------------------------- | +| **Front-month feed** | Tracks the nearest unexpired eligible contract | +| **Second-month feed** | Tracks the next eligible contract after the front-month contract | +| **Third-month feed** | Tracks the eligible contract after that | + +This design means: + +- **Zero maintenance.** Integrate the three generic feeds once. You never need to re-point feed endpoints when a contract expires — the feeds re-map internally. +- **Full visibility of the curve.** Because the front, second, and third contracts are exposed simultaneously, you retain full autonomy over your own rolling logic. You can roll positions on a fixed schedule ahead of expiry, or when liquidity migrates from the front contract to the second — Data Streams does not impose a roll strategy. + +### How the roll works + +When the front-month contract reaches its expiration, the generic feeds cascade forward: + +- The **front-month feed** takes over the contract previously tracked by the second-month feed +- The **second-month feed** takes over the contract previously tracked by the third-month feed +- The **third-month feed** begins tracking the next eligible contract in that instrument's cycle + +A few properties of the roll are worth calling out explicitly: + +- **The roll is triggered by the front-month contract's expiration**, as defined by the listed expiration calendar for that specific instrument. Expiration conventions differ by instrument, so rolls for different instruments happen on different dates — there is no single "roll day" across all instruments. +- **The roll is a re-mapping, not a price adjustment.** At the moment of the roll, the front-month feed switches from quoting the expiring contract to quoting what was previously the second-month contract. Because different contract months can trade at different prices, **expect a price discontinuity on the generic feed at each roll**. Feeds are not back-adjusted into a smooth continuous series — if your application needs a continuous series, construct it from the raw generic feeds on your end. +- **Until expiration, the front-month feed continues to track the expiring contract**, even in its final days when liquidity has typically already migrated to the next contract. This is precisely why the second-month feed is exposed — so you can implement your own liquidity-based rolls ahead of expiry instead of holding the front-month contract to the end. + +### Contract eligibility varies by instrument + +"Front-month" does not always mean "nearest calendar month." Each instrument has its own set of listed contract months, and for several instruments, the actively traded contracts are only a subset of what is listed: + +- **Energy** (Oil, Natural Gas): every calendar month is listed and liquid. The generic feeds walk the full monthly strip, so the front-, second-, and third-month feeds track three **consecutive** calendar months. +- **Precious metals** (Gold, Silver): many calendar months are listed, but liquidity concentrates in a benchmark cycle. The generic feeds follow the benchmark cycle only and skip non-benchmark months, even though those contracts exist and trade. + +| Commodity | Benchmark months | +| --------- | ---------------------------- | +| Gold | Feb, Apr, Jun, Aug, Oct, Dec | +| Silver | Mar, May, Jul, Sep, Dec | + +The practical consequence: **the gap between the front-, second-, and third-month feeds is not always one month.** For Gold or Silver, consecutive generic feeds can be one to three months apart. Do not assume monthly spacing in your integration. + +### Worked example + +Gold follows its benchmark cycle (Feb/Apr/Jun/Aug/Oct/Dec). In August 2026, before the August contract expires: + +| Feed | Contract tracked | +| ----------------- | ---------------- | +| Front-month feed | August 2026 | +| Second-month feed | October 2026 | +| Third-month feed | December 2026 | + +When the August contract expires, the front-month feed jumps directly to October, the second-month feed jumps to December, and the third-month feed begins tracking February 2027 — skipping the non-benchmark September and November contracts entirely, since they never appear on the generic feeds. + +## Integration guidance + +- **Do not hardcode contract-month assumptions.** The spacing between the front-, second-, and third-month feeds varies by instrument — one month for energy, up to a few months for precious metals. +- **Expect price steps at rolls.** A protocol using the front-month feed directly for margining or liquidation should either accept the step as economically correct (the front contract genuinely changed), implement its own early roll using the second-month feed, or build an adjusted continuous series off-chain from the raw generic feeds. +- **Roll early if you depend on liquidity.** In the final days of a contract's life, trading volume typically migrates to the next contract while the front-month feed still tracks the expiring one. If your application is sensitive to thin markets, consider rolling ahead of expiry using the second-month feed. +- **Follow the listed expiration calendar.** Expiration dates follow the official listed calendar of the exchange where the underlying contract trades, including holiday adjustments. Consult that exchange for the operative source of truth. + +## Trading hours + +Futures trade during standard trading hours for each instrument, with a scheduled break each trading day. Consult the exchange where the underlying contract is listed for holiday and early-close schedules. + +## Support + +For inquiries related to a data outage, contact Chainlink Labs at [chainlink_data_feeds@smartcontract.com](mailto:chainlink_data_feeds@smartcontract.com). + +--- + # Handling Market Events (v11) Source: https://docs.chain.link/data-streams/rwa-streams/handling-market-events-v11 diff --git a/src/content/data-streams/rwa-streams/futures.mdx b/src/content/data-streams/rwa-streams/futures.mdx new file mode 100644 index 00000000000..d6449a95852 --- /dev/null +++ b/src/content/data-streams/rwa-streams/futures.mdx @@ -0,0 +1,117 @@ +--- +section: dataStreams +date: "Last Modified" +title: "Futures" +metadata: + title: "Futures | Chainlink Data Streams" + description: "Reference for Chainlink Futures Data Streams, covering coverage, generic feed rotation, and risk considerations." +whatsnext: + { + "Learn about developer responsibilities": "/data-streams/developer-responsibilities", + "Learn about Data Streams market hours and schedules": "/data-streams/market-hours", + "Find the list of available RWA streams": "/data-streams/rwa-streams", + } +--- + +import { Aside } from "@components" + + + +Futures streams provide price data for exchange-traded futures contracts. These streams enable onchain protocols to build markets around futures price exposure. At launch, coverage is limited to commodities — energy and precious metals — described below. + +Because futures contracts expire, Data Streams does not publish one feed per contract. Instead, each instrument is represented by three **generic** feeds that always track the current front, second, and third contract. This is explained in [Rotation methodology](#rotation-methodology) below. + +Developers are responsible for choosing the appropriate feed and ensuring that the operation and performance of their choice matches expectations. For more information, see the [Developer Responsibilities](/data-streams/developer-responsibilities) guidance. + +## Coverage + +At launch, Futures streams are available for the following commodities. Additional commodities and asset classes may be added based on demand. + +| Commodity | Generic feeds | +| ----------- | ------------------------------------------------ | +| Gold | Front-month, second-month, and third-month feeds | +| Silver | Front-month, second-month, and third-month feeds | +| Oil (WTI) | Front-month, second-month, and third-month feeds | +| Natural Gas | Front-month, second-month, and third-month feeds | + +## Naming and price representation + +Feed names use the plain instrument name only (for example, "WTI," "Gold," "Natural Gas"). Chainlink does not use any exchange's proprietary contract ticker in its feed or stream identifiers. + +Contract specifications — contract size, tick size, quotation units, and similar terms — can vary between exchanges for the same underlying instrument. Chainlink does not publish these specifications, since they belong to the exchange where a given contract is listed. If your application needs exact contract specifications, consult that exchange's own public product documentation directly. + +## Rotation methodology + +Unlike spot instruments, futures contracts have a finite life. For example, a given month's Natural Gas contract trades for a limited window and then expires. If Data Streams published a dedicated feed per contract, integrators would need to re-point their integration to a new feed every time a contract expired. + +To avoid this, each instrument is represented by three static, non-expiring **generic feeds** that always represent the near-term forward curve of eligible contracts: + +| Generic feed | Meaning | +| --------------------- | ---------------------------------------------------------------- | +| **Front-month feed** | Tracks the nearest unexpired eligible contract | +| **Second-month feed** | Tracks the next eligible contract after the front-month contract | +| **Third-month feed** | Tracks the eligible contract after that | + +This design means: + +- **Zero maintenance.** Integrate the three generic feeds once. You never need to re-point feed endpoints when a contract expires — the feeds re-map internally. +- **Full visibility of the curve.** Because the front, second, and third contracts are exposed simultaneously, you retain full autonomy over your own rolling logic. You can roll positions on a fixed schedule ahead of expiry, or when liquidity migrates from the front contract to the second — Data Streams does not impose a roll strategy. + +### How the roll works + +When the front-month contract reaches its expiration, the generic feeds cascade forward: + +- The **front-month feed** takes over the contract previously tracked by the second-month feed +- The **second-month feed** takes over the contract previously tracked by the third-month feed +- The **third-month feed** begins tracking the next eligible contract in that instrument's cycle + +A few properties of the roll are worth calling out explicitly: + +- **The roll is triggered by the front-month contract's expiration**, as defined by the listed expiration calendar for that specific instrument. Expiration conventions differ by instrument, so rolls for different instruments happen on different dates — there is no single "roll day" across all instruments. +- **The roll is a re-mapping, not a price adjustment.** At the moment of the roll, the front-month feed switches from quoting the expiring contract to quoting what was previously the second-month contract. Because different contract months can trade at different prices, **expect a price discontinuity on the generic feed at each roll**. Feeds are not back-adjusted into a smooth continuous series — if your application needs a continuous series, construct it from the raw generic feeds on your end. +- **Until expiration, the front-month feed continues to track the expiring contract**, even in its final days when liquidity has typically already migrated to the next contract. This is precisely why the second-month feed is exposed — so you can implement your own liquidity-based rolls ahead of expiry instead of holding the front-month contract to the end. + +### Contract eligibility varies by instrument + +"Front-month" does not always mean "nearest calendar month." Each instrument has its own set of listed contract months, and for several instruments, the actively traded contracts are only a subset of what is listed: + +- **Energy** (Oil, Natural Gas): every calendar month is listed and liquid. The generic feeds walk the full monthly strip, so the front-, second-, and third-month feeds track three **consecutive** calendar months. +- **Precious metals** (Gold, Silver): many calendar months are listed, but liquidity concentrates in a benchmark cycle. The generic feeds follow the benchmark cycle only and skip non-benchmark months, even though those contracts exist and trade. + +| Commodity | Benchmark months | +| --------- | ---------------------------- | +| Gold | Feb, Apr, Jun, Aug, Oct, Dec | +| Silver | Mar, May, Jul, Sep, Dec | + +The practical consequence: **the gap between the front-, second-, and third-month feeds is not always one month.** For Gold or Silver, consecutive generic feeds can be one to three months apart. Do not assume monthly spacing in your integration. + +### Worked example + +Gold follows its benchmark cycle (Feb/Apr/Jun/Aug/Oct/Dec). In August 2026, before the August contract expires: + +| Feed | Contract tracked | +| ----------------- | ---------------- | +| Front-month feed | August 2026 | +| Second-month feed | October 2026 | +| Third-month feed | December 2026 | + +When the August contract expires, the front-month feed jumps directly to October, the second-month feed jumps to December, and the third-month feed begins tracking February 2027 — skipping the non-benchmark September and November contracts entirely, since they never appear on the generic feeds. + +## Integration guidance + +- **Do not hardcode contract-month assumptions.** The spacing between the front-, second-, and third-month feeds varies by instrument — one month for energy, up to a few months for precious metals. +- **Expect price steps at rolls.** A protocol using the front-month feed directly for margining or liquidation should either accept the step as economically correct (the front contract genuinely changed), implement its own early roll using the second-month feed, or build an adjusted continuous series off-chain from the raw generic feeds. +- **Roll early if you depend on liquidity.** In the final days of a contract's life, trading volume typically migrates to the next contract while the front-month feed still tracks the expiring one. If your application is sensitive to thin markets, consider rolling ahead of expiry using the second-month feed. +- **Follow the listed expiration calendar.** Expiration dates follow the official listed calendar of the exchange where the underlying contract trades, including holiday adjustments. Consult that exchange for the operative source of truth. + +## Trading hours + +Futures trade during standard trading hours for each instrument, with a scheduled break each trading day. Consult the exchange where the underlying contract is listed for holiday and early-close schedules. + +## Support + +For inquiries related to a data outage, contact Chainlink Labs at [chainlink_data_feeds@smartcontract.com](mailto:chainlink_data_feeds@smartcontract.com). From 557e8abb9eea242f40e23d0077c161c7dfec8826 Mon Sep 17 00:00:00 2001 From: Sebastian Lerner Date: Sat, 22 Aug 2026 14:13:01 -0400 Subject: [PATCH 02/19] Add single-source data risk note to Futures page Mirrors the same risk consideration already documented for APAC Equities: each instrument is sourced from a single data provider with no cross-validation or fallback. Co-Authored-By: Claude Sonnet 5 --- src/content/data-streams/llms-full.txt | 10 ++++++++++ src/content/data-streams/rwa-streams/futures.mdx | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index ff2d73e0f74..1931dbefe18 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -6618,6 +6618,16 @@ When the August contract expires, the front-month feed jumps directly to October Futures trade during standard trading hours for each instrument, with a scheduled break each trading day. Consult the exchange where the underlying contract is listed for holiday and early-close schedules. +## Risk considerations + +Integrating protocols are responsible for implementing appropriate monitoring and risk mitigation mechanisms to ensure safe market operation. + +### Single-source data + +Each Futures instrument is sourced from a single institutional-grade data provider per feed. While this enables high-frequency, low-latency delivery, it introduces dependency on that provider's data quality and availability. There is no redundant cross-validation between providers for a given feed. + +If the underlying provider fails to deliver data, there is no fallback source, and a gap in data may not be immediately obvious from price alone. Protocols should continuously monitor feed freshness and implement safeguards — such as pausing trading or restricting liquidations — if updates stop arriving or a feed appears stale. Review the [Developer Responsibilities](/data-streams/developer-responsibilities) guidance before integration. + ## Support For inquiries related to a data outage, contact Chainlink Labs at [chainlink_data_feeds@smartcontract.com](mailto:chainlink_data_feeds@smartcontract.com). diff --git a/src/content/data-streams/rwa-streams/futures.mdx b/src/content/data-streams/rwa-streams/futures.mdx index d6449a95852..d064159b036 100644 --- a/src/content/data-streams/rwa-streams/futures.mdx +++ b/src/content/data-streams/rwa-streams/futures.mdx @@ -112,6 +112,16 @@ When the August contract expires, the front-month feed jumps directly to October Futures trade during standard trading hours for each instrument, with a scheduled break each trading day. Consult the exchange where the underlying contract is listed for holiday and early-close schedules. +## Risk considerations + +Integrating protocols are responsible for implementing appropriate monitoring and risk mitigation mechanisms to ensure safe market operation. + +### Single-source data + +Each Futures instrument is sourced from a single institutional-grade data provider per feed. While this enables high-frequency, low-latency delivery, it introduces dependency on that provider's data quality and availability. There is no redundant cross-validation between providers for a given feed. + +If the underlying provider fails to deliver data, there is no fallback source, and a gap in data may not be immediately obvious from price alone. Protocols should continuously monitor feed freshness and implement safeguards — such as pausing trading or restricting liquidations — if updates stop arriving or a feed appears stale. Review the [Developer Responsibilities](/data-streams/developer-responsibilities) guidance before integration. + ## Support For inquiries related to a data outage, contact Chainlink Labs at [chainlink_data_feeds@smartcontract.com](mailto:chainlink_data_feeds@smartcontract.com). From 4a40e1e88585501c9380fbbbacbf11ff6b546837 Mon Sep 17 00:00:00 2001 From: Sebastian Lerner Date: Sun, 23 Aug 2026 09:06:52 -0400 Subject: [PATCH 03/19] Simplify beta note and drop launch-specific language Schema and fields are settled, not subject to change, so the beta note now only flags access. Coverage wording no longer frames current availability as launch-specific, so the page doesn't need updating when it's no longer new. Co-Authored-By: Claude Sonnet 5 --- src/content/data-streams/llms-full.txt | 7 +++---- src/content/data-streams/rwa-streams/futures.mdx | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index 1931dbefe18..80079862b2e 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -6522,12 +6522,11 @@ For inquiries related to a data outage, contact Chainlink Labs at [data_support@ Source: https://docs.chain.link/data-streams/rwa-streams/futures -Futures streams provide price data for exchange-traded futures contracts. These streams enable onchain protocols to build markets around futures price exposure. At launch, coverage is limited to commodities — energy and precious metals — described below. +Futures streams provide price data for exchange-traded futures contracts. These streams enable onchain protocols to build markets around futures price exposure. Coverage currently includes commodities — energy and precious metals — described below. Because futures contracts expire, Data Streams does not publish one feed per contract. Instead, each instrument is represented by three **generic** feeds that always track the current front, second, and third contract. This is explained in [Rotation methodology](#rotation-methodology) below. @@ -6535,7 +6534,7 @@ Developers are responsible for choosing the appropriate feed and ensuring that t ## Coverage -At launch, Futures streams are available for the following commodities. Additional commodities and asset classes may be added based on demand. +Futures streams are currently available for the following commodities. Additional commodities and asset classes may be added based on demand. | Commodity | Generic feeds | | ----------- | ------------------------------------------------ | diff --git a/src/content/data-streams/rwa-streams/futures.mdx b/src/content/data-streams/rwa-streams/futures.mdx index d064159b036..dc7c20d49f5 100644 --- a/src/content/data-streams/rwa-streams/futures.mdx +++ b/src/content/data-streams/rwa-streams/futures.mdx @@ -16,12 +16,11 @@ whatsnext: import { Aside } from "@components" -Futures streams provide price data for exchange-traded futures contracts. These streams enable onchain protocols to build markets around futures price exposure. At launch, coverage is limited to commodities — energy and precious metals — described below. +Futures streams provide price data for exchange-traded futures contracts. These streams enable onchain protocols to build markets around futures price exposure. Coverage currently includes commodities — energy and precious metals — described below. Because futures contracts expire, Data Streams does not publish one feed per contract. Instead, each instrument is represented by three **generic** feeds that always track the current front, second, and third contract. This is explained in [Rotation methodology](#rotation-methodology) below. @@ -29,7 +28,7 @@ Developers are responsible for choosing the appropriate feed and ensuring that t ## Coverage -At launch, Futures streams are available for the following commodities. Additional commodities and asset classes may be added based on demand. +Futures streams are currently available for the following commodities. Additional commodities and asset classes may be added based on demand. | Commodity | Generic feeds | | ----------- | ------------------------------------------------ | From 0a1ddac5cd79af1c241fb4fd757c00344a0c0e8a Mon Sep 17 00:00:00 2001 From: Sebastian Lerner Date: Sun, 23 Aug 2026 09:12:55 -0400 Subject: [PATCH 04/19] Trim redundant naming disclaimer Co-Authored-By: Claude Sonnet 5 --- src/content/data-streams/llms-full.txt | 2 +- src/content/data-streams/rwa-streams/futures.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index 80079862b2e..8d90b1d898c 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -6545,7 +6545,7 @@ Futures streams are currently available for the following commodities. Additiona ## Naming and price representation -Feed names use the plain instrument name only (for example, "WTI," "Gold," "Natural Gas"). Chainlink does not use any exchange's proprietary contract ticker in its feed or stream identifiers. +Feed names use the plain instrument name only (for example, "WTI," "Gold," "Natural Gas"). Contract specifications — contract size, tick size, quotation units, and similar terms — can vary between exchanges for the same underlying instrument. Chainlink does not publish these specifications, since they belong to the exchange where a given contract is listed. If your application needs exact contract specifications, consult that exchange's own public product documentation directly. diff --git a/src/content/data-streams/rwa-streams/futures.mdx b/src/content/data-streams/rwa-streams/futures.mdx index dc7c20d49f5..25fd59880c4 100644 --- a/src/content/data-streams/rwa-streams/futures.mdx +++ b/src/content/data-streams/rwa-streams/futures.mdx @@ -39,7 +39,7 @@ Futures streams are currently available for the following commodities. Additiona ## Naming and price representation -Feed names use the plain instrument name only (for example, "WTI," "Gold," "Natural Gas"). Chainlink does not use any exchange's proprietary contract ticker in its feed or stream identifiers. +Feed names use the plain instrument name only (for example, "WTI," "Gold," "Natural Gas"). Contract specifications — contract size, tick size, quotation units, and similar terms — can vary between exchanges for the same underlying instrument. Chainlink does not publish these specifications, since they belong to the exchange where a given contract is listed. If your application needs exact contract specifications, consult that exchange's own public product documentation directly. From e2ad5af7f7ff1a525bf61cd7ec0491da099aa597 Mon Sep 17 00:00:00 2001 From: Sebastian Lerner Date: Mon, 24 Aug 2026 13:21:35 +0100 Subject: [PATCH 05/19] Add schema fields, exact roll time, and tighten liquidity wording Adds a Schema section (bid/ask/mid) matching the heading pattern used on other Data Streams product pages, states the 00:00:00 ET roll time per product spec, and clarifies that energy contracts are listed every month but liquidity concentrates in nearer maturities. Co-Authored-By: Claude Sonnet 5 --- src/content/data-streams/llms-full.txt | 8 ++++++-- src/content/data-streams/rwa-streams/futures.mdx | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index 8d90b1d898c..71411cb1ace 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -6532,6 +6532,10 @@ Because futures contracts expire, Data Streams does not publish one feed per con Developers are responsible for choosing the appropriate feed and ensuring that the operation and performance of their choice matches expectations. For more information, see the [Developer Responsibilities](/data-streams/developer-responsibilities) guidance. +## Schema + +Futures feeds publish bid, ask, and mid prices for each generic contract. + ## Coverage Futures streams are currently available for the following commodities. Additional commodities and asset classes may be added based on demand. @@ -6568,7 +6572,7 @@ This design means: ### How the roll works -When the front-month contract reaches its expiration, the generic feeds cascade forward: +When the front-month contract reaches its expiration, the generic feeds cascade forward at 00:00:00 (midnight) Eastern Time on the expiration date: - The **front-month feed** takes over the contract previously tracked by the second-month feed - The **second-month feed** takes over the contract previously tracked by the third-month feed @@ -6584,7 +6588,7 @@ A few properties of the roll are worth calling out explicitly: "Front-month" does not always mean "nearest calendar month." Each instrument has its own set of listed contract months, and for several instruments, the actively traded contracts are only a subset of what is listed: -- **Energy** (Oil, Natural Gas): every calendar month is listed and liquid. The generic feeds walk the full monthly strip, so the front-, second-, and third-month feeds track three **consecutive** calendar months. +- **Energy** (Oil, Natural Gas): every calendar month is listed, though liquidity is generally concentrated in nearer maturities. The generic feeds walk the full monthly strip regardless, so the front-, second-, and third-month feeds track three **consecutive** calendar months. - **Precious metals** (Gold, Silver): many calendar months are listed, but liquidity concentrates in a benchmark cycle. The generic feeds follow the benchmark cycle only and skip non-benchmark months, even though those contracts exist and trade. | Commodity | Benchmark months | diff --git a/src/content/data-streams/rwa-streams/futures.mdx b/src/content/data-streams/rwa-streams/futures.mdx index 25fd59880c4..5e874f00036 100644 --- a/src/content/data-streams/rwa-streams/futures.mdx +++ b/src/content/data-streams/rwa-streams/futures.mdx @@ -26,6 +26,10 @@ Because futures contracts expire, Data Streams does not publish one feed per con Developers are responsible for choosing the appropriate feed and ensuring that the operation and performance of their choice matches expectations. For more information, see the [Developer Responsibilities](/data-streams/developer-responsibilities) guidance. +## Schema + +Futures feeds publish bid, ask, and mid prices for each generic contract. + ## Coverage Futures streams are currently available for the following commodities. Additional commodities and asset classes may be added based on demand. @@ -62,7 +66,7 @@ This design means: ### How the roll works -When the front-month contract reaches its expiration, the generic feeds cascade forward: +When the front-month contract reaches its expiration, the generic feeds cascade forward at 00:00:00 (midnight) Eastern Time on the expiration date: - The **front-month feed** takes over the contract previously tracked by the second-month feed - The **second-month feed** takes over the contract previously tracked by the third-month feed @@ -78,7 +82,7 @@ A few properties of the roll are worth calling out explicitly: "Front-month" does not always mean "nearest calendar month." Each instrument has its own set of listed contract months, and for several instruments, the actively traded contracts are only a subset of what is listed: -- **Energy** (Oil, Natural Gas): every calendar month is listed and liquid. The generic feeds walk the full monthly strip, so the front-, second-, and third-month feeds track three **consecutive** calendar months. +- **Energy** (Oil, Natural Gas): every calendar month is listed, though liquidity is generally concentrated in nearer maturities. The generic feeds walk the full monthly strip regardless, so the front-, second-, and third-month feeds track three **consecutive** calendar months. - **Precious metals** (Gold, Silver): many calendar months are listed, but liquidity concentrates in a benchmark cycle. The generic feeds follow the benchmark cycle only and skip non-benchmark months, even though those contracts exist and trade. | Commodity | Benchmark months | From d789e6162ab9e5419b5cde2770b427fda4e60217 Mon Sep 17 00:00:00 2001 From: Sebastian Lerner Date: Mon, 24 Aug 2026 13:32:39 +0100 Subject: [PATCH 06/19] Expand Schema section with v14 field list Names the v14 schema and lists its fields (mid, bid, ask, expiry_time, roll_date, lastSeenTimestampNs, marketStatus, contract_month) per the Lo Tech schema requirements. Co-Authored-By: Claude Sonnet 5 --- src/content/data-streams/llms-full.txt | 13 ++++++++++++- src/content/data-streams/rwa-streams/futures.mdx | 13 ++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index 71411cb1ace..6730f2aef60 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -6534,7 +6534,18 @@ Developers are responsible for choosing the appropriate feed and ensuring that t ## Schema -Futures feeds publish bid, ask, and mid prices for each generic contract. +Futures streams use the v14 schema. + +| Field | Description | +| --------------------- | ---------------------------------------------------------------------------------------------------------------- | +| `mid` | Mid price | +| `bid` | Bid price | +| `ask` | Ask price | +| `expiry_time` | Contract expiration time | +| `roll_date` | First day of notice, as a Unix timestamp | +| `lastSeenTimestampNs` | Timestamp of the last update received from the data provider | +| `marketStatus` | Market status indicator | +| `contract_month` | Standard futures month code (F=Jan, G=Feb, H=Mar, J=Apr, K=May, M=Jun, N=Jul, Q=Aug, U=Sep, V=Oct, X=Nov, Z=Dec) | ## Coverage diff --git a/src/content/data-streams/rwa-streams/futures.mdx b/src/content/data-streams/rwa-streams/futures.mdx index 5e874f00036..cda39fd7e97 100644 --- a/src/content/data-streams/rwa-streams/futures.mdx +++ b/src/content/data-streams/rwa-streams/futures.mdx @@ -28,7 +28,18 @@ Developers are responsible for choosing the appropriate feed and ensuring that t ## Schema -Futures feeds publish bid, ask, and mid prices for each generic contract. +Futures streams use the v14 schema. + +| Field | Description | +| --------------------- | ---------------------------------------------------------------------------------------------------------------- | +| `mid` | Mid price | +| `bid` | Bid price | +| `ask` | Ask price | +| `expiry_time` | Contract expiration time | +| `roll_date` | First day of notice, as a Unix timestamp | +| `lastSeenTimestampNs` | Timestamp of the last update received from the data provider | +| `marketStatus` | Market status indicator | +| `contract_month` | Standard futures month code (F=Jan, G=Feb, H=Mar, J=Apr, K=May, M=Jun, N=Jul, Q=Aug, U=Sep, V=Oct, X=Nov, Z=Dec) | ## Coverage From 50af80d8612697c9ca743a3406c70ea70f080072 Mon Sep 17 00:00:00 2001 From: Sebastian Lerner Date: Tue, 25 Aug 2026 00:07:52 +0100 Subject: [PATCH 07/19] Address review feedback from Will - Drop "-month" from feed labels (front-month/second-month/third-month -> front/second/third) since the ordinal naming implied literal calendar-month spacing, contradicting the benchmark-cycle explanation for Gold/Silver - Rename WTI -> US Oil per Nora's naming guidance - Remove the specific 00:00:00 ET roll time, which is disputed internally (LO Tech/DSA still need to confirm exact timing) - Reframe the early-roll guidance around price volatility and liquidation risk near expiry, not just thin liquidity - Note that marketStatus reflects the primary exchange venue's current status, in Trading hours Co-Authored-By: Claude Sonnet 5 --- src/content/data-streams/llms-full.txt | 64 ++++++++++--------- .../data-streams/rwa-streams/futures.mdx | 64 ++++++++++--------- 2 files changed, 66 insertions(+), 62 deletions(-) diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index 6730f2aef60..eca69551cb7 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -6551,16 +6551,16 @@ Futures streams use the v14 schema. Futures streams are currently available for the following commodities. Additional commodities and asset classes may be added based on demand. -| Commodity | Generic feeds | -| ----------- | ------------------------------------------------ | -| Gold | Front-month, second-month, and third-month feeds | -| Silver | Front-month, second-month, and third-month feeds | -| Oil (WTI) | Front-month, second-month, and third-month feeds | -| Natural Gas | Front-month, second-month, and third-month feeds | +| Commodity | Generic feeds | +| ----------- | ------------------------------ | +| Gold | Front, second, and third feeds | +| Silver | Front, second, and third feeds | +| US Oil | Front, second, and third feeds | +| Natural Gas | Front, second, and third feeds | ## Naming and price representation -Feed names use the plain instrument name only (for example, "WTI," "Gold," "Natural Gas"). +Feed names use the plain instrument name only (for example, "US Oil," "Gold," "Natural Gas"). Contract specifications — contract size, tick size, quotation units, and similar terms — can vary between exchanges for the same underlying instrument. Chainlink does not publish these specifications, since they belong to the exchange where a given contract is listed. If your application needs exact contract specifications, consult that exchange's own public product documentation directly. @@ -6570,11 +6570,11 @@ Unlike spot instruments, futures contracts have a finite life. For example, a gi To avoid this, each instrument is represented by three static, non-expiring **generic feeds** that always represent the near-term forward curve of eligible contracts: -| Generic feed | Meaning | -| --------------------- | ---------------------------------------------------------------- | -| **Front-month feed** | Tracks the nearest unexpired eligible contract | -| **Second-month feed** | Tracks the next eligible contract after the front-month contract | -| **Third-month feed** | Tracks the eligible contract after that | +| Generic feed | Meaning | +| --------------- | ---------------------------------------------------------- | +| **Front feed** | Tracks the nearest unexpired eligible contract | +| **Second feed** | Tracks the next eligible contract after the front contract | +| **Third feed** | Tracks the eligible contract after that | This design means: @@ -6583,23 +6583,23 @@ This design means: ### How the roll works -When the front-month contract reaches its expiration, the generic feeds cascade forward at 00:00:00 (midnight) Eastern Time on the expiration date: +When the front contract reaches its expiration, the generic feeds cascade forward: -- The **front-month feed** takes over the contract previously tracked by the second-month feed -- The **second-month feed** takes over the contract previously tracked by the third-month feed -- The **third-month feed** begins tracking the next eligible contract in that instrument's cycle +- The **front feed** takes over the contract previously tracked by the second feed +- The **second feed** takes over the contract previously tracked by the third feed +- The **third feed** begins tracking the next eligible contract in that instrument's cycle A few properties of the roll are worth calling out explicitly: -- **The roll is triggered by the front-month contract's expiration**, as defined by the listed expiration calendar for that specific instrument. Expiration conventions differ by instrument, so rolls for different instruments happen on different dates — there is no single "roll day" across all instruments. -- **The roll is a re-mapping, not a price adjustment.** At the moment of the roll, the front-month feed switches from quoting the expiring contract to quoting what was previously the second-month contract. Because different contract months can trade at different prices, **expect a price discontinuity on the generic feed at each roll**. Feeds are not back-adjusted into a smooth continuous series — if your application needs a continuous series, construct it from the raw generic feeds on your end. -- **Until expiration, the front-month feed continues to track the expiring contract**, even in its final days when liquidity has typically already migrated to the next contract. This is precisely why the second-month feed is exposed — so you can implement your own liquidity-based rolls ahead of expiry instead of holding the front-month contract to the end. +- **The roll is triggered by the front contract's expiration**, as defined by the listed expiration calendar for that specific instrument. Expiration conventions differ by instrument, so rolls for different instruments happen on different dates — there is no single "roll day" across all instruments. +- **The roll is a re-mapping, not a price adjustment.** At the moment of the roll, the front feed switches from quoting the expiring contract to quoting what was previously the second contract. Because different contract months can trade at different prices, **expect a price discontinuity on the generic feed at each roll**. Feeds are not back-adjusted into a smooth continuous series — if your application needs a continuous series, construct it from the raw generic feeds on your end. +- **Until expiration, the front feed continues to track the expiring contract**, even in its final days when liquidity has typically already migrated to the next contract. This is precisely why the second feed is exposed — so you can implement your own liquidity-based rolls ahead of expiry instead of holding the front contract to the end. ### Contract eligibility varies by instrument -"Front-month" does not always mean "nearest calendar month." Each instrument has its own set of listed contract months, and for several instruments, the actively traded contracts are only a subset of what is listed: +The front feed does not necessarily track the nearest calendar month — it tracks the nearest unexpired eligible contract, whatever month that happens to be. Each instrument has its own set of listed contract months, and for several instruments, the actively traded contracts are only a subset of what is listed: -- **Energy** (Oil, Natural Gas): every calendar month is listed, though liquidity is generally concentrated in nearer maturities. The generic feeds walk the full monthly strip regardless, so the front-, second-, and third-month feeds track three **consecutive** calendar months. +- **Energy** (US Oil, Natural Gas): every calendar month is listed, though liquidity is generally concentrated in nearer maturities. The generic feeds walk the full monthly strip regardless, so the front, second, and third feeds track three **consecutive** calendar months. - **Precious metals** (Gold, Silver): many calendar months are listed, but liquidity concentrates in a benchmark cycle. The generic feeds follow the benchmark cycle only and skip non-benchmark months, even though those contracts exist and trade. | Commodity | Benchmark months | @@ -6607,31 +6607,33 @@ A few properties of the roll are worth calling out explicitly: | Gold | Feb, Apr, Jun, Aug, Oct, Dec | | Silver | Mar, May, Jul, Sep, Dec | -The practical consequence: **the gap between the front-, second-, and third-month feeds is not always one month.** For Gold or Silver, consecutive generic feeds can be one to three months apart. Do not assume monthly spacing in your integration. +The practical consequence: **the gap between the front, second, and third feeds is not always one month.** For Gold or Silver, consecutive generic feeds can be one to three months apart. Do not assume monthly spacing in your integration. ### Worked example Gold follows its benchmark cycle (Feb/Apr/Jun/Aug/Oct/Dec). In August 2026, before the August contract expires: -| Feed | Contract tracked | -| ----------------- | ---------------- | -| Front-month feed | August 2026 | -| Second-month feed | October 2026 | -| Third-month feed | December 2026 | +| Feed | Contract tracked | +| ----------- | ---------------- | +| Front feed | August 2026 | +| Second feed | October 2026 | +| Third feed | December 2026 | -When the August contract expires, the front-month feed jumps directly to October, the second-month feed jumps to December, and the third-month feed begins tracking February 2027 — skipping the non-benchmark September and November contracts entirely, since they never appear on the generic feeds. +When the August contract expires, the front feed jumps directly to October, the second feed jumps to December, and the third feed begins tracking February 2027 — skipping the non-benchmark September and November contracts entirely, since they never appear on the generic feeds. ## Integration guidance -- **Do not hardcode contract-month assumptions.** The spacing between the front-, second-, and third-month feeds varies by instrument — one month for energy, up to a few months for precious metals. -- **Expect price steps at rolls.** A protocol using the front-month feed directly for margining or liquidation should either accept the step as economically correct (the front contract genuinely changed), implement its own early roll using the second-month feed, or build an adjusted continuous series off-chain from the raw generic feeds. -- **Roll early if you depend on liquidity.** In the final days of a contract's life, trading volume typically migrates to the next contract while the front-month feed still tracks the expiring one. If your application is sensitive to thin markets, consider rolling ahead of expiry using the second-month feed. +- **Do not hardcode contract-month assumptions.** The spacing between the front, second, and third feeds varies by instrument — one month for energy, up to a few months for precious metals. +- **Expect price steps at rolls.** A protocol using the front feed directly for margining or liquidation should either accept the step as economically correct (the front contract genuinely changed), implement its own early roll using the second feed, or build an adjusted continuous series off-chain from the raw generic feeds. +- **Roll early to avoid volatility near expiry.** In the final days of a contract's life, trading volume typically migrates to the next contract while the front feed still tracks the expiring one. Thin liquidity in the expiring contract can increase price volatility, which may unexpectedly trigger perpetual trades, liquidations, or other price-sensitive logic. If your application is sensitive to this, consider rolling ahead of expiry using the second feed. - **Follow the listed expiration calendar.** Expiration dates follow the official listed calendar of the exchange where the underlying contract trades, including holiday adjustments. Consult that exchange for the operative source of truth. ## Trading hours Futures trade during standard trading hours for each instrument, with a scheduled break each trading day. Consult the exchange where the underlying contract is listed for holiday and early-close schedules. +Each feed's `marketStatus` field reflects the current market status of the primary exchange venue for that instrument. + ## Risk considerations Integrating protocols are responsible for implementing appropriate monitoring and risk mitigation mechanisms to ensure safe market operation. diff --git a/src/content/data-streams/rwa-streams/futures.mdx b/src/content/data-streams/rwa-streams/futures.mdx index cda39fd7e97..08ae7853641 100644 --- a/src/content/data-streams/rwa-streams/futures.mdx +++ b/src/content/data-streams/rwa-streams/futures.mdx @@ -45,16 +45,16 @@ Futures streams use the v14 schema. Futures streams are currently available for the following commodities. Additional commodities and asset classes may be added based on demand. -| Commodity | Generic feeds | -| ----------- | ------------------------------------------------ | -| Gold | Front-month, second-month, and third-month feeds | -| Silver | Front-month, second-month, and third-month feeds | -| Oil (WTI) | Front-month, second-month, and third-month feeds | -| Natural Gas | Front-month, second-month, and third-month feeds | +| Commodity | Generic feeds | +| ----------- | ------------------------------ | +| Gold | Front, second, and third feeds | +| Silver | Front, second, and third feeds | +| US Oil | Front, second, and third feeds | +| Natural Gas | Front, second, and third feeds | ## Naming and price representation -Feed names use the plain instrument name only (for example, "WTI," "Gold," "Natural Gas"). +Feed names use the plain instrument name only (for example, "US Oil," "Gold," "Natural Gas"). Contract specifications — contract size, tick size, quotation units, and similar terms — can vary between exchanges for the same underlying instrument. Chainlink does not publish these specifications, since they belong to the exchange where a given contract is listed. If your application needs exact contract specifications, consult that exchange's own public product documentation directly. @@ -64,11 +64,11 @@ Unlike spot instruments, futures contracts have a finite life. For example, a gi To avoid this, each instrument is represented by three static, non-expiring **generic feeds** that always represent the near-term forward curve of eligible contracts: -| Generic feed | Meaning | -| --------------------- | ---------------------------------------------------------------- | -| **Front-month feed** | Tracks the nearest unexpired eligible contract | -| **Second-month feed** | Tracks the next eligible contract after the front-month contract | -| **Third-month feed** | Tracks the eligible contract after that | +| Generic feed | Meaning | +| --------------- | ---------------------------------------------------------- | +| **Front feed** | Tracks the nearest unexpired eligible contract | +| **Second feed** | Tracks the next eligible contract after the front contract | +| **Third feed** | Tracks the eligible contract after that | This design means: @@ -77,23 +77,23 @@ This design means: ### How the roll works -When the front-month contract reaches its expiration, the generic feeds cascade forward at 00:00:00 (midnight) Eastern Time on the expiration date: +When the front contract reaches its expiration, the generic feeds cascade forward: -- The **front-month feed** takes over the contract previously tracked by the second-month feed -- The **second-month feed** takes over the contract previously tracked by the third-month feed -- The **third-month feed** begins tracking the next eligible contract in that instrument's cycle +- The **front feed** takes over the contract previously tracked by the second feed +- The **second feed** takes over the contract previously tracked by the third feed +- The **third feed** begins tracking the next eligible contract in that instrument's cycle A few properties of the roll are worth calling out explicitly: -- **The roll is triggered by the front-month contract's expiration**, as defined by the listed expiration calendar for that specific instrument. Expiration conventions differ by instrument, so rolls for different instruments happen on different dates — there is no single "roll day" across all instruments. -- **The roll is a re-mapping, not a price adjustment.** At the moment of the roll, the front-month feed switches from quoting the expiring contract to quoting what was previously the second-month contract. Because different contract months can trade at different prices, **expect a price discontinuity on the generic feed at each roll**. Feeds are not back-adjusted into a smooth continuous series — if your application needs a continuous series, construct it from the raw generic feeds on your end. -- **Until expiration, the front-month feed continues to track the expiring contract**, even in its final days when liquidity has typically already migrated to the next contract. This is precisely why the second-month feed is exposed — so you can implement your own liquidity-based rolls ahead of expiry instead of holding the front-month contract to the end. +- **The roll is triggered by the front contract's expiration**, as defined by the listed expiration calendar for that specific instrument. Expiration conventions differ by instrument, so rolls for different instruments happen on different dates — there is no single "roll day" across all instruments. +- **The roll is a re-mapping, not a price adjustment.** At the moment of the roll, the front feed switches from quoting the expiring contract to quoting what was previously the second contract. Because different contract months can trade at different prices, **expect a price discontinuity on the generic feed at each roll**. Feeds are not back-adjusted into a smooth continuous series — if your application needs a continuous series, construct it from the raw generic feeds on your end. +- **Until expiration, the front feed continues to track the expiring contract**, even in its final days when liquidity has typically already migrated to the next contract. This is precisely why the second feed is exposed — so you can implement your own liquidity-based rolls ahead of expiry instead of holding the front contract to the end. ### Contract eligibility varies by instrument -"Front-month" does not always mean "nearest calendar month." Each instrument has its own set of listed contract months, and for several instruments, the actively traded contracts are only a subset of what is listed: +The front feed does not necessarily track the nearest calendar month — it tracks the nearest unexpired eligible contract, whatever month that happens to be. Each instrument has its own set of listed contract months, and for several instruments, the actively traded contracts are only a subset of what is listed: -- **Energy** (Oil, Natural Gas): every calendar month is listed, though liquidity is generally concentrated in nearer maturities. The generic feeds walk the full monthly strip regardless, so the front-, second-, and third-month feeds track three **consecutive** calendar months. +- **Energy** (US Oil, Natural Gas): every calendar month is listed, though liquidity is generally concentrated in nearer maturities. The generic feeds walk the full monthly strip regardless, so the front, second, and third feeds track three **consecutive** calendar months. - **Precious metals** (Gold, Silver): many calendar months are listed, but liquidity concentrates in a benchmark cycle. The generic feeds follow the benchmark cycle only and skip non-benchmark months, even though those contracts exist and trade. | Commodity | Benchmark months | @@ -101,31 +101,33 @@ A few properties of the roll are worth calling out explicitly: | Gold | Feb, Apr, Jun, Aug, Oct, Dec | | Silver | Mar, May, Jul, Sep, Dec | -The practical consequence: **the gap between the front-, second-, and third-month feeds is not always one month.** For Gold or Silver, consecutive generic feeds can be one to three months apart. Do not assume monthly spacing in your integration. +The practical consequence: **the gap between the front, second, and third feeds is not always one month.** For Gold or Silver, consecutive generic feeds can be one to three months apart. Do not assume monthly spacing in your integration. ### Worked example Gold follows its benchmark cycle (Feb/Apr/Jun/Aug/Oct/Dec). In August 2026, before the August contract expires: -| Feed | Contract tracked | -| ----------------- | ---------------- | -| Front-month feed | August 2026 | -| Second-month feed | October 2026 | -| Third-month feed | December 2026 | +| Feed | Contract tracked | +| ----------- | ---------------- | +| Front feed | August 2026 | +| Second feed | October 2026 | +| Third feed | December 2026 | -When the August contract expires, the front-month feed jumps directly to October, the second-month feed jumps to December, and the third-month feed begins tracking February 2027 — skipping the non-benchmark September and November contracts entirely, since they never appear on the generic feeds. +When the August contract expires, the front feed jumps directly to October, the second feed jumps to December, and the third feed begins tracking February 2027 — skipping the non-benchmark September and November contracts entirely, since they never appear on the generic feeds. ## Integration guidance -- **Do not hardcode contract-month assumptions.** The spacing between the front-, second-, and third-month feeds varies by instrument — one month for energy, up to a few months for precious metals. -- **Expect price steps at rolls.** A protocol using the front-month feed directly for margining or liquidation should either accept the step as economically correct (the front contract genuinely changed), implement its own early roll using the second-month feed, or build an adjusted continuous series off-chain from the raw generic feeds. -- **Roll early if you depend on liquidity.** In the final days of a contract's life, trading volume typically migrates to the next contract while the front-month feed still tracks the expiring one. If your application is sensitive to thin markets, consider rolling ahead of expiry using the second-month feed. +- **Do not hardcode contract-month assumptions.** The spacing between the front, second, and third feeds varies by instrument — one month for energy, up to a few months for precious metals. +- **Expect price steps at rolls.** A protocol using the front feed directly for margining or liquidation should either accept the step as economically correct (the front contract genuinely changed), implement its own early roll using the second feed, or build an adjusted continuous series off-chain from the raw generic feeds. +- **Roll early to avoid volatility near expiry.** In the final days of a contract's life, trading volume typically migrates to the next contract while the front feed still tracks the expiring one. Thin liquidity in the expiring contract can increase price volatility, which may unexpectedly trigger perpetual trades, liquidations, or other price-sensitive logic. If your application is sensitive to this, consider rolling ahead of expiry using the second feed. - **Follow the listed expiration calendar.** Expiration dates follow the official listed calendar of the exchange where the underlying contract trades, including holiday adjustments. Consult that exchange for the operative source of truth. ## Trading hours Futures trade during standard trading hours for each instrument, with a scheduled break each trading day. Consult the exchange where the underlying contract is listed for holiday and early-close schedules. +Each feed's `marketStatus` field reflects the current market status of the primary exchange venue for that instrument. + ## Risk considerations Integrating protocols are responsible for implementing appropriate monitoring and risk mitigation mechanisms to ensure safe market operation. From 5dad3438be3e40dbd00f958d548ec8e45d2129ab Mon Sep 17 00:00:00 2001 From: Sebastian Lerner Date: Fri, 28 Aug 2026 15:12:59 +0100 Subject: [PATCH 08/19] Add Brent coverage, last_trading_day field, roll methodology fields, and confirmed roll timing - Add Brent to Coverage and the Energy grouping (WTI, Brent, NatGas, Gold, Silver ingestion confirmed in progress per Nora) - Add last_trading_day to the base schema field list (confirmed by Lo Tech) - Add a Continuous roll price fields section: price_notice_roll, price_goldman_roll (GSCI methodology), price_continuous_roll, and first_notice_date, plus a note on the planned current-business-day field pending finalization - Add confirmed roll timing: the switch happens right after the primary exchange's session close (e.g. ~17:00 ET for CME), not at a fixed midnight time as previously assumed Co-Authored-By: Claude Sonnet 5 --- src/content/data-streams/llms-full.txt | 18 +++++++++++++++++- .../data-streams/rwa-streams/futures.mdx | 18 +++++++++++++++++- 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index eca69551cb7..e3f267a1ae9 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -6546,6 +6546,20 @@ Futures streams use the v14 schema. | `lastSeenTimestampNs` | Timestamp of the last update received from the data provider | | `marketStatus` | Market status indicator | | `contract_month` | Standard futures month code (F=Jan, G=Feb, H=Mar, J=Apr, K=May, M=Jun, N=Jul, Q=Aug, U=Sep, V=Oct, X=Nov, Z=Dec) | +| `last_trading_day` | The final day the current contract trades | + +### Continuous roll price fields + +In addition to the raw generic feed prices above — which switch entirely to the next contract at the first notice date — Chainlink also publishes continuous price series built using alternative rolling methodologies, for integrators who want a smoothed price instead of a hard cutover: + +| Field | Description | +| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `price_notice_roll` | Equivalent to the generic front feed price: switches entirely to the next contract at the first notice date | +| `price_goldman_roll` | Uses the Goldman Roll (GSCI methodology): shifts 20% of the position to the next contract each business day, over business days 5–9 of the month preceding delivery | +| `price_continuous_roll` | Smooths the transition evenly (1/N per business day) across the entire contract cycle, rather than a fixed window | +| `first_notice_date` | Date on which `price_notice_roll` switches to the next contract | + +Chainlink also plans to publish the current business day count within the active roll window, so integrators can implement the Goldman Roll or Continuous Roll methodology themselves. Behavior on non-trading days (holding the last value versus resetting to zero) is still being finalized. ## Coverage @@ -6556,6 +6570,7 @@ Futures streams are currently available for the following commodities. Additiona | Gold | Front, second, and third feeds | | Silver | Front, second, and third feeds | | US Oil | Front, second, and third feeds | +| Brent | Front, second, and third feeds | | Natural Gas | Front, second, and third feeds | ## Naming and price representation @@ -6592,6 +6607,7 @@ When the front contract reaches its expiration, the generic feeds cascade forwar A few properties of the roll are worth calling out explicitly: - **The roll is triggered by the front contract's expiration**, as defined by the listed expiration calendar for that specific instrument. Expiration conventions differ by instrument, so rolls for different instruments happen on different dates — there is no single "roll day" across all instruments. +- **The switch happens right after the primary exchange's trading session closes** on the expiration date, not at a fixed clock time across all instruments. For example, CME-listed instruments typically close around 17:00 ET. - **The roll is a re-mapping, not a price adjustment.** At the moment of the roll, the front feed switches from quoting the expiring contract to quoting what was previously the second contract. Because different contract months can trade at different prices, **expect a price discontinuity on the generic feed at each roll**. Feeds are not back-adjusted into a smooth continuous series — if your application needs a continuous series, construct it from the raw generic feeds on your end. - **Until expiration, the front feed continues to track the expiring contract**, even in its final days when liquidity has typically already migrated to the next contract. This is precisely why the second feed is exposed — so you can implement your own liquidity-based rolls ahead of expiry instead of holding the front contract to the end. @@ -6599,7 +6615,7 @@ A few properties of the roll are worth calling out explicitly: The front feed does not necessarily track the nearest calendar month — it tracks the nearest unexpired eligible contract, whatever month that happens to be. Each instrument has its own set of listed contract months, and for several instruments, the actively traded contracts are only a subset of what is listed: -- **Energy** (US Oil, Natural Gas): every calendar month is listed, though liquidity is generally concentrated in nearer maturities. The generic feeds walk the full monthly strip regardless, so the front, second, and third feeds track three **consecutive** calendar months. +- **Energy** (US Oil, Brent, Natural Gas): every calendar month is listed, though liquidity is generally concentrated in nearer maturities. The generic feeds walk the full monthly strip regardless, so the front, second, and third feeds track three **consecutive** calendar months. - **Precious metals** (Gold, Silver): many calendar months are listed, but liquidity concentrates in a benchmark cycle. The generic feeds follow the benchmark cycle only and skip non-benchmark months, even though those contracts exist and trade. | Commodity | Benchmark months | diff --git a/src/content/data-streams/rwa-streams/futures.mdx b/src/content/data-streams/rwa-streams/futures.mdx index 08ae7853641..474f1dcddaa 100644 --- a/src/content/data-streams/rwa-streams/futures.mdx +++ b/src/content/data-streams/rwa-streams/futures.mdx @@ -40,6 +40,20 @@ Futures streams use the v14 schema. | `lastSeenTimestampNs` | Timestamp of the last update received from the data provider | | `marketStatus` | Market status indicator | | `contract_month` | Standard futures month code (F=Jan, G=Feb, H=Mar, J=Apr, K=May, M=Jun, N=Jul, Q=Aug, U=Sep, V=Oct, X=Nov, Z=Dec) | +| `last_trading_day` | The final day the current contract trades | + +### Continuous roll price fields + +In addition to the raw generic feed prices above — which switch entirely to the next contract at the first notice date — Chainlink also publishes continuous price series built using alternative rolling methodologies, for integrators who want a smoothed price instead of a hard cutover: + +| Field | Description | +| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `price_notice_roll` | Equivalent to the generic front feed price: switches entirely to the next contract at the first notice date | +| `price_goldman_roll` | Uses the Goldman Roll (GSCI methodology): shifts 20% of the position to the next contract each business day, over business days 5–9 of the month preceding delivery | +| `price_continuous_roll` | Smooths the transition evenly (1/N per business day) across the entire contract cycle, rather than a fixed window | +| `first_notice_date` | Date on which `price_notice_roll` switches to the next contract | + +Chainlink also plans to publish the current business day count within the active roll window, so integrators can implement the Goldman Roll or Continuous Roll methodology themselves. Behavior on non-trading days (holding the last value versus resetting to zero) is still being finalized. ## Coverage @@ -50,6 +64,7 @@ Futures streams are currently available for the following commodities. Additiona | Gold | Front, second, and third feeds | | Silver | Front, second, and third feeds | | US Oil | Front, second, and third feeds | +| Brent | Front, second, and third feeds | | Natural Gas | Front, second, and third feeds | ## Naming and price representation @@ -86,6 +101,7 @@ When the front contract reaches its expiration, the generic feeds cascade forwar A few properties of the roll are worth calling out explicitly: - **The roll is triggered by the front contract's expiration**, as defined by the listed expiration calendar for that specific instrument. Expiration conventions differ by instrument, so rolls for different instruments happen on different dates — there is no single "roll day" across all instruments. +- **The switch happens right after the primary exchange's trading session closes** on the expiration date, not at a fixed clock time across all instruments. For example, CME-listed instruments typically close around 17:00 ET. - **The roll is a re-mapping, not a price adjustment.** At the moment of the roll, the front feed switches from quoting the expiring contract to quoting what was previously the second contract. Because different contract months can trade at different prices, **expect a price discontinuity on the generic feed at each roll**. Feeds are not back-adjusted into a smooth continuous series — if your application needs a continuous series, construct it from the raw generic feeds on your end. - **Until expiration, the front feed continues to track the expiring contract**, even in its final days when liquidity has typically already migrated to the next contract. This is precisely why the second feed is exposed — so you can implement your own liquidity-based rolls ahead of expiry instead of holding the front contract to the end. @@ -93,7 +109,7 @@ A few properties of the roll are worth calling out explicitly: The front feed does not necessarily track the nearest calendar month — it tracks the nearest unexpired eligible contract, whatever month that happens to be. Each instrument has its own set of listed contract months, and for several instruments, the actively traded contracts are only a subset of what is listed: -- **Energy** (US Oil, Natural Gas): every calendar month is listed, though liquidity is generally concentrated in nearer maturities. The generic feeds walk the full monthly strip regardless, so the front, second, and third feeds track three **consecutive** calendar months. +- **Energy** (US Oil, Brent, Natural Gas): every calendar month is listed, though liquidity is generally concentrated in nearer maturities. The generic feeds walk the full monthly strip regardless, so the front, second, and third feeds track three **consecutive** calendar months. - **Precious metals** (Gold, Silver): many calendar months are listed, but liquidity concentrates in a benchmark cycle. The generic feeds follow the benchmark cycle only and skip non-benchmark months, even though those contracts exist and trade. | Commodity | Benchmark months | From b69b851aae9a255a6b9c62cbd921aef890fe3ea1 Mon Sep 17 00:00:00 2001 From: Sebastian Lerner Date: Fri, 28 Aug 2026 17:51:40 -0400 Subject: [PATCH 09/19] Rename Brent to UK Oil for naming consistency Matches the US Oil / UK Oil naming pair already confirmed for this product (Jira OPDATA-8442: assetName "NY UKOIL / USD") instead of using the plain commodity name. Co-Authored-By: Claude Sonnet 5 --- src/content/data-streams/llms-full.txt | 4 ++-- src/content/data-streams/rwa-streams/futures.mdx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index e3f267a1ae9..d949f4b014e 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -6570,7 +6570,7 @@ Futures streams are currently available for the following commodities. Additiona | Gold | Front, second, and third feeds | | Silver | Front, second, and third feeds | | US Oil | Front, second, and third feeds | -| Brent | Front, second, and third feeds | +| UK Oil | Front, second, and third feeds | | Natural Gas | Front, second, and third feeds | ## Naming and price representation @@ -6615,7 +6615,7 @@ A few properties of the roll are worth calling out explicitly: The front feed does not necessarily track the nearest calendar month — it tracks the nearest unexpired eligible contract, whatever month that happens to be. Each instrument has its own set of listed contract months, and for several instruments, the actively traded contracts are only a subset of what is listed: -- **Energy** (US Oil, Brent, Natural Gas): every calendar month is listed, though liquidity is generally concentrated in nearer maturities. The generic feeds walk the full monthly strip regardless, so the front, second, and third feeds track three **consecutive** calendar months. +- **Energy** (US Oil, UK Oil, Natural Gas): every calendar month is listed, though liquidity is generally concentrated in nearer maturities. The generic feeds walk the full monthly strip regardless, so the front, second, and third feeds track three **consecutive** calendar months. - **Precious metals** (Gold, Silver): many calendar months are listed, but liquidity concentrates in a benchmark cycle. The generic feeds follow the benchmark cycle only and skip non-benchmark months, even though those contracts exist and trade. | Commodity | Benchmark months | diff --git a/src/content/data-streams/rwa-streams/futures.mdx b/src/content/data-streams/rwa-streams/futures.mdx index 474f1dcddaa..e23ac912f5a 100644 --- a/src/content/data-streams/rwa-streams/futures.mdx +++ b/src/content/data-streams/rwa-streams/futures.mdx @@ -64,7 +64,7 @@ Futures streams are currently available for the following commodities. Additiona | Gold | Front, second, and third feeds | | Silver | Front, second, and third feeds | | US Oil | Front, second, and third feeds | -| Brent | Front, second, and third feeds | +| UK Oil | Front, second, and third feeds | | Natural Gas | Front, second, and third feeds | ## Naming and price representation @@ -109,7 +109,7 @@ A few properties of the roll are worth calling out explicitly: The front feed does not necessarily track the nearest calendar month — it tracks the nearest unexpired eligible contract, whatever month that happens to be. Each instrument has its own set of listed contract months, and for several instruments, the actively traded contracts are only a subset of what is listed: -- **Energy** (US Oil, Brent, Natural Gas): every calendar month is listed, though liquidity is generally concentrated in nearer maturities. The generic feeds walk the full monthly strip regardless, so the front, second, and third feeds track three **consecutive** calendar months. +- **Energy** (US Oil, UK Oil, Natural Gas): every calendar month is listed, though liquidity is generally concentrated in nearer maturities. The generic feeds walk the full monthly strip regardless, so the front, second, and third feeds track three **consecutive** calendar months. - **Precious metals** (Gold, Silver): many calendar months are listed, but liquidity concentrates in a benchmark cycle. The generic feeds follow the benchmark cycle only and skip non-benchmark months, even though those contracts exist and trade. | Commodity | Benchmark months | From b730d9581ada35b52ff5f6666d1cadf8ad9c57b2 Mon Sep 17 00:00:00 2001 From: Sebastian Lerner Date: Fri, 28 Aug 2026 18:08:11 -0400 Subject: [PATCH 10/19] Remove CME name from roll-timing example Same rule as everywhere else on this page: no exchange names. The CME reference slipped in when the exact roll-timing detail was added. Co-Authored-By: Claude Sonnet 5 --- src/content/data-streams/llms-full.txt | 2 +- src/content/data-streams/rwa-streams/futures.mdx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index d949f4b014e..d2d564b215f 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -6607,7 +6607,7 @@ When the front contract reaches its expiration, the generic feeds cascade forwar A few properties of the roll are worth calling out explicitly: - **The roll is triggered by the front contract's expiration**, as defined by the listed expiration calendar for that specific instrument. Expiration conventions differ by instrument, so rolls for different instruments happen on different dates — there is no single "roll day" across all instruments. -- **The switch happens right after the primary exchange's trading session closes** on the expiration date, not at a fixed clock time across all instruments. For example, CME-listed instruments typically close around 17:00 ET. +- **The switch happens right after the primary exchange's trading session closes** on the expiration date, not at a fixed clock time across all instruments. For these commodities, that session close is typically around 17:00 ET. - **The roll is a re-mapping, not a price adjustment.** At the moment of the roll, the front feed switches from quoting the expiring contract to quoting what was previously the second contract. Because different contract months can trade at different prices, **expect a price discontinuity on the generic feed at each roll**. Feeds are not back-adjusted into a smooth continuous series — if your application needs a continuous series, construct it from the raw generic feeds on your end. - **Until expiration, the front feed continues to track the expiring contract**, even in its final days when liquidity has typically already migrated to the next contract. This is precisely why the second feed is exposed — so you can implement your own liquidity-based rolls ahead of expiry instead of holding the front contract to the end. diff --git a/src/content/data-streams/rwa-streams/futures.mdx b/src/content/data-streams/rwa-streams/futures.mdx index e23ac912f5a..f7c2be24e90 100644 --- a/src/content/data-streams/rwa-streams/futures.mdx +++ b/src/content/data-streams/rwa-streams/futures.mdx @@ -101,7 +101,7 @@ When the front contract reaches its expiration, the generic feeds cascade forwar A few properties of the roll are worth calling out explicitly: - **The roll is triggered by the front contract's expiration**, as defined by the listed expiration calendar for that specific instrument. Expiration conventions differ by instrument, so rolls for different instruments happen on different dates — there is no single "roll day" across all instruments. -- **The switch happens right after the primary exchange's trading session closes** on the expiration date, not at a fixed clock time across all instruments. For example, CME-listed instruments typically close around 17:00 ET. +- **The switch happens right after the primary exchange's trading session closes** on the expiration date, not at a fixed clock time across all instruments. For these commodities, that session close is typically around 17:00 ET. - **The roll is a re-mapping, not a price adjustment.** At the moment of the roll, the front feed switches from quoting the expiring contract to quoting what was previously the second contract. Because different contract months can trade at different prices, **expect a price discontinuity on the generic feed at each roll**. Feeds are not back-adjusted into a smooth continuous series — if your application needs a continuous series, construct it from the raw generic feeds on your end. - **Until expiration, the front feed continues to track the expiring contract**, even in its final days when liquidity has typically already migrated to the next contract. This is precisely why the second feed is exposed — so you can implement your own liquidity-based rolls ahead of expiry instead of holding the front contract to the end. From 6044d7fe8b5b38eb16b088a445584a66fef86015 Mon Sep 17 00:00:00 2001 From: devin distefano Date: Wed, 16 Sep 2026 16:50:24 -0500 Subject: [PATCH 11/19] restructure, ingest, tested examples, wip development notes --- public/samples/DataStreams/FuturesFetch.go | 86 +++++++ public/samples/DataStreams/FuturesFetch.rs | 60 +++++ public/samples/DataStreams/FuturesFetch.ts | 51 ++++ src/config/sidebar.ts | 4 + src/content/data-streams/llms-full.txt | 224 ++++++++++++++++-- .../reference/report-schema-overview.mdx | 21 +- .../reference/report-schema-v14.mdx | 76 ++++++ .../data-streams/rwa-streams/futures.mdx | 223 +++++++++++++++-- .../data-streams/tutorials/go-sdk-fetch.mdx | 6 + .../common/ReportSchemaTabs.astro | 4 + src/features/feeds/components/FeedList.tsx | 123 ++++++---- src/features/feeds/components/Tables.tsx | 19 +- .../feeds/components/reportSchemaData.ts | 49 ++++ src/features/feeds/types.ts | 4 +- src/features/feeds/utils/feedMetadata.ts | 22 +- src/features/feeds/utils/feedVisibility.ts | 13 +- src/features/feeds/utils/tableFilters.ts | 4 + 17 files changed, 897 insertions(+), 92 deletions(-) create mode 100644 public/samples/DataStreams/FuturesFetch.go create mode 100644 public/samples/DataStreams/FuturesFetch.rs create mode 100644 public/samples/DataStreams/FuturesFetch.ts create mode 100644 src/content/data-streams/reference/report-schema-v14.mdx diff --git a/public/samples/DataStreams/FuturesFetch.go b/public/samples/DataStreams/FuturesFetch.go new file mode 100644 index 00000000000..294d07dbec8 --- /dev/null +++ b/public/samples/DataStreams/FuturesFetch.go @@ -0,0 +1,86 @@ +// FuturesFetch.go — Fetch and decode a Futures (v14) report with the Go SDK. +// +// Usage: +// export API_KEY="..." +// export API_SECRET="..." +// go run FuturesFetch.go 0x000ebfe7b7560e1866ef91d4607ce5ee7474382794e5ec755f38b70b1f30e647 +package main + +import ( + "context" + "fmt" + "os" + "time" + + streams "github.com/smartcontractkit/data-streams-sdk/go/v2" + feed "github.com/smartcontractkit/data-streams-sdk/go/v2/feed" + report "github.com/smartcontractkit/data-streams-sdk/go/v2/report" + v14 "github.com/smartcontractkit/data-streams-sdk/go/v2/report/v14" +) + +func main() { + if len(os.Args) < 2 { + fmt.Fprintf(os.Stderr, "Usage: go run FuturesFetch.go [FeedID]\n") + os.Exit(1) + } + feedIDInput := os.Args[1] + + apiKey := os.Getenv("API_KEY") + apiSecret := os.Getenv("API_SECRET") + if apiKey == "" || apiSecret == "" { + fmt.Fprintf(os.Stderr, "API_KEY and API_SECRET environment variables must be set\n") + os.Exit(1) + } + + cfg := streams.Config{ + ApiKey: apiKey, + ApiSecret: apiSecret, + RestURL: "https://api.testnet-dataengine.chain.link", + Logger: streams.LogPrintf, + } + + client, err := streams.New(cfg) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to create client: %v\n", err) + os.Exit(1) + } + + ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second) + defer cancel() + + var feedID feed.ID + if err := feedID.FromString(feedIDInput); err != nil { + fmt.Fprintf(os.Stderr, "Invalid feed ID format '%s': %v\n", feedIDInput, err) + os.Exit(1) + } + + reportResponse, err := client.GetLatestReport(ctx, feedID) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to get latest report: %v\n", err) + os.Exit(1) + } + + // Decode the v14 (Futures) report + decodedReport, err := report.Decode[v14.Data](reportResponse.FullReport) + if err != nil { + fmt.Fprintf(os.Stderr, "Failed to decode report: %v\n", err) + os.Exit(1) + } + + d := decodedReport.Data + + fmt.Printf("\nDecoded V14 Report for Stream ID %s:\n", feedIDInput) + fmt.Println("------------------------------------------") + fmt.Printf("Mid Price : %s\n", d.MidPrice.String()) + fmt.Printf("Bid Price : %s\n", d.BidPrice.String()) + fmt.Printf("Ask Price : %s\n", d.AskPrice.String()) + fmt.Printf("Expiry Time : %d\n", d.ExpiryTime.Unix()) + fmt.Printf("First Day of Notice : %d\n", d.FirstDayOfNotice.Unix()) + fmt.Printf("Last Seen TimestampNs : %d\n", d.LastSeenTimestampNs.UnixNano()) + fmt.Printf("Market Status : %d\n", d.MarketStatus) + fmt.Printf("Contract Month : %d\n", d.ContractMonth) + fmt.Printf("Goldman Roll Price : %s\n", d.GoldmanRollPrice.String()) + fmt.Printf("Current Business Day : %d\n", d.CurrentBusinessDay) + fmt.Printf("Interp Goldman Roll : %s\n", d.InterpolatedGoldmanRollPrice.String()) + fmt.Println("------------------------------------------") +} diff --git a/public/samples/DataStreams/FuturesFetch.rs b/public/samples/DataStreams/FuturesFetch.rs new file mode 100644 index 00000000000..bce5c806b7a --- /dev/null +++ b/public/samples/DataStreams/FuturesFetch.rs @@ -0,0 +1,60 @@ +// FuturesFetch.rs — Fetch and decode a Futures (v14) report with the Rust SDK. +// +// Usage: +// export API_KEY="..." +// export API_SECRET="..." +// cargo run 0x000ebfe7b7560e1866ef91d4607ce5ee7474382794e5ec755f38b70b1f30e647 +use chainlink_data_streams_report::feed_id::ID; +use chainlink_data_streams_report::report::{ decode_full_report, v14::ReportDataV14 }; +use chainlink_data_streams_sdk::client::Client; +use chainlink_data_streams_sdk::config::Config; +use std::env; +use std::error::Error; + +#[tokio::main] +async fn main() -> Result<(), Box> { + let args: Vec = env::args().collect(); + if args.len() < 2 { + eprintln!("Usage: cargo run [FeedID]"); + std::process::exit(1); + } + let feed_id_input = &args[1]; + + let api_key = env::var("API_KEY").expect("API_KEY must be set"); + let api_secret = env::var("API_SECRET").expect("API_SECRET must be set"); + + let config = Config::new( + api_key, + api_secret, + "https://api.testnet-dataengine.chain.link".to_string(), + "wss://api.testnet-dataengine.chain.link/ws".to_string(), + ) + .build()?; + + let client = Client::new(config)?; + + let feed_id = ID::from_hex_str(feed_id_input)?; + + let response = client.get_latest_report(feed_id).await?; + + let full_report = hex::decode(&response.report.full_report[2..])?; + let (_report_context, report_blob) = decode_full_report(&full_report)?; + let report_data = ReportDataV14::decode(&report_blob)?; + + println!("\nDecoded V14 Report for Stream ID {}:", feed_id_input); + println!("------------------------------------------"); + println!("Mid Price : {}", report_data.mid_price); + println!("Bid Price : {}", report_data.bid_price); + println!("Ask Price : {}", report_data.ask_price); + println!("Expiry Time : {}", report_data.expiry_time); + println!("First Day of Notice : {}", report_data.first_day_of_notice); + println!("Last Seen TimestampNs : {}", report_data.last_seen_timestamp_ns); + println!("Market Status : {}", report_data.market_status); + println!("Contract Month : {}", report_data.contract_month); + println!("Goldman Roll Price : {}", report_data.goldman_roll_price); + println!("Current Business Day : {}", report_data.current_business_day); + println!("Interp Goldman Roll : {}", report_data.interpolated_goldman_roll_price); + println!("------------------------------------------"); + + Ok(()) +} diff --git a/public/samples/DataStreams/FuturesFetch.ts b/public/samples/DataStreams/FuturesFetch.ts new file mode 100644 index 00000000000..1190169f135 --- /dev/null +++ b/public/samples/DataStreams/FuturesFetch.ts @@ -0,0 +1,51 @@ +// FuturesFetch.ts — Fetch and decode a Futures (v14) report with the TypeScript SDK. +// +// Usage: +// export API_KEY="..." +// export USER_SECRET="..." +// npx tsx FuturesFetch.ts 0x000ebfe7b7560e1866ef91d4607ce5ee7474382794e5ec755f38b70b1f30e647 +import { createClient, decodeReport, getReportVersion, formatReport, LogLevel } from "@chainlink/data-streams-sdk" +import "dotenv/config" + +async function main() { + if (process.argv.length < 3) { + console.error("Please provide a feed ID as an argument") + process.exit(1) + } + + const feedId = process.argv[2] + const version = getReportVersion(feedId) + + const config = { + apiKey: process.env.API_KEY || "YOUR_API_KEY", + userSecret: process.env.USER_SECRET || "YOUR_USER_SECRET", + endpoint: "https://api.testnet-dataengine.chain.link", + wsEndpoint: "wss://ws.testnet-dataengine.chain.link", + logging: { + logger: console, + logLevel: LogLevel.INFO, + }, + } + + const client = createClient(config) + console.log(`\nFetching latest report for feed ${feedId} (${version})...\n`) + + const report = await client.getLatestReport(feedId) + console.log(`Raw Report Blob: ${report.fullReport}`) + + // The TS SDK auto-detects the report version from the feed ID. + const decodedData = decodeReport(report.fullReport, report.feedID) + + const decodedReport = { + ...decodedData, + feedID: report.feedID, + validFromTimestamp: report.validFromTimestamp, + observationsTimestamp: report.observationsTimestamp, + } + console.log(formatReport(decodedReport, version)) +} + +main().catch((error) => { + console.error("Error:", error instanceof Error ? error.message : error) + process.exit(1) +}) diff --git a/src/config/sidebar.ts b/src/config/sidebar.ts index a047082ceff..6c4bd733bf3 100644 --- a/src/config/sidebar.ts +++ b/src/config/sidebar.ts @@ -1602,6 +1602,10 @@ export const SIDEBAR: Partial> = { title: "Report Schema v11 (RWA Advanced)", url: "data-streams/reference/report-schema-v11", }, + { + title: "Report Schema v14 (Futures)", + url: "data-streams/reference/report-schema-v14", + }, { title: "Handling Market Events", url: "data-streams/rwa-streams/handling-market-events", diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index dcfd825aa5f..02d4dcade96 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -6077,10 +6077,11 @@ While the Data Streams architecture is designed to deliver updates at least once ## Real-World Assets (RWA) -[Chainlink RWA streams](/data-streams/rwa-streams) deliver real-world asset pricing through two report schemas: +[Chainlink RWA streams](/data-streams/rwa-streams) deliver real-world asset pricing through three report schemas: - **[RWA Standard (v8)](/data-streams/reference/report-schema-v8)** — standard RWA format with consolidated mid price, market status, and freshness indicators. Used by the majority of RWA streams. - **[RWA Advanced (v11)](/data-streams/reference/report-schema-v11)** — adds bid/ask prices, volume depth, last traded price where supported, nanosecond-precision timestamps, and expanded market status values. Supports extended trading sessions where applicable. +- **[Futures (v14)](/data-streams/reference/report-schema-v14)** — futures price data with contract expiration, market status, and continuous roll price series. Used by [Futures streams](/data-streams/rwa-streams/futures). ### RWA Standard (v8) @@ -6096,6 +6097,12 @@ The [RWA Advanced (v11)](/data-streams/reference/report-schema-v11) report schem These advanced fields enable protocols to implement more sophisticated risk management and settlement logic. Where applicable, streams using this schema can provide coverage across extended trading sessions including pre-market, post-market, and overnight hours — though extended hours availability varies by stream. See individual [RWA stream details](/data-streams/rwa-streams?schema=v11) for specific coverage and the [RWA Advanced (v11) reference](/data-streams/reference/report-schema-v11) for complete field specifications. +### Futures (v14) + +The [Futures (v14)](/data-streams/reference/report-schema-v14) report schema provides price data for exchange-traded futures contracts. Each report includes consensus mid, bid, and ask prices (`midPrice`, `bidPrice`, `askPrice`), contract expiration (`expiryTime`), the first day of notice (`firstDayOfNotice`), the tracked contract month (`contractMonth`), market status (`marketStatus`), and a staleness measure (`lastSeenTimestampNs`). + +Because futures contracts expire, streams using this schema expose three **generic** feeds per instrument that always track the current front, second, and third contract. The schema also includes continuous roll price series — `goldmanRollPrice`, `interpolatedGoldmanRollPrice`, and `currentBusinessDay` — for integrators who want a smoothed price instead of a hard cutover at contract expiration. See the [Futures](/data-streams/rwa-streams/futures) reference for rotation methodology and the [Futures (v14) reference](/data-streams/reference/report-schema-v14) for complete field specifications. + ## SmartData [Chainlink SmartData streams](/data-streams/smartdata-streams) use the [SmartData (v9)](/data-streams/reference/report-schema-v9) report schema to provide real-time, tamper-proof access to data such as Net Asset Value (`navPerShare`) of tokenized assets, funds, or portfolios, as well as Proof of Reserve data. Each report includes NAV per share (`navPerShare`), NAV date (`navDate`), assets under management (`aum`), and ripcord status (`ripcord`). The ripcord is set to true (`1`) by the asset issuer when the consumer should ignore the value being sent (for cases such as maintenance, upstream data source outages, etc). The feed data will remain stale until the ripcord returns false (`0`). @@ -6269,6 +6276,79 @@ As a result, these volume fields should not be treated as a proxy for total mark --- +# Report Schema: Futures (v14) +Source: https://docs.chain.link/data-streams/reference/report-schema-v14 + +import { Aside } from "@components" + + + +Chainlink Data Streams that use the Futures (v14) schema adhere to the structure outlined below. + + + +## Schema Fields + +| Field | Type | Description | +| ------------------------------ | --------- | ---------------------------------------------------------------------------------------------------------------- | +| `feedId` | `bytes32` | Unique identifier for the Data Streams feed | +| `validFromTimestamp` | `uint32` | Earliest timestamp when the price is valid (seconds) | +| `observationsTimestamp` | `uint32` | Latest timestamp when the price is valid (seconds) | +| `nativeFee` | `uint192` | Legacy onchain verification fee field | +| `linkFee` | `uint192` | Legacy onchain verification fee field; not used for subscription billing | +| `expiresAt` | `uint32` | Expiration date of the report (seconds) | +| `midPrice` | `int192` | DON consensus mid price | +| `bidPrice` | `int192` | DON consensus bid price | +| `askPrice` | `int192` | DON consensus ask price | +| `expiryTime` | `uint64` | Contract expiration time (Unix seconds) | +| `firstDayOfNotice` | `uint64` | First day of notice for the tracked contract (Unix seconds) | +| `lastSeenTimestampNs` | `uint64` | Timestamp of the last update received from the data provider (nanoseconds) | +| `marketStatus` | `uint32` | Market status. Mapping varies by feed; see schema docs. | +| `contractMonth` | `uint32` | Standard futures month code (F=Jan, G=Feb, H=Mar, J=Apr, K=May, M=Jun, N=Jul, Q=Aug, U=Sep, V=Oct, X=Nov, Z=Dec) | +| `goldmanRollPrice` | `int192` | Continuous price using the Goldman Roll (GSCI) methodology | +| `currentBusinessDay` | `uint32` | Current business day count within the active roll window | +| `interpolatedGoldmanRollPrice` | `int192` | Interpolated Goldman Roll price (0 when not in an active roll window) | + +### Market Status Values + + + +Each feed's `marketStatus` field reflects the current market status of the primary exchange venue for that instrument. Futures trade during standard trading hours for each instrument, with a scheduled break each trading day. Consult the exchange where the underlying contract is listed for holiday and early-close schedules. + +For full trading schedules and `marketStatus` mappings, see [Market Hours](/data-streams/market-hours) and the [Futures](/data-streams/rwa-streams/futures) reference. + +### Continuous roll price fields + +In addition to the raw generic feed prices — which switch entirely to the next contract at the first notice date — the v14 schema includes continuous price series built using alternative rolling methodologies, for integrators who want a smoothed price instead of a hard cutover: + +| Field | Description | +| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `goldmanRollPrice` | Uses the Goldman Roll (GSCI methodology): shifts 20% of the position to the next contract each business day, over business days 5–9 of the month preceding delivery | +| `interpolatedGoldmanRollPrice` | Interpolated Goldman Roll price. Reported as `0` when the feed is not within an active roll window | +| `currentBusinessDay` | Current business day count within the active roll window, so integrators can implement the Goldman Roll methodology themselves | + +For details on how the generic feeds rotate between contracts and how the continuous roll fields behave, see the [Futures](/data-streams/rwa-streams/futures) reference. + +### Notes + +#### `lastSeenTimestampNs` + +- `lastSeenTimestampNs` helps applications detect stale data, especially important during market transitions and holidays. +- **Do not use `lastSeenTimestampNs` (or any other timestamp field) to determine whether the market is open.** Timestamps indicate when data was last recorded, not whether the market is currently active. Use the `marketStatus` field as the authoritative signal for market availability. + +#### `interpolatedGoldmanRollPrice` + +`interpolatedGoldmanRollPrice` is reported as `0` when the feed is not within an active roll window. Behavior on non-trading days (holding the last value versus resetting to zero) is still being finalized. + +--- + # Report Schema: Crypto Standard (v2) Source: https://docs.chain.link/data-streams/reference/report-schema-v2 @@ -6971,32 +7051,126 @@ Developers are responsible for choosing the appropriate feed and ensuring that t ## Schema -Futures streams use the v14 schema. +Futures streams use the [Futures (v14) schema](/data-streams/reference/report-schema-v14). -| Field | Description | -| --------------------- | ---------------------------------------------------------------------------------------------------------------- | -| `mid` | Mid price | -| `bid` | Bid price | -| `ask` | Ask price | -| `expiry_time` | Contract expiration time | -| `roll_date` | First day of notice, as a Unix timestamp | -| `lastSeenTimestampNs` | Timestamp of the last update received from the data provider | -| `marketStatus` | Market status indicator | -| `contract_month` | Standard futures month code (F=Jan, G=Feb, H=Mar, J=Apr, K=May, M=Jun, N=Jul, Q=Aug, U=Sep, V=Oct, X=Nov, Z=Dec) | -| `last_trading_day` | The final day the current contract trades | +The v14 schema includes consensus mid, bid, and ask prices, contract expiration and first day of notice, the tracked contract month, market status, and a staleness measure. It also includes continuous roll price fields — `goldmanRollPrice`, `interpolatedGoldmanRollPrice`, and `currentBusinessDay` — described below. ### Continuous roll price fields In addition to the raw generic feed prices above — which switch entirely to the next contract at the first notice date — Chainlink also publishes continuous price series built using alternative rolling methodologies, for integrators who want a smoothed price instead of a hard cutover: -| Field | Description | -| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `price_notice_roll` | Equivalent to the generic front feed price: switches entirely to the next contract at the first notice date | -| `price_goldman_roll` | Uses the Goldman Roll (GSCI methodology): shifts 20% of the position to the next contract each business day, over business days 5–9 of the month preceding delivery | -| `price_continuous_roll` | Smooths the transition evenly (1/N per business day) across the entire contract cycle, rather than a fixed window | -| `first_notice_date` | Date on which `price_notice_roll` switches to the next contract | +| Field | Description | +| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `goldmanRollPrice` | Uses the Goldman Roll (GSCI methodology): shifts 20% of the position to the next contract each business day, over business days 5–9 of the month preceding delivery | +| `interpolatedGoldmanRollPrice` | Interpolated Goldman Roll price. Reported as `0` when the feed is not within an active roll window | +| `currentBusinessDay` | Current business day count within the active roll window, so integrators can implement the Goldman Roll methodology themselves | + +For the complete field list and definitions, see the [Futures (v14) schema](/data-streams/reference/report-schema-v14). + +## Implementation + + + +Futures streams are consumed like any other [Data Streams report](/data-streams/tutorials/go-sdk-fetch): you fetch the latest report for a feed ID and decode it with the SDK. The only difference is the report schema version, which is **v14** for futures streams. + +The examples below fetch and decode a live `NY-UKOIL/USD` futures report from the testnet API. Each SDK auto-detects or explicitly targets the v14 schema. + + + + +### Expected output -Chainlink also plans to publish the current business day count within the active roll window, so integrators can implement the Goldman Roll or Continuous Roll methodology themselves. Behavior on non-trading days (holding the last value versus resetting to zero) is still being finalized. +Running any of the examples above against a live `NY-UKOIL/USD` futures feed produces a decoded report similar to the following (values are illustrative and change with each report): + +```text +Decoded V14 Report for Stream ID 0x000ebfe7b7560e1866ef91d4607ce5ee7474382794e5ec755f38b70b1f30e647: +------------------------------------------ +Valid From Timestamp : 1789593821 +Observations Timestamp: 1789593821 +Native Fee : 132954556310247 +LINK Fee : 29292627326579709 +Expires At : 1792185821 +Mid Price : 105584000000000000000 +Bid Price : 105539000000000000000 +Ask Price : 105629000000000000000 +Expiry Time : 1790740800 +First Day of Notice : 1790740800 +Last Seen TimestampNs : 1789592399813000000 +Market Status : 1 +Contract Month : 11 +Goldman Roll Price : 100574999999999990000 +Current Business Day : 11 +Interp Goldman Roll : 0 +------------------------------------------ +``` + +The prices above are 18-decimal fixed-point integers. For example, `Mid Price` `105584000000000000000` equals `105.584` USD. `Contract Month` `11` is November, and `Market Status` `1` means the market is closed. + +### Decoded fields + +The v14 report decodes to the following fields. Prices are 18-decimal fixed-point integers; timestamps are Unix epoch seconds unless noted. + +| Field | Type | Meaning | +| ---------------------------------- | -------- | ---------------------------------------------------------- | +| `midPrice`, `bidPrice`, `askPrice` | `int192` | Consensus mid, bid, and ask prices (18 decimals) | +| `expiryTime` | `uint64` | Contract expiration, Unix seconds | +| `firstDayOfNotice` | `uint64` | First day of notice, Unix seconds | +| `lastSeenTimestampNs` | `uint64` | Last provider update, nanoseconds | +| `marketStatus` | `uint32` | Market status: `0` Unknown, `1` Closed, `2` Open | +| `contractMonth` | `uint32` | Contract month, `1` (Jan) to `12` (Dec) | +| `goldmanRollPrice` | `int192` | Goldman Roll continuous price (18 decimals) | +| `currentBusinessDay` | `uint32` | Current business day in the roll window | +| `interpolatedGoldmanRollPrice` | `int192` | Interpolated Goldman Roll price; `0` outside a roll window | + +### Implementation patterns + +Futures streams differ from spot streams in a few ways that affect how you consume them: + +- **Use `marketStatus`, not timestamps, to gate trading.** `marketStatus` is the authoritative signal for whether the market is open. Do not infer market state from `lastSeenTimestampNs` or other timestamps; they only indicate when data was last recorded. See [Market Hours](/data-streams/market-hours) for the value mapping per feed. +- **Monitor `lastSeenTimestampNs` for staleness.** Futures are sourced from a single provider per feed. If updates stop arriving, the price can go stale without an obvious price change. Pause trading or restrict liquidations when the timestamp lags your freshness threshold. +- **Expect a price discontinuity at each roll.** When the front contract expires, the feed re-maps to the next contract, which can trade at a different price. Do not treat this step as a data error. If your application needs a smooth series, build it from the continuous roll fields (`goldmanRollPrice`, `interpolatedGoldmanRollPrice`) or construct your own off-chain. +- **Do not hardcode contract-month spacing.** The gap between the front, second, and third feeds varies by instrument (one month for energy, up to a few months for precious metals). Read `contractMonth` from the report rather than assuming monthly spacing. +- **Roll early if you are expiry-sensitive.** In the final days of a contract, liquidity migrates to the next contract while the front feed still tracks the expiring one, which can increase volatility. If your application is sensitive to this, roll ahead of expiry using the second feed. + +### Consuming the three generic feeds + + + +Each instrument is exposed as three feeds that always track the front, second, and third eligible contracts. The three feeds are the same schema (v14) and differ only in which contract they currently reference. To consume the curve correctly: + +- **Identify the cut from `contractMonth` and `expiryTime`, not from the feed ID.** The feed IDs are static and do not encode which cut a feed is. Read `contractMonth` and `expiryTime` from each report to know which contract a feed currently tracks. The feed with the nearest `expiryTime` is the front; the next two are the second and third. +- **The three feeds cascade on the front contract's expiry.** When the front expires, the front feed takes over the second feed's contract, the second takes over the third's, and the third picks up the next eligible contract. Your integration should not hardcode which contract a feed tracks; it should re-read `contractMonth`/`expiryTime` each report. +- **Build your own roll strategy.** Data Streams does not impose one. You can hold the front feed to expiry, roll early to the second feed when liquidity migrates, or construct a continuous series off-chain. The three feeds give you the visibility to implement whichever you choose. + +The example below fetches all three feeds for an instrument and prints which contract each currently tracks, so you can see the curve and detect a roll: + + + + +### Notes + +- **Prices are 18-decimal fixed-point integers.** `midPrice`, `bidPrice`, `askPrice`, `goldmanRollPrice`, and `interpolatedGoldmanRollPrice` are raw integers. Divide by `10^18` to get the human-readable price. In Go and Rust these are big-number types; call `.String()` to display them. +- **`interpolatedGoldmanRollPrice` is `0` outside a roll window.** Do not treat a `0` value as a price of zero; it means the feed is not currently in an active roll window. +- **`contractMonth` is validated to `1`–`12`.** The SDKs reject reports with an out-of-range month, so a successful decode guarantees a valid month. +- **The feed ID encodes the schema version.** The TypeScript SDK's `getReportVersion` and the Go SDK's `feedID.Version()` derive the schema from the feed ID. Use the v14 decoder for futures feeds. ## Coverage @@ -7097,6 +7271,10 @@ Each Futures instrument is sourced from a single institutional-grade data provid If the underlying provider fails to deliver data, there is no fallback source, and a gap in data may not be immediately obvious from price alone. Protocols should continuously monitor feed freshness and implement safeguards — such as pausing trading or restricting liquidations — if updates stop arriving or a feed appears stale. Review the [Developer Responsibilities](/data-streams/developer-responsibilities) guidance before integration. +## Available streams + +The table below shows all available Futures streams. + ## Support For inquiries related to a data outage, contact Chainlink Labs at [chainlink_data_feeds@smartcontract.com](mailto:chainlink_data_feeds@smartcontract.com). @@ -9001,6 +9179,12 @@ When working with different versions of [Data Stream reports](/data-streams/refe 3. Access fields according to the schema version structure. Refer to the [Report Schemas](/data-streams/reference/report-schema-overview) documentation for complete field references for each version. + + ## Explanation ### Initializing the client and configuration diff --git a/src/content/data-streams/reference/report-schema-overview.mdx b/src/content/data-streams/reference/report-schema-overview.mdx index 9fb1727790c..deda8064133 100644 --- a/src/content/data-streams/reference/report-schema-overview.mdx +++ b/src/content/data-streams/reference/report-schema-overview.mdx @@ -71,7 +71,7 @@ Each stream category uses one or more report schemas to deliver data. Several ca - + RWA @@ -92,6 +92,16 @@ Each stream category uses one or more report schemas to deliver data. Several ca lastTradedPrice, marketStatus + + + Futures (v14) + + Futures price data with continuous roll price series + + midPrice, bidPrice, askPrice, expiryTime,{" "} + contractMonth, goldmanRollPrice, marketStatus + + SmartData @@ -154,10 +164,11 @@ While the Data Streams architecture is designed to deliver updates at least once ## Real-World Assets (RWA) -[Chainlink RWA streams](/data-streams/rwa-streams) deliver real-world asset pricing through two report schemas: +[Chainlink RWA streams](/data-streams/rwa-streams) deliver real-world asset pricing through three report schemas: - **[RWA Standard (v8)](/data-streams/reference/report-schema-v8)** — standard RWA format with consolidated mid price, market status, and freshness indicators. Used by the majority of RWA streams. - **[RWA Advanced (v11)](/data-streams/reference/report-schema-v11)** — adds bid/ask prices, volume depth, last traded price where supported, nanosecond-precision timestamps, and expanded market status values. Supports extended trading sessions where applicable. +- **[Futures (v14)](/data-streams/reference/report-schema-v14)** — futures price data with contract expiration, market status, and continuous roll price series. Used by [Futures streams](/data-streams/rwa-streams/futures). ### RWA Standard (v8) @@ -173,6 +184,12 @@ The [RWA Advanced (v11)](/data-streams/reference/report-schema-v11) report schem These advanced fields enable protocols to implement more sophisticated risk management and settlement logic. Where applicable, streams using this schema can provide coverage across extended trading sessions including pre-market, post-market, and overnight hours — though extended hours availability varies by stream. See individual [RWA stream details](/data-streams/rwa-streams?schema=v11) for specific coverage and the [RWA Advanced (v11) reference](/data-streams/reference/report-schema-v11) for complete field specifications. +### Futures (v14) + +The [Futures (v14)](/data-streams/reference/report-schema-v14) report schema provides price data for exchange-traded futures contracts. Each report includes consensus mid, bid, and ask prices (`midPrice`, `bidPrice`, `askPrice`), contract expiration (`expiryTime`), the first day of notice (`firstDayOfNotice`), the tracked contract month (`contractMonth`), market status (`marketStatus`), and a staleness measure (`lastSeenTimestampNs`). + +Because futures contracts expire, streams using this schema expose three **generic** feeds per instrument that always track the current front, second, and third contract. The schema also includes continuous roll price series — `goldmanRollPrice`, `interpolatedGoldmanRollPrice`, and `currentBusinessDay` — for integrators who want a smoothed price instead of a hard cutover at contract expiration. See the [Futures](/data-streams/rwa-streams/futures) reference for rotation methodology and the [Futures (v14) reference](/data-streams/reference/report-schema-v14) for complete field specifications. + ## SmartData [Chainlink SmartData streams](/data-streams/smartdata-streams) use the [SmartData (v9)](/data-streams/reference/report-schema-v9) report schema to provide real-time, tamper-proof access to data such as Net Asset Value (`navPerShare`) of tokenized assets, funds, or portfolios, as well as Proof of Reserve data. Each report includes NAV per share (`navPerShare`), NAV date (`navDate`), assets under management (`aum`), and ripcord status (`ripcord`). The ripcord is set to true (`1`) by the asset issuer when the consumer should ignore the value being sent (for cases such as maintenance, upstream data source outages, etc). The feed data will remain stale until the ripcord returns false (`0`). diff --git a/src/content/data-streams/reference/report-schema-v14.mdx b/src/content/data-streams/reference/report-schema-v14.mdx new file mode 100644 index 00000000000..f6939b11365 --- /dev/null +++ b/src/content/data-streams/reference/report-schema-v14.mdx @@ -0,0 +1,76 @@ +--- +section: dataStreams +date: Last Modified +title: "Report Schema: Futures (v14)" +metadata: + title: "Futures (v14) | Chainlink Data Streams" + description: "Learn about Chainlink Data Streams Futures (v14) schema, including fields, encoding, and examples for integrating futures price data in your applications." + keywords: + [ + "Report Schema", + "v14 Schema", + "Data Format", + "Report Structure", + "Futures", + "Commodities", + "Goldman Roll", + "marketStatus", + "contractMonth", + ] +--- + +import DataStreams from "@features/data-streams/common/DataStreams.astro" +import ReportSchemaTabs from "@features/data-streams/common/ReportSchemaTabs.astro" +import SchemaFieldsTable from "@features/data-streams/common/SchemaFieldsTable.astro" + +import { Aside } from "@components" + + + + + +Chainlink Data Streams that use the Futures (v14) schema adhere to the structure outlined below. + + + +## Schema Fields + + + +### Market Status Values + + + +Each feed's `marketStatus` field reflects the current market status of the primary exchange venue for that instrument. Futures trade during standard trading hours for each instrument, with a scheduled break each trading day. Consult the exchange where the underlying contract is listed for holiday and early-close schedules. + +For full trading schedules and `marketStatus` mappings, see [Market Hours](/data-streams/market-hours) and the [Futures](/data-streams/rwa-streams/futures) reference. + +### Continuous roll price fields + +In addition to the raw generic feed prices — which switch entirely to the next contract at the first notice date — the v14 schema includes continuous price series built using alternative rolling methodologies, for integrators who want a smoothed price instead of a hard cutover: + +| Field | Description | +| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `goldmanRollPrice` | Uses the Goldman Roll (GSCI methodology): shifts 20% of the position to the next contract each business day, over business days 5–9 of the month preceding delivery | +| `interpolatedGoldmanRollPrice` | Interpolated Goldman Roll price. Reported as `0` when the feed is not within an active roll window | +| `currentBusinessDay` | Current business day count within the active roll window, so integrators can implement the Goldman Roll methodology themselves | + +For details on how the generic feeds rotate between contracts and how the continuous roll fields behave, see the [Futures](/data-streams/rwa-streams/futures) reference. + +### Notes + +#### `lastSeenTimestampNs` + +- `lastSeenTimestampNs` helps applications detect stale data, especially important during market transitions and holidays. +- **Do not use `lastSeenTimestampNs` (or any other timestamp field) to determine whether the market is open.** Timestamps indicate when data was last recorded, not whether the market is currently active. Use the `marketStatus` field as the authoritative signal for market availability. + +#### `interpolatedGoldmanRollPrice` + +`interpolatedGoldmanRollPrice` is reported as `0` when the feed is not within an active roll window. Behavior on non-trading days (holding the last value versus resetting to zero) is still being finalized. diff --git a/src/content/data-streams/rwa-streams/futures.mdx b/src/content/data-streams/rwa-streams/futures.mdx index f7c2be24e90..a9bc0153877 100644 --- a/src/content/data-streams/rwa-streams/futures.mdx +++ b/src/content/data-streams/rwa-streams/futures.mdx @@ -7,13 +7,16 @@ metadata: description: "Reference for Chainlink Futures Data Streams, covering coverage, generic feed rotation, and risk considerations." whatsnext: { + "Find the schema of data to expect from Futures reports": "/data-streams/reference/report-schema-v14", "Learn about developer responsibilities": "/data-streams/developer-responsibilities", "Learn about Data Streams market hours and schedules": "/data-streams/market-hours", "Find the list of available RWA streams": "/data-streams/rwa-streams", } --- -import { Aside } from "@components" +import { Aside, CodeSample } from "@components" +import { Tabs } from "@components/Tabs" +import { FeedList } from "@features/feeds" -Futures streams provide price data for exchange-traded futures contracts. These streams enable onchain protocols to build markets around futures price exposure. Coverage currently includes commodities — energy and precious metals — described below. +Futures streams provide price data for exchange-traded futures contracts. These streams enable onchain protocols to build markets around futures price exposure. Coverage currently includes US Oil, UK Oil, and Natural Gas. Additional commodities are planned. -Because futures contracts expire, Data Streams does not publish one feed per contract. Instead, each instrument is represented by three **generic** feeds that always track the current front, second, and third contract. This is explained in [Rotation methodology](#rotation-methodology) below. +Because futures contracts expire, Data Streams uses **generic** feeds that track the active contract instead of publishing one feed per expiry. Each instrument currently has a single front feed, which tracks the nearest unexpired eligible contract. Additional feeds for later contracts are planned. See [Rotation methodology](#rotation-methodology) below. Developers are responsible for choosing the appropriate feed and ensuring that the operation and performance of their choice matches expectations. For more information, see the [Developer Responsibilities](/data-streams/developer-responsibilities) guidance. @@ -37,29 +37,45 @@ The v14 schema includes consensus mid, bid, and ask prices, contract expiration ### Continuous roll price fields -In addition to the raw generic feed prices above — which switch entirely to the next contract at the first notice date — Chainlink also publishes continuous price series built using alternative rolling methodologies, for integrators who want a smoothed price instead of a hard cutover: +In addition to the raw generic feed prices above — which switch entirely to the next contract when the front contract expires — Chainlink also publishes continuous price series built using alternative rolling methodologies, for integrators who want a smoothed price instead of a hard cutover: | Field | Description | | ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `goldmanRollPrice` | Uses the Goldman Roll (GSCI methodology): shifts 20% of the position to the next contract each business day, over business days 5–9 of the month preceding delivery | | `interpolatedGoldmanRollPrice` | Interpolated Goldman Roll price, smoothing the roll across the full cycle rather than the fixed Goldman window | -| `currentBusinessDay` | Current business day count within the active roll window, so integrators can implement the Goldman Roll methodology themselves | +| `currentBusinessDay` | Current business day of the month, used to determine the Goldman Roll window | For the complete field list and definitions, see the [Futures (v14) schema](/data-streams/reference/report-schema-v14). +## Available streams + + + +The table below shows all available Futures streams. + + + ## Implementation Futures streams are consumed like any other [Data Streams report](/data-streams/tutorials/go-sdk-fetch): you fetch the latest report for a feed ID and decode it with the SDK. The only difference is the report schema version, which is **v14** for futures streams. -The examples below fetch and decode a live `NY-UKOIL/USD` futures report from the testnet API. Each SDK auto-detects or explicitly targets the v14 schema. +The examples below fetch and decode a live `NY-UKOIL/USD` front feed from the testnet API. Each SDK auto-detects or explicitly targets the v14 schema. {/* prettier-ignore */} @@ -85,31 +101,31 @@ The examples below fetch and decode a live `NY-UKOIL/USD` futures report from th ### Expected output -Running any of the examples above against a live `NY-UKOIL/USD` futures feed produces a decoded report similar to the following (values are illustrative and change with each report): +Running any of the examples above against a live `NY-UKOIL/USD` front feed produces a decoded report similar to the following (values are illustrative and change with each report): ```text -Decoded V14 Report for Stream ID 0x000ebfe7b7560e1866ef91d4607ce5ee7474382794e5ec755f38b70b1f30e647: +Decoded V14 Report for Stream ID 0x000e4b991d02aa6ce023f80f6fdebd8ec5039f9d2b184ffcc7bd3fc4a3ed2a9d: ------------------------------------------ -Valid From Timestamp : 1789593821 -Observations Timestamp: 1789593821 -Native Fee : 132954556310247 -LINK Fee : 29292627326579709 -Expires At : 1792185821 -Mid Price : 105584000000000000000 -Bid Price : 105539000000000000000 -Ask Price : 105629000000000000000 -Expiry Time : 1790740800 -First Day of Notice : 1790740800 -Last Seen TimestampNs : 1789592399813000000 -Market Status : 1 -Contract Month : 11 -Goldman Roll Price : 100574999999999990000 -Current Business Day : 11 -Interp Goldman Roll : 0 +Valid From Timestamp : 1792614089 +Observations Timestamp: 1792614089 +Native Fee : 128559788905831 +LINK Fee : 25306002187814827 +Expires At : 1795206089 +Mid Price : 109748000000000000000 +Bid Price : 109733000000000000000 +Ask Price : 109763000000000000000 +Expiry Time : 1793332800 +First Day of Notice : 1793332800 +Last Seen TimestampNs : 1792614081347000000 +Market Status : 2 +Contract Month : 12 +Goldman Roll Price : 105806666666666660000 +Current Business Day : 15 +Interp Goldman Roll : 105806666666666660000 ------------------------------------------ ``` -The prices above are 18-decimal fixed-point integers. For example, `Mid Price` `105584000000000000000` equals `105.584` USD. `Contract Month` `11` is November, and `Market Status` `1` means the market is closed. +The prices above are 18-decimal fixed-point integers. For example, `Mid Price` `109748000000000000000` equals `109.748` USD. `Contract Month` `12` is December, and `Market Status` `2` means the market is open. ### Decoded fields @@ -124,34 +140,33 @@ The v14 report decodes to the following fields. Prices are 18-decimal fixed-poin | `marketStatus` | `uint32` | Market status: `0` Unknown, `1` Closed, `2` Open | | `contractMonth` | `uint32` | Contract month, `1` (Jan) to `12` (Dec) | | `goldmanRollPrice` | `int192` | Goldman Roll continuous price (18 decimals) | -| `currentBusinessDay` | `uint32` | Current business day in the roll window | +| `currentBusinessDay` | `uint32` | Current business day of the month | | `interpolatedGoldmanRollPrice` | `int192` | Interpolated Goldman Roll price, smoothed across the full cycle | ### Implementation patterns Futures streams differ from spot streams in a few ways that affect how you consume them: -- **Use `marketStatus`, not timestamps, to gate trading.** `marketStatus` is the authoritative signal for whether the market is open. Do not infer market state from `lastSeenTimestampNs` or other timestamps; they only indicate when data was last recorded. See [Market Hours](/data-streams/market-hours) for the value mapping per feed. -- **Monitor `lastSeenTimestampNs` for staleness.** Futures are sourced from a single provider per feed. If updates stop arriving, the price can go stale without an obvious price change. Pause trading or restrict liquidations when the timestamp lags your freshness threshold. +- **Gate trading with `marketStatus`.** `marketStatus` is the authoritative signal for whether the market is open. Do not infer market state from `lastSeenTimestampNs` or other timestamps; they only indicate when data was last recorded. See [Market Hours](/data-streams/market-hours) for the value mapping per feed. +- **Monitor `lastSeenTimestampNs` for staleness.** Futures are sourced from a single underlying provider per feed. If updates stop arriving, the price can go stale without an obvious price change. Pause trading or restrict liquidations when the timestamp lags your freshness threshold. - **Expect a price discontinuity at each roll.** When the front contract expires, the feed re-maps to the next contract, which can trade at a different price. Do not treat this step as a data error. If your application needs a smooth series, build it from the continuous roll fields (`goldmanRollPrice`, `interpolatedGoldmanRollPrice`) or construct your own off-chain. -- **Do not hardcode contract-month spacing.** The gap between the front, second, and third feeds varies by instrument (one month for energy, up to a few months for precious metals). Read `contractMonth` from the report rather than assuming monthly spacing. -- **Roll early if you are expiry-sensitive.** In the final days of a contract, liquidity migrates to the next contract while the front feed still tracks the expiring one, which can increase volatility. If your application is sensitive to this, roll ahead of expiry using the second feed. +- **Do not hardcode contract-month spacing.** The gap between the contracts tracked by consecutive feeds varies by instrument (one month for energy, wider for precious metals). Read `contractMonth` from the report rather than assuming monthly spacing. +- **Roll early if you are expiry-sensitive.** In the final days of a contract, liquidity migrates to the next contract while the front feed still tracks the expiring one, which can increase volatility. If your application is sensitive to this, roll ahead of expiry to a later feed when one is available. -### Consuming the three generic feeds +### Example implementation for full rollout -Each instrument is exposed as three feeds that always track the front, second, and third eligible contracts. The three feeds are the same schema (v14) and differ only in which contract they currently reference. To consume the curve correctly: +When the full set is released, each instrument will be exposed as three feeds that always track the front, second, and third eligible contracts. The three feeds share the same schema (v14) and differ only in which contract they currently reference. To consume the curve correctly: -- **Identify the cut from `contractMonth` and `expiryTime`, not from the feed ID.** The feed IDs are static and do not encode which cut a feed is. Read `contractMonth` and `expiryTime` from each report to know which contract a feed currently tracks. The feed with the nearest `expiryTime` is the front; the next two are the second and third. -- **The three feeds cascade on the front contract's expiry.** When the front expires, the front feed takes over the second feed's contract, the second takes over the third's, and the third picks up the next eligible contract. Your integration should not hardcode which contract a feed tracks; it should re-read `contractMonth`/`expiryTime` each report. -- **Build your own roll strategy.** Data Streams does not impose one. You can hold the front feed to expiry, roll early to the second feed when liquidity migrates, or construct a continuous series off-chain. The three feeds give you the visibility to implement whichever you choose. +- **Read the cut from `contractMonth` and `expiryTime`.** The feed IDs are static and do not encode which cut a feed is. The feed with the nearest `expiryTime` is the front; the next two are the second and third. +- **The three feeds will cascade on the front contract's expiry.** When the front expires, the front feed takes over the second feed's contract, the second takes over the third's, and the third picks up the next eligible contract. Your integration should not hardcode which contract a feed tracks; it should re-read `contractMonth`/`expiryTime` each report. +- **Build your own roll strategy.** Data Streams does not impose one. You can hold the front feed to expiry, roll early to a later feed when liquidity migrates, or construct a continuous series off-chain. -The example below fetches all three feeds for an instrument and prints which contract each currently tracks, so you can see the curve and detect a roll: +The example below fetches all three feeds for an instrument once they are available and prints which contract each currently tracks, so you can see the curve and detect a roll: {/* prettier-ignore */} @@ -161,7 +176,7 @@ The example below fetches all three feeds for an instrument and prints which con ```go // Read the front, second, and third feeds for an instrument. - // Replace the three feed IDs with the front/second/third feeds for your instrument. + // Replace the three feed IDs with the front/second/third feeds for your instrument once they are available. feedIDs := []feed.ID{frontID, secondID, thirdID} for _, id := range feedIDs { @@ -183,7 +198,7 @@ The example below fetches all three feeds for an instrument and prints which con ```typescript // Read the front, second, and third feeds for an instrument. - // Replace the three feed IDs with the front/second/third feeds for your instrument. + // Replace the three feed IDs with the front/second/third feeds for your instrument once they are available. const feedIds = [frontId, secondId, thirdId] for (const id of feedIds) { @@ -197,7 +212,7 @@ The example below fetches all three feeds for an instrument and prints which con ```rust // Read the front, second, and third feeds for an instrument. - // Replace the three feed IDs with the front/second/third feeds for your instrument. + // Replace the three feed IDs with the front/second/third feeds for your instrument once they are available. let feed_ids = [front_id, second_id, third_id]; for id in feed_ids { @@ -222,25 +237,17 @@ The example below fetches all three feeds for an instrument and prints which con ### Notes - **Prices are 18-decimal fixed-point integers.** `midPrice`, `bidPrice`, `askPrice`, `goldmanRollPrice`, and `interpolatedGoldmanRollPrice` are raw integers. Divide by `10^18` to get the human-readable price. In Go and Rust these are big-number types; call `.String()` to display them. -- **`interpolatedGoldmanRollPrice` is populated continuously.** It smooths the roll across the full contract cycle rather than only the fixed Goldman window, so it is not limited to business days 5–9. +- **`interpolatedGoldmanRollPrice` smooths the roll across the full contract cycle** rather than only the fixed Goldman window, so it is not limited to business days 5–9. - **`contractMonth` is validated to `1`–`12`.** The SDKs reject reports with an out-of-range month, so a successful decode guarantees a valid month. - **The feed ID encodes the schema version.** The TypeScript SDK's `getReportVersion` and the Go SDK's `feedID.Version()` derive the schema from the feed ID. Use the v14 decoder for futures feeds. ## Coverage -Futures streams are currently available for the following commodities. Additional commodities and asset classes may be added based on demand. - -| Commodity | Generic feeds | -| ----------- | ------------------------------ | -| Gold | Front, second, and third feeds | -| Silver | Front, second, and third feeds | -| US Oil | Front, second, and third feeds | -| UK Oil | Front, second, and third feeds | -| Natural Gas | Front, second, and third feeds | +Futures streams currently cover US Oil, UK Oil, and Natural Gas. Additional commodities are planned. ## Naming and price representation -Feed names use the plain instrument name only (for example, "US Oil," "Gold," "Natural Gas"). +Feed names follow the instrument name as it appears in the available streams table (for example, "NY USOIL," "NY UK OIL," and "NatGas"). Naming may change as coverage expands. Contract specifications — contract size, tick size, quotation units, and similar terms — can vary between exchanges for the same underlying instrument. Chainlink does not publish these specifications, since they belong to the exchange where a given contract is listed. If your application needs exact contract specifications, consult that exchange's own public product documentation directly. @@ -248,22 +255,22 @@ Contract specifications — contract size, tick size, quotation units, and simil Unlike spot instruments, futures contracts have a finite life. For example, a given month's Natural Gas contract trades for a limited window and then expires. If Data Streams published a dedicated feed per contract, integrators would need to re-point their integration to a new feed every time a contract expired. -To avoid this, each instrument is represented by three static, non-expiring **generic feeds** that always represent the near-term forward curve of eligible contracts: +To avoid this, each instrument is represented by static, non-expiring **generic feeds** that follow the near-term forward curve of eligible contracts. The front feed is available now. The second and third feeds are planned: -| Generic feed | Meaning | -| --------------- | ---------------------------------------------------------- | -| **Front feed** | Tracks the nearest unexpired eligible contract | -| **Second feed** | Tracks the next eligible contract after the front contract | -| **Third feed** | Tracks the eligible contract after that | +| Generic feed | Meaning | Availability | +| --------------- | ---------------------------------------------------------- | ------------ | +| **Front feed** | Tracks the nearest unexpired eligible contract | Available | +| **Second feed** | Tracks the next eligible contract after the front contract | Planned | +| **Third feed** | Tracks the eligible contract after that | Planned | -This design means: +Once the full set is available, this design means: -- **Zero maintenance.** Integrate the three generic feeds once. You never need to re-point feed endpoints when a contract expires — the feeds re-map internally. -- **Full visibility of the curve.** Because the front, second, and third contracts are exposed simultaneously, you retain full autonomy over your own rolling logic. You can roll positions on a fixed schedule ahead of expiry, or when liquidity migrates from the front contract to the second — Data Streams does not impose a roll strategy. +- **Zero maintenance.** Integrate the generic feeds once. You never need to re-point feed endpoints when a contract expires. The feeds re-map internally. +- **Full visibility of the curve.** Because the front, second, and third contracts are exposed simultaneously, you retain full autonomy over your own rolling logic. You can roll positions on a fixed schedule ahead of expiry, or when liquidity migrates from the front contract to the next one. Data Streams does not impose a roll strategy. ### How the roll works -When the front contract reaches its expiration, the generic feeds cascade forward: +When the front contract reaches its expiration, the front feed re-maps to the next eligible contract. Once the second and third feeds are available, all three will cascade forward together: - The **front feed** takes over the contract previously tracked by the second feed - The **second feed** takes over the contract previously tracked by the third feed @@ -272,48 +279,48 @@ When the front contract reaches its expiration, the generic feeds cascade forwar A few properties of the roll are worth calling out explicitly: - **The roll is triggered by the front contract's expiration**, as defined by the listed expiration calendar for that specific instrument. Expiration conventions differ by instrument, so rolls for different instruments happen on different dates — there is no single "roll day" across all instruments. -- **The switch happens right after the primary exchange's trading session closes** on the expiration date, not at a fixed clock time across all instruments. For these commodities, that session close is typically around 17:00 ET. -- **The roll is a re-mapping, not a price adjustment.** At the moment of the roll, the front feed switches from quoting the expiring contract to quoting what was previously the second contract. Because different contract months can trade at different prices, **expect a price discontinuity on the generic feed at each roll**. Feeds are not back-adjusted into a smooth continuous series — if your application needs a continuous series, construct it from the raw generic feeds on your end. -- **Until expiration, the front feed continues to track the expiring contract**, even in its final days when liquidity has typically already migrated to the next contract. This is precisely why the second feed is exposed — so you can implement your own liquidity-based rolls ahead of expiry instead of holding the front contract to the end. +- **The switch happens immediately after the primary exchange's trading session closes** on the expiration date. For these commodities, that is typically around 17:00 ET. +- **The roll re-maps the feed.** At the moment of the roll, the front feed switches from quoting the expiring contract to quoting the next eligible contract. Because different contract months can trade at different prices, **expect a price discontinuity on the generic feed at each roll**. Feeds are not back-adjusted into a smooth continuous series. If your application needs a continuous series, construct it from the raw generic feeds on your end. +- **Until expiration, the front feed continues to track the expiring contract**, even in its final days when liquidity has typically already migrated to the next contract. This is why later feeds are being added: so you can implement your own liquidity-based rolls ahead of expiry instead of holding the front contract to the end. ### Contract eligibility varies by instrument -The front feed does not necessarily track the nearest calendar month — it tracks the nearest unexpired eligible contract, whatever month that happens to be. Each instrument has its own set of listed contract months, and for several instruments, the actively traded contracts are only a subset of what is listed: +The front feed tracks the nearest unexpired eligible contract, which may not be the nearest calendar month. Each instrument has its own set of listed contract months, and for several instruments, the actively traded contracts are only a subset of what is listed: -- **Energy** (US Oil, UK Oil, Natural Gas): every calendar month is listed, though liquidity is generally concentrated in nearer maturities. The generic feeds walk the full monthly strip regardless, so the front, second, and third feeds track three **consecutive** calendar months. -- **Precious metals** (Gold, Silver): many calendar months are listed, but liquidity concentrates in a benchmark cycle. The generic feeds follow the benchmark cycle only and skip non-benchmark months, even though those contracts exist and trade. +- **Energy** (US Oil, UK Oil, Natural Gas): every calendar month is listed, though liquidity is generally concentrated in nearer maturities. The generic feeds walk the full monthly strip regardless, so consecutive feeds track **consecutive** calendar months. +- **Precious metals** (planned): many calendar months are listed, but liquidity concentrates in a benchmark cycle. When precious metals streams are available, the generic feeds will follow the benchmark cycle only and skip non-benchmark months, even though those contracts exist and trade. | Commodity | Benchmark months | | --------- | ---------------------------- | | Gold | Feb, Apr, Jun, Aug, Oct, Dec | | Silver | Mar, May, Jul, Sep, Dec | -The practical consequence: **the gap between the front, second, and third feeds is not always one month.** For Gold or Silver, consecutive generic feeds can be one to three months apart. Do not assume monthly spacing in your integration. +The practical consequence: **the gap between consecutive feeds is not always one month.** For Gold or Silver, consecutive generic feeds can be one to three months apart. Do not assume monthly spacing in your integration. ### Worked example -Gold follows its benchmark cycle (Feb/Apr/Jun/Aug/Oct/Dec). In August 2026, before the August contract expires: +For example, with US Oil, before the September contract expires: | Feed | Contract tracked | | ----------- | ---------------- | -| Front feed | August 2026 | -| Second feed | October 2026 | -| Third feed | December 2026 | +| Front feed | September | +| Second feed | October | +| Third feed | November | -When the August contract expires, the front feed jumps directly to October, the second feed jumps to December, and the third feed begins tracking February 2027 — skipping the non-benchmark September and November contracts entirely, since they never appear on the generic feeds. +When the September contract expires, the front feed moves to October, the second feed moves to November, and the third feed begins tracking December. The front feed is available now; the second and third feeds are planned. ## Integration guidance -- **Do not hardcode contract-month assumptions.** The spacing between the front, second, and third feeds varies by instrument — one month for energy, up to a few months for precious metals. -- **Expect price steps at rolls.** A protocol using the front feed directly for margining or liquidation should either accept the step as economically correct (the front contract genuinely changed), implement its own early roll using the second feed, or build an adjusted continuous series off-chain from the raw generic feeds. -- **Roll early to avoid volatility near expiry.** In the final days of a contract's life, trading volume typically migrates to the next contract while the front feed still tracks the expiring one. Thin liquidity in the expiring contract can increase price volatility, which may unexpectedly trigger perpetual trades, liquidations, or other price-sensitive logic. If your application is sensitive to this, consider rolling ahead of expiry using the second feed. +- **Do not hardcode contract-month assumptions.** The spacing between the feeds available for an instrument varies by instrument: one month for energy, up to a few months for precious metals. +- **Expect price steps at rolls.** A protocol using the front feed directly for margining or liquidation should either accept the step as economically correct (the front contract genuinely changed), roll early to a later feed when one is available, or build an adjusted continuous series off-chain from the raw generic feeds. +- **Roll early to avoid volatility near expiry.** In the final days of a contract's life, trading volume typically migrates to the next contract while the front feed still tracks the expiring one. Thin liquidity in the expiring contract can increase price volatility, which may unexpectedly trigger perpetual trades, liquidations, or other price-sensitive logic. If your application is sensitive to this, consider rolling ahead of expiry to a later feed when one is available. - **Follow the listed expiration calendar.** Expiration dates follow the official listed calendar of the exchange where the underlying contract trades, including holiday adjustments. Consult that exchange for the operative source of truth. ## Trading hours -Futures trade during standard trading hours for each instrument, with a scheduled break each trading day. Consult the exchange where the underlying contract is listed for holiday and early-close schedules. +Futures streams follow commodity market hours, with a scheduled break each trading day. Trading hours and holiday schedules are set by the exchange where the underlying contract is listed. -Each feed's `marketStatus` field reflects the current market status of the primary exchange venue for that instrument. +Each feed's `marketStatus` field reflects the current market status for that instrument. For the value mapping and generic commodity schedule, see [Market Hours](/data-streams/market-hours#futures-v14). ## Risk considerations @@ -321,22 +328,10 @@ Integrating protocols are responsible for implementing appropriate monitoring an ### Single-source data -Each Futures instrument is sourced from a single institutional-grade data provider per feed. While this enables high-frequency, low-latency delivery, it introduces dependency on that provider's data quality and availability. There is no redundant cross-validation between providers for a given feed. +Each Futures instrument is sourced from a single underlying institutional-grade data provider per feed. The Data Streams DON operators all source from that same provider, so there is no redundant cross-validation between independent providers for a given feed. While this enables high-frequency, low-latency delivery, it introduces dependency on that provider's data quality and availability. If the underlying provider fails to deliver data, there is no fallback source, and a gap in data may not be immediately obvious from price alone. Protocols should continuously monitor feed freshness and implement safeguards — such as pausing trading or restricting liquidations — if updates stop arriving or a feed appears stale. Review the [Developer Responsibilities](/data-streams/developer-responsibilities) guidance before integration. -## Available streams - -The table below shows all available Futures streams. - - - ## Support For inquiries related to a data outage, contact Chainlink Labs at [chainlink_data_feeds@smartcontract.com](mailto:chainlink_data_feeds@smartcontract.com). diff --git a/src/features/feeds/components/reportSchemaData.ts b/src/features/feeds/components/reportSchemaData.ts index 809a77ae3b9..c7f303b23fe 100644 --- a/src/features/feeds/components/reportSchemaData.ts +++ b/src/features/feeds/components/reportSchemaData.ts @@ -283,8 +283,7 @@ export const REPORT_SCHEMA_DEFINITIONS: Record = { { field: "contractMonth", type: "uint32", - description: - "Standard futures month code (F=Jan, G=Feb, H=Mar, J=Apr, K=May, M=Jun, N=Jul, Q=Aug, U=Sep, V=Oct, X=Nov, Z=Dec)", + description: "Contract month, from 1 (Jan) to 12 (Dec)", }, { field: "goldmanRollPrice", @@ -294,12 +293,12 @@ export const REPORT_SCHEMA_DEFINITIONS: Record = { { field: "currentBusinessDay", type: "uint32", - description: "Current business day count within the active roll window", + description: "Current business day of the month, used to determine the Goldman Roll window", }, { field: "interpolatedGoldmanRollPrice", type: "int192", - description: "Interpolated Goldman Roll price (0 when not in an active roll window)", + description: "Interpolated Goldman Roll price, smoothed across the full contract cycle", }, ], }, From c95ad9cd9e6302ac0ea8d2f485c04633ced1106f Mon Sep 17 00:00:00 2001 From: devin distefano Date: Wed, 21 Oct 2026 17:08:13 -0500 Subject: [PATCH 15/19] update to reflect real contract --- public/samples/DataStreams/FuturesFetch.go | 2 +- public/samples/DataStreams/FuturesFetch.rs | 2 +- public/samples/DataStreams/FuturesFetch.ts | 2 +- src/content/data-streams/llms-full.txt | 34 +++++++++---------- .../data-streams/rwa-streams/futures.mdx | 28 +++++++-------- 5 files changed, 34 insertions(+), 34 deletions(-) diff --git a/public/samples/DataStreams/FuturesFetch.go b/public/samples/DataStreams/FuturesFetch.go index 0ce7dccb20a..0d9b5f87a4d 100644 --- a/public/samples/DataStreams/FuturesFetch.go +++ b/public/samples/DataStreams/FuturesFetch.go @@ -3,7 +3,7 @@ // Usage: // export API_KEY="..." // export API_SECRET="..." -// go run FuturesFetch.go 0x000e4b991d02aa6ce023f80f6fdebd8ec5039f9d2b184ffcc7bd3fc4a3ed2a9d +// go run FuturesFetch.go 0x000eaf52614042ff33b2726b0d9c5db032fc816d4a215bd823d9385662afd57d package main import ( diff --git a/public/samples/DataStreams/FuturesFetch.rs b/public/samples/DataStreams/FuturesFetch.rs index d73f1d97766..e7ffbc8e187 100644 --- a/public/samples/DataStreams/FuturesFetch.rs +++ b/public/samples/DataStreams/FuturesFetch.rs @@ -3,7 +3,7 @@ // Usage: // export API_KEY="..." // export API_SECRET="..." -// cargo run 0x000e4b991d02aa6ce023f80f6fdebd8ec5039f9d2b184ffcc7bd3fc4a3ed2a9d +// cargo run 0x000eaf52614042ff33b2726b0d9c5db032fc816d4a215bd823d9385662afd57d use chainlink_data_streams_report::feed_id::ID; use chainlink_data_streams_report::report::{ decode_full_report, v14::ReportDataV14 }; use chainlink_data_streams_sdk::client::Client; diff --git a/public/samples/DataStreams/FuturesFetch.ts b/public/samples/DataStreams/FuturesFetch.ts index 9f8a35744de..66599f10268 100644 --- a/public/samples/DataStreams/FuturesFetch.ts +++ b/public/samples/DataStreams/FuturesFetch.ts @@ -3,7 +3,7 @@ // Usage: // export API_KEY="..." // export USER_SECRET="..." -// npx tsx FuturesFetch.ts 0x000e4b991d02aa6ce023f80f6fdebd8ec5039f9d2b184ffcc7bd3fc4a3ed2a9d +// npx tsx FuturesFetch.ts 0x000eaf52614042ff33b2726b0d9c5db032fc816d4a215bd823d9385662afd57d import { createClient, decodeReport, getReportVersion, formatReport, LogLevel } from "@chainlink/data-streams-sdk" import "dotenv/config" diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index 07cdede3baf..987cd7387c5 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -7709,7 +7709,7 @@ The examples below fetch and decode a live `NY-UKOIL/USD` front feed from the te // Usage: // export API_KEY="..." // export API_SECRET="..." -// go run FuturesFetch.go 0x000e4b991d02aa6ce023f80f6fdebd8ec5039f9d2b184ffcc7bd3fc4a3ed2a9d +// go run FuturesFetch.go 0x000eaf52614042ff33b2726b0d9c5db032fc816d4a215bd823d9385662afd57d package main import ( @@ -7800,7 +7800,7 @@ func main() { // Usage: // export API_KEY="..." // export USER_SECRET="..." -// npx tsx FuturesFetch.ts 0x000e4b991d02aa6ce023f80f6fdebd8ec5039f9d2b184ffcc7bd3fc4a3ed2a9d +// npx tsx FuturesFetch.ts 0x000eaf52614042ff33b2726b0d9c5db032fc816d4a215bd823d9385662afd57d import { createClient, decodeReport, getReportVersion, formatReport, LogLevel } from "@chainlink/data-streams-sdk" import "dotenv/config" @@ -7856,7 +7856,7 @@ main().catch((error) => { // Usage: // export API_KEY="..." // export API_SECRET="..." -// cargo run 0x000e4b991d02aa6ce023f80f6fdebd8ec5039f9d2b184ffcc7bd3fc4a3ed2a9d +// cargo run 0x000eaf52614042ff33b2726b0d9c5db032fc816d4a215bd823d9385662afd57d use chainlink_data_streams_report::feed_id::ID; use chainlink_data_streams_report::report::{ decode_full_report, v14::ReportDataV14 }; use chainlink_data_streams_sdk::client::Client; @@ -7924,28 +7924,28 @@ async fn main() -> Result<(), Box> { Running any of the examples above against a live `NY-UKOIL/USD` front feed produces a decoded report similar to the following (values are illustrative and change with each report): ```text -Decoded V14 Report for Stream ID 0x000e4b991d02aa6ce023f80f6fdebd8ec5039f9d2b184ffcc7bd3fc4a3ed2a9d: +Decoded V14 Report for Stream ID 0x000eaf52614042ff33b2726b0d9c5db032fc816d4a215bd823d9385662afd57d: ------------------------------------------ -Valid From Timestamp : 1792614089 -Observations Timestamp: 1792614089 -Native Fee : 128559788905831 -LINK Fee : 25306002187814827 -Expires At : 1795206089 -Mid Price : 109748000000000000000 -Bid Price : 109733000000000000000 -Ask Price : 109763000000000000000 +Valid From Timestamp : 1792619840 +Observations Timestamp: 1792619840 +Native Fee : 128232412751773 +LINK Fee : 25280896962790859 +Expires At : 1795211840 +Mid Price : 109741000000000000000 +Bid Price : 109716000000000000000 +Ask Price : 109766000000000000000 Expiry Time : 1793332800 First Day of Notice : 1793332800 -Last Seen TimestampNs : 1792614081347000000 -Market Status : 2 +Last Seen TimestampNs : 1792619593886000000 +Market Status : 1 Contract Month : 12 -Goldman Roll Price : 105806666666666660000 +Goldman Roll Price : 105740000000000000000 Current Business Day : 15 -Interp Goldman Roll : 105806666666666660000 +Interp Goldman Roll : 105740000000000000000 ------------------------------------------ ``` -The prices above are 18-decimal fixed-point integers. For example, `Mid Price` `109748000000000000000` equals `109.748` USD. `Contract Month` `12` is December, and `Market Status` `2` means the market is open. +The prices above are 18-decimal fixed-point integers. For example, `Mid Price` `109741000000000000000` equals `109.741` USD. `Contract Month` `12` is December, and `Market Status` `1` means the market is closed. ### Decoded fields diff --git a/src/content/data-streams/rwa-streams/futures.mdx b/src/content/data-streams/rwa-streams/futures.mdx index 30ed12fa37e..18f60371c81 100644 --- a/src/content/data-streams/rwa-streams/futures.mdx +++ b/src/content/data-streams/rwa-streams/futures.mdx @@ -104,28 +104,28 @@ The examples below fetch and decode a live `NY-UKOIL/USD` front feed from the te Running any of the examples above against a live `NY-UKOIL/USD` front feed produces a decoded report similar to the following (values are illustrative and change with each report): ```text -Decoded V14 Report for Stream ID 0x000e4b991d02aa6ce023f80f6fdebd8ec5039f9d2b184ffcc7bd3fc4a3ed2a9d: +Decoded V14 Report for Stream ID 0x000eaf52614042ff33b2726b0d9c5db032fc816d4a215bd823d9385662afd57d: ------------------------------------------ -Valid From Timestamp : 1792614089 -Observations Timestamp: 1792614089 -Native Fee : 128559788905831 -LINK Fee : 25306002187814827 -Expires At : 1795206089 -Mid Price : 109748000000000000000 -Bid Price : 109733000000000000000 -Ask Price : 109763000000000000000 +Valid From Timestamp : 1792619840 +Observations Timestamp: 1792619840 +Native Fee : 128232412751773 +LINK Fee : 25280896962790859 +Expires At : 1795211840 +Mid Price : 109741000000000000000 +Bid Price : 109716000000000000000 +Ask Price : 109766000000000000000 Expiry Time : 1793332800 First Day of Notice : 1793332800 -Last Seen TimestampNs : 1792614081347000000 -Market Status : 2 +Last Seen TimestampNs : 1792619593886000000 +Market Status : 1 Contract Month : 12 -Goldman Roll Price : 105806666666666660000 +Goldman Roll Price : 105740000000000000000 Current Business Day : 15 -Interp Goldman Roll : 105806666666666660000 +Interp Goldman Roll : 105740000000000000000 ------------------------------------------ ``` -The prices above are 18-decimal fixed-point integers. For example, `Mid Price` `109748000000000000000` equals `109.748` USD. `Contract Month` `12` is December, and `Market Status` `2` means the market is open. +The prices above are 18-decimal fixed-point integers. For example, `Mid Price` `109741000000000000000` equals `109.741` USD. `Contract Month` `12` is December, and `Market Status` `1` means the market is closed. ### Decoded fields From 73bd00f42e0a15c37c27449d02b6cb7101481db0 Mon Sep 17 00:00:00 2001 From: devin distefano Date: Wed, 21 Oct 2026 17:18:40 -0500 Subject: [PATCH 16/19] update market hours considerations --- src/content/data-streams/llms-full.txt | 20 +++++++++---------- src/content/data-streams/market-hours.mdx | 6 +++--- .../data-streams/rwa-streams/futures.mdx | 14 ++++++------- 3 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index 987cd7387c5..ad7de88f189 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -1092,9 +1092,9 @@ This page covers trading schedules and `marketStatus` value mappings for each Ch | [**FX Majors**](#forex-precious-metals-and-commodities)(G10 + KRW, SGD, HKD, CNH …) | **17:00 Sun** | **17:00 Fri** | None | Jan 1, Dec 25 | | [**Precious Metals Spot**](#forex-precious-metals-and-commodities)(XAU, XAG) | **18:00 Sun** | **17:00 Fri** | 17:00–18:00 Mon–Thu | Major US holidays ([early closures](#precious-metals-early-closures)); Jan 1, Good Fri, Dec 25 | | [**Commodities**](#forex-precious-metals-and-commodities)(WTI Synthetic Spot) | **18:00 Sun** | **17:00 Fri** | 17:00–18:00 Mon–Thu | [NYMEX holiday calendar](https://www.cmegroup.com/tools-information/holiday-calendar/) | -| [**Futures (v14)**](#futures-v14)(US Oil, UK Oil, Natural Gas) | Per listing exchange | Per listing exchange | Scheduled daily break | Exchange holiday calendar | +| [**Futures (v14)**](#futures-v14)(US Oil, UK Oil, Natural Gas) | Per underlying market | Per underlying market | Scheduled daily break | Underlying market holidays | -US Equities, FX Majors, Precious Metals Spot, and Commodities times are **ET (Eastern Time)** and follow US daylight saving time. APAC Equities times are **local exchange time**. Futures schedules are set by the exchange where the underlying contract is listed. Early closes may apply on major US holidays for Precious Metals Spot — see [Precious Metals Spot early closures](#precious-metals-early-closures). +US Equities, FX Majors, Precious Metals Spot, and Commodities times are **ET (Eastern Time)** and follow US daylight saving time. APAC Equities times are **local exchange time**. Futures schedules follow the underlying market. Early closes may apply on major US holidays for Precious Metals Spot — see [Precious Metals Spot early closures](#precious-metals-early-closures). *** @@ -1206,7 +1206,7 @@ On major US holidays, Precious Metals Spot markets may close early instead of at ## Futures (v14) -Futures streams follow commodity market hours for the underlying contract, with a scheduled break each trading day. Holidays and early closes follow the calendar of the exchange where the contract is listed. +Futures streams follow the trading hours of the underlying contract, with a scheduled break each trading day. Holidays and early closes follow the underlying market's calendar. | Value | Status | Description | | ----- | ----------- | ---------------------------------- | @@ -7967,7 +7967,7 @@ The v14 report decodes to the following fields. Prices are 18-decimal fixed-poin Futures streams differ from spot streams in a few ways that affect how you consume them: -- **Gate trading with `marketStatus`.** `marketStatus` is the authoritative signal for whether the market is open. Do not infer market state from `lastSeenTimestampNs` or other timestamps; they only indicate when data was last recorded. See [Market Hours](/data-streams/market-hours) for the value mapping per feed. +- **Gate trading with `marketStatus`.** Use `marketStatus` to decide whether the underlying market is open: `2` = Open, `1` = Closed, `0` = unknown. Treat `0` as not open, and do not infer market state from `lastSeenTimestampNs` or expected session hours. The mapping is the same for every v14 futures feed; see [Market Hours](/data-streams/market-hours#futures-v14). - **Monitor `lastSeenTimestampNs` for staleness.** Futures are sourced from a single underlying provider per feed. If updates stop arriving, the price can go stale without an obvious price change. Pause trading or restrict liquidations when the timestamp lags your freshness threshold. - **Expect a price discontinuity at each roll.** When the front contract expires, the feed re-maps to the next contract, which can trade at a different price. Do not treat this step as a data error. If your application needs a smooth series, build it from the continuous roll fields (`goldmanRollPrice`, `interpolatedGoldmanRollPrice`) or construct your own off-chain. - **Do not hardcode contract-month spacing.** The gap between the contracts tracked by consecutive feeds varies by instrument (one month for energy, wider for precious metals). Read `contractMonth` from the report rather than assuming monthly spacing. @@ -8062,7 +8062,7 @@ Futures streams currently cover US Oil, UK Oil, and Natural Gas. Additional comm Feed names follow the instrument name as it appears in the available streams table (for example, "NY USOIL," "NY UK OIL," and "NatGas"). Naming may change as coverage expands. -Contract specifications — contract size, tick size, quotation units, and similar terms — can vary between exchanges for the same underlying instrument. Chainlink does not publish these specifications, since they belong to the exchange where a given contract is listed. If your application needs exact contract specifications, consult that exchange's own public product documentation directly. +Contract specifications such as contract size, tick size, and quotation units vary by contract and are outside the scope of these streams. If your application needs exact contract specifications, source them independently. ## Rotation methodology @@ -8091,8 +8091,8 @@ When the front contract reaches its expiration, the front feed re-maps to the ne A few properties of the roll are worth calling out explicitly: -- **The roll is triggered by the front contract's expiration**, as defined by the listed expiration calendar for that specific instrument. Expiration conventions differ by instrument, so rolls for different instruments happen on different dates — there is no single "roll day" across all instruments. -- **The switch happens immediately after the primary exchange's trading session closes** on the expiration date. For these commodities, that is typically around 17:00 ET. +- **The roll is triggered by the front contract's expiration**, which the feed reports in `expiryTime`. Expiration conventions differ by instrument, so rolls for different instruments happen on different dates — there is no single "roll day" across all instruments. +- **The switch happens after the underlying market's trading session closes** on the expiration date. Exact timing follows that market's schedule. - **The roll re-maps the feed.** At the moment of the roll, the front feed switches from quoting the expiring contract to quoting the next eligible contract. Because different contract months can trade at different prices, **expect a price discontinuity on the generic feed at each roll**. Feeds are not back-adjusted into a smooth continuous series. If your application needs a continuous series, construct it from the raw generic feeds on your end. - **Until expiration, the front feed continues to track the expiring contract**, even in its final days when liquidity has typically already migrated to the next contract. This is why later feeds are being added: so you can implement your own liquidity-based rolls ahead of expiry instead of holding the front contract to the end. @@ -8127,13 +8127,11 @@ When the September contract expires, the front feed moves to October, the second - **Do not hardcode contract-month assumptions.** The spacing between the feeds available for an instrument varies by instrument: one month for energy, up to a few months for precious metals. - **Expect price steps at rolls.** A protocol using the front feed directly for margining or liquidation should either accept the step as economically correct (the front contract genuinely changed), roll early to a later feed when one is available, or build an adjusted continuous series off-chain from the raw generic feeds. - **Roll early to avoid volatility near expiry.** In the final days of a contract's life, trading volume typically migrates to the next contract while the front feed still tracks the expiring one. Thin liquidity in the expiring contract can increase price volatility, which may unexpectedly trigger perpetual trades, liquidations, or other price-sensitive logic. If your application is sensitive to this, consider rolling ahead of expiry to a later feed when one is available. -- **Follow the listed expiration calendar.** Expiration dates follow the official listed calendar of the exchange where the underlying contract trades, including holiday adjustments. Consult that exchange for the operative source of truth. +- **Use the expirations reported in the feed.** Take `expiryTime` and `firstDayOfNotice` from the report as the operative values, including any holiday-adjusted dates reflected in the data. ## Trading hours -Futures streams follow commodity market hours, with a scheduled break each trading day. Trading hours and holiday schedules are set by the exchange where the underlying contract is listed. - -Each feed's `marketStatus` field reflects the current market status for that instrument. For the value mapping and generic commodity schedule, see [Market Hours](/data-streams/market-hours#futures-v14). +Futures streams follow the trading hours of the underlying market, with a scheduled break each trading day. Because schedules can change, each feed's `marketStatus` field reflects the current status for that instrument. Use it in each report rather than an expected session schedule. For the value mapping, see [Market Hours](/data-streams/market-hours#futures-v14). ## Risk considerations diff --git a/src/content/data-streams/market-hours.mdx b/src/content/data-streams/market-hours.mdx index a89c065115a..8773158d822 100644 --- a/src/content/data-streams/market-hours.mdx +++ b/src/content/data-streams/market-hours.mdx @@ -55,9 +55,9 @@ This page covers trading schedules and `marketStatus` value mappings for each Ch | [**FX Majors**](#forex-precious-metals-and-commodities)
(G10 + KRW, SGD, HKD, CNH …) | **17:00 Sun** | **17:00 Fri** | None | Jan 1, Dec 25 | | [**Precious Metals Spot**](#forex-precious-metals-and-commodities)
(XAU, XAG) | **18:00 Sun** | **17:00 Fri** | 17:00–18:00 Mon–Thu | Major US holidays ([early closures](#precious-metals-early-closures)); Jan 1, Good Fri, Dec 25 | | [**Commodities**](#forex-precious-metals-and-commodities)
(WTI Synthetic Spot) | **18:00 Sun** | **17:00 Fri** | 17:00–18:00 Mon–Thu | [NYMEX holiday calendar](https://www.cmegroup.com/tools-information/holiday-calendar/) | -| [**Futures (v14)**](#futures-v14)
(US Oil, UK Oil, Natural Gas) | Per listing exchange | Per listing exchange | Scheduled daily break | Exchange holiday calendar | +| [**Futures (v14)**](#futures-v14)
(US Oil, UK Oil, Natural Gas) | Per underlying market | Per underlying market | Scheduled daily break | Underlying market holidays | -US Equities, FX Majors, Precious Metals Spot, and Commodities times are **ET (Eastern Time)** and follow US daylight saving time. APAC Equities times are **local exchange time**. Futures schedules are set by the exchange where the underlying contract is listed. Early closes may apply on major US holidays for Precious Metals Spot — see [Precious Metals Spot early closures](#precious-metals-early-closures). +US Equities, FX Majors, Precious Metals Spot, and Commodities times are **ET (Eastern Time)** and follow US daylight saving time. APAC Equities times are **local exchange time**. Futures schedules follow the underlying market. Early closes may apply on major US holidays for Precious Metals Spot — see [Precious Metals Spot early closures](#precious-metals-early-closures). --- @@ -169,7 +169,7 @@ On major US holidays, Precious Metals Spot markets may close early instead of at ## Futures (v14) -Futures streams follow commodity market hours for the underlying contract, with a scheduled break each trading day. Holidays and early closes follow the calendar of the exchange where the contract is listed. +Futures streams follow the trading hours of the underlying contract, with a scheduled break each trading day. Holidays and early closes follow the underlying market's calendar. | Value | Status | Description | | ----- | ----------- | ---------------------------------- | diff --git a/src/content/data-streams/rwa-streams/futures.mdx b/src/content/data-streams/rwa-streams/futures.mdx index 18f60371c81..b638b8a6264 100644 --- a/src/content/data-streams/rwa-streams/futures.mdx +++ b/src/content/data-streams/rwa-streams/futures.mdx @@ -147,7 +147,7 @@ The v14 report decodes to the following fields. Prices are 18-decimal fixed-poin Futures streams differ from spot streams in a few ways that affect how you consume them: -- **Gate trading with `marketStatus`.** `marketStatus` is the authoritative signal for whether the market is open. Do not infer market state from `lastSeenTimestampNs` or other timestamps; they only indicate when data was last recorded. See [Market Hours](/data-streams/market-hours) for the value mapping per feed. +- **Gate trading with `marketStatus`.** Use `marketStatus` to decide whether the underlying market is open: `2` = Open, `1` = Closed, `0` = unknown. Treat `0` as not open, and do not infer market state from `lastSeenTimestampNs` or expected session hours. The mapping is the same for every v14 futures feed; see [Market Hours](/data-streams/market-hours#futures-v14). - **Monitor `lastSeenTimestampNs` for staleness.** Futures are sourced from a single underlying provider per feed. If updates stop arriving, the price can go stale without an obvious price change. Pause trading or restrict liquidations when the timestamp lags your freshness threshold. - **Expect a price discontinuity at each roll.** When the front contract expires, the feed re-maps to the next contract, which can trade at a different price. Do not treat this step as a data error. If your application needs a smooth series, build it from the continuous roll fields (`goldmanRollPrice`, `interpolatedGoldmanRollPrice`) or construct your own off-chain. - **Do not hardcode contract-month spacing.** The gap between the contracts tracked by consecutive feeds varies by instrument (one month for energy, wider for precious metals). Read `contractMonth` from the report rather than assuming monthly spacing. @@ -249,7 +249,7 @@ Futures streams currently cover US Oil, UK Oil, and Natural Gas. Additional comm Feed names follow the instrument name as it appears in the available streams table (for example, "NY USOIL," "NY UK OIL," and "NatGas"). Naming may change as coverage expands. -Contract specifications — contract size, tick size, quotation units, and similar terms — can vary between exchanges for the same underlying instrument. Chainlink does not publish these specifications, since they belong to the exchange where a given contract is listed. If your application needs exact contract specifications, consult that exchange's own public product documentation directly. +Contract specifications such as contract size, tick size, and quotation units vary by contract and are outside the scope of these streams. If your application needs exact contract specifications, source them independently. ## Rotation methodology @@ -278,8 +278,8 @@ When the front contract reaches its expiration, the front feed re-maps to the ne A few properties of the roll are worth calling out explicitly: -- **The roll is triggered by the front contract's expiration**, as defined by the listed expiration calendar for that specific instrument. Expiration conventions differ by instrument, so rolls for different instruments happen on different dates — there is no single "roll day" across all instruments. -- **The switch happens immediately after the primary exchange's trading session closes** on the expiration date. For these commodities, that is typically around 17:00 ET. +- **The roll is triggered by the front contract's expiration**, which the feed reports in `expiryTime`. Expiration conventions differ by instrument, so rolls for different instruments happen on different dates — there is no single "roll day" across all instruments. +- **The switch happens after the underlying market's trading session closes** on the expiration date. Exact timing follows that market's schedule. - **The roll re-maps the feed.** At the moment of the roll, the front feed switches from quoting the expiring contract to quoting the next eligible contract. Because different contract months can trade at different prices, **expect a price discontinuity on the generic feed at each roll**. Feeds are not back-adjusted into a smooth continuous series. If your application needs a continuous series, construct it from the raw generic feeds on your end. - **Until expiration, the front feed continues to track the expiring contract**, even in its final days when liquidity has typically already migrated to the next contract. This is why later feeds are being added: so you can implement your own liquidity-based rolls ahead of expiry instead of holding the front contract to the end. @@ -314,13 +314,11 @@ When the September contract expires, the front feed moves to October, the second - **Do not hardcode contract-month assumptions.** The spacing between the feeds available for an instrument varies by instrument: one month for energy, up to a few months for precious metals. - **Expect price steps at rolls.** A protocol using the front feed directly for margining or liquidation should either accept the step as economically correct (the front contract genuinely changed), roll early to a later feed when one is available, or build an adjusted continuous series off-chain from the raw generic feeds. - **Roll early to avoid volatility near expiry.** In the final days of a contract's life, trading volume typically migrates to the next contract while the front feed still tracks the expiring one. Thin liquidity in the expiring contract can increase price volatility, which may unexpectedly trigger perpetual trades, liquidations, or other price-sensitive logic. If your application is sensitive to this, consider rolling ahead of expiry to a later feed when one is available. -- **Follow the listed expiration calendar.** Expiration dates follow the official listed calendar of the exchange where the underlying contract trades, including holiday adjustments. Consult that exchange for the operative source of truth. +- **Use the expirations reported in the feed.** Take `expiryTime` and `firstDayOfNotice` from the report as the operative values, including any holiday-adjusted dates reflected in the data. ## Trading hours -Futures streams follow commodity market hours, with a scheduled break each trading day. Trading hours and holiday schedules are set by the exchange where the underlying contract is listed. - -Each feed's `marketStatus` field reflects the current market status for that instrument. For the value mapping and generic commodity schedule, see [Market Hours](/data-streams/market-hours#futures-v14). +Futures streams follow the trading hours of the underlying market, with a scheduled break each trading day. Because schedules can change, each feed's `marketStatus` field reflects the current status for that instrument. Use it in each report rather than an expected session schedule. For the value mapping, see [Market Hours](/data-streams/market-hours#futures-v14). ## Risk considerations From 59d4c1d38a3f7b52bb4c03eb46c5d15f76f4488b Mon Sep 17 00:00:00 2001 From: devin distefano Date: Wed, 21 Oct 2026 17:25:46 -0500 Subject: [PATCH 17/19] revert changes back to sebastin's og copy --- src/content/data-streams/llms-full.txt | 4 ++-- src/content/data-streams/rwa-streams/futures.mdx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index ad7de88f189..22c2a4f6693 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -8092,7 +8092,7 @@ When the front contract reaches its expiration, the front feed re-maps to the ne A few properties of the roll are worth calling out explicitly: - **The roll is triggered by the front contract's expiration**, which the feed reports in `expiryTime`. Expiration conventions differ by instrument, so rolls for different instruments happen on different dates — there is no single "roll day" across all instruments. -- **The switch happens after the underlying market's trading session closes** on the expiration date. Exact timing follows that market's schedule. +- **The switch happens after the underlying market's trading session closes** on the expiration date. For these commodities, that is often around 5:00 PM ET. - **The roll re-maps the feed.** At the moment of the roll, the front feed switches from quoting the expiring contract to quoting the next eligible contract. Because different contract months can trade at different prices, **expect a price discontinuity on the generic feed at each roll**. Feeds are not back-adjusted into a smooth continuous series. If your application needs a continuous series, construct it from the raw generic feeds on your end. - **Until expiration, the front feed continues to track the expiring contract**, even in its final days when liquidity has typically already migrated to the next contract. This is why later feeds are being added: so you can implement your own liquidity-based rolls ahead of expiry instead of holding the front contract to the end. @@ -8139,7 +8139,7 @@ Integrating protocols are responsible for implementing appropriate monitoring an ### Single-source data -Each Futures instrument is sourced from a single underlying institutional-grade data provider per feed. The Data Streams DON operators all source from that same provider, so there is no redundant cross-validation between independent providers for a given feed. While this enables high-frequency, low-latency delivery, it introduces dependency on that provider's data quality and availability. +Each Futures instrument is sourced from a single institutional-grade data provider per feed. While this enables high-frequency, low-latency delivery, it introduces dependency on that provider's data quality and availability. There is no redundant cross-validation between providers for a given feed. If the underlying provider fails to deliver data, there is no fallback source, and a gap in data may not be immediately obvious from price alone. Protocols should continuously monitor feed freshness and implement safeguards — such as pausing trading or restricting liquidations — if updates stop arriving or a feed appears stale. Review the [Developer Responsibilities](/data-streams/developer-responsibilities) guidance before integration. diff --git a/src/content/data-streams/rwa-streams/futures.mdx b/src/content/data-streams/rwa-streams/futures.mdx index b638b8a6264..2236b246c5c 100644 --- a/src/content/data-streams/rwa-streams/futures.mdx +++ b/src/content/data-streams/rwa-streams/futures.mdx @@ -279,7 +279,7 @@ When the front contract reaches its expiration, the front feed re-maps to the ne A few properties of the roll are worth calling out explicitly: - **The roll is triggered by the front contract's expiration**, which the feed reports in `expiryTime`. Expiration conventions differ by instrument, so rolls for different instruments happen on different dates — there is no single "roll day" across all instruments. -- **The switch happens after the underlying market's trading session closes** on the expiration date. Exact timing follows that market's schedule. +- **The switch happens after the underlying market's trading session closes** on the expiration date. For these commodities, that is often around 5:00 PM ET. - **The roll re-maps the feed.** At the moment of the roll, the front feed switches from quoting the expiring contract to quoting the next eligible contract. Because different contract months can trade at different prices, **expect a price discontinuity on the generic feed at each roll**. Feeds are not back-adjusted into a smooth continuous series. If your application needs a continuous series, construct it from the raw generic feeds on your end. - **Until expiration, the front feed continues to track the expiring contract**, even in its final days when liquidity has typically already migrated to the next contract. This is why later feeds are being added: so you can implement your own liquidity-based rolls ahead of expiry instead of holding the front contract to the end. @@ -326,7 +326,7 @@ Integrating protocols are responsible for implementing appropriate monitoring an ### Single-source data -Each Futures instrument is sourced from a single underlying institutional-grade data provider per feed. The Data Streams DON operators all source from that same provider, so there is no redundant cross-validation between independent providers for a given feed. While this enables high-frequency, low-latency delivery, it introduces dependency on that provider's data quality and availability. +Each Futures instrument is sourced from a single institutional-grade data provider per feed. While this enables high-frequency, low-latency delivery, it introduces dependency on that provider's data quality and availability. There is no redundant cross-validation between providers for a given feed. If the underlying provider fails to deliver data, there is no fallback source, and a gap in data may not be immediately obvious from price alone. Protocols should continuously monitor feed freshness and implement safeguards — such as pausing trading or restricting liquidations — if updates stop arriving or a feed appears stale. Review the [Developer Responsibilities](/data-streams/developer-responsibilities) guidance before integration. From bdf71d003da469e8b8b22c0ae864a38a311eb95f Mon Sep 17 00:00:00 2001 From: devin distefano Date: Thu, 22 Oct 2026 12:05:53 -0500 Subject: [PATCH 18/19] review updates --- src/content/data-streams/llms-full.txt | 55 ++++++++++--------- .../reference/report-schema-v14.mdx | 16 +++--- .../data-streams/rwa-streams/futures.mdx | 39 +++++++------ 3 files changed, 58 insertions(+), 52 deletions(-) diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index 22c2a4f6693..682f14ccc1f 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -6805,7 +6805,7 @@ Chainlink Data Streams that use the Futures (v14) schema adhere to the structure > `observationsTimestamp`, `lastSeenTimestampNs`, or other timestamp fields — timestamps indicate > when data was last recorded, not whether the market is currently active. -Each feed's `marketStatus` field reflects the current market status of the primary exchange venue for that instrument. Futures trade during standard trading hours for each instrument, with a scheduled break each trading day. Consult the exchange where the underlying contract is listed for holiday and early-close schedules. +Each feed's `marketStatus` field reflects the current market status for that instrument. Futures streams follow the trading hours of the underlying market, with a scheduled break each trading day. Use `marketStatus` in each report rather than an expected session schedule. For full trading schedules and `marketStatus` mappings, see [Market Hours](/data-streams/market-hours) and the [Futures](/data-streams/rwa-streams/futures) reference. @@ -6813,11 +6813,11 @@ For full trading schedules and `marketStatus` mappings, see [Market Hours](/data In addition to the raw generic feed prices — which switch entirely to the next contract when the front contract expires — the v14 schema includes continuous price series built using alternative rolling methodologies, for integrators who want a smoothed price instead of a hard cutover: -| Field | Description | -| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `goldmanRollPrice` | Uses the Goldman Roll (GSCI methodology): shifts 20% of the position to the next contract each business day, over business days 5–9 of the month preceding delivery | -| `interpolatedGoldmanRollPrice` | Interpolated Goldman Roll price, smoothing the roll across the full cycle rather than the fixed Goldman window | -| `currentBusinessDay` | Current business day of the month, used to determine the Goldman Roll window | +| Field | Description | +| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `goldmanRollPrice` | Uses the Goldman Roll (GSCI methodology): shifts 20% of the position to the next contract each business day, over business days 5–9 of the month preceding delivery | +| `interpolatedGoldmanRollPrice` | Interpolated Goldman Roll price: the Goldman Roll's 20% daily shift to the next contract, smoothed over the course of each business day, 5–9, of the month preceding delivery | +| `currentBusinessDay` | Current business day of the month, used to determine the Goldman Roll window | For details on how the generic feeds rotate between contracts and how the continuous roll fields behave, see the [Futures](/data-streams/rwa-streams/futures) reference. @@ -6826,11 +6826,11 @@ For details on how the generic feeds rotate between contracts and how the contin #### `lastSeenTimestampNs` - `lastSeenTimestampNs` helps applications detect stale data, especially important during market transitions and holidays. -- **Do not use `lastSeenTimestampNs` (or any other timestamp field) to determine whether the market is open.** Timestamps indicate when data was last recorded, not whether the market is currently active. Use the `marketStatus` field as the authoritative signal for market availability. +- **Do not use `lastSeenTimestampNs` (or any other timestamp field) to determine whether the market is open.** Timestamps indicate when data was last recorded, not whether the market is currently active. Use the `marketStatus` field to determine market availability. #### `interpolatedGoldmanRollPrice` -`interpolatedGoldmanRollPrice` smooths the roll across the full contract cycle rather than the fixed Goldman window. It is not limited to business days 5–9. +`interpolatedGoldmanRollPrice` is a smoothed version of the Goldman Roll. It applies the 20% daily shift to the next contract over the course of each business day, 5–9, of the month preceding delivery. --- @@ -7671,11 +7671,11 @@ The v14 schema includes consensus mid, bid, and ask prices, contract expiration In addition to the raw generic feed prices above — which switch entirely to the next contract when the front contract expires — Chainlink also publishes continuous price series built using alternative rolling methodologies, for integrators who want a smoothed price instead of a hard cutover: -| Field | Description | -| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `goldmanRollPrice` | Uses the Goldman Roll (GSCI methodology): shifts 20% of the position to the next contract each business day, over business days 5–9 of the month preceding delivery | -| `interpolatedGoldmanRollPrice` | Interpolated Goldman Roll price, smoothing the roll across the full cycle rather than the fixed Goldman window | -| `currentBusinessDay` | Current business day of the month, used to determine the Goldman Roll window | +| Field | Description | +| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `goldmanRollPrice` | Uses the Goldman Roll (GSCI methodology): shifts 20% of the position to the next contract each business day, over business days 5–9 of the month preceding delivery | +| `interpolatedGoldmanRollPrice` | Interpolated Goldman Roll price: the Goldman Roll's 20% daily shift to the next contract, smoothed over the course of each business day, 5–9, of the month preceding delivery | +| `currentBusinessDay` | Current business day of the month, used to determine the Goldman Roll window | For the complete field list and definitions, see the [Futures (v14) schema](/data-streams/reference/report-schema-v14). @@ -7951,17 +7951,17 @@ The prices above are 18-decimal fixed-point integers. For example, `Mid Price` ` The v14 report decodes to the following fields. Prices are 18-decimal fixed-point integers; timestamps are Unix epoch seconds unless noted. -| Field | Type | Meaning | -| ---------------------------------- | -------- | --------------------------------------------------------------- | -| `midPrice`, `bidPrice`, `askPrice` | `int192` | Consensus mid, bid, and ask prices (18 decimals) | -| `expiryTime` | `uint64` | Contract expiration, Unix seconds | -| `firstDayOfNotice` | `uint64` | First day of notice, Unix seconds | -| `lastSeenTimestampNs` | `uint64` | Last provider update, nanoseconds | -| `marketStatus` | `uint32` | Market status: `0` Unknown, `1` Closed, `2` Open | -| `contractMonth` | `uint32` | Contract month, `1` (Jan) to `12` (Dec) | -| `goldmanRollPrice` | `int192` | Goldman Roll continuous price (18 decimals) | -| `currentBusinessDay` | `uint32` | Current business day of the month | -| `interpolatedGoldmanRollPrice` | `int192` | Interpolated Goldman Roll price, smoothed across the full cycle | +| Field | Type | Meaning | +| ---------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------ | +| `midPrice`, `bidPrice`, `askPrice` | `int192` | Consensus mid, bid, and ask prices (18 decimals) | +| `expiryTime` | `uint64` | Contract expiration, Unix seconds | +| `firstDayOfNotice` | `uint64` | First day of notice, Unix seconds | +| `lastSeenTimestampNs` | `uint64` | Last provider update, nanoseconds | +| `marketStatus` | `uint32` | Market status: `0` Unknown, `1` Closed, `2` Open | +| `contractMonth` | `uint32` | Contract month, `1` (Jan) to `12` (Dec) | +| `goldmanRollPrice` | `int192` | Goldman Roll continuous price (18 decimals) | +| `currentBusinessDay` | `uint32` | Current business day of the month | +| `interpolatedGoldmanRollPrice` | `int192` | Interpolated Goldman Roll price: the 20% daily shift to the next contract, smoothed over business days 5–9 of the month preceding delivery | ### Implementation patterns @@ -8050,7 +8050,7 @@ for id in feed_ids { ### Notes - **Prices are 18-decimal fixed-point integers.** `midPrice`, `bidPrice`, `askPrice`, `goldmanRollPrice`, and `interpolatedGoldmanRollPrice` are raw integers. Divide by `10^18` to get the human-readable price. In Go and Rust these are big-number types; call `.String()` to display them. -- **`interpolatedGoldmanRollPrice` smooths the roll across the full contract cycle** rather than only the fixed Goldman window, so it is not limited to business days 5–9. +- **`interpolatedGoldmanRollPrice` is a smoothed Goldman Roll.** It applies the same 20% daily shift to the next contract, smoothed over the course of each business day, 5–9, of the month preceding delivery. - **`contractMonth` is validated to `1`–`12`.** The SDKs reject reports with an out-of-range month, so a successful decode guarantees a valid month. - **The feed ID encodes the schema version.** The TypeScript SDK's `getReportVersion` and the Go SDK's `feedID.Version()` derive the schema from the feed ID. Use the v14 decoder for futures feeds. @@ -8102,13 +8102,16 @@ The front feed tracks the nearest unexpired eligible contract, which may not be - **Energy** (US Oil, UK Oil, Natural Gas): every calendar month is listed, though liquidity is generally concentrated in nearer maturities. The generic feeds walk the full monthly strip regardless, so consecutive feeds track **consecutive** calendar months. - **Precious metals** (planned): many calendar months are listed, but liquidity concentrates in a benchmark cycle. When precious metals streams are available, the generic feeds will follow the benchmark cycle only and skip non-benchmark months, even though those contracts exist and trade. +- **Industrial metals** (Copper, Aluminum, planned): listed contracts follow a benchmark cycle. When these streams are available, the generic feeds will follow the benchmark months only and skip non-benchmark months. | Commodity | Benchmark months | | --------- | ---------------------------- | | Gold | Feb, Apr, Jun, Aug, Oct, Dec | | Silver | Mar, May, Jul, Sep, Dec | +| Copper | Mar, May, Jul, Sep, Dec | +| Aluminum | Mar, May, Jul, Sep, Dec | -The practical consequence: **the gap between consecutive feeds is not always one month.** For Gold or Silver, consecutive generic feeds can be one to three months apart. Do not assume monthly spacing in your integration. +The practical consequence: **the gap between consecutive feeds is not always one month.** For Gold, Silver, Copper, or Aluminum, consecutive generic feeds can be one to three months apart. Do not assume monthly spacing in your integration. ### Worked example diff --git a/src/content/data-streams/reference/report-schema-v14.mdx b/src/content/data-streams/reference/report-schema-v14.mdx index 902df63e2f6..c8f89395d15 100644 --- a/src/content/data-streams/reference/report-schema-v14.mdx +++ b/src/content/data-streams/reference/report-schema-v14.mdx @@ -48,7 +48,7 @@ Chainlink Data Streams that use the Futures (v14) schema adhere to the structure when data was last recorded, not whether the market is currently active. -Each feed's `marketStatus` field reflects the current market status of the primary exchange venue for that instrument. Futures trade during standard trading hours for each instrument, with a scheduled break each trading day. Consult the exchange where the underlying contract is listed for holiday and early-close schedules. +Each feed's `marketStatus` field reflects the current market status for that instrument. Futures streams follow the trading hours of the underlying market, with a scheduled break each trading day. Use `marketStatus` in each report rather than an expected session schedule. For full trading schedules and `marketStatus` mappings, see [Market Hours](/data-streams/market-hours) and the [Futures](/data-streams/rwa-streams/futures) reference. @@ -56,11 +56,11 @@ For full trading schedules and `marketStatus` mappings, see [Market Hours](/data In addition to the raw generic feed prices — which switch entirely to the next contract when the front contract expires — the v14 schema includes continuous price series built using alternative rolling methodologies, for integrators who want a smoothed price instead of a hard cutover: -| Field | Description | -| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `goldmanRollPrice` | Uses the Goldman Roll (GSCI methodology): shifts 20% of the position to the next contract each business day, over business days 5–9 of the month preceding delivery | -| `interpolatedGoldmanRollPrice` | Interpolated Goldman Roll price, smoothing the roll across the full cycle rather than the fixed Goldman window | -| `currentBusinessDay` | Current business day of the month, used to determine the Goldman Roll window | +| Field | Description | +| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `goldmanRollPrice` | Uses the Goldman Roll (GSCI methodology): shifts 20% of the position to the next contract each business day, over business days 5–9 of the month preceding delivery | +| `interpolatedGoldmanRollPrice` | Interpolated Goldman Roll price: the Goldman Roll's 20% daily shift to the next contract, smoothed over the course of each business day, 5–9, of the month preceding delivery | +| `currentBusinessDay` | Current business day of the month, used to determine the Goldman Roll window | For details on how the generic feeds rotate between contracts and how the continuous roll fields behave, see the [Futures](/data-streams/rwa-streams/futures) reference. @@ -69,8 +69,8 @@ For details on how the generic feeds rotate between contracts and how the contin #### `lastSeenTimestampNs` - `lastSeenTimestampNs` helps applications detect stale data, especially important during market transitions and holidays. -- **Do not use `lastSeenTimestampNs` (or any other timestamp field) to determine whether the market is open.** Timestamps indicate when data was last recorded, not whether the market is currently active. Use the `marketStatus` field as the authoritative signal for market availability. +- **Do not use `lastSeenTimestampNs` (or any other timestamp field) to determine whether the market is open.** Timestamps indicate when data was last recorded, not whether the market is currently active. Use the `marketStatus` field to determine market availability. #### `interpolatedGoldmanRollPrice` -`interpolatedGoldmanRollPrice` smooths the roll across the full contract cycle rather than the fixed Goldman window. It is not limited to business days 5–9. +`interpolatedGoldmanRollPrice` is a smoothed version of the Goldman Roll. It applies the 20% daily shift to the next contract over the course of each business day, 5–9, of the month preceding delivery. diff --git a/src/content/data-streams/rwa-streams/futures.mdx b/src/content/data-streams/rwa-streams/futures.mdx index 2236b246c5c..9a1ef26b4d2 100644 --- a/src/content/data-streams/rwa-streams/futures.mdx +++ b/src/content/data-streams/rwa-streams/futures.mdx @@ -39,11 +39,11 @@ The v14 schema includes consensus mid, bid, and ask prices, contract expiration In addition to the raw generic feed prices above — which switch entirely to the next contract when the front contract expires — Chainlink also publishes continuous price series built using alternative rolling methodologies, for integrators who want a smoothed price instead of a hard cutover: -| Field | Description | -| ------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `goldmanRollPrice` | Uses the Goldman Roll (GSCI methodology): shifts 20% of the position to the next contract each business day, over business days 5–9 of the month preceding delivery | -| `interpolatedGoldmanRollPrice` | Interpolated Goldman Roll price, smoothing the roll across the full cycle rather than the fixed Goldman window | -| `currentBusinessDay` | Current business day of the month, used to determine the Goldman Roll window | +| Field | Description | +| ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `goldmanRollPrice` | Uses the Goldman Roll (GSCI methodology): shifts 20% of the position to the next contract each business day, over business days 5–9 of the month preceding delivery | +| `interpolatedGoldmanRollPrice` | Interpolated Goldman Roll price: the Goldman Roll's 20% daily shift to the next contract, smoothed over the course of each business day, 5–9, of the month preceding delivery | +| `currentBusinessDay` | Current business day of the month, used to determine the Goldman Roll window | For the complete field list and definitions, see the [Futures (v14) schema](/data-streams/reference/report-schema-v14). @@ -131,17 +131,17 @@ The prices above are 18-decimal fixed-point integers. For example, `Mid Price` ` The v14 report decodes to the following fields. Prices are 18-decimal fixed-point integers; timestamps are Unix epoch seconds unless noted. -| Field | Type | Meaning | -| ---------------------------------- | -------- | --------------------------------------------------------------- | -| `midPrice`, `bidPrice`, `askPrice` | `int192` | Consensus mid, bid, and ask prices (18 decimals) | -| `expiryTime` | `uint64` | Contract expiration, Unix seconds | -| `firstDayOfNotice` | `uint64` | First day of notice, Unix seconds | -| `lastSeenTimestampNs` | `uint64` | Last provider update, nanoseconds | -| `marketStatus` | `uint32` | Market status: `0` Unknown, `1` Closed, `2` Open | -| `contractMonth` | `uint32` | Contract month, `1` (Jan) to `12` (Dec) | -| `goldmanRollPrice` | `int192` | Goldman Roll continuous price (18 decimals) | -| `currentBusinessDay` | `uint32` | Current business day of the month | -| `interpolatedGoldmanRollPrice` | `int192` | Interpolated Goldman Roll price, smoothed across the full cycle | +| Field | Type | Meaning | +| ---------------------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------ | +| `midPrice`, `bidPrice`, `askPrice` | `int192` | Consensus mid, bid, and ask prices (18 decimals) | +| `expiryTime` | `uint64` | Contract expiration, Unix seconds | +| `firstDayOfNotice` | `uint64` | First day of notice, Unix seconds | +| `lastSeenTimestampNs` | `uint64` | Last provider update, nanoseconds | +| `marketStatus` | `uint32` | Market status: `0` Unknown, `1` Closed, `2` Open | +| `contractMonth` | `uint32` | Contract month, `1` (Jan) to `12` (Dec) | +| `goldmanRollPrice` | `int192` | Goldman Roll continuous price (18 decimals) | +| `currentBusinessDay` | `uint32` | Current business day of the month | +| `interpolatedGoldmanRollPrice` | `int192` | Interpolated Goldman Roll price: the 20% daily shift to the next contract, smoothed over business days 5–9 of the month preceding delivery | ### Implementation patterns @@ -237,7 +237,7 @@ The example below fetches all three feeds for an instrument once they are availa ### Notes - **Prices are 18-decimal fixed-point integers.** `midPrice`, `bidPrice`, `askPrice`, `goldmanRollPrice`, and `interpolatedGoldmanRollPrice` are raw integers. Divide by `10^18` to get the human-readable price. In Go and Rust these are big-number types; call `.String()` to display them. -- **`interpolatedGoldmanRollPrice` smooths the roll across the full contract cycle** rather than only the fixed Goldman window, so it is not limited to business days 5–9. +- **`interpolatedGoldmanRollPrice` is a smoothed Goldman Roll.** It applies the same 20% daily shift to the next contract, smoothed over the course of each business day, 5–9, of the month preceding delivery. - **`contractMonth` is validated to `1`–`12`.** The SDKs reject reports with an out-of-range month, so a successful decode guarantees a valid month. - **The feed ID encodes the schema version.** The TypeScript SDK's `getReportVersion` and the Go SDK's `feedID.Version()` derive the schema from the feed ID. Use the v14 decoder for futures feeds. @@ -289,13 +289,16 @@ The front feed tracks the nearest unexpired eligible contract, which may not be - **Energy** (US Oil, UK Oil, Natural Gas): every calendar month is listed, though liquidity is generally concentrated in nearer maturities. The generic feeds walk the full monthly strip regardless, so consecutive feeds track **consecutive** calendar months. - **Precious metals** (planned): many calendar months are listed, but liquidity concentrates in a benchmark cycle. When precious metals streams are available, the generic feeds will follow the benchmark cycle only and skip non-benchmark months, even though those contracts exist and trade. +- **Industrial metals** (Copper, Aluminum, planned): listed contracts follow a benchmark cycle. When these streams are available, the generic feeds will follow the benchmark months only and skip non-benchmark months. | Commodity | Benchmark months | | --------- | ---------------------------- | | Gold | Feb, Apr, Jun, Aug, Oct, Dec | | Silver | Mar, May, Jul, Sep, Dec | +| Copper | Mar, May, Jul, Sep, Dec | +| Aluminum | Mar, May, Jul, Sep, Dec | -The practical consequence: **the gap between consecutive feeds is not always one month.** For Gold or Silver, consecutive generic feeds can be one to three months apart. Do not assume monthly spacing in your integration. +The practical consequence: **the gap between consecutive feeds is not always one month.** For Gold, Silver, Copper, or Aluminum, consecutive generic feeds can be one to three months apart. Do not assume monthly spacing in your integration. ### Worked example From 51411b2e0a5749e2ba6d3bbb0a5696cd07cabc68 Mon Sep 17 00:00:00 2001 From: devin distefano Date: Thu, 22 Oct 2026 16:55:16 -0500 Subject: [PATCH 19/19] goldeman fix --- src/content/data-streams/llms-full.txt | 18 +++++++++--------- .../reference/report-schema-overview.mdx | 6 +++--- .../reference/report-schema-v14.mdx | 2 +- .../data-streams/rwa-streams/futures.mdx | 6 +++--- .../feeds/components/reportSchemaData.ts | 5 +++-- 5 files changed, 19 insertions(+), 18 deletions(-) diff --git a/src/content/data-streams/llms-full.txt b/src/content/data-streams/llms-full.txt index 682f14ccc1f..7ede8b3bbf0 100644 --- a/src/content/data-streams/llms-full.txt +++ b/src/content/data-streams/llms-full.txt @@ -6505,7 +6505,7 @@ Real-world asset prices (multiple price points and enhanced market data) [Futures (v14)](/data-streams/reference/report-schema-v14) -Futures price data with continuous roll price series +Futures price data with Goldman Roll price fields `midPrice`, `bidPrice`, `askPrice`, `expiryTime`, `contractMonth`, `goldmanRollPrice`, `marketStatus` @@ -6563,7 +6563,7 @@ While the Data Streams architecture is designed to deliver updates at least once - **[RWA Standard (v8)](/data-streams/reference/report-schema-v8)** — standard RWA format with consolidated mid price, market status, and freshness indicators. Used by the majority of RWA streams. - **[RWA Advanced (v11)](/data-streams/reference/report-schema-v11)** — adds bid/ask prices, volume depth, last traded price where supported, nanosecond-precision timestamps, and expanded market status values. Supports extended trading sessions where applicable. -- **[Futures (v14)](/data-streams/reference/report-schema-v14)** — futures price data with contract expiration, market status, and continuous roll price series. Used by [Futures streams](/data-streams/rwa-streams/futures). +- **[Futures (v14)](/data-streams/reference/report-schema-v14)** — futures price data with contract expiration, market status, and Goldman Roll price fields. Used by [Futures streams](/data-streams/rwa-streams/futures). ### RWA Standard (v8) @@ -6583,7 +6583,7 @@ These advanced fields enable protocols to implement more sophisticated risk mana The [Futures (v14)](/data-streams/reference/report-schema-v14) report schema provides price data for exchange-traded futures contracts. Each report includes consensus mid, bid, and ask prices (`midPrice`, `bidPrice`, `askPrice`), contract expiration (`expiryTime`), the first day of notice (`firstDayOfNotice`), the tracked contract month (`contractMonth`), market status (`marketStatus`), and a staleness measure (`lastSeenTimestampNs`). -Because futures contracts expire, streams using this schema expose three **generic** feeds per instrument that always track the current front, second, and third contract. The schema also includes continuous roll price series — `goldmanRollPrice`, `interpolatedGoldmanRollPrice`, and `currentBusinessDay` — for integrators who want a smoothed price instead of a hard cutover at contract expiration. See the [Futures](/data-streams/rwa-streams/futures) reference for rotation methodology and the [Futures (v14) reference](/data-streams/reference/report-schema-v14) for complete field specifications. +Because futures contracts expire, streams using this schema expose three **generic** feeds per instrument that always track the current front, second, and third contract. The schema also includes Goldman Roll price fields — `goldmanRollPrice`, `interpolatedGoldmanRollPrice`, and `currentBusinessDay` — for integrators who want a smoothed price instead of a hard cutover at contract expiration. See the [Futures](/data-streams/rwa-streams/futures) reference for rotation methodology and the [Futures (v14) reference](/data-streams/reference/report-schema-v14) for complete field specifications. ## SmartData @@ -6793,9 +6793,9 @@ Chainlink Data Streams that use the Futures (v14) schema adhere to the structure | `lastSeenTimestampNs` | `uint64` | Timestamp of the last update received from the data provider (nanoseconds) | | `marketStatus` | `uint32` | Market status. Mapping varies by feed; see schema docs. — [Status values](/data-streams/reference/report-schema-v14#market-status-values) | | `contractMonth` | `uint32` | Contract month, from 1 (Jan) to 12 (Dec) | -| `goldmanRollPrice` | `int192` | Continuous price using the Goldman Roll (GSCI) methodology | +| `goldmanRollPrice` | `int192` | Goldman Roll price (GSCI methodology; 20% shifted per business day over days 5–9) | | `currentBusinessDay` | `uint32` | Current business day of the month, used to determine the Goldman Roll window | -| `interpolatedGoldmanRollPrice` | `int192` | Interpolated Goldman Roll price, smoothed across the full contract cycle | +| `interpolatedGoldmanRollPrice` | `int192` | Interpolated Goldman Roll price: the 20% daily shift to the next contract, smoothed over each business day in the 5–9 window | ### Market Status Values @@ -6819,7 +6819,7 @@ In addition to the raw generic feed prices — which switch entirely to the next | `interpolatedGoldmanRollPrice` | Interpolated Goldman Roll price: the Goldman Roll's 20% daily shift to the next contract, smoothed over the course of each business day, 5–9, of the month preceding delivery | | `currentBusinessDay` | Current business day of the month, used to determine the Goldman Roll window | -For details on how the generic feeds rotate between contracts and how the continuous roll fields behave, see the [Futures](/data-streams/rwa-streams/futures) reference. +For details on how the generic feeds rotate between contracts and how the Goldman Roll fields behave, see the [Futures](/data-streams/rwa-streams/futures) reference. ### Notes @@ -7665,7 +7665,7 @@ Developers are responsible for choosing the appropriate feed and ensuring that t Futures streams use the [Futures (v14) schema](/data-streams/reference/report-schema-v14). -The v14 schema includes consensus mid, bid, and ask prices, contract expiration and first day of notice, the tracked contract month, market status, and a staleness measure. It also includes continuous roll price fields — `goldmanRollPrice`, `interpolatedGoldmanRollPrice`, and `currentBusinessDay` — described below. +The v14 schema includes consensus mid, bid, and ask prices, contract expiration and first day of notice, the tracked contract month, market status, and a staleness measure. It also includes Goldman Roll price fields — `goldmanRollPrice`, `interpolatedGoldmanRollPrice`, and `currentBusinessDay` — described below. ### Continuous roll price fields @@ -7959,7 +7959,7 @@ The v14 report decodes to the following fields. Prices are 18-decimal fixed-poin | `lastSeenTimestampNs` | `uint64` | Last provider update, nanoseconds | | `marketStatus` | `uint32` | Market status: `0` Unknown, `1` Closed, `2` Open | | `contractMonth` | `uint32` | Contract month, `1` (Jan) to `12` (Dec) | -| `goldmanRollPrice` | `int192` | Goldman Roll continuous price (18 decimals) | +| `goldmanRollPrice` | `int192` | Goldman Roll price (18 decimals) | | `currentBusinessDay` | `uint32` | Current business day of the month | | `interpolatedGoldmanRollPrice` | `int192` | Interpolated Goldman Roll price: the 20% daily shift to the next contract, smoothed over business days 5–9 of the month preceding delivery | @@ -7969,7 +7969,7 @@ Futures streams differ from spot streams in a few ways that affect how you consu - **Gate trading with `marketStatus`.** Use `marketStatus` to decide whether the underlying market is open: `2` = Open, `1` = Closed, `0` = unknown. Treat `0` as not open, and do not infer market state from `lastSeenTimestampNs` or expected session hours. The mapping is the same for every v14 futures feed; see [Market Hours](/data-streams/market-hours#futures-v14). - **Monitor `lastSeenTimestampNs` for staleness.** Futures are sourced from a single underlying provider per feed. If updates stop arriving, the price can go stale without an obvious price change. Pause trading or restrict liquidations when the timestamp lags your freshness threshold. -- **Expect a price discontinuity at each roll.** When the front contract expires, the feed re-maps to the next contract, which can trade at a different price. Do not treat this step as a data error. If your application needs a smooth series, build it from the continuous roll fields (`goldmanRollPrice`, `interpolatedGoldmanRollPrice`) or construct your own off-chain. +- **Expect a price discontinuity at each roll.** When the front contract expires, the feed re-maps to the next contract, which can trade at a different price. Do not treat this step as a data error. If your application needs a smooth series, build it from the Goldman Roll fields (`goldmanRollPrice`, `interpolatedGoldmanRollPrice`) or construct your own off-chain. - **Do not hardcode contract-month spacing.** The gap between the contracts tracked by consecutive feeds varies by instrument (one month for energy, wider for precious metals). Read `contractMonth` from the report rather than assuming monthly spacing. - **Roll early if you are expiry-sensitive.** In the final days of a contract, liquidity migrates to the next contract while the front feed still tracks the expiring one, which can increase volatility. If your application is sensitive to this, roll ahead of expiry to a later feed when one is available. diff --git a/src/content/data-streams/reference/report-schema-overview.mdx b/src/content/data-streams/reference/report-schema-overview.mdx index deda8064133..f361ea87ca2 100644 --- a/src/content/data-streams/reference/report-schema-overview.mdx +++ b/src/content/data-streams/reference/report-schema-overview.mdx @@ -96,7 +96,7 @@ Each stream category uses one or more report schemas to deliver data. Several ca Futures (v14) - Futures price data with continuous roll price series + Futures price data with Goldman Roll price fields midPrice, bidPrice, askPrice, expiryTime,{" "} contractMonth, goldmanRollPrice, marketStatus @@ -168,7 +168,7 @@ While the Data Streams architecture is designed to deliver updates at least once - **[RWA Standard (v8)](/data-streams/reference/report-schema-v8)** — standard RWA format with consolidated mid price, market status, and freshness indicators. Used by the majority of RWA streams. - **[RWA Advanced (v11)](/data-streams/reference/report-schema-v11)** — adds bid/ask prices, volume depth, last traded price where supported, nanosecond-precision timestamps, and expanded market status values. Supports extended trading sessions where applicable. -- **[Futures (v14)](/data-streams/reference/report-schema-v14)** — futures price data with contract expiration, market status, and continuous roll price series. Used by [Futures streams](/data-streams/rwa-streams/futures). +- **[Futures (v14)](/data-streams/reference/report-schema-v14)** — futures price data with contract expiration, market status, and Goldman Roll price fields. Used by [Futures streams](/data-streams/rwa-streams/futures). ### RWA Standard (v8) @@ -188,7 +188,7 @@ These advanced fields enable protocols to implement more sophisticated risk mana The [Futures (v14)](/data-streams/reference/report-schema-v14) report schema provides price data for exchange-traded futures contracts. Each report includes consensus mid, bid, and ask prices (`midPrice`, `bidPrice`, `askPrice`), contract expiration (`expiryTime`), the first day of notice (`firstDayOfNotice`), the tracked contract month (`contractMonth`), market status (`marketStatus`), and a staleness measure (`lastSeenTimestampNs`). -Because futures contracts expire, streams using this schema expose three **generic** feeds per instrument that always track the current front, second, and third contract. The schema also includes continuous roll price series — `goldmanRollPrice`, `interpolatedGoldmanRollPrice`, and `currentBusinessDay` — for integrators who want a smoothed price instead of a hard cutover at contract expiration. See the [Futures](/data-streams/rwa-streams/futures) reference for rotation methodology and the [Futures (v14) reference](/data-streams/reference/report-schema-v14) for complete field specifications. +Because futures contracts expire, streams using this schema expose three **generic** feeds per instrument that always track the current front, second, and third contract. The schema also includes Goldman Roll price fields — `goldmanRollPrice`, `interpolatedGoldmanRollPrice`, and `currentBusinessDay` — for integrators who want a smoothed price instead of a hard cutover at contract expiration. See the [Futures](/data-streams/rwa-streams/futures) reference for rotation methodology and the [Futures (v14) reference](/data-streams/reference/report-schema-v14) for complete field specifications. ## SmartData diff --git a/src/content/data-streams/reference/report-schema-v14.mdx b/src/content/data-streams/reference/report-schema-v14.mdx index c8f89395d15..945a4e0031e 100644 --- a/src/content/data-streams/reference/report-schema-v14.mdx +++ b/src/content/data-streams/reference/report-schema-v14.mdx @@ -62,7 +62,7 @@ In addition to the raw generic feed prices — which switch entirely to the next | `interpolatedGoldmanRollPrice` | Interpolated Goldman Roll price: the Goldman Roll's 20% daily shift to the next contract, smoothed over the course of each business day, 5–9, of the month preceding delivery | | `currentBusinessDay` | Current business day of the month, used to determine the Goldman Roll window | -For details on how the generic feeds rotate between contracts and how the continuous roll fields behave, see the [Futures](/data-streams/rwa-streams/futures) reference. +For details on how the generic feeds rotate between contracts and how the Goldman Roll fields behave, see the [Futures](/data-streams/rwa-streams/futures) reference. ### Notes diff --git a/src/content/data-streams/rwa-streams/futures.mdx b/src/content/data-streams/rwa-streams/futures.mdx index 9a1ef26b4d2..afdf2bb28a5 100644 --- a/src/content/data-streams/rwa-streams/futures.mdx +++ b/src/content/data-streams/rwa-streams/futures.mdx @@ -33,7 +33,7 @@ Developers are responsible for choosing the appropriate feed and ensuring that t Futures streams use the [Futures (v14) schema](/data-streams/reference/report-schema-v14). -The v14 schema includes consensus mid, bid, and ask prices, contract expiration and first day of notice, the tracked contract month, market status, and a staleness measure. It also includes continuous roll price fields — `goldmanRollPrice`, `interpolatedGoldmanRollPrice`, and `currentBusinessDay` — described below. +The v14 schema includes consensus mid, bid, and ask prices, contract expiration and first day of notice, the tracked contract month, market status, and a staleness measure. It also includes Goldman Roll price fields — `goldmanRollPrice`, `interpolatedGoldmanRollPrice`, and `currentBusinessDay` — described below. ### Continuous roll price fields @@ -139,7 +139,7 @@ The v14 report decodes to the following fields. Prices are 18-decimal fixed-poin | `lastSeenTimestampNs` | `uint64` | Last provider update, nanoseconds | | `marketStatus` | `uint32` | Market status: `0` Unknown, `1` Closed, `2` Open | | `contractMonth` | `uint32` | Contract month, `1` (Jan) to `12` (Dec) | -| `goldmanRollPrice` | `int192` | Goldman Roll continuous price (18 decimals) | +| `goldmanRollPrice` | `int192` | Goldman Roll price (18 decimals) | | `currentBusinessDay` | `uint32` | Current business day of the month | | `interpolatedGoldmanRollPrice` | `int192` | Interpolated Goldman Roll price: the 20% daily shift to the next contract, smoothed over business days 5–9 of the month preceding delivery | @@ -149,7 +149,7 @@ Futures streams differ from spot streams in a few ways that affect how you consu - **Gate trading with `marketStatus`.** Use `marketStatus` to decide whether the underlying market is open: `2` = Open, `1` = Closed, `0` = unknown. Treat `0` as not open, and do not infer market state from `lastSeenTimestampNs` or expected session hours. The mapping is the same for every v14 futures feed; see [Market Hours](/data-streams/market-hours#futures-v14). - **Monitor `lastSeenTimestampNs` for staleness.** Futures are sourced from a single underlying provider per feed. If updates stop arriving, the price can go stale without an obvious price change. Pause trading or restrict liquidations when the timestamp lags your freshness threshold. -- **Expect a price discontinuity at each roll.** When the front contract expires, the feed re-maps to the next contract, which can trade at a different price. Do not treat this step as a data error. If your application needs a smooth series, build it from the continuous roll fields (`goldmanRollPrice`, `interpolatedGoldmanRollPrice`) or construct your own off-chain. +- **Expect a price discontinuity at each roll.** When the front contract expires, the feed re-maps to the next contract, which can trade at a different price. Do not treat this step as a data error. If your application needs a smooth series, build it from the Goldman Roll fields (`goldmanRollPrice`, `interpolatedGoldmanRollPrice`) or construct your own off-chain. - **Do not hardcode contract-month spacing.** The gap between the contracts tracked by consecutive feeds varies by instrument (one month for energy, wider for precious metals). Read `contractMonth` from the report rather than assuming monthly spacing. - **Roll early if you are expiry-sensitive.** In the final days of a contract, liquidity migrates to the next contract while the front feed still tracks the expiring one, which can increase volatility. If your application is sensitive to this, roll ahead of expiry to a later feed when one is available. diff --git a/src/features/feeds/components/reportSchemaData.ts b/src/features/feeds/components/reportSchemaData.ts index c7f303b23fe..88bae5792fd 100644 --- a/src/features/feeds/components/reportSchemaData.ts +++ b/src/features/feeds/components/reportSchemaData.ts @@ -288,7 +288,7 @@ export const REPORT_SCHEMA_DEFINITIONS: Record = { { field: "goldmanRollPrice", type: "int192", - description: "Continuous price using the Goldman Roll (GSCI) methodology", + description: "Goldman Roll price (GSCI methodology; 20% shifted per business day over days 5–9)", }, { field: "currentBusinessDay", @@ -298,7 +298,8 @@ export const REPORT_SCHEMA_DEFINITIONS: Record = { { field: "interpolatedGoldmanRollPrice", type: "int192", - description: "Interpolated Goldman Roll price, smoothed across the full contract cycle", + description: + "Interpolated Goldman Roll price: the 20% daily shift to the next contract, smoothed over each business day in the 5–9 window", }, ], },