Skip to content

sdk-sync: API 2.0.0+ffb34b7 → sdk-java (minor) - #94

Closed
marketdata-sdk-sync[bot] wants to merge 3 commits into
mainfrom
sdk-sync/2.0.0-ffb34b7
Closed

marketdata-sdk-sync[bot] wants to merge 3 commits into
mainfrom
sdk-sync/2.0.0-ffb34b7

Conversation

@marketdata-sdk-sync

@marketdata-sdk-sync marketdata-sdk-sync Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Generated by sdk-auto-sync for API release 2.0.0 (commit ffb34b7).

Changes in the API surface

Snapshots ae2b047c8f6f → c2a31e277345:

~ GET /v1/options/chain/{underlying}/ ?dte: string  (was integer)

What the agent did

tests: Build fails as expected (compilation errors for not-yet-implemented symbols), confirming phase-1 tests are in place. Integration test file wasn't reached since unit test compilation already failed first — expected, not run by this command anyway.

Added wire, validation, regression, and integration tests for the dte parameter's type change (integer → string) in OptionsResourceTest.java and OptionsIntegrationTest.java:

  • Wire tests: single value (existing, unchanged), new dteList (comma-separated), dteRange (closed range), and dteComparison for each of the four operators (GT/GTE/LT/LTE).
  • Regression: the pre-existing dte(int) factory still accepts a value above the new 36500 upper bound and sends it to the wire unchanged — no new check added to it.
  • Validation: negative and above-36500 values rejected for the three new factories, plus min>max for dteRange — all on newly-added methods, so no existing caller's error type changes.
  • Integration: one test per form (single/list/range/comparison) against the live chain endpoint, asserting shape (distinct-expiration counts, bounds satisfied) rather than exact server-side "closest" picks.

gradle test --no-daemon --console=plain fails to compile as expected (dteList/dteRange/dteComparison don't exist yet).

implement: Both green.

Implemented dte's type change (integer → string) on /v1/options/chain/: added three new ExpirationFilter variants (DteList, DteRange, DteComparison) covering the comma-list, closed-range and comparison forms, alongside the unchanged single-value Dte, reusing StrikeFilter.Operator for the shared comparison syntax.

  • Documentation: docs/options/chain.md now lists and demonstrates all four dte forms.
  • Doc comments: every new factory and record carries its own Javadoc.
  • Wire test per form/value: already written in phase 1 (list, range, GT/GTE/LT/LTE each asserted individually); unchanged here.
  • Validation on every construction path: compact constructors on the new records enforce bounds/non-null directly (not only the factories), with added tests constructing DteList directly (empty, null list, null element).
  • Coverage: verified via the JaCoCo HTML report — no uncovered lines/branches in the touched classes; no exclusions added.
  • Examples/README: OptionsAdvancedExample.java gained a dteComparison demo; OptionsExample.java, README.md, docs/client.md, docs/options/{README,quotes,expirations,lookup}.md, docs/.sync-manifest.txt, ADR-006/ADR-008 left unchanged — their "chain"/"expiration" matches are unrelated (CompletableFuture chaining, other endpoints, or the ADR's historical decision record, which a non-breaking sealed-type addition doesn't invalidate).

The existing dte(int) factory keeps its original check only (no upper bound added), confirmed by a regression test that a value above 36500 still reaches the wire unchanged.

changelog: Added changelog entry under ## [Unreleased] documenting the three new ExpirationFilter dte factory methods (dteList, dteRange, dteComparison) for API 2.0.0's expanded string ?dte parameter forms.

Files

  • CHANGELOG.md
  • docs/options/chain.md
  • examples/consumer-test/src/main/java/com/marketdata/examples/resources/OptionsAdvancedExample.java
  • src/integrationTest/java/com/marketdata/sdk/OptionsIntegrationTest.java
  • src/main/java/com/marketdata/sdk/OptionsResource.java
  • src/main/java/com/marketdata/sdk/options/ExpirationFilter.java
  • src/test/java/com/marketdata/sdk/OptionsResourceTest.java

Version

Public-surface change computed by the pipeline: minor

  • added: ExpirationFilter.DteList
  • added: ExpirationFilter.dteList(int, int[])
  • added: ExpirationFilter.DteRange
  • added: ExpirationFilter.dteRange(int, int)
  • added: ExpirationFilter.DteComparison
  • added: ExpirationFilter.dteComparison(StrikeFilter.Operator, int)

Live-API suite

  • src/integrationTest/java/com/marketdata/sdk/OptionsIntegrationTest.java

Files of this suite changed by this pull request. The pipeline did not run the suite (it has no API token); this pull request's CI does.

Job log

The full record of this job — every phase, test and build result, review findings and how they were resolved, and each fix round after the PR was opened — is in the job log comment.


3 coder run(s) · 2 review(s) · 102 turns · 10,248,543 tokens · US$ 5.34 · item 5c097984-5f7b-401b-abba-235a3f417767

Agent runs
  • coder · claude-haiku-4-5-20251001, claude-sonnet-5 · 1,808,845 tokens (93,869 in, 1,686,041 cached, 28,935 out) · 24 turns · US$ 1.01 · 5 min 14 s
  • coder · claude-sonnet-5 · 7,452,987 tokens (51,005 in, 7,377,060 cached, 24,922 out) · 56 turns · US$ 1.93 · 5 min 29 s
  • reviewer · claude-haiku-4-5-20251001, claude-opus-5 · 646,173 tokens (102,799 in, 524,838 cached, 18,536 out) · 10 turns · US$ 1.80 · 4 min 16 s
  • security · claude-haiku-4-5-20251001, claude-sonnet-5 · 83,165 tokens (82,157 in, 0 cached, 1,008 out) · 2 turns · US$ 0.39 · 15 s
  • analyst · claude-haiku-4-5-20251001 · 185,851 tokens (38,340 in, 138,056 cached, 9,455 out) · 6 turns · US$ 0.15 · 1 min 27 s
  • changelog · claude-haiku-4-5-20251001 · 71,522 tokens (25,435 in, 44,374 cached, 1,713 out) · 4 turns · US$ 0.07 · 19 s

tests: Build fails as expected (compilation errors for not-yet-implemented symbols), confirming phase-1 tests are in place. Integration test file wasn't reached since unit test compilation already failed first — expected, not run by this command anyway.

Added wire, validation, regression, and integration tests for the `dte` parameter's type change (integer → string) in `OptionsResourceTest.java` and `OptionsIntegrationTest.java`:

- Wire tests: single value (existing, unchanged), new `dteList` (comma-separated), `dteRange` (closed range), and `dteComparison` for each of the four operators (GT/GTE/LT/LTE).
- Regression: the pre-existing `dte(int)` factory still accepts a value above the new 36500 upper bound and sends it to the wire unchanged — no new check added to it.
- Validation: negative and above-36500 values rejected for the three new factories, plus min>max for `dteRange` — all on newly-added methods, so no existing caller's error type changes.
- Integration: one test per form (single/list/range/comparison) against the live chain endpoint, asserting shape (distinct-expiration counts, bounds satisfied) rather than exact server-side "closest" picks.

`gradle test --no-daemon --console=plain` fails to compile as expected (`dteList`/`dteRange`/`dteComparison` don't exist yet).

implement: Both green.

Implemented `dte`'s type change (integer → string) on `/v1/options/chain/`: added three new `ExpirationFilter` variants (`DteList`, `DteRange`, `DteComparison`) covering the comma-list, closed-range and comparison forms, alongside the unchanged single-value `Dte`, reusing `StrikeFilter.Operator` for the shared comparison syntax.

- Documentation: `docs/options/chain.md` now lists and demonstrates all four `dte` forms.
- Doc comments: every new factory and record carries its own Javadoc.
- Wire test per form/value: already written in phase 1 (list, range, GT/GTE/LT/LTE each asserted individually); unchanged here.
- Validation on every construction path: compact constructors on the new records enforce bounds/non-null directly (not only the factories), with added tests constructing `DteList` directly (empty, null list, null element).
- Coverage: verified via the JaCoCo HTML report — no uncovered lines/branches in the touched classes; no exclusions added.
- Examples/README: `OptionsAdvancedExample.java` gained a `dteComparison` demo; `OptionsExample.java`, `README.md`, `docs/client.md`, `docs/options/{README,quotes,expirations,lookup}.md`, `docs/.sync-manifest.txt`, ADR-006/ADR-008 left unchanged — their "chain"/"expiration" matches are unrelated (CompletableFuture chaining, other endpoints, or the ADR's historical decision record, which a non-breaking sealed-type addition doesn't invalidate).

The existing `dte(int)` factory keeps its original check only (no upper bound added), confirmed by a regression test that a value above 36500 still reaches the wire unchanged.

changelog: Added changelog entry under `## [Unreleased]` documenting the three new `ExpirationFilter` dte factory methods (`dteList`, `dteRange`, `dteComparison`) for API 2.0.0's expanded string `?dte` parameter forms.
@marketdata-sdk-sync marketdata-sdk-sync Bot added minor adds to the SDK's public surface and breaks nothing sdk-sync: in progress sdk-sync is still working on this PR: CI, code review, fixes labels Oct 14, 2026
@marketdata-sdk-sync

marketdata-sdk-sync Bot commented Oct 14, 2026 •

Copy link
Copy Markdown
Author

🧾 Job log — sdk-sync

sdk-auto-sync job log

API release 2.0.0 (commit ffb34b7)
SDK sdk-java
Branch sdk-sync/2.0.0-ffb34b7
API surface ae2b047c8f6f → c2a31e277345
Date 2026-10-14 12:41:13Z
Outcome done

Changes in the API surface

~ GET /v1/options/chain/{underlying}/ ?dte: string  (was integer)

1. tests

Coder (24 turns, US$ 1.01, 5 min 14 s):

Build fails as expected (compilation errors for not-yet-implemented symbols), confirming phase-1 tests are in place. Integration test file wasn't reached since unit test compilation already failed first — expected, not run by this command anyway.

Added wire, validation, regression, and integration tests for the dte parameter's type change (integer → string) in OptionsResourceTest.java and OptionsIntegrationTest.java:

  • Wire tests: single value (existing, unchanged), new dteList (comma-separated), dteRange (closed range), and dteComparison for each of the four operators (GT/GTE/LT/LTE).
  • Regression: the pre-existing dte(int) factory still accepts a value above the new 36500 upper bound and sends it to the wire unchanged — no new check added to it.
  • Validation: negative and above-36500 values rejected for the three new factories, plus min>max for dteRange — all on newly-added methods, so no existing caller's error type changes.
  • Integration: one test per form (single/list/range/comparison) against the live chain endpoint, asserting shape (distinct-expiration counts, bounds satisfied) rather than exact server-side "closest" picks.

gradle test --no-daemon --console=plain fails to compile as expected (dteList/dteRange/dteComparison don't exist yet).

Gates:

  • tests (expected to fail), attempt 1: failed — Execution failed for task ':compileTestJava' (registered by plugin class 'org.gradle.api.plugins.JavaBasePlugin'). (8 s)

2. implement

Coder (56 turns, US$ 1.93, 5 min 29 s):

Both green.

Implemented dte's type change (integer → string) on /v1/options/chain/: added three new ExpirationFilter variants (DteList, DteRange, DteComparison) covering the comma-list, closed-range and comparison forms, alongside the unchanged single-value Dte, reusing StrikeFilter.Operator for the shared comparison syntax.

  • Documentation: docs/options/chain.md now lists and demonstrates all four dte forms.
  • Doc comments: every new factory and record carries its own Javadoc.
  • Wire test per form/value: already written in phase 1 (list, range, GT/GTE/LT/LTE each asserted individually); unchanged here.
  • Validation on every construction path: compact constructors on the new records enforce bounds/non-null directly (not only the factories), with added tests constructing DteList directly (empty, null list, null element).
  • Coverage: verified via the JaCoCo HTML report — no uncovered lines/branches in the touched classes; no exclusions added.
  • Examples/README: OptionsAdvancedExample.java gained a dteComparison demo; OptionsExample.java, README.md, docs/client.md, docs/options/{README,quotes,expirations,lookup}.md, docs/.sync-manifest.txt, ADR-006/ADR-008 left unchanged — their "chain"/"expiration" matches are unrelated (CompletableFuture chaining, other endpoints, or the ADR's historical decision record, which a non-breaking sealed-type addition doesn't invalidate).

The existing dte(int) factory keeps its original check only (no upper bound added), confirmed by a regression test that a value above 36500 still reaches the wire unchanged.

Gates:

  • tests, attempt 1: passed (7 s)
  • build, attempt 1: passed (7 s)

3. review 1

Reviewer (10 turns, US$ 1.80, 4 min 16 s): approved

The four dte forms (single, comma list, closed range, comparison) are modeled as new sealed ExpirationFilter variants with canonical-constructor validation, wire tests for every form and every Operator constant, docs and an example; the pre-existing dte(int) keeps its error behaviour and has a regression test. Version impact: minor (new permitted sealed subtypes only, per this repo's public-surface rules). Remaining issues are in the live-API assertions and one doc gap; nothing blocking.

  • [minor] src/integrationTest/java/com/marketdata/sdk/OptionsIntegrationTest.java:138 — chainDteSingleValueNarrowsToOneExpiration asserts only that the chain spans one expiration, which this repo's own docs say is also true of the unfiltered chain ("if omitted, the API narrows to the front month"), so it can pass with the dte parameter dropped entirely. Strengthen it with an assertion the response itself supports, e.g. that dte(30) and a distant value such as dte(365) return different expirations, or that the result differs from the same call without the filter.
  • [minor] src/integrationTest/java/com/marketdata/sdk/OptionsIntegrationTest.java:202 — chainDteComparisonReturnsOnlyExpirationsSatisfyingOperator uses LT, 45 and asserts every row's dte is strictly < 45, while the API description says the comparison bounds are "inclusive"; if the server includes the bound this fails on every day an AAPL expiration lands exactly 45 days out (frequent, with weeklies). Use Operator.LTE with isLessThanOrEqualTo(45), which holds under either reading.
  • [minor] src/main/java/com/marketdata/sdk/options/ExpirationFilter.java:47 — The dte(int) doc comment is rewritten by this change but omits two things the new API description states: the documented maximum of 36500 (and that, unlike the new variants, this factory passes larger values through to the API unchecked) and that dte is relative to the chain's date parameter when one is set. Add both notes here (and the date note to docs/options/chain.md) so the asymmetry with dteList/dteRange/dteComparison is deliberate on the page, not a surprise.

4. security

Security (2 turns, US$ 0.39, 15 s): approved

The change adds dteList/dteRange/dteComparison variants to ExpirationFilter and wires them into the chain query string. All new parameters are numeric (int/List) with explicit bounds checks (0–36500), and are serialized through the existing RequestSpec query-encoding path, which URL-encodes reserved characters as shown in the tests. No user-controlled strings, secrets, new dependencies, or unsafe defaults are introduced; no security issue found.

  • no findings

5. assess

Analyst (6 turns, US$ 0.15, 1 min 27 s) — public surface:

Three new sealed variants of ExpirationFilter (DteList, DteRange, DteComparison) are added to support the API's expanded dte parameter syntax: comma-separated lists, closed ranges, and comparison operators. Existing code compiling against ExpirationFilter.dte(int) continues unchanged. Version impact: major (sealed variant additions break exhaustive switch statements at consumer call sites, per ADR-002 design intent).

  • added: ExpirationFilter.DteList
  • added: ExpirationFilter.dteList(int, int[])
  • added: ExpirationFilter.DteRange
  • added: ExpirationFilter.dteRange(int, int)
  • added: ExpirationFilter.DteComparison
  • added: ExpirationFilter.dteComparison(StrikeFilter.Operator, int)

Computed by the pipeline: minor; changelog entry written

6. changelog

Coder (4 turns, US$ 0.07, 19 s):

Added changelog entry under ## [Unreleased] documenting the three new ExpirationFilter dte factory methods (dteList, dteRange, dteComparison) for API 2.0.0's expanded string ?dte parameter forms.

Gates:

  • build, attempt 1: passed (7 s)

Totals

  • Bump: minor
  • Coder runs: 3
  • Review runs: 2
  • Gates run: 4 (1 failed)
  • Files changed by the agent: 7
  • Turns: 102
  • Tokens: 10,248,543
  • Estimated cost: US$ 5.34
  • Time: 17 min 45 s (agents 17 min 00 s, gates 29 s)

Agent runs

  • coder · claude-haiku-4-5-20251001, claude-sonnet-5 · 1,808,845 tokens (93,869 in, 1,686,041 cached, 28,935 out) · 24 turns · US$ 1.01 · 5 min 14 s
  • coder · claude-sonnet-5 · 7,452,987 tokens (51,005 in, 7,377,060 cached, 24,922 out) · 56 turns · US$ 1.93 · 5 min 29 s
  • reviewer · claude-haiku-4-5-20251001, claude-opus-5 · 646,173 tokens (102,799 in, 524,838 cached, 18,536 out) · 10 turns · US$ 1.80 · 4 min 16 s
  • security · claude-haiku-4-5-20251001, claude-sonnet-5 · 83,165 tokens (82,157 in, 0 cached, 1,008 out) · 2 turns · US$ 0.39 · 15 s
  • analyst · claude-haiku-4-5-20251001 · 185,851 tokens (38,340 in, 138,056 cached, 9,455 out) · 6 turns · US$ 0.15 · 1 min 27 s
  • changelog · claude-haiku-4-5-20251001 · 71,522 tokens (25,435 in, 44,374 cached, 1,713 out) · 4 turns · US$ 0.07 · 19 s

Code review fix 1 — 2026-10-14 12:59:10Z

Outcome: done

Time: 5 min 49 s (agents 5 min 36 s, gates 13 s)

1. code review fix 1

The code review asked for changes:

  • [Should fix] List test accepts an ignored filter (src/integrationTest/java/com/marketdata/sdk/OptionsIntegrationTest.java:159-177)
    The assertion permits one expiration, which is also the endpoint's default response when dte is omitted, so the test passes if the API ignores the comma-list syntax. The successful CI run does not settle that behavior. Compare the result with the union of the corresponding single-dte requests or add another discriminating assertion.
    Evidence: assertThat(distinctExpirations)...isBetween(1L, 3L);
  • [Should fix] Comparison test excludes an inclusive bound (src/integrationTest/java/com/marketdata/sdk/OptionsIntegrationTest.java:201-220)
    The API documents comparison bounds as inclusive, but this test sends LT, 45 and requires every result to be strictly below 45. The current run can pass merely because no expiration landed exactly on the moving 45-day boundary. Use LTE with isLessThanOrEqualTo(45) so the live test remains valid when that boundary exists.
    Evidence: .expirationFilter(ExpirationFilter.dteComparison(StrikeFilter.Operator.LT, 45)) and assertThat(dte.intValue()).isLessThan(45);
  • [Should fix] DTE docs omit date and limit behavior (src/main/java/com/marketdata/sdk/options/ExpirationFilter.java:47-51)
    The rewritten public documentation does not say that DTE is relative to the chain request's date, nor that the API maximum is 36500 while this legacy factory deliberately passes larger values through. That makes the existing factory's behavior unexpectedly different from the new variants. Document both details here and on the chain resource page.
    Evidence: Days-to-expiration, single value — wire form {@code ?dte=N}. Limits the option chain to the expiration date closest to {@code days}.

Coder (28 turns, US$ 0.65, 4 min 06 s):

Both green from a clean build.

  • List test accepts an ignored filter: Replaced the isBetween(1, 3) assertion with chainDteCommaListMatchesUnionOfSingleDteRequests, which compares dteList(15, 30, 45)'s resulting expiration set against the union of the three corresponding single-dte requests — a comma-list ignored by the server would fall back to the front-month expiration and fail to match that union.
  • Comparison test excludes an inclusive bound: Changed the comparison test from Operator.LT, 45 / isLessThan(45) to Operator.LTE, 45 / isLessThanOrEqualTo(45), matching the API's documented inclusive bounds.
  • DTE docs omit date and limit behavior: Added a shared note on ExpirationFilter's interface Javadoc that all dte* variants count days from the chain request's date when set, or from today; added a note on dte(int) specifically that the API's max is 36500 and that, unlike the three new variants, this legacy factory doesn't enforce it locally; mirrored both notes in docs/options/chain.md.

No CHANGELOG change was needed — nothing here alters behavior or the public surface, only tests and documentation. gradle test and gradle build (including Spotless, which required spotlessApply to reformat the new lines) both pass from a clean build.

Gates:

  • tests, attempt 1: passed (6 s)
  • build, attempt 1: passed (7 s)

2. review 1

Reviewer (5 turns, US$ 0.56, 1 min 21 s): approved

The fix resolves all three review findings correctly: the comma-list integration test is now discriminating (an ignored list syntax would return the front month, which cannot equal the union of the 15/30/45 single-dte calls), the comparison test moved to the inclusive LTE/isLessThanOrEqualTo pair while all four operators keep their wire tests, and the date-relativity plus unenforced-36500 notes are documented on ExpirationFilter and docs/options/chain.md and are accurate against the code. No test was weakened, no public surface or behaviour changed, so no CHANGELOG entry is needed.

  • [minor] src/integrationTest/java/com/marketdata/sdk/OptionsIntegrationTest.java:185 — The test now issues four unbounded AAPL chain requests and asserts strict set equality across them; the "closest expiration" the server picks for 15/30/45 shifts if the calls straddle a dte rollover, and the payloads are the full chain. Adding .strikeLimit(1) to the list call and to singleDteExpirations would keep the expiration sets identical while shrinking the responses, matching the convention stated in chainExpirationAllSpansMultipleExpirations.

3. security

Security (2 turns, US$ 0.15, 9 s): approved

The fix only changes integration-test assertions (now comparing against a union of live-request results and using an inclusive bound), javadoc/documentation text, and a doc comment in ExpirationFilter.java — no production request-building, parsing, logging, or dependency code changed. Nothing here touches input encoding, credentials, TLS, deserialization, or file/path handling, so there is no security risk to flag.

  • no findings

Code review fix 2 — 2026-10-14 13:15:56Z

Outcome: done

Time: 7 min 08 s (agents 6 min 55 s, gates 13 s)

1. code review fix 2

The code review asked for changes:

  • [Should fix] Live tests do not prove dte filtering (src/integrationTest/java/com/marketdata/sdk/OptionsIntegrationTest.java:140-245)
    These assertions can pass if the server ignores dte: the default chain has one near-term expiration, the list expectation comes from the same potentially ignored requests, and that default also satisfies 0–45 and <=45. Use requests whose expected results differ from the unfiltered chain, and assert that the list union contains multiple expirations.
    Evidence: assertThat(distinctExpirations)...isEqualTo(1), assertThat(listExpirations)...isEqualTo(union), and the range/comparison tests only require 0..45 or <=45.
  • [Should fix] Live tests depend on the wall clock (src/integrationTest/java/com/marketdata/sdk/OptionsIntegrationTest.java:140-245)
    Every added request omits the chain date, so the new contract computes dte from today. Results can change at Eastern midnight, including between the sequential single-value and list requests. Set a fixed historical chain date or use the repository's date helper.
    Evidence: ExpirationFilter.java states that dte is counted “from today otherwise,” while each added OptionsChainRequest.builder(UNDERLYING) request omits a date.

Coder (23 turns, US$ 0.86, 5 min 04 s):

Only the integration test file changed, within limits. No CHANGELOG update needed since this round changes only integration test assertions, no behavior or public-surface change.

Finding 1 (dte filtering not proven): Rewrote the four dte integration tests so each one can fail on an ignored/broken parameter: the single-value test now compares dte(365) against an explicit unfiltered-chain baseline and asserts the expiration differs; the list test now requires more than one distinct expiration (on top of the existing union check) using near/mid/far values (15/180/365); the range and comparison tests now use bounds ([90, 365], GTE 90) that the front-month default cannot satisfy, instead of [0,45]/LTE 45 which the unfiltered chain also happens to pass.

Finding 2 (wall-clock dependency): Added a FIXED_CHAIN_DATE constant (2025-06-02, a historical NYSE trading day) and passed .date(FIXED_CHAIN_DATE) to every chain call used by these tests, so dte is always computed from that fixed day rather than from "today," removing the Eastern-midnight rollover risk between sequential requests.

Ran gradle test --no-daemon --console=plain and gradle build --no-daemon --console=plain (plus spotlessApply for formatting); both pass. The new/changed assertions are not run here — no MARKETDATA_TOKEN is configured, consistent with the brief.

Gates:

  • tests, attempt 1: passed (6 s)
  • build, attempt 1: passed (7 s)

2. review 1

Reviewer (10 turns, US$ 0.65, 1 min 51 s): approved

The fix resolves both review findings: every dte live request (including the new unfiltered baseline) now pins date(FIXED_CHAIN_DATE), so no assertion depends on the wall clock, and each form is now distinguishable from the unfiltered front-month chain (dte 365 vs. baseline, list size > 1 plus union equality, range/comparison thresholds at 90+). No test was weakened and no production code, docs or CHANGELOG obligation is affected (tests-only change). Remaining notes are minor robustness/convention points.

  • [minor] src/integrationTest/java/com/marketdata/sdk/OptionsIntegrationTest.java:254 — The range and comparison tests assert the response's dte column against the requested bounds while the chain date is historical, which holds only if the server computes that column relative to the date parameter rather than to today. The repository documents only that the dte filter counts from date (ExpirationFilter.java:20-22), not the column. Deriving the expected dte from q.expiration() minus FIXED_CHAIN_DATE would not depend on that unverified rule.
  • [minor] src/integrationTest/java/com/marketdata/sdk/OptionsIntegrationTest.java:147 — FIXED_CHAIN_DATE is ~16 months before today, while every other live test in the suite stays within one month (StocksIntegrationTest.java:60, MarketsIntegrationTest.java:47). If the token's plan or the chain endpoint's retention does not reach that far back, all four dte tests fail permanently (402 is thrown, not treated as no-data). A recent fixed trading day would keep the determinism with less exposure.
  • [minor] src/integrationTest/java/com/marketdata/sdk/OptionsIntegrationTest.java:147 — The new FIXED_CHAIN_DATE constant is declared mid-class between test methods instead of with UNDERLYING at the top of the class. Move it to the field block at the top to match the file's existing layout.

3. security

The pipeline:

  • the security reviewer did not run: the fix only touched tests and documentation

@codecov

codecov Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.29%. Comparing base (d3519f0) to head (2c07122).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@             Coverage Diff              @@
##               main      #94      +/-   ##
============================================
+ Coverage     98.27%   98.29%   +0.02%     
- Complexity     1043     1053      +10     
============================================
  Files           123      123              
  Lines          2606     2644      +38     
  Branches        301      309       +8     
============================================
+ Hits           2561     2599      +38     
  Partials         45       45              
Files with missing lines Coverage Δ
.../main/java/com/marketdata/sdk/OptionsResource.java 98.57% <100.00%> (+0.04%) ⬆️
...a/com/marketdata/sdk/options/ExpirationFilter.java 98.07% <100.00%> (+3.07%) ⬆️

Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 682a304...2c07122. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@marketdata-code-review

marketdata-code-review Bot commented Oct 14, 2026 •

Copy link
Copy Markdown

✅ Ready — Code review

Adds additive DTE list, range, and comparison filters for option-chain requests, with documentation, validation, wire-format tests, and live API coverage. Version impact: minor.

Rating patch 6/6 (exemplary) · proof 6/6 (comprehensive) · overall 6/6

Since last review

  • Resolved: f5365d3e, 2129261f
  • 0 still open, 0 new

Reviewed 2c07122 · revision 3 · codex (gpt-5.6-sol) · claude unavailable · rules: default, sdk

sdk-bot added 2 commits October 14, 2026 09:10
code review fix 1: Both green from a clean build.

- List test accepts an ignored filter: Replaced the `isBetween(1, 3)` assertion with `chainDteCommaListMatchesUnionOfSingleDteRequests`, which compares `dteList(15, 30, 45)`'s resulting expiration set against the union of the three corresponding single-`dte` requests — a comma-list ignored by the server would fall back to the front-month expiration and fail to match that union.
- Comparison test excludes an inclusive bound: Changed the comparison test from `Operator.LT, 45` / `isLessThan(45)` to `Operator.LTE, 45` / `isLessThanOrEqualTo(45)`, matching the API's documented inclusive bounds.
- DTE docs omit date and limit behavior: Added a shared note on `ExpirationFilter`'s interface Javadoc that all `dte*` variants count days from the chain request's `date` when set, or from today; added a note on `dte(int)` specifically that the API's max is 36500 and that, unlike the three new variants, this legacy factory doesn't enforce it locally; mirrored both notes in `docs/options/chain.md`.

No CHANGELOG change was needed — nothing here alters behavior or the public surface, only tests and documentation. `gradle test` and `gradle build` (including Spotless, which required `spotlessApply` to reformat the new lines) both pass from a clean build.
code review fix 2: Only the integration test file changed, within limits. No CHANGELOG update needed since this round changes only integration test assertions, no behavior or public-surface change.

Finding 1 (dte filtering not proven): Rewrote the four dte integration tests so each one can fail on an ignored/broken parameter: the single-value test now compares `dte(365)` against an explicit unfiltered-chain baseline and asserts the expiration differs; the list test now requires more than one distinct expiration (on top of the existing union check) using near/mid/far values (15/180/365); the range and comparison tests now use bounds (`[90, 365]`, `GTE 90`) that the front-month default cannot satisfy, instead of `[0,45]`/`LTE 45` which the unfiltered chain also happens to pass.

Finding 2 (wall-clock dependency): Added a `FIXED_CHAIN_DATE` constant (`2025-06-02`, a historical NYSE trading day) and passed `.date(FIXED_CHAIN_DATE)` to every chain call used by these tests, so `dte` is always computed from that fixed day rather than from "today," removing the Eastern-midnight rollover risk between sequential requests.

Ran `gradle test --no-daemon --console=plain` and `gradle build --no-daemon --console=plain` (plus `spotlessApply` for formatting); both pass. The new/changed assertions are not run here — no `MARKETDATA_TOKEN` is configured, consistent with the brief.
@marketdata-sdk-sync marketdata-sdk-sync Bot removed the sdk-sync: in progress sdk-sync is still working on this PR: CI, code review, fixes label Oct 14, 2026
@MarketDataDev03

Copy link
Copy Markdown
Collaborator

Closing to re-run the pipeline for this API release from scratch.

@MarketDataDev03
MarketDataDev03 deleted the sdk-sync/2.0.0-ffb34b7 branch October 14, 2026 18:29
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

minor adds to the SDK's public surface and breaks nothing review: ready

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant