Skip to content

feat: add volatility surface API and JavaFX visualization - #17

Merged
iamchorchos merged 6 commits into
mainfrom
feat/javafx-volatility-surface
Jul 23, 2026
Merged

feat: add volatility surface API and JavaFX visualization#17
iamchorchos merged 6 commits into
mainfrom
feat/javafx-volatility-surface

Conversation

@iamchorchos

Copy link
Copy Markdown
Owner

Summary

Adds a volatility-surface market-data API and optional JavaFX visualization module.

  • Adds VolatilitySurface and FlatVolatilitySurface, indexed by expiry and
    ln(K / F(T)).
  • Extends ForwardBlack76 to obtain implied volatility from a surface while
    preserving scalar-volatility overloads.
  • Avoids querying VolatilitySurface for expired options; T = 0 returns
    intrinsic value after validating the forward and funding discount factor.
  • Adds thegreeklab-visualization, which samples a surface into an immutable
    grid and renders a resizable JavaFX heatmap.
  • Converts the Maven build to core and optional visualization artifacts, and
    updates CI, release packaging, README, usage, math, publishing notes and
    changelog.

Validation

  • Ran .\mvnw.cmd verify on JDK 22 successfully.
  • Added tests for FlatVolatilitySurface, surface-aware ForwardBlack76,
    expiry short-circuiting without a volatility-surface query, sampler spacing,
    grid validation and defensive copying.
  • Existing Forward Black flat-curve equivalence and direct-forward tests pass.
  • Verified source, Javadoc and license artifacts are produced for the optional
    visualization module.
  • Verified the Windows native-DLL Maven scenario in the multi-module reactor.

Checklist

  • I kept the pull request focused and reviewed my own diff.
  • I ran ./mvnw verify (or explained why it is not applicable).
  • I added or updated tests for changed behavior.
  • I updated public documentation when required.
  • I documented the source and tolerance of new numerical reference data. No new numerical reference data was added.
  • I verified that new code, data and dependencies have compatible licenses. OpenJFX is GPLv2 with the Classpath Exception and remains an optional dependency; see OpenJFX licensing.
  • I did not commit secrets, generated build output or local configuration.

@codacy-production

codacy-production Bot commented Jul 23, 2026

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 97 complexity · -2 duplication

Metric Results
Complexity 97
Duplication -2

View in Codacy

🟢 Coverage 100.00% diff coverage · +0.21% coverage variation

Metric Results
Coverage variation +0.21% coverage variation (-1.00%)
Diff coverage 100.00% diff coverage

View coverage diff in Codacy

Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (7814fd9) 1643 1502 91.42%
Head commit (81e4e10) 1672 (+29) 1532 (+30) 91.63% (+0.21%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#17) 41 41 100.00%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

AI Reviewer: first review requested successfully. AI can make mistakes. Always validate suggestions.

Run reviewer

TIP This summary will be updated as you push new changes.

@iamchorchos
iamchorchos merged commit b967aaa into main Jul 23, 2026
5 checks passed

@codacy-production codacy-production Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

The pull request introduces a well-structured Volatility Surface API, but the project organization for the thegreeklab-core module deviates significantly from standard Maven conventions by referencing source directories outside its own module root. This structural inconsistency should be corrected to ensure build portability and proper inheritance.

The documentation in CHANGELOG.md is currently inaccurate, listing several major features such as American option pricing and calibration that are not part of this PR. Furthermore, the thegreeklab-visualization module presents a maintenance risk; specifically, the VolatilitySurfaceChart component has high cyclomatic complexity (36) and zero unit test coverage. This risk is exacerbated by the CI pipeline, which is currently configured to ignore coverage reports for the visualization module. Addressing these structural, documentation, and testing gaps is necessary to maintain the project's quality standards.

About this PR

  • The documentation in CHANGELOG.md includes several features (e.g., model-driven calibration, American call pricing) that are not present in this PR. The organization is also inconsistent, with new features placed outside of a version header. Realign the changelog content with the actual delivery.

Test suggestions

  • Verify ForwardBlack76 produces identical prices using scalar volatility vs a FlatVolatilitySurface.
  • Ensure ForwardBlack76 rejects a VolatilitySurface with a valuation timestamp differing from the forward curve.
  • Confirm ForwardBlack76 queries the surface using the correct expiry and ln(K/F) moneyness coordinates.
  • Verify that expired options do not trigger queries to the volatility surface.
  • Test that FlatVolatilitySurface returns the configured volatility across its supported domain.
  • Validate that VolatilitySurfaceGrid performs defensive copies of the provided volatility matrix.
  • Verify VolatilitySurfaceSampler produces evenly spaced samples across the time and moneyness axes.
  • Implement unit tests for VolatilitySurfaceChart coordinate mapping and index calculation logic.
Prompt proposal for missing tests
Consider implementing these tests if applicable:
1. Implement unit tests for `VolatilitySurfaceChart` coordinate mapping and index calculation logic.
Low confidence findings
  • ForwardBlack76 enforces a strict tolerance (1e-12) for discount factors at expiry (T=0). While mathematically correct, this may cause unexpected failures for users providing raw discount curves that are not perfectly normalized at the valuation node.

TIP Improve review quality by adding custom instructions
TIP How was this review? Give us feedback

return Color.hsb(225.0 - 225.0 * Math.clamp(normalized, 0.0, 1.0), 0.72, 0.88);
}

private void updateAccessibleCell(double x, double y) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MEDIUM RISK

The coordinate-to-grid mapping logic in updateAccessibleCell and drawCells is highly complex (Cyclomatic Complexity: 36) and currently has no test coverage. Consider extracting this logic into a testable GridCoordinateMapper utility to verify indices independently of the JavaFX context.

See Complexity in Codacy

Comment thread thegreeklab-core/pom.xml
@@ -0,0 +1,427 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MEDIUM RISK

The thegreeklab-core module should inherit from the parent POM, and its source code should be moved from the project root into the module's standard Maven directory structure (thegreeklab-core/src/main/java). Currently, it points to source directories in the parent folder, which is non-standard.

Comment thread CHANGELOG.md
Comment on lines +101 to +114
## [2.2.0] - 2026-07-22

### Added

- Universal model-driven implied-volatility calibration for European,
American, lattice and discrete-dividend pricing models.
- Immutable `ImpliedVolatilityResult` diagnostics covering convergence,
residual error, iteration counts and explicit failure statuses.
- `VolatilityPricer` as the common calibration contract for immutable pricing
models, including recovery from trial points outside a model's valid domain.
- Roll-Geske-Whaley American call pricing for a single discrete cash dividend,
with immutable bump scenarios, five standard Greeks and implied volatility.
- Explicit `InvalidModelDomainException` reporting for numerically invalid
model parameter regions.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 MEDIUM RISK

The CHANGELOG.md entry references calibration and American pricing features that are not included in this implementation. Update the changelog to match the current PR scope.

Comment thread .github/workflows/ci.yml
with:
project-token: ${{ secrets.CODACY_PROJECT_TOKEN }}
coverage-reports: target/site/jacoco/jacoco.xml
coverage-reports: thegreeklab-core/target/site/jacoco/jacoco.xml

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚪ LOW RISK

Suggestion: The coverage report configuration is restricted to the core directory. Update the path to **/target/site/jacoco/jacoco.xml to include the visualization module's metrics.

Comment on lines +101 to +124
public double minimumVolatility() {
double minimum = Double.POSITIVE_INFINITY;
for (double[] row : impliedVolatilities) {
for (double volatility : row) {
minimum = Math.min(minimum, volatility);
}
}
return minimum;
}

/**
* Returns the largest sampled volatility.
*
* @return maximum annualized implied volatility
*/
public double maximumVolatility() {
double maximum = Double.NEGATIVE_INFINITY;
for (double[] row : impliedVolatilities) {
for (double volatility : row) {
maximum = Math.max(maximum, volatility);
}
}
return maximum;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚪ LOW RISK

Suggestion: Precompute the minimum and maximum volatility values in the VolatilitySurfaceGrid constructor to ensure O(1) performance during chart rendering, rather than recalculating them on every cell update.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant