From ac2951253ac99c922102174d24d88a678637fe42 Mon Sep 17 00:00:00 2001 From: MarketDataApp <112879596+MarketDataApp@users.noreply.github.com> Date: Tue, 13 Oct 2026 12:59:52 -0400 Subject: [PATCH 01/13] docs(internal): correct four BYOK prompt statements against the API E2 kept cached mode as the recommendation and never said it is paid-only. Free Forever and every trial get a 402 for mode=cached, so an app that followed E2 literally broke for exactly the users F1 tells it to onboard. It now says to repeat the request without mode on a 402. E4 said the 403 clears after five minutes with no requests. The block expires five minutes after the IP switch, and requests during it do not extend it. F3 said a missing entitlement raises no error. That holds with no mode, and on paid plans, which are downgraded silently. On Free and trial keys an explicit mode=live/delayed/eod is a 402, and so is a date older than the plan allows. The historical case applied the options cutoff to everything. It now states the stock (4:15:01 PM ET) and option (9:30:01 AM ET next open) cutoffs separately, matching account/data-freshness.md, and the 06:00 ET example is about options. The fee-liability wording is unchanged; a TODO asks compliance whether the stock cutoff is also the fee boundary. Prime Trial joins the cached-mode exclusion in api/rate-limiting.md and account/plan-limits.md. Fixes #222 --- account/plan-limits.md | 2 +- api/rate-limiting.md | 2 +- internal/byok-audit-prompt.md | 27 +++++++++++++++++++-------- 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/account/plan-limits.md b/account/plan-limits.md index d54779c7..7ceb8c00 100644 --- a/account/plan-limits.md +++ b/account/plan-limits.md @@ -27,7 +27,7 @@ For users working with options, take care before repeatedly requesting quotes fo ::: :::note[Trial plans] -Starter Trial and Trader Trial do not support `mode=cached`. +Starter Trial, Trader Trial, and Prime Trial do not support `mode=cached`. ::: ## Device Restrictions diff --git a/api/rate-limiting.md b/api/rate-limiting.md index 0f1251b8..314717bb 100644 --- a/api/rate-limiting.md +++ b/api/rate-limiting.md @@ -82,5 +82,5 @@ We provide the following headers in our responses to help you manage the rate li - Paying customers can make use of the reduced-price cached mode. Use the `mode=cached` parameter on supported bulk endpoints to retrieve previously cached quotes instead of making a live request. This can save thousands of credits. For more details, refer to the [mode parameter documentation](/api/universal-parameters/mode). :::note[Trial plans] -`mode=cached` is not available on Starter Trial and Trader Trial plans. +`mode=cached` is not available on Starter Trial, Trader Trial, and Prime Trial plans. ::: diff --git a/internal/byok-audit-prompt.md b/internal/byok-audit-prompt.md index d30fe2e0..6ae6f22f 100644 --- a/internal/byok-audit-prompt.md +++ b/internal/byok-audit-prompt.md @@ -65,6 +65,12 @@ reading as a failure. ## The prompt +{/* TODO(compliance): confirm whether the 4:15:01 PM ET stock cutoff, taken from +account/data-freshness.md, is also the exchange redistribution-fee boundary for +stock data. The prompt's "One case that is neither a PASS nor a plain FAIL" +section treats it as historical, and so as fee-free, until compliance says +otherwise. See #222. */} + ```` You are an independent compliance auditor. Audit the repository at [REPO PATH] against the Market Data BYOK model and the Market Data data policies. Write your @@ -183,9 +189,9 @@ or UNRESOLVED. | ID | The rule | |----|----------| | E1 | Every request carries a unique `User-Agent` that names the application and its version. A library default such as `axios/1.6.0`, `python-requests/2.31.0`, or `okhttp/4.12.0` fails this rule. | -| E2 | Option chain requests use `mode=cached` unless the use case needs live data. A live chain costs one credit per contract; a cached chain costs one credit. | +| E2 | Option chain requests use `mode=cached` unless the use case needs live data. A live chain costs one credit per contract; a cached chain costs one credit. Cached mode is available only on paid plans that are not trials. Free Forever and every trial (Starter Trial, Trader Trial, Prime Trial) get a `402` for `mode=cached`, so on a `402` the application repeats the request without `mode`. | | E3 | Polling intervals fit a credit budget. A free key holds 100 credits a day. State the worst-case daily credit spend you can derive from the code. | -| E4 | The application handles `429`, `402`, and `403` with a message to the user. A `403` is the single-IP control and clears after five minutes with no requests. | +| E4 | The application handles `429`, `402`, and `403` with a message to the user. A `403` is the single-IP control. The block expires five minutes after the IP switch; further requests during the block do not extend it. | ### Group F — Onboarding and entitlement (all P2) @@ -193,7 +199,7 @@ or UNRESOLVED. |----|----------| | F1 | Onboarding tells the user they need a second account, and links to the Market Data sign-up page. | | F2 | Onboarding explains the verification step and the wait of up to one business day before real-time data arrives. | -| F3 | The application works on a delayed, historical, or quota-limited key, and reads response timestamps rather than assuming the data is live. A missing entitlement raises no error: the API returns the freshest data the user is entitled to. | +| F3 | The application works on a delayed, historical, or quota-limited key, and reads response timestamps rather than assuming the data is live. When the request sends no `mode`, a missing entitlement raises no error: the API returns the freshest data the user is entitled to. A paid plan is also downgraded silently. On a Free Forever or trial key, an explicit `mode=live`, `mode=delayed`, or `mode=eod` returns `402` "Feed not available for your plan.", and so does a date older than the plan allows. The application omits `mode` unless it needs one, and handles the `402`. | | F4 | The application does not assume every user is non-professional. A user our compliance team classifies as professional never receives real-time data on a self-service plan. | ## What is NOT a finding @@ -220,8 +226,8 @@ Do not report these. Each one is a legitimate design. A developer server that handles only **historical** data is not BYOK, and it is also not automatically a violation. The exchanges charge no redistribution fee -for historical data, meaning data from a completed session once the next session -has opened. Delayed data does not qualify. +for historical data, meaning data from a completed session. Delayed data does not +qualify. If you find a server path that carries only historical data, record it as a P1 against A2, and add a note that the product may qualify under the historical-only @@ -229,9 +235,14 @@ model. Recommend that the developer contact Market Data sales rather than recommending a code change. Say plainly that you cannot grant that model, and that only Market Data can. -Data becomes historical at the open of the next trading session. A product that -serves the previous session's data at 06:00 Eastern is serving delayed data and -is fee-liable until the bell. +Stocks and options become historical at different times: + +- Stock data becomes historical at 4:15:01 PM Eastern on the session day. +- Option data becomes historical at 9:30:01 AM Eastern, at the open of the next + trading session. + +A product that serves the previous session's option data at 06:00 Eastern is +serving delayed data and is fee-liable until the bell. ## Search seeds From a923ba2cf3c800f9d350eeed25c56eab02171fa5 Mon Sep 17 00:00:00 2001 From: MarketDataApp <112879596+MarketDataApp@users.noreply.github.com> Date: Tue, 13 Oct 2026 13:15:59 -0400 Subject: [PATCH 02/13] docs(internal): let E1 accept X-MarketData-Client, which browsers can send E1 required a unique User-Agent. Chrome and Safari drop a User-Agent set from JavaScript, so every browser app failed a P2 it had no way to fix. E1 now accepts the X-MarketData-Client: / header, and requires it of a browser app. A native app may send either the header or a User-Agent that names it. A library default with no header still fails, and so does a header whose app name is generic or not the app's own. The header is attribution only: it grants no access, credits, or exemption. X-MarketData-Client joins the search seeds, and the page's note on live request behaviour no longer names User-Agent alone. Do not merge before MarketData-App/api#532 deploys: until then the CORS preflight rejects the header and a browser request that sends it fails. Refs MarketData-App/api#532 --- internal/byok-audit-prompt.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/internal/byok-audit-prompt.md b/internal/byok-audit-prompt.md index 6ae6f22f..a70d916a 100644 --- a/internal/byok-audit-prompt.md +++ b/internal/byok-audit-prompt.md @@ -188,7 +188,7 @@ or UNRESOLVED. | ID | The rule | |----|----------| -| E1 | Every request carries a unique `User-Agent` that names the application and its version. A library default such as `axios/1.6.0`, `python-requests/2.31.0`, or `okhttp/4.12.0` fails this rule. | +| E1 | Every request identifies the application and its version, in one of two ways. The first is the header `X-MarketData-Client: /`, where `` is lowercase letters, digits, `.`, `_`, or `-`, at most 64 characters, and `` is at most 32 characters. A browser application must use this header, because Chrome and Safari drop a `User-Agent` set from JavaScript. The second is for a native application only (desktop, mobile, a CLI with no server, a platform plugin): a `User-Agent` that names the application and its version. A native application may use either one. A library default such as `axios/1.6.0`, `python-requests/2.31.0`, or `okhttp/4.12.0` with no `X-MarketData-Client` header fails this rule. So does a header whose app name is generic or is not the application's own, such as `app`, `test`, `sheets`, or a language name. The header identifies the application for attribution only. It grants no access, no credits, and no exemption from any control. An application that relies on it for anything else is wrong. | | E2 | Option chain requests use `mode=cached` unless the use case needs live data. A live chain costs one credit per contract; a cached chain costs one credit. Cached mode is available only on paid plans that are not trials. Free Forever and every trial (Starter Trial, Trader Trial, Prime Trial) get a `402` for `mode=cached`, so on a `402` the application repeats the request without `mode`. | | E3 | Polling intervals fit a credit budget. A free key holds 100 credits a day. State the worst-case daily credit spend you can derive from the code. | | E4 | The application handles `429`, `402`, and `403` with a message to the user. A `403` is the single-IP control. The block expires five minutes after the IP switch; further requests during the block do not extend it. | @@ -256,6 +256,7 @@ Bearer # authorization headers /v1/options/chain # and the other endpoints mode=cached User-Agent +X-MarketData-Client ``` Then search the repository's own vocabulary for each rule group: the name of @@ -344,6 +345,6 @@ outside its reach, and the report should not be read as covering them: hosting dashboard leaves no file to find. - **A binary or closed dependency.** The prompt records these as unresolved rather than clearing them. -- **Live request behaviour.** Our own API logs answer this. A `User-Agent` in - the code and a `User-Agent` on the wire are two claims. +- **Live request behaviour.** Our own API logs answer this. An identifying header + in the code and the same header on the wire are two claims. - **Whether the developer follows the report.** A GO is a verdict on a commit. From 30707637a707917654e4ac656ca5d0bc8afa6874 Mon Sep 17 00:00:00 2001 From: MarketDataDev03 Date: Wed, 14 Oct 2026 09:41:04 -0400 Subject: [PATCH 03/13] docs(sheets): document OPTIONDATA ranges and correct when noheaders is needed OPTIONDATA now quotes a range of contracts in one formula (one row per cell, blank rows for contracts it cannot serve, single date only, no tables); the noheaders note said one attribute never has a header, which is false for several symbols or a date range, and the samples used STOCKQUOTE, which no longer exists. --- sheets/options/optiondata.md | 29 +++++++++++++++++++---- sheets/universal-attributes/no-headers.md | 7 +++--- 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/sheets/options/optiondata.md b/sheets/options/optiondata.md index a174edde..53be2a75 100644 --- a/sheets/options/optiondata.md +++ b/sheets/options/optiondata.md @@ -1,10 +1,10 @@ --- title: OPTIONDATA -description: The OPTIONDATA formula fetches a current or historical option quote into your spreadsheet. See the syntax, sample usage and data availability. +description: The OPTIONDATA formula fetches current or historical option quotes for one contract or a whole range of contracts. See the syntax, samples and limits. sidebar_position: 1 --- -Fetches a current or historical option quote from Market Data. +Fetches current or historical option quotes from Market Data, for one option contract or many at once. ## Sample Usage ```excel-formula @@ -13,12 +13,19 @@ Fetches a current or historical option quote from Market Data. =OPTIONDATA("AAPL271217C00250000", "date,bid,ask", "9/1/2022", "1/31/2023") =OPTIONDATA("AAPL271217C00250000", "all", TODAY()-30, 30) ``` +### Multiple Contracts +```excel-formula +=OPTIONDATA(A1:A500) +=OPTIONDATA(A1:A500, "bid,ask,noheaders") +=OPTIONDATA("AAPL271217C00250000,AAPL271217P00250000", "mid") +=OPTIONDATA(A1:A500, "mid", "9/15/2026") +``` ## Syntax ```excel-formula =OPTIONDATA(option symbol, [attributes], start date, end date) ``` -- **option symbol** _(REQUIRED)_ Use the current OCC option symbol format for the option symbol, even for historic options prior to the symbol format change in 2010. +- **option symbol** _(REQUIRED)_ Use the current OCC option symbol format for the option symbol, even for historic options prior to the symbol format change in 2010. Several contracts can be fetched at once: pass a range of cells in a single row or a single column, or several OCC symbols separated by commas. See [Working With Multiple Contracts](#working-with-multiple-contracts). - **attribute** _(OPTIONAL "price" by default)_ Use at least one of the following attributes; seperate multiple attributes with commas: - "symbol" - The OCC option symbol. - "date", "updated" - The date and time of the quote. @@ -41,7 +48,7 @@ Fetches a current or historical option quote from Market Data. - "vega" - The vega of the option. - "all" – Returns all values. - "noheaders" – Returns values without column headers. -- **start date** _(OPTIONAL)_ – The start date when fetching historical data. If start date is specified, but endDate is not, only the single day's data is returned. +- **start date** _(OPTIONAL)_ – The start date when fetching historical data. If start date is specified, but endDate is not, only the single day's data is returned. When fetching more than one contract, only a single date may be used. - **end date** _(OPTIONAL)_ – The end date when fetching historical data, or the number of calendar days (not trading days) from startDate for which to return data. ## Usage Information @@ -80,8 +87,20 @@ When you use `OPTIONDATA` with date parameters, it returns historical option quo If you attempt to access historical data older than your plan's limit permits, the formula will return an error. [Learn more about plan limits](/account/plan-limits). ::: +### Working With Multiple Contracts + +A single `OPTIONDATA` formula can fetch quotes for many option contracts at once. Pass a range of cells, or several OCC symbols separated by commas, as the option symbol. + +- One row comes back for each cell, in the same order as the range, even when the range is a row. Wrap the formula in `TRANSPOSE()` to lay the results out horizontally. +- A contract that cannot be found, or that has expired, comes back as a blank row in its place, so the results stay aligned with your contracts. +- Use a single historical date (start date only). Date ranges are not supported with more than one contract. +- The range must be a single row or a single column. A table of several rows and several columns returns an error. +- A row of cells can also describe one contract in parts: underlying, expiration date, strike and side (for example, `AAPL | 12/17/2027 | 250 | call`). A row like that is read as a single contract, so it also accepts a date range. +- With more than one contract the results include a header row. Add `noheaders` to the attributes to line the results up with your cells. +- For best results use OCC symbols. Contracts written in words are slower to read, and a long list of them may fill in over a few refreshes. + ## Notes - All parameters must be enclosed in quotation marks or be references to cells containing text. A possible exception is when end date is specified as a number of days. -- Results will be returned as a value within a single cell if a single attribute is requested. Multiple attributes or multi-day results will be returned with column headers. +- Results will be returned as a value within a single cell if a single attribute is requested for a single contract. Multiple attributes, multiple contracts or multi-day results will be returned with column headers. - Dates and times are returned in the same timezone of the exchange. \ No newline at end of file diff --git a/sheets/universal-attributes/no-headers.md b/sheets/universal-attributes/no-headers.md index 0497e225..78723499 100644 --- a/sheets/universal-attributes/no-headers.md +++ b/sheets/universal-attributes/no-headers.md @@ -1,6 +1,6 @@ --- title: No Headers -description: Add the noheaders attribute to any Market Data Google Sheets formula, such as STOCKQUOTE or OPTIONDATA, to leave the header row out of the output. +description: Add the noheaders attribute to any Market Data Google Sheets formula, such as STOCKDATA or OPTIONDATA, to leave the header row out of the output. sidebar_position: 1 --- @@ -8,8 +8,9 @@ Add the "noheaders" attribute to exclude the header row from the output of any M ## Sample Usage ```excel-formula -=STOCKQUOTE("AAPL","all,noheaders") =STOCKDATA("AAPL", "all,noheaders") +=STOCKDATA(A1:A50, "mid,noheaders") +=OPTIONDATA(A1:A50, "bid,ask,noheaders") =OPTIONDATA("AAPL271217C00250000", "bid,ask,noheaders", "1/5/2026", "2/5/2026") ``` @@ -24,6 +25,6 @@ Add `noheaders` anywhere in the attribute list of any Market Data formula. Ensur :::info -The `noheaders` attribute is only needed if you've requested more than one attribute. If you request a single attribute in any Market Data formula, the output will be a single cell with no headers. +The `noheaders` attribute is needed whenever the output has more than one row or column: several attributes, several symbols or contracts, or a date range. A single attribute for a single symbol and date returns one cell with no header. ::: From 3213f8e6a602a0e79c124682c22348e3da3a6245 Mon Sep 17 00:00:00 2001 From: MarketDataDev03 Date: Mon, 19 Oct 2026 13:14:36 -0400 Subject: [PATCH 04/13] docs(sheets): document four-column OPTIONDATA tables and the OPTIONCHAIN as of quote date OPTIONDATA now accepts a table of exactly four columns, one contract per row in the order the first row sets, and a failed contract shows what was entered in the symbol column instead of a blank row (MarketData-App/api#550); OPTIONCHAIN gains a sixth argument for one past session's end-of-day chain, with omitted meaning current, a blank meaning an error, DTE counted from the quote date and no delta or greeks on a historical chain (MarketData-App/sheets#82) --- sheets/options/optionchain.md | 36 ++++++++++++++++++++++++++++++----- sheets/options/optiondata.md | 31 +++++++++++++++++++++++------- 2 files changed, 55 insertions(+), 12 deletions(-) diff --git a/sheets/options/optionchain.md b/sheets/options/optionchain.md index ea003399..20131a82 100644 --- a/sheets/options/optionchain.md +++ b/sheets/options/optionchain.md @@ -1,12 +1,12 @@ --- title: OPTIONCHAIN -description: The OPTIONCHAIN formula fetches a current option chain into your spreadsheet. See the syntax, sample usage and data availability. +description: The OPTIONCHAIN formula fetches a current or end-of-day historical option chain into your spreadsheet. See the syntax, samples and data availability. sidebar_position: 3 sidebar_custom_props: badge: h --- -Fetches a current option chain from Market Data. +Fetches a current option chain, or the end-of-day option chain of a past trading day, from Market Data. ## Video Tutorial @@ -18,10 +18,16 @@ Fetches a current option chain from Market Data. =OPTIONCHAIN("AAPL","all,noheaders","60 DTE","150,160) =OPTIONCHAIN("AAPL","all","60 DTE","100-200","calls") ``` +### Historical Chains +```excel-formula +=OPTIONCHAIN("AAPL","strike,bid,ask","45 DTE","200-250","puts","2026-09-01") +=OPTIONCHAIN("AAPL",,,,,"last session") +=OPTIONCHAIN(A2,"strike,bid,ask","45 DTE","200-250","puts",B2) +``` ## Syntax ```excel-formula -=OPTIONCHAIN(underlying symbol, [attributes], expiration date, [strikes], [filters]) +=OPTIONCHAIN(underlying symbol, [attributes], expiration date, [strikes], [filters], [as of]) ``` - **underlying symbol** _(REQUIRED)_ Use the stock, etf, or underlying index symbol. @@ -55,7 +61,8 @@ Fetches a current option chain from Market Data. - **expiration date** - _(OPTIONAL)_ - The expiration date of the option chain. Options from this expiration will be returned. If no value is specified, the next monthly expiration will be used. - "date" - A single date in YYYY-MM-DD or MM/DD/YYYY format enclosed between quotes. - \[date cell reference] - A cell reference to a date in Sheets. - - "dte _number_" - Days to expiry. Return the expiration date most closely matching the indicated number. For example, if today was Jan 1 and you used a DTE of 45, the expiration closest to Feb 15 would be selected. + - "dte _number_" - Days to expiry. Return the expiration date most closely matching the indicated number. For example, if today was Jan 1 and you used a DTE of 45, the expiration closest to Feb 15 would be selected. With an **as of** date, the days are counted from that date instead of today. + - The expiration date is always the contract's expiration, never the quote date. To see a chain as it was on a past day, use **as of**. - **strikes** _(OPTIONAL)_ – Limit the strikes returned from the option chain formula to only the specified strikes or deltas. The formula will assume strikes for numbers greater than 1 and deltas for numbers less than 1 or when the word `delta` is placed before the number(s). - \[number] - A single number or a cell reference to a number. Example: `150` - \[decimal] - A decimal number will be interpreted as a delta value to be matched and the formula will return the strike that most closely matches the delta provided. Example: `.60` @@ -68,18 +75,26 @@ Fetches a current option chain from Market Data. - "string of decimals" - Seperate multiple deltas with commas. Example: `".50,.60.,70"` - "logical expression" - A logical expression. Example: `"<200 delta <.50"` - "limit \[number]" - Limit the output to \[number] strikes closest to the money. Example: `"limit 4"` + - Deltas are only available for current chains. Selecting strikes by delta together with an **as of** date returns an error; use strikes instead. - **filters** _(OPTIONAL)_ – Use specific keywords to further filter the option chain. - "call", "calls" - Only return calls. - "put", "puts" - Only return puts. - "itm", "in the money" - Only return in the money options. - "otm", "out of the money" - Only return out of the money options. - "nonstandard", "non-standard" - Include non-standard contracts in the optionchain output. +- **as of** _(OPTIONAL)_ – The quote date. Leave it out for the current chain, or give one past trading day to get that day's end-of-day chain. See [Working With Historical Chains](#working-with-historical-chains). + - _(omitted)_ or "current" - The current chain, the same as a formula without this parameter. + - "date" - A single date in YYYY-MM-DD or MM/DD/YYYY format enclosed between quotes. + - \[date cell reference] - A cell reference to a date in Sheets. + - "last session" - The most recent trading day whose end-of-day chain has been published. + - "yesterday", "today" - The calendar day before today, or today. On a weekend or holiday these return an error, so "last session" is usually the better choice. + - An empty cell or `""` returns an error, not the current chain. To switch a sheet between current and historical chains with one cell, write "current" in it. ## Usage Information ### Data Availability -The `OPTIONCHAIN` function fetches current option chain data. The type of data you receive depends on your user type and OPRA entitlement. This may include real-time data, 15-minute delayed data, or historical data, depending on the plan or access level. To get real-time options data, users need to sign the OPRA agreement. +Without an **as of** date, the `OPTIONCHAIN` function fetches current option chain data. The type of data you receive depends on your user type and OPRA entitlement. This may include real-time data, 15-minute delayed data, or historical data, depending on the plan or access level. To get real-time options data, users need to sign the OPRA agreement. | User Type | OPRA Entitlement | Data Type | |------------------|------------------|------------------------| @@ -89,6 +104,17 @@ The `OPTIONCHAIN` function fetches current option chain data. The type of data y | Professional | ❌ | Historical (1 day old) | | Unknown | Any | Historical (1 day old) | +### Working With Historical Chains + +With an **as of** date, `OPTIONCHAIN` returns the chain as it closed on that trading day. + +- Only end-of-day chains are available. There are no intraday snapshots, and only one date per formula. +- The columns are the same as for a current chain. Implied volatility and the greeks (delta, gamma, theta, vega) are blank, and selecting strikes by delta is not available. +- Open interest is the figure settled out of the previous session, as described under the "open interest" attribute. +- A date in the future, a weekend or a market holiday returns an error. Today's chain returns a "not available yet" error until the end-of-day chain is published after the close. +- A relative date such as "last session" is resolved when the formula calculates. It updates when the sheet is refreshed or a referenced cell changes, not on its own as days pass. +- Historical data is subject to your plan's limits. [Learn more about plan limits](/account/plan-limits). + :::info[What are entitlements?] Entitlements are permissions granted by exchanges that allow access to their data. To get real-time options data, users need to sign the [OPRA agreement](/account/entitlements). [Learn more about entitlements](/account/entitlements). ::: diff --git a/sheets/options/optiondata.md b/sheets/options/optiondata.md index 53be2a75..d403b352 100644 --- a/sheets/options/optiondata.md +++ b/sheets/options/optiondata.md @@ -19,13 +19,14 @@ Fetches current or historical option quotes from Market Data, for one option con =OPTIONDATA(A1:A500, "bid,ask,noheaders") =OPTIONDATA("AAPL271217C00250000,AAPL271217P00250000", "mid") =OPTIONDATA(A1:A500, "mid", "9/15/2026") +=OPTIONDATA(A1:D50, "symbol,mid") ``` ## Syntax ```excel-formula =OPTIONDATA(option symbol, [attributes], start date, end date) ``` -- **option symbol** _(REQUIRED)_ Use the current OCC option symbol format for the option symbol, even for historic options prior to the symbol format change in 2010. Several contracts can be fetched at once: pass a range of cells in a single row or a single column, or several OCC symbols separated by commas. See [Working With Multiple Contracts](#working-with-multiple-contracts). +- **option symbol** _(REQUIRED)_ Use the current OCC option symbol format for the option symbol, even for historic options prior to the symbol format change in 2010. Several contracts can be fetched at once: pass a range of cells in a single row or a single column, several OCC symbols separated by commas, or a table of four columns with one contract per row. See [Working With Multiple Contracts](#working-with-multiple-contracts). - **attribute** _(OPTIONAL "price" by default)_ Use at least one of the following attributes; seperate multiple attributes with commas: - "symbol" - The OCC option symbol. - "date", "updated" - The date and time of the quote. @@ -89,15 +90,31 @@ If you attempt to access historical data older than your plan's limit permits, t ### Working With Multiple Contracts -A single `OPTIONDATA` formula can fetch quotes for many option contracts at once. Pass a range of cells, or several OCC symbols separated by commas, as the option symbol. +A single `OPTIONDATA` formula can fetch quotes for many option contracts at once. Pass a range of cells, several OCC symbols separated by commas, or a table of contracts as the option symbol. -- One row comes back for each cell, in the same order as the range, even when the range is a row. Wrap the formula in `TRANSPOSE()` to lay the results out horizontally. -- A contract that cannot be found, or that has expired, comes back as a blank row in its place, so the results stay aligned with your contracts. +- One row comes back for each contract, in the same order as your cells, even when the range is a row. Wrap the formula in `TRANSPOSE()` to lay the results out horizontally. +- A contract that cannot be served (not found, expired, or misspelled) keeps its place, so the results stay aligned with your contracts. Its row shows what you entered in the symbol column, with the other columns blank, so you can spot it. Request the `symbol` attribute to see it; without it the row is blank. - Use a single historical date (start date only). Date ranges are not supported with more than one contract. -- The range must be a single row or a single column. A table of several rows and several columns returns an error. -- A row of cells can also describe one contract in parts: underlying, expiration date, strike and side (for example, `AAPL | 12/17/2027 | 250 | call`). A row like that is read as a single contract, so it also accepts a date range. +- A range must be a single row, a single column, or a table of exactly four columns. Any other table, such as three or five columns, returns an error. +- A row of four cells can describe one contract in parts: underlying, expiration date, strike and side (for example, `AAPL | 12/17/2027 | 250 | call`). On its own, a row like that is read as a single contract, so it also accepts a date range. - With more than one contract the results include a header row. Add `noheaders` to the attributes to line the results up with your cells. -- For best results use OCC symbols. Contracts written in words are slower to read, and a long list of them may fill in over a few refreshes. +- For best results use OCC symbols, or a table with dates in `YYYY-MM-DD` format and numeric strikes. Contracts written in words are slower to read, and a long list of them may fill in over a few refreshes. + +#### Tables of Contracts + +A table of four columns is read as one contract per row, with the underlying, expiration date, strike and side in its columns: + +| | A | B | C | D | +|---|------|------------|-----|------| +| 1 | AAPL | 2027-12-17 | 250 | call | +| 2 | AAPL | 2027-12-17 | 250 | put | +| 3 | MSFT | 2027-12-17 | 500 | call | + +`=OPTIONDATA(A1:D3, "symbol,mid")` returns a header row and one row for each of the three contracts. + +- The columns can be in any order. The first row sets it, and every other row is read the same way. +- Because of that, the first row must be a contract, not a header. A table that starts with a header row returns an error, so start the range on the first contract (for example, `A2:D50`). +- A later row that does not fit the order of the first row (columns swapped, a missing or misspelled cell) fails on its own, without affecting the other rows. ## Notes From e6d90ea049f34c125a5c755cc31dd21f6c6e9256 Mon Sep 17 00:00:00 2001 From: MarketDataDev03 Date: Thu, 22 Oct 2026 10:31:09 -0400 Subject: [PATCH 05/13] docs(sheets,api): list the contract columns and DTE for both option formulas, the 52-week columns for STOCKDATA, and the contract fields of options/quotes OPTIONDATA now documents underlying, expiration, side, strike, first traded and dte as OPTIONCHAIN does, and OPTIONCHAIN gains dte, counted from today or from the quote date on a historical request; STOCKDATA's quote attributes gain 52weekHigh, 52weekLow and 52week, with all noted as leaving them out unless written all,52week; the public options/quotes page lists the six contract fields the endpoint returns after optionSymbol, worded as on options/chain (MarketData-App/sheets#94) --- api/options/quotes.mdx | 24 ++++++++++++++++++++++++ sheets/options/optionchain.md | 1 + sheets/options/optiondata.md | 6 ++++++ sheets/stocks/stockdata.md | 5 ++++- 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/api/options/quotes.mdx b/api/options/quotes.mdx index e0f6d335..f350a737 100644 --- a/api/options/quotes.mdx +++ b/api/options/quotes.mdx @@ -225,6 +225,30 @@ foreach (var quote in (await client.Options.GetQuoteAsync("AAPL271217C00250000") The option symbol according to OCC symbology. +- **underlying** `array[string]` + + The ticker symbol of the underlying security. + +- **expiration** `array[number]` + + The option's expiration date and time. Equity options expire at 4:00 PM Eastern and index options expire at 4:15 PM Eastern. All timestamps use US Eastern Time (America/New_York). See [Response Timezone](/docs/api/dates-and-times#response-timezone) for details. + +- **side** `array[string]` + + The response will be `call` or `put`. + +- **strike** `array[number]` + + The exercise price of the option. + +- **firstTraded** `array[date]` + + The date the option was first traded. + +- **dte** `array[number]` + + The number of days until the option expires. + - **ask** `array[number]` The ask price. diff --git a/sheets/options/optionchain.md b/sheets/options/optionchain.md index 20131a82..6d5327b4 100644 --- a/sheets/options/optionchain.md +++ b/sheets/options/optionchain.md @@ -38,6 +38,7 @@ Fetches a current option chain, or the end-of-day option chain of a past trading - "side" - Call or put. - "strike" - The option's strike price. - "first traded" - The date this option first began to trade. + - "dte" - Days to expiration: the calendar days until the option expires, counted from today on a current quote and from the quote date on a historical one. - "date", "updated" - The date and time of the quote. - "bid" – The bid price of the option. - "bid size" – The quantity of contracts offered at the bid price. diff --git a/sheets/options/optiondata.md b/sheets/options/optiondata.md index d403b352..335e9afd 100644 --- a/sheets/options/optiondata.md +++ b/sheets/options/optiondata.md @@ -29,6 +29,12 @@ Fetches current or historical option quotes from Market Data, for one option con - **option symbol** _(REQUIRED)_ Use the current OCC option symbol format for the option symbol, even for historic options prior to the symbol format change in 2010. Several contracts can be fetched at once: pass a range of cells in a single row or a single column, several OCC symbols separated by commas, or a table of four columns with one contract per row. See [Working With Multiple Contracts](#working-with-multiple-contracts). - **attribute** _(OPTIONAL "price" by default)_ Use at least one of the following attributes; seperate multiple attributes with commas: - "symbol" - The OCC option symbol. + - "underlying" - The underlying symbol. + - "expiration" - The option's expiration date. + - "side" - Call or put. + - "strike" - The option's strike price. + - "first traded" - The date this option first began to trade. + - "dte" - Days to expiration: the calendar days until the option expires, counted from today on a current quote and from the quote date on a historical one. - "date", "updated" - The date and time of the quote. - "price", "mid", "mark" – The midpoint price of the option. - "bid" – The bid price of the option. diff --git a/sheets/stocks/stockdata.md b/sheets/stocks/stockdata.md index 976fac10..0d33fa32 100644 --- a/sheets/stocks/stockdata.md +++ b/sheets/stocks/stockdata.md @@ -60,8 +60,11 @@ Fetches a current stock quote or historical stock candles from Market Data. It c - "bidSize" – The quantity of shares offered at the bid price. - "askSize" – The quantity of shares offered at the ask price. - "volume" – The quantity of shares traded. + - "52weekHigh" – The 52-week high for the stock. + - "52weekLow" – The 52-week low for the stock. + - "52week" – Adds both 52-week columns. "all" does not include them: use "all,52week" to return every value and the 52-week high and low. - "symbol" - The ticker symbol of the stock. _Only returned when using a bulk quotes formula._ - - "all" – Returns all values. + - "all" – Returns all values except the 52-week high and low. - **start date** _(OPTIONAL)_ The start date when fetching historical data. If start date is specified, but endDate is not, only the single day’s data is returned. Multiple tickers may be used if only a single day's data is being returned. From 8a8f15013d2afd75ae80b0169877c0aef5c289c2 Mon Sep 17 00:00:00 2001 From: MarketDataApp <112879596+MarketDataApp@users.noreply.github.com> Date: Tue, 20 Oct 2026 12:03:28 -0400 Subject: [PATCH 06/13] docs(sheets): correct OPTIONCHAIN today and last session, and three OPTIONDATA and noheaders details OPTIONCHAIN refuses today's date on a trading day even after the close (api sheets/handlers.py:421), so "today" is dropped, as the add-on's own README and JSDoc already leave it out. "last session" now points at the one definition on the dates-and-times page instead of describing a third reading; MarketData-App/api#576 makes that definition universal. OPTIONDATA: a range where nothing resolves is an error, not blank rows, and date cells work in a table as well as YYYY-MM-DD text. noheaders: OPTIONCHAIN prints no header over a single column. --- sheets/options/optionchain.md | 6 +++--- sheets/options/optiondata.md | 3 ++- sheets/universal-attributes/no-headers.md | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/sheets/options/optionchain.md b/sheets/options/optionchain.md index 6d5327b4..08089545 100644 --- a/sheets/options/optionchain.md +++ b/sheets/options/optionchain.md @@ -87,8 +87,8 @@ Fetches a current option chain, or the end-of-day option chain of a past trading - _(omitted)_ or "current" - The current chain, the same as a formula without this parameter. - "date" - A single date in YYYY-MM-DD or MM/DD/YYYY format enclosed between quotes. - \[date cell reference] - A cell reference to a date in Sheets. - - "last session" - The most recent trading day whose end-of-day chain has been published. - - "yesterday", "today" - The calendar day before today, or today. On a weekend or holiday these return an error, so "last session" is usually the better choice. + - "last session" - The last closed market session. See [Relative Dates and Times](/sheets/dates-and-times#relative-dates-and-times). + - "yesterday" - The calendar day before today. If that day was a weekend or a market holiday, the formula returns an error, so "last session" is usually the better choice. - An empty cell or `""` returns an error, not the current chain. To switch a sheet between current and historical chains with one cell, write "current" in it. ## Usage Information @@ -112,7 +112,7 @@ With an **as of** date, `OPTIONCHAIN` returns the chain as it closed on that tra - Only end-of-day chains are available. There are no intraday snapshots, and only one date per formula. - The columns are the same as for a current chain. Implied volatility and the greeks (delta, gamma, theta, vega) are blank, and selecting strikes by delta is not available. - Open interest is the figure settled out of the previous session, as described under the "open interest" attribute. -- A date in the future, a weekend or a market holiday returns an error. Today's chain returns a "not available yet" error until the end-of-day chain is published after the close. +- A date in the future, a weekend or a market holiday returns an error. The chain of the most recent session returns a "not available yet" error until its end-of-day data is published. - A relative date such as "last session" is resolved when the formula calculates. It updates when the sheet is refreshed or a referenced cell changes, not on its own as days pass. - Historical data is subject to your plan's limits. [Learn more about plan limits](/account/plan-limits). diff --git a/sheets/options/optiondata.md b/sheets/options/optiondata.md index 335e9afd..f99a0326 100644 --- a/sheets/options/optiondata.md +++ b/sheets/options/optiondata.md @@ -100,11 +100,12 @@ A single `OPTIONDATA` formula can fetch quotes for many option contracts at once - One row comes back for each contract, in the same order as your cells, even when the range is a row. Wrap the formula in `TRANSPOSE()` to lay the results out horizontally. - A contract that cannot be served (not found, expired, or misspelled) keeps its place, so the results stay aligned with your contracts. Its row shows what you entered in the symbol column, with the other columns blank, so you can spot it. Request the `symbol` attribute to see it; without it the row is blank. +- If none of the contracts can be served, the formula returns an error instead of blank rows. - Use a single historical date (start date only). Date ranges are not supported with more than one contract. - A range must be a single row, a single column, or a table of exactly four columns. Any other table, such as three or five columns, returns an error. - A row of four cells can describe one contract in parts: underlying, expiration date, strike and side (for example, `AAPL | 12/17/2027 | 250 | call`). On its own, a row like that is read as a single contract, so it also accepts a date range. - With more than one contract the results include a header row. Add `noheaders` to the attributes to line the results up with your cells. -- For best results use OCC symbols, or a table with dates in `YYYY-MM-DD` format and numeric strikes. Contracts written in words are slower to read, and a long list of them may fill in over a few refreshes. +- For best results use OCC symbols, or a table with date cells (or dates in `YYYY-MM-DD` format) and numeric strikes. Contracts written in words are slower to read, and a long list of them may fill in over a few refreshes. #### Tables of Contracts diff --git a/sheets/universal-attributes/no-headers.md b/sheets/universal-attributes/no-headers.md index 78723499..d8724105 100644 --- a/sheets/universal-attributes/no-headers.md +++ b/sheets/universal-attributes/no-headers.md @@ -25,6 +25,6 @@ Add `noheaders` anywhere in the attribute list of any Market Data formula. Ensur :::info -The `noheaders` attribute is needed whenever the output has more than one row or column: several attributes, several symbols or contracts, or a date range. A single attribute for a single symbol and date returns one cell with no header. +The `noheaders` attribute is needed whenever the output has more than one row or column: several attributes, several symbols or contracts, or a date range. A single attribute for a single symbol and date returns one cell with no header. `OPTIONCHAIN` with a single attribute returns one column with no header row. ::: From d20c1104323270c4a5cee507fddfeb6f95aec1da Mon Sep 17 00:00:00 2001 From: MarketDataApp <112879596+MarketDataApp@users.noreply.github.com> Date: Thu, 22 Oct 2026 11:12:40 -0400 Subject: [PATCH 07/13] docs: last session is the same date on every plan, and today's options data is readable after the close Ahead of MarketData-App/api#576. `last session` names the newest closed session for every endpoint and plan, as these pages already said; what changes is that a plan with only Historical options data now gets a 402 between the close and the next open instead of an older session, so both dates-and-times pages say so and point at Data Freshness. The shared handler serves today's closed session from the end-of-day snapshot, so today's date is refused only while the market is open: the OPTIONCHAIN page and Case 4 of the 400 troubleshooting page say that now. --- api/dates-and-times.mdx | 2 +- api/troubleshooting/bad-request.mdx | 4 ++-- sheets/dates-and-times.md | 2 +- sheets/options/optionchain.md | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/api/dates-and-times.mdx b/api/dates-and-times.mdx index 3f8f3570..af57995a 100644 --- a/api/dates-and-times.mdx +++ b/api/dates-and-times.mdx @@ -81,7 +81,7 @@ Relative dates allow Market Data endpoints to continually modify the date sent t - `yesterday` Yesterday's date. - - `last session` Returns the date of the last closed market session. This keyphrase always gets the previous closed session, accounting for weekends, holidays, and half-days (which are counted as valid sessions). For example, on Monday during market hours, it would return Friday's date. After market close on Monday, it would return Monday's date. This allows you to always track the previous session without having to account for weekends, holidays, or other market closures. + - `last session` Returns the date of the last closed market session. This keyphrase always gets the previous closed session, accounting for weekends, holidays, and half-days (which are counted as valid sessions). For example, on Monday during market hours, it would return Friday's date. After market close on Monday, it would return Monday's date. This allows you to always track the previous session without having to account for weekends, holidays, or other market closures. The date is the same on every plan. On a plan that provides only Historical options data, an options session becomes Historical at the next session's open (see [Data Freshness](/account/data-freshness)), so between the close and the next open an options request for `last session` returns a 402 error. - `-[number] days` Use negative days to specify a time in the past _n_ days before. When this is used alone, it is relative to the current day. When used in conjunction in `from` field (i.e. the starting date), it is relative to the `to` field (i.e. the ending date). For example, if the current date is January 20, but January 10 is used in the `to` field and `-5 days` in the `from` field, then the starting day will be January 5. The query would return values from January 5 to January 10. However, if the `to` field were to be omitted, then the same query would return data from January 15 to January 20 since `-5 days` would be relative to the current date of January 20. diff --git a/api/troubleshooting/bad-request.mdx b/api/troubleshooting/bad-request.mdx index bd293aa7..4f9949ef 100644 --- a/api/troubleshooting/bad-request.mdx +++ b/api/troubleshooting/bad-request.mdx @@ -83,12 +83,12 @@ You may receive: Meaning: - Request can be otherwise valid -- `date` was used in a current-data context +- `date` was used in a current-data context, such as today's date while the market is open How to fix: 1. For current data: omit `date` -2. For historical data: provide a past trading date +2. For historical data: provide a past trading date, or today's date after the market closes ```http # Current request (correct): no date parameter diff --git a/sheets/dates-and-times.md b/sheets/dates-and-times.md index ccfd47e9..7aca34ef 100644 --- a/sheets/dates-and-times.md +++ b/sheets/dates-and-times.md @@ -42,7 +42,7 @@ Relative dates allow Market Data formulas to continually modify the date sent to - `yesterday` Yesterday's date. The same as Sheets formula `today()-1`. - - `last session` Returns the date of the last closed market session. This keyphrase always gets the previous closed session, accounting for weekends, holidays, and half-days (which are counted as valid sessions). For example, on Monday during market hours, it would return Friday's date. After market close on Monday, it would return Monday's date. This allows you to always track the previous session without having to account for weekends, holidays, or other market closures. + - `last session` Returns the date of the last closed market session. This keyphrase always gets the previous closed session, accounting for weekends, holidays, and half-days (which are counted as valid sessions). For example, on Monday during market hours, it would return Friday's date. After market close on Monday, it would return Monday's date. This allows you to always track the previous session without having to account for weekends, holidays, or other market closures. The date is the same on every plan. On a plan that provides only Historical options data, an options session becomes Historical at the next session's open (see [Data Freshness](/account/data-freshness)), so between the close and the next open an options request for `last session` returns a 402 error. - `-[number] days` Use negative days to specify a time in the past _n_ days before. When this is used alone, it is relative to the current day. When used in conjunction in `from` field (i.e. the starting date), it is relative to the `to` field (i.e. the ending date). For example, if the current date is January 20, but January 10 is used in the `to` field and `-5 days` in the `from` field, then the starting day will be January 5. The query would return values from January 5 to January 10. However, if the `to` field were to be omitted, then the same query would return data from January 15 to January 20 since `-5 days` would be relative to the current date of January 20. diff --git a/sheets/options/optionchain.md b/sheets/options/optionchain.md index 08089545..fcbe5591 100644 --- a/sheets/options/optionchain.md +++ b/sheets/options/optionchain.md @@ -112,7 +112,7 @@ With an **as of** date, `OPTIONCHAIN` returns the chain as it closed on that tra - Only end-of-day chains are available. There are no intraday snapshots, and only one date per formula. - The columns are the same as for a current chain. Implied volatility and the greeks (delta, gamma, theta, vega) are blank, and selecting strikes by delta is not available. - Open interest is the figure settled out of the previous session, as described under the "open interest" attribute. -- A date in the future, a weekend or a market holiday returns an error. The chain of the most recent session returns a "not available yet" error until its end-of-day data is published. +- A date in the future, a weekend or a market holiday returns an error, and so does today's date while the market is open. After the close, today's chain is available as soon as its end-of-day data is published; until then the formula returns a "not available yet" error. - A relative date such as "last session" is resolved when the formula calculates. It updates when the sheet is refreshed or a referenced cell changes, not on its own as days pass. - Historical data is subject to your plan's limits. [Learn more about plan limits](/account/plan-limits). From 3a11d70991f60ba6869082d301081d9a8c9c3294 Mon Sep 17 00:00:00 2001 From: MarketDataApp <112879596+MarketDataApp@users.noreply.github.com> Date: Fri, 23 Oct 2026 09:01:41 -0400 Subject: [PATCH 08/13] docs(plans): publish the Commercial Plan at $333/month to start, billed quarterly The plan now starts at $333/month and steps to $666 in months 7-12 and $999 from month 13, billed as $999, $1,998 and $2,997 a quarter, with a 14-day free trial. It lists real-time derived stock and options prices over REST and WebSocket, 15-minute delayed CBOE data, end-of-day, historical and tick-level data, US fundamentals, MCP access, and its rate limits. SmartMid, our API limits, the T+1 text and the links to the Commercial Use Addendum are gone, the addendum being withdrawn. Redistribution follows the plan's licence: display in your own product, no resale of the raw data. The comparison table shows only what the plan adds. Every purchase link goes to the contact form. The page is no longer unlisted or noindex, sits after Prime in the sidebar, and so appears on the plans index and in the sitemap. Its description is cut to 153 characters for lint:seo, and removing the block also stops it printing as text in the Markdown twin. Two comments that called the page noindex are corrected. --- account/plans/commercial.mdx | 98 ++++++++++++++++-------------------- lib/noindex-head.js | 4 +- redirects.js | 4 +- 3 files changed, 48 insertions(+), 58 deletions(-) diff --git a/account/plans/commercial.mdx b/account/plans/commercial.mdx index f4063263..2dbcff43 100644 --- a/account/plans/commercial.mdx +++ b/account/plans/commercial.mdx @@ -1,92 +1,82 @@ --- title: Commercial Plan -unlisted: true -description: Market Data's commercially-licensed plan for businesses, indie developers, and apps that distribute derived data to end users. +description: Market Data's commercial plan for businesses and apps that display market data to users, with real-time stock and options prices over REST and WebSocket. +sidebar_position: 8 --- -import Head from '@docusaurus/Head'; +The **Commercial Plan** is for businesses launching an app, dashboard, or product that shows market data to its users. It starts at **$333/month, billed quarterly**, and includes commercial use and display rights, real-time stock and options prices over both REST and WebSocket, and no exchange fees or exchange paperwork. - - - +## Pricing -The **Commercial Plan** is the most common starting point for businesses launching an app, dashboard, or product on top of Market Data. At **$250/month** it's the most affordable commercially-licensed market data subscription on the market — and it includes a generous package of data that you can redistribute to your end users under our [Commercial Use Addendum](https://www.marketdata.app/terms/commercial-use-addendum/). It's enough to get a product to market, on budget, with the option to add exchange licensing later as your business grows. +**$333/month to start, billed quarterly.** The price steps up twice during the first year, then stays fixed: -## Pricing +| Months | Monthly Price | Billed Each Quarter | +|-----------|---------------|---------------------| +| 1–6 | $333/month | $999 | +| 7–12 | $666/month | $1,998 | +| 13 and on | $999/month | $2,997 | -**$250/month** — month-to-month billing only. The Commercial Plan does not offer an annual billing option. +Every Commercial Plan starts with a **14-day free trial**, with no charge until the trial ends, and there is no long-term contract. [Contact us](https://www.marketdata.app/contact/) to get started. ## What You Get with the Commercial Plan -- **Commercial Use License**: The only Market Data plan that permits business and commercial use of our data, governed by our [Commercial Use Addendum](https://www.marketdata.app/terms/commercial-use-addendum/). -- **No Daily API Credit Limit**: Use our API as much as your application needs, with no daily cap. -- **100,000 Credits Per Minute**: A generous per-minute rate limit suited to production workloads. -- **50 Concurrent Requests**: Run requests in parallel to keep latency low under load. -- **Real-Time SmartMid Stock Prices**: Get current-day real-time stock prices on the [`/stocks/prices`](/api/stocks/prices) endpoint via our proprietary **SmartMid** model — a Market Data product that you can redistribute to your end users under our Commercial Use Addendum. **SmartMid is the only real-time data source included on the Commercial Plan.** -- **Historical Data, Full Depth**: Full historical access on every endpoint — stocks, options, and more — for backtesting, analytics, and historical charts. -- **Premium Endpoints**: Full access to all premium endpoints, including fundamentals and earnings data. - -### Exchange Data Is Historical Only +- **Commercial Use and Display Rights**: A business-wide commercial license. Use the data in your business and display it to the users of your app, dashboard, or product. +- **No Exchange Fees or Paperwork**: No exchange agreements to sign and no exchange fees to pay. See [About the Real-Time Prices](#about-the-real-time-prices) below. +- **Real-Time Stock Prices**: Real-time derived prices for stocks, with last price, open, close, volume, and pre-market and post-market volume. +- **Real-Time Options Prices**: Real-time derived options prices, with implied volatility and the greeks — delta, gamma, theta, and vega. +- **WebSocket Streaming**: Stream real-time stock and options prices over WebSocket, or request them over the REST API. +- **15-Minute Delayed CBOE Data**: Exchange data from CBOE on a 15-minute delay. +- **End-of-Day and Historical Data**: End-of-day and historical data for stocks and options, for backtesting, analytics, and historical charts. +- **Tick-Level Market Data**: Market data down to the individual tick. +- **US Fundamentals**: Fundamentals data for US companies. +- **AI Assistant Access**: Connect Claude, ChatGPT, and other AI assistants to the data through an MCP server. +- **Rate Limits**: 2,000 API calls per minute, 1 request per minute for bulk downloads and paging, and 3 WebSocket connections. -The Commercial Plan does **not** include any real-time exchange data. All exchange-sourced data — stock bid/ask quotes, daily and intraday candles, options chains and quotes, all of it — is delivered **historical only**, available starting from the **T+1 session** (today's session becomes available the following session). +## About the Real-Time Prices -The single exception is **SmartMid stock prices**, which are real-time because SmartMid is our own derived product and not exchange data. +The real-time stock and options prices on the Commercial Plan are **derived prices**, not exchange quotes. They are calculated to track exchange prices closely, but they are not exchange data, so they carry no exchange licensing requirements. That is what lets the plan include commercial display rights with no exchange fees and no exchange paperwork. -This is what keeps the plan affordable and lets you redistribute data to your end users without additional exchange paperwork. When your business is ready, exchange licensing can be added on top of your Commercial Plan — see [Why SmartMid Instead of Exchange Real-Time?](#why-smartmid-instead-of-exchange-real-time) below. +Exchange-sourced data on the Commercial Plan comes as **15-minute delayed CBOE data** and as **end-of-day and historical data**. If your product needs real-time exchange data, such as live bid/ask quotes from the exchanges, that requires exchange licensing, which the Commercial Plan does not include. [Contact our sales team](https://www.marketdata.app/contact/) to discuss it. ## Who the Commercial Plan Is For -The Commercial Plan is the entry point for businesses bringing a product to market on top of Market Data. Common use cases include: +The Commercial Plan is for businesses bringing a product to market on top of market data. Common use cases include: - **Stock and options apps** that display data to paying users - **Financial dashboards** distributed to clients or employees - **Research products and newsletters** that publish data-driven content -- **Charting and analytics tools** built on historical data +- **Charting and analytics tools** built on real-time and historical data - **Internal business analytics** at firms that need market data for internal use -Most businesses start here when launching and add exchange licensing later, as their product matures and their budget grows. - -If you're an indie developer **still in development** and not yet charging users or distributing data, you can build on the [Starter Plan](/account/plans/starter) until you're ready to launch. Once you go live with a commercial product, the Commercial Plan is your next step. See our guide on [how stock market data licensing works](https://www.marketdata.app/education/stocks/stock-market-data-licensing) for background. - ### Not Suitable for Trading -The Commercial Plan is **not suitable for trading applications** or any product where users make execution decisions based on the data. SmartMid is a derived midpoint price — useful for display, charting, and informational purposes — but it is not a live bid/ask quote and should not be used to determine trade prices, route orders, or trigger execution logic. Trading platforms and order-routing tools require real-time exchange data, which means direct exchange licensing. [Contact our sales team](https://www.marketdata.app/contact/) to discuss licensing options for trading use cases. +The Commercial Plan is **not suitable for trading applications** or any product where users make execution decisions based on the data. Its real-time prices are derived prices — useful for display, charting, and informational purposes — but they are not live bid/ask quotes from the exchanges, and they should not be used to determine trade prices, route orders, or trigger execution logic. Trading platforms and order-routing tools require real-time exchange data, which means direct exchange licensing. [Contact our sales team](https://www.marketdata.app/contact/) to discuss licensing options for trading use cases. ## Redistribution Rules -The Commercial Plan permits you to **distribute your own derived data** through your application — including via your own API — but does **not** permit redistributing Market Data's raw API responses. In other words: - -- ✅ You can build a UI, dashboard, or product that displays Market Data's data to your users. -- ✅ You can compute derived metrics, signals, or aggregates from our data and serve those to your users (including over your own API). -- ❌ You cannot resell or proxy our raw API responses to your customers. - -If you're looking to offer a market data API to other businesses, you'll need direct exchange licensing — which the Commercial Plan does not provide. [Contact our sales team](https://www.marketdata.app/contact/) if you'd like to discuss your use case. - -## Why SmartMid Instead of Exchange Real-Time? - -Real-time data sourced directly from exchanges has its own [licensing requirements](https://www.marketdata.app/education/stocks/stock-market-data-licensing) that apply on top of any data subscription. By using SmartMid for real-time prices, the Commercial Plan keeps the cost of launching low — most businesses don't need exchange licensing on day one. +The Commercial Plan permits you to **display data to the users of your own product**, but does **not** permit you to redistribute the raw data itself. In other words: -**SmartMid** is our own proprietary derived midpoint price. Because it's a Market Data product rather than exchange data, your application can deliver SmartMid prices to any end user under our Commercial Use Addendum. +- ✅ You can build an app, dashboard, or product that displays the data to your users. +- ✅ You can build SaaS and fintech products on top of the data. +- ❌ You cannot resell or redistribute the raw data. +- ❌ You cannot offer the data as a standalone data service. +- ❌ You cannot white-label the raw data or license it to third parties. -When your business is ready to add real-time exchange data — bid/ask quotes, intraday candles, or real-time options — exchange licensing can be added on top of your Commercial Plan. [Contact our sales team](https://www.marketdata.app/contact/) when you're ready. +If your business needs to resell data or offer a market data API to other businesses, [contact our sales team](https://www.marketdata.app/contact/) to discuss your use case. ## Comparison with Other Plans -| Feature | Starter | Trader | Prime | **Commercial** | -|-------------------------|---------------|---------------|---------------|--------------------------| -| Price | $30/mo | $75/mo | $250/mo | **$250/mo** | -| Commercial Use License | ❌ | ❌ | ❌ | ✅ | -| Daily API Credits | 10,000/day | 100,000/day | Unlimited | Unlimited | -| Per-Minute Rate Limit | No Limit | No Limit | 100,000 | 100,000 | -| Concurrent Requests | 50 | 50 | 50 | 50 | -| Real-Time Stock Prices | Exchange data | Exchange data | Exchange data | SmartMid (derived) | -| Real-Time Exchange Data | ✅ | ✅ | ✅ | ❌ (T+1 historical only) | -| Real-Time Options | 15-min delay | Real-time | Real-time | ❌ (T+1 historical only) | -| Premium Endpoints | ✅ | ✅ | ✅ | ✅ | -| Historical Data | 5 Years | Full Access | Full Access | Full Access (T+1) | +| Feature | Starter | Trader | Prime | **Commercial** | +|--------------------------------|---------|--------|---------|----------------------| +| Price | $30/mo | $75/mo | $250/mo | **$333/mo to start** | +| Commercial Use | ❌ | ❌ | ❌ | ✅ | +| Public Display to Your Users | ❌ | ❌ | ❌ | ✅ | +| Redistribution in Your Product | ❌ | ❌ | ❌ | ✅ | +| WebSocket Streaming | ❌ | ❌ | ❌ | ✅ | +| Tick-Level Market Data | ❌ | ❌ | ❌ | ✅ | ## Why Choose the Commercial Plan? -The Commercial Plan is where most businesses start. At **$250/month**, it's the cheapest commercially-licensed market data subscription on the market — and it's enough to launch a real product, with real-time SmartMid stock prices, full historical depth, no daily credit caps, and generous concurrency. Add exchange licensing later, when your business is ready for it. +The Commercial Plan gives your business what it needs to launch a product on market data: commercial use and display rights, real-time stock and options prices over REST and WebSocket, tick-level and historical data, and no exchange fees or paperwork. It starts at **$333/month, billed quarterly**, with a 14-day free trial. The Commercial Plan is sold through our sales team. [Contact us](https://www.marketdata.app/contact/) to get started or to discuss your specific use case. diff --git a/lib/noindex-head.js b/lib/noindex-head.js index 42e5927d..e546c1a9 100644 --- a/lib/noindex-head.js +++ b/lib/noindex-head.js @@ -49,8 +49,8 @@ * nobody should ever index, on a page that says not to. Measured live on * 2026-09-04. * - * On production it is the `noindex` pages: `account/plans/commercial` and the - * `/internal/` section. + * On production it is the `noindex` pages: the `/internal/` section and the + * search page. * * **Only the canonical is removed.** `og:url` and the JSON-LD `@id` stay, on * every page, in both environments -- Open Graph is not a search directive and diff --git a/redirects.js b/redirects.js index b371720f..ee3b8c92 100644 --- a/redirects.js +++ b/redirects.js @@ -263,8 +263,8 @@ const REDIRECTS = [ // licensing no page of that name, but account/data-policies is the // index of exactly that subject -- redistribution rights, // exchange agreements, professional status. Deliberately - // NOT account/plans/commercial.mdx, which is `unlisted` - // and noindex and must not be a redirect destination. + // NOT account/plans/commercial.mdx, which sells one plan + // rather than explaining licensing. // // option-chain is the singular-hyphenated sibling of options/chains, which // this array already redirects. The plural was fixed and the hyphen was From 1fe777deaaa553151d2e7a9773e12847b876decc Mon Sep 17 00:00:00 2001 From: MarketDataApp <112879596+MarketDataApp@users.noreply.github.com> Date: Fri, 23 Oct 2026 09:42:40 -0400 Subject: [PATCH 09/13] docs(plans): lead the Commercial Plan with what it includes, and point business use at it The Commercial Plan page now opens on its advantage: real-time, delayed, historical and tick-level data and the commercial licence for one price, with no exchange agreements, exchange fees or per-user fees, and no IP limit. A "No Exchange Licensing, No Extra Fees" section says why that matters; the feature list is grouped into data, rights, and tools and limits; "What You Can Build" lists only what the plan permits; the comparison table gains Multiple IP Addresses. The "Not Suitable for Trading" warning and the list of what the plan forbids are gone. A closing "Need More?" sends dedicated exchange feeds, API distribution and resale rights to the contact form as enterprise licensing. The pages that told a business user to "contact sales" for a commercial or exchange licence now name the Commercial Plan instead: the data redistribution, professional status and single-IP policies, the classification dispute and self-employed guides, CORS, and the multiple-environments option of the 403 multiple-IP guide. Enterprise licensing keeps the contact form. Fixes "varity" on Data Plans. --- account/data-policies/data-redistribution.md | 4 +- account/data-policies/professional-status.md | 2 +- account/data-policies/single-ip.md | 2 +- account/plans/commercial.mdx | 72 ++++++++++--------- account/plans/index.mdx | 2 +- .../troubleshooting/classification-dispute.md | 2 +- account/troubleshooting/self-employed.md | 2 + api/cors.mdx | 2 +- api/troubleshooting/multiple-ip-addresses.mdx | 2 +- 9 files changed, 48 insertions(+), 42 deletions(-) diff --git a/account/data-policies/data-redistribution.md b/account/data-policies/data-redistribution.md index 611d1556..d769e170 100644 --- a/account/data-policies/data-redistribution.md +++ b/account/data-policies/data-redistribution.md @@ -21,7 +21,9 @@ The single-IP restriction is one enforcement mechanism for this policy. See [Sin ## Commercial Redistribution -Redistribution is permitted, but it requires a license granted directly by the exchanges — not by Market Data. Market Data cannot authorize redistribution on behalf of an exchange. If your use case involves distributing data to others, contact our sales team and we will connect you with the appropriate exchanges to get the required licenses in place. +To display market data to the users of your own app, dashboard, or product, use the [Commercial Plan](/docs/account/plans/commercial/). It includes a business-wide commercial license with display rights, and there are no exchange agreements to sign, no exchange fees, and no per-user fees. + +For dedicated exchange feeds, API distribution to other businesses, or resale rights, [contact us](https://www.marketdata.app/contact/) about enterprise licensing. ## Violations diff --git a/account/data-policies/professional-status.md b/account/data-policies/professional-status.md index 9834049c..90b5a2fc 100644 --- a/account/data-policies/professional-status.md +++ b/account/data-policies/professional-status.md @@ -4,7 +4,7 @@ description: Market Data self-service plans serve non-professional subscribers o sidebar_position: 4 --- -All Market Data self-service plans are available to **non-professional subscribers only**. Exchange rules require vendors to classify and certify the status of every subscriber who receives real-time market data. It is your responsibility to subscribe under the correct classification. Business use of market data is only available under a commercial plan. +All Market Data self-service plans are available to **non-professional subscribers only**. Exchange rules require vendors to classify and certify the status of every subscriber who receives real-time market data. It is your responsibility to subscribe under the correct classification. Business use of market data is only available under the [Commercial Plan](/docs/account/plans/commercial/), which includes real-time stock and options prices with no exchange licensing and no exchange fees. For a full explanation of how the exchanges define professional status and how to determine your own classification, see [Professional Status Explained](https://www.marketdata.app/education/stocks/professional-status-explained/). diff --git a/account/data-policies/single-ip.md b/account/data-policies/single-ip.md index 6b8987ef..ceced122 100644 --- a/account/data-policies/single-ip.md +++ b/account/data-policies/single-ip.md @@ -31,7 +31,7 @@ If your account has been blocked, see [403: Multiple IP Addresses](/docs/api/tro ## Commercial Use and Multi-Device Access -The single IP policy applies to all standard subscription plans. If your use case legitimately requires API access from multiple IP addresses simultaneously — for example, distributed systems or serving data to multiple users — this constitutes redistribution and requires a commercial license. Please contact sales to discuss licensing options. +The single IP policy applies to all self-service plans. The [Commercial Plan](/docs/account/plans/commercial/) has no IP limit: if your use case requires API access from multiple IP addresses simultaneously — for example, distributed systems or serving data to multiple users — the Commercial Plan lets you call the API from as many servers and IP addresses as your product needs. For needs beyond the Commercial Plan, [contact us](https://www.marketdata.app/contact/) about enterprise licensing. ## Violations diff --git a/account/plans/commercial.mdx b/account/plans/commercial.mdx index 2dbcff43..6e3eb74a 100644 --- a/account/plans/commercial.mdx +++ b/account/plans/commercial.mdx @@ -1,10 +1,10 @@ --- title: Commercial Plan -description: Market Data's commercial plan for businesses and apps that display market data to users, with real-time stock and options prices over REST and WebSocket. +description: Real-time, historical and tick-level stock and options data with a commercial license, and no exchange licensing, exchange fees or per-user fees. sidebar_position: 8 --- -The **Commercial Plan** is for businesses launching an app, dashboard, or product that shows market data to its users. It starts at **$333/month, billed quarterly**, and includes commercial use and display rights, real-time stock and options prices over both REST and WebSocket, and no exchange fees or exchange paperwork. +The **Commercial Plan** gives your business real-time, delayed, historical, and tick-level market data for stocks and options, together with a commercial license to display it to your users — all for one price, starting at **$333/month**. There are no exchange agreements to sign, no exchange fees, and no per-user fees. ## Pricing @@ -16,53 +16,50 @@ The **Commercial Plan** is for businesses launching an app, dashboard, or produc | 7–12 | $666/month | $1,998 | | 13 and on | $999/month | $2,997 | +The price includes the commercial license. There are no exchange fees and no per-user fees on top of it, however many users your product serves. + Every Commercial Plan starts with a **14-day free trial**, with no charge until the trial ends, and there is no long-term contract. [Contact us](https://www.marketdata.app/contact/) to get started. +## No Exchange Licensing, No Extra Fees + +A business that shows market data to its users usually has to sign agreements with each exchange, pay monthly exchange fees, and pay again for every user who sees the data. Those costs grow with every user you add, and the paperwork comes before you can launch. + +The Commercial Plan removes all of it. Real-time prices, delayed exchange data, historical data, and tick-level data all come under one license, at one price. You sign nothing with the exchanges, you pay no exchange fees, and you pay nothing more as your user base grows — so your data costs stay the same whether your product has ten users or ten thousand. + ## What You Get with the Commercial Plan -- **Commercial Use and Display Rights**: A business-wide commercial license. Use the data in your business and display it to the users of your app, dashboard, or product. -- **No Exchange Fees or Paperwork**: No exchange agreements to sign and no exchange fees to pay. See [About the Real-Time Prices](#about-the-real-time-prices) below. -- **Real-Time Stock Prices**: Real-time derived prices for stocks, with last price, open, close, volume, and pre-market and post-market volume. +### Data + +- **Real-Time Stock Prices**: Real-time derived prices that closely track exchange prices, with last price, open, close, volume, and pre-market and post-market volume. - **Real-Time Options Prices**: Real-time derived options prices, with implied volatility and the greeks — delta, gamma, theta, and vega. - **WebSocket Streaming**: Stream real-time stock and options prices over WebSocket, or request them over the REST API. +- **Tick-Level Market Data**: Market data down to the individual tick. - **15-Minute Delayed CBOE Data**: Exchange data from CBOE on a 15-minute delay. - **End-of-Day and Historical Data**: End-of-day and historical data for stocks and options, for backtesting, analytics, and historical charts. -- **Tick-Level Market Data**: Market data down to the individual tick. - **US Fundamentals**: Fundamentals data for US companies. -- **AI Assistant Access**: Connect Claude, ChatGPT, and other AI assistants to the data through an MCP server. -- **Rate Limits**: 2,000 API calls per minute, 1 request per minute for bulk downloads and paging, and 3 WebSocket connections. -## About the Real-Time Prices +### Rights -The real-time stock and options prices on the Commercial Plan are **derived prices**, not exchange quotes. They are calculated to track exchange prices closely, but they are not exchange data, so they carry no exchange licensing requirements. That is what lets the plan include commercial display rights with no exchange fees and no exchange paperwork. +- **Commercial Use and Display Rights**: A business-wide commercial license. Use the data across your business and display it to the users of your app, dashboard, or product. +- **No Exchange Licensing**: No exchange agreements to sign and no exchange paperwork. +- **No Exchange Fees or Per-User Fees**: One price, however many users see the data. +- **No IP Limit**: Call the API from as many servers and IP addresses as your product needs. -Exchange-sourced data on the Commercial Plan comes as **15-minute delayed CBOE data** and as **end-of-day and historical data**. If your product needs real-time exchange data, such as live bid/ask quotes from the exchanges, that requires exchange licensing, which the Commercial Plan does not include. [Contact our sales team](https://www.marketdata.app/contact/) to discuss it. +### Tools and Limits -## Who the Commercial Plan Is For - -The Commercial Plan is for businesses bringing a product to market on top of market data. Common use cases include: - -- **Stock and options apps** that display data to paying users -- **Financial dashboards** distributed to clients or employees -- **Research products and newsletters** that publish data-driven content -- **Charting and analytics tools** built on real-time and historical data -- **Internal business analytics** at firms that need market data for internal use - -### Not Suitable for Trading - -The Commercial Plan is **not suitable for trading applications** or any product where users make execution decisions based on the data. Its real-time prices are derived prices — useful for display, charting, and informational purposes — but they are not live bid/ask quotes from the exchanges, and they should not be used to determine trade prices, route orders, or trigger execution logic. Trading platforms and order-routing tools require real-time exchange data, which means direct exchange licensing. [Contact our sales team](https://www.marketdata.app/contact/) to discuss licensing options for trading use cases. - -## Redistribution Rules +- **AI Assistant Access**: Connect Claude, ChatGPT, and other AI assistants to the data through an MCP server. +- **Rate Limits**: 2,000 API calls per minute, 1 request per minute for bulk downloads and paging, and 3 WebSocket connections. -The Commercial Plan permits you to **display data to the users of your own product**, but does **not** permit you to redistribute the raw data itself. In other words: +## What You Can Build -- ✅ You can build an app, dashboard, or product that displays the data to your users. -- ✅ You can build SaaS and fintech products on top of the data. -- ❌ You cannot resell or redistribute the raw data. -- ❌ You cannot offer the data as a standalone data service. -- ❌ You cannot white-label the raw data or license it to third parties. +The Commercial Plan is made for businesses bringing a product to market on top of market data: -If your business needs to resell data or offer a market data API to other businesses, [contact our sales team](https://www.marketdata.app/contact/) to discuss your use case. +- ✅ **Stock and options apps** that display real-time and historical data to paying users +- ✅ **SaaS and fintech products** built on top of the data +- ✅ **Financial dashboards** distributed to clients or employees +- ✅ **Research products and newsletters** that publish data-driven content +- ✅ **Charting and analytics tools** built on real-time, historical, and tick-level data +- ✅ **Internal business analytics** across your whole company ## Comparison with Other Plans @@ -74,9 +71,14 @@ If your business needs to resell data or offer a market data API to other busine | Redistribution in Your Product | ❌ | ❌ | ❌ | ✅ | | WebSocket Streaming | ❌ | ❌ | ❌ | ✅ | | Tick-Level Market Data | ❌ | ❌ | ❌ | ✅ | +| Multiple IP Addresses | ❌ | ❌ | ❌ | ✅ | ## Why Choose the Commercial Plan? -The Commercial Plan gives your business what it needs to launch a product on market data: commercial use and display rights, real-time stock and options prices over REST and WebSocket, tick-level and historical data, and no exchange fees or paperwork. It starts at **$333/month, billed quarterly**, with a 14-day free trial. +The Commercial Plan is the simplest way to launch a product on market data. One price covers real-time stock and options prices over REST and WebSocket, tick-level, delayed, and historical data, and the commercial license to display all of it — with no exchange agreements, no exchange fees, and no per-user fees as you grow. It starts at **$333/month, billed quarterly**, with a 14-day free trial. + +[Contact us](https://www.marketdata.app/contact/) to get started or to discuss your specific use case. + +## Need More? -The Commercial Plan is sold through our sales team. [Contact us](https://www.marketdata.app/contact/) to get started or to discuss your specific use case. +For dedicated exchange feeds, API distribution to other businesses, or resale rights, [contact us](https://www.marketdata.app/contact/) about enterprise licensing. diff --git a/account/plans/index.mdx b/account/plans/index.mdx index bedb6db2..5a669b86 100644 --- a/account/plans/index.mdx +++ b/account/plans/index.mdx @@ -5,7 +5,7 @@ slug: /plans sidebar_position: 2 --- -Market Data provides a varity of data subscriptions for users who need on-going access to Market Data. Explore the details of all our plans and decide which one is right for you. +Market Data provides a variety of data subscriptions for users who need on-going access to Market Data. Explore the details of all our plans and decide which one is right for you. ## Explore our Plans diff --git a/account/troubleshooting/classification-dispute.md b/account/troubleshooting/classification-dispute.md index c09fe56f..6be9da70 100644 --- a/account/troubleshooting/classification-dispute.md +++ b/account/troubleshooting/classification-dispute.md @@ -31,7 +31,7 @@ If you plan to use market data in connection with a business — including a sta Any use of data to support a business function — such as building a product, providing a service, generating reports for clients, or integrating data into an application — is classified as professional. This includes personal LLCs, even single-member pass-through entities. -Non-professional plans are for **personal, non-commercial use only**. If you need data for a business, you will need a commercial or exchange license. [Contact our sales team](https://www.marketdata.app/contact/) to discuss licensing. +Non-professional plans are for **personal, non-commercial use only**. If you need data for a business, the [Commercial Plan](/docs/account/plans/commercial/) is made for business use. [Contact our sales team](https://www.marketdata.app/contact/) to get started. ### Job Function Suggests Professional Use diff --git a/account/troubleshooting/self-employed.md b/account/troubleshooting/self-employed.md index 0f5ed68d..e87a2ace 100644 --- a/account/troubleshooting/self-employed.md +++ b/account/troubleshooting/self-employed.md @@ -64,6 +64,8 @@ If your business is in a non-financial field (e.g., construction, healthcare, re Professional subscribers never receive real-time exchange data on a self-service plan, no matter which exchange agreements they sign. Real-time access for professional use requires direct exchange licensing, which Market Data arranges individually. [Contact our sales team](https://www.marketdata.app/contact/) to discuss it. Delayed / historical data access remains available on your current plan, depending on the data policies of each exchange. +If your business uses market data in a product or service, the [Commercial Plan](/docs/account/plans/commercial/) is made for it: real-time stock and options prices with a commercial license, and no exchange licensing or exchange fees. + ## Still Need Help? If you are unsure how your business would be classified, please contact our [support helpdesk](https://www.marketdata.app/dashboard/) and describe what your business does. Our support team will let you know what classification applies and what documentation, if any, is needed. diff --git a/api/cors.mdx b/api/cors.mdx index a95d957e..b63594ed 100644 --- a/api/cors.mdx +++ b/api/cors.mdx @@ -23,7 +23,7 @@ Using CORS to serve market data to other people is **redistribution**, regardles - Browser-based products or services that expose Market Data's data to your users or customers - Shared dashboards or tools accessible to people outside your organization -These use cases require a commercial redistribution license. See the [Data Redistribution Policy](/docs/account/data-policies/data-redistribution) for details, or [contact our sales team](https://www.marketdata.app/contact/) to discuss licensing. +These are the uses the [Commercial Plan](/docs/account/plans/commercial/) is made for: it includes the right to display data to your users, with no exchange licensing and no per-user fees. See the [Data Redistribution Policy](/docs/account/data-policies/data-redistribution) for details, or [contact our sales team](https://www.marketdata.app/contact/) to get started. ## CORS Headers diff --git a/api/troubleshooting/multiple-ip-addresses.mdx b/api/troubleshooting/multiple-ip-addresses.mdx index 05d64981..9f33b280 100644 --- a/api/troubleshooting/multiple-ip-addresses.mdx +++ b/api/troubleshooting/multiple-ip-addresses.mdx @@ -82,7 +82,7 @@ When you access the API: Compliant options: - **Serialize**: run only one environment at a time. For most testing and A/B workflows, running scenarios sequentially is sufficient. - **Use the no-auth demo symbols in development**: stock and option endpoints accept **AAPL** (and any AAPL option contract, e.g. `AAPL271217C00250000`) with no token at all. Development and integration tests that exercise the API surface — request shape, response parsing, error handling — can use these symbols without ever touching your account. See [Authentication › Demo The API With No Authentication](/docs/api/authentication/#demo-the-api-with-no-authentication). Note that no-auth requests return historical data only. - - **Commercial license**: if your use case genuinely requires simultaneous parallel data across multiple environments (not testing), contact sales — that case requires a commercial license and our sales team will assist. + - **Commercial Plan**: if your use case genuinely requires simultaneous parallel data across multiple environments (not testing), the [Commercial Plan](/docs/account/plans/commercial/) has no IP limit, so you can call the API from as many servers and IP addresses as your product needs. ## Important Note From 3117b2019680199c9de80523ab775135ff618e60 Mon Sep 17 00:00:00 2001 From: MarketDataApp <112879596+MarketDataApp@users.noreply.github.com> Date: Fri, 23 Oct 2026 11:51:46 -0400 Subject: [PATCH 10/13] docs(plans): drop the check marks from the What You Can Build list The list is a plain bulleted list again; the check marks stay only in the comparison table, where they compare plans. --- account/plans/commercial.mdx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/account/plans/commercial.mdx b/account/plans/commercial.mdx index 6e3eb74a..ddbca7fd 100644 --- a/account/plans/commercial.mdx +++ b/account/plans/commercial.mdx @@ -54,12 +54,12 @@ The Commercial Plan removes all of it. Real-time prices, delayed exchange data, The Commercial Plan is made for businesses bringing a product to market on top of market data: -- ✅ **Stock and options apps** that display real-time and historical data to paying users -- ✅ **SaaS and fintech products** built on top of the data -- ✅ **Financial dashboards** distributed to clients or employees -- ✅ **Research products and newsletters** that publish data-driven content -- ✅ **Charting and analytics tools** built on real-time, historical, and tick-level data -- ✅ **Internal business analytics** across your whole company +- **Stock and options apps** that display real-time and historical data to paying users +- **SaaS and fintech products** built on top of the data +- **Financial dashboards** distributed to clients or employees +- **Research products and newsletters** that publish data-driven content +- **Charting and analytics tools** built on real-time, historical, and tick-level data +- **Internal business analytics** across your whole company ## Comparison with Other Plans From edc11b9566a081ce51b9c2a8e316167ffab4ffe2 Mon Sep 17 00:00:00 2001 From: MarketDataApp <112879596+MarketDataApp@users.noreply.github.com> Date: Fri, 23 Oct 2026 11:55:35 -0400 Subject: [PATCH 11/13] fix(theme): restore the space above the next/previous cards on every doc page src/theme/DocItem/Paginator was the 3.0.1 file with no change of ours. Upstream 3.10 gives the paginator `className="docusaurus-mt-lg"` (3rem); the fork did not, so the cards sat directly under the article. The tag footer used to carry the same margin, and since the tags were retired it renders on no page, so every one of the 263 pages with cards showed a 0px gap. Deleting the swizzle restores upstream: 48px, measured in a browser on two pages of a local build. --- CLAUDE.md | 11 ++++++++++- src/theme/DocItem/Paginator/index.js | 11 ----------- 2 files changed, 10 insertions(+), 12 deletions(-) delete mode 100644 src/theme/DocItem/Paginator/index.js diff --git a/CLAUDE.md b/CLAUDE.md index 5c04e8cb..1b528e81 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -614,7 +614,16 @@ anything that matches. Reconcile the rest by hand -- and check the sibling `styles.module.css` separately, because a component and its stylesheet drift independently. -Twelve customised swizzles and four of our own remain. +Eleven customised swizzles and four of our own remain. + +`src/theme/DocItem/Paginator` was the twelfth, and it was not customised: it +was the 3.0.1 file, which the classification above misread as a change because +upstream had since ADDED `className="docusaurus-mt-lg"` to it. That class is +the only space between the article and the next/previous cards. It went +unnoticed while the tag footer, which carries the same class, rendered above +the cards; retiring the tags on 2026-09-04 left every page with a 0px gap. +Deleted on 2026-10-23. **A swizzle that differs from upstream only by +upstream's newer lines is stale, not customised.** ## `future.v4` is on, and one flag needed a counterweight diff --git a/src/theme/DocItem/Paginator/index.js b/src/theme/DocItem/Paginator/index.js deleted file mode 100644 index caaed73c..00000000 --- a/src/theme/DocItem/Paginator/index.js +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; -import {useDoc} from '@docusaurus/plugin-content-docs/client'; -import DocPaginator from '@theme/DocPaginator'; -/** - * This extra component is needed, because should remain generic. - * DocPaginator is used in non-docs contexts too: generated-index pages... - */ -export default function DocItemPaginator() { - const {metadata} = useDoc(); - return ; -} From 927ca3a3af71ebcc45cb4e6a19ef6360a8151713 Mon Sep 17 00:00:00 2001 From: MarketDataApp <112879596+MarketDataApp@users.noreply.github.com> Date: Fri, 23 Oct 2026 11:59:21 -0400 Subject: [PATCH 12/13] docs(sdk/csharp): PresentGreeks says a greek can be null, not that some feeds omit it The API is not a set of feeds, and the sentence was the only place in the SDK docs that said so. --- sdk/csharp/options/chain.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/csharp/options/chain.mdx b/sdk/csharp/options/chain.mdx index 7d1620d1..3d826e89 100644 --- a/sdk/csharp/options/chain.mdx +++ b/sdk/csharp/options/chain.mdx @@ -92,7 +92,7 @@ public record OptionQuote( double? Iv, double? Delta, double? Gamma, double? Theta, double? Vega, double? Rho); ``` -`OptionQuote.PresentGreeks` returns the set of greeks that are non-null on a given row (some feeds omit `Rho`). +`OptionQuote.PresentGreeks` returns the set of greeks that are non-null on a given row (for example, `Rho` can be null). ## Examples From aa146bce4ff480fa8503d5eac11dea460901dc40 Mon Sep 17 00:00:00 2001 From: MarketDataApp <112879596+MarketDataApp@users.noreply.github.com> Date: Mon, 26 Oct 2026 13:50:10 -0400 Subject: [PATCH 13/13] fix(options): an expiring SPXW contract expires at 4:00 PM, not 4:15 PM Three pages said "index options expire at 4:15 PM Eastern". No contract the API returns carries 4:15 PM. Measured 2026-10-26 on /v1/options/chain/: - PM-settled index options (SPXW, NDXP, RUTW, XSP) carry 16:00 ET, and so do equity options (AAPL). - AM-settled monthlies (SPX, NDX, RUT, VIX) carry 09:30 ET on the expiration date, the time of the opening settlement. Cboe's SPX specification agrees: "Trading in SPXW options will ordinarily cease on the day of expiration, 4:00 pm ET", and SPX options cease "on the business day (usually a Thursday) preceding" expiration. 4:15 PM is the end of the regular session for non-expiring index options, not an expiration time. A customer asked which time applies; the docs were the only source that disagreed with the API. VIXW is left out on purpose: the API stamps it 16:00 although Cboe settles VIX and VIXW on the Special Opening Quotation. That is an API question. --- api/dates-and-times.mdx | 2 +- api/options/chain.mdx | 2 +- api/options/quotes.mdx | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/dates-and-times.mdx b/api/dates-and-times.mdx index af57995a..74e410dd 100644 --- a/api/dates-and-times.mdx +++ b/api/dates-and-times.mdx @@ -38,7 +38,7 @@ For real-time quotes, intraday candles, and `updated` fields, the timestamp repr Although US-listed options primarily trade on exchanges in Chicago (CBOE), the API returns all option timestamps in **Eastern Time**, consistent with the rest of the API. The `updated` field on option quotes and chain responses reflects the Eastern Time snapshot of the data. -Option expiration timestamps reflect the **actual expiration time**, not midnight. Equity options expire at **4:00 PM Eastern** and index options expire at **4:15 PM Eastern**. +Option expiration timestamps reflect the **actual expiration time**, not midnight. Equity options and PM-settled index options, such as SPXW, NDXP, RUTW and XSP, expire at **4:00 PM Eastern**. AM-settled index options, such as the monthly SPX, NDX and RUT contracts, carry **9:30 AM Eastern** on the expiration date, the time of the opening settlement; their last trading day is the business day before. ## Request Date Formats diff --git a/api/options/chain.mdx b/api/options/chain.mdx index 375e17ea..95ef881b 100644 --- a/api/options/chain.mdx +++ b/api/options/chain.mdx @@ -413,7 +413,7 @@ The `am` and `pm` parameters are only applicable for index options such as SPX, - **expiration** `array[number]` - The option's expiration date and time. Equity options expire at 4:00 PM Eastern and index options expire at 4:15 PM Eastern. All timestamps use US Eastern Time (America/New_York). See [Response Timezone](/docs/api/dates-and-times#response-timezone) for details. + The option's expiration date and time. Equity options and PM-settled index options (such as SPXW) expire at 4:00 PM Eastern. AM-settled index options (such as the monthly SPX) carry 9:30 AM Eastern on the expiration date, the time of the opening settlement. All timestamps use US Eastern Time (America/New_York). See [Response Timezone](/docs/api/dates-and-times#response-timezone) for details. - **side** `array[string]` diff --git a/api/options/quotes.mdx b/api/options/quotes.mdx index f350a737..3b21e240 100644 --- a/api/options/quotes.mdx +++ b/api/options/quotes.mdx @@ -231,7 +231,7 @@ foreach (var quote in (await client.Options.GetQuoteAsync("AAPL271217C00250000") - **expiration** `array[number]` - The option's expiration date and time. Equity options expire at 4:00 PM Eastern and index options expire at 4:15 PM Eastern. All timestamps use US Eastern Time (America/New_York). See [Response Timezone](/docs/api/dates-and-times#response-timezone) for details. + The option's expiration date and time. Equity options and PM-settled index options (such as SPXW) expire at 4:00 PM Eastern. AM-settled index options (such as the monthly SPX) carry 9:30 AM Eastern on the expiration date, the time of the opening settlement. All timestamps use US Eastern Time (America/New_York). See [Response Timezone](/docs/api/dates-and-times#response-timezone) for details. - **side** `array[string]`