feat: add volatility surface API and JavaFX visualization - #17
Conversation
Up to standards ✅🟢 Issues
|
| Metric | Results |
|---|---|
| Complexity | 97 |
| Duplication | -2 |
🟢 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 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.
TIP This summary will be updated as you push new changes.
…into feat/javafx-volatility-surface
There was a problem hiding this comment.
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
VolatilitySurfaceChartcoordinate 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) { |
There was a problem hiding this comment.
🟡 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.
| @@ -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"> | |||
There was a problem hiding this comment.
🟡 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.
| ## [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. |
There was a problem hiding this comment.
🟡 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.
| with: | ||
| project-token: ${{ secrets.CODACY_PROJECT_TOKEN }} | ||
| coverage-reports: target/site/jacoco/jacoco.xml | ||
| coverage-reports: thegreeklab-core/target/site/jacoco/jacoco.xml |
There was a problem hiding this comment.
⚪ 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.
| 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; | ||
| } |
There was a problem hiding this comment.
⚪ 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.
Summary
Adds a volatility-surface market-data API and optional JavaFX visualization module.
VolatilitySurfaceandFlatVolatilitySurface, indexed by expiry andln(K / F(T)).ForwardBlack76to obtain implied volatility from a surface whilepreserving scalar-volatility overloads.
VolatilitySurfacefor expired options;T = 0returnsintrinsic value after validating the forward and funding discount factor.
thegreeklab-visualization, which samples a surface into an immutablegrid and renders a resizable JavaFX heatmap.
updates CI, release packaging, README, usage, math, publishing notes and
changelog.
Validation
.\mvnw.cmd verifyon JDK 22 successfully.FlatVolatilitySurface, surface-awareForwardBlack76,expiry short-circuiting without a volatility-surface query, sampler spacing,
grid validation and defensive copying.
visualization module.
Checklist
./mvnw verify(or explained why it is not applicable).