Repository navigation
Conversation
…e pair fx_market prices each FX print from the pair's other prints (leave-one-out) and re-extracted every peer record, twice, for each print; the swap_trades forex priceability gate does that for every print of the day, so a forex swap_trades call was quadratic in a pair's prints: over an hour of CPU on a day of ~43k FX prints, holding the event loop the whole time. option_vol likewise re-extracted and re-implied every vanilla option of the pair for each option print. fx_market now prepares each pair once per call. The extraction's only cross-record input is its median anchor, and leaving out one print leaves one of a few possible anchors, so each anchor's oriented, carry-checked observations are built once and a print only re-takes the medians its own observation touches. Markets carry a key (pair, anchor, left-out prints, min_trades); equal keys mean equal markets, and option_vol prices a family once per key. Results are unchanged. A new test checks every print's spot and forward against extract_fx_observations + ndf_forward_curve over its peers; on a real 2026-10-08 DTCC file, 889 sampled prints (506 forwards, 383 options) gave field-for-field the same value_fx_trade output, and all 57,536 records valued in 5.1 s. Tests that stubbed the extraction helpers now stub _peer_curve, the new seam, with unchanged assertions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Could a maintainer approve the workflow runs for this PR? They're waiting for approval because it comes from a fork ( |
dlee-bq
left a comment
There was a problem hiding this comment.
Hi @artcashin, thanks for the PR. I've left some comments in the code regarding code duplication through reimplementations. Please have a look and refactor accordingly.
Thanks
Address review: drop the leave-one-out reimplementation (_pair_view, _anchored, _median_without and the inline forward interpolator). fx_market now calls extract_fx_observations and ndf_forward_curve once per pair and curve date over all of the pair's prints, package legs included, so valuation and the vol surface use the same NDF curve. The curve, market and option-pricing memo keys include the curve date. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01SEna2ixXYhEGEAQdJM2D3G
|
Thanks for the review. Addressed in 70c3257:
One behaviour change to confirm: since valuation now shares the vol surface's curve, a print is valued against a curve that includes itself, so the old leave-one-out exclusion, and its test |
|
Hi @artcashin, sorry for the delay getting back to you on this. These functions are fiddly by nature, and the raw data is noisy to begin with. They command a higher level of scrutiny vs other provider endpoints simply returning cleaned data. Can we please restore the own-print exclusion? It can force flat extrapolation and marks at zero. The new memo keys carry the date, but fx-pair and fx-df do not. Let's align them all to carry the date. As an enhacement, let's see if we can build the market in one shared function that both Another small enhancement we can look at is to make the valued option read its vol the way the surface does. Thanks, and let me know if you need more info or help. |
Problem
fx_marketbuilt a forward curve for every FX print from the pair's other prints, re-extracting every peer record each time. Theswap_tradesforex priceability gate calls it for every print of the day, so oneGET /cftc/swap_trades?asset_class=forexwas quadratic in a pair's prints. On a day of about 43,000 FX prints (USDKRW alone has 12,231), it ran for over an hour at 100% CPU.option_volre-extracted and re-priced every vanilla option of the pair for each option print.Change
_pair_curvecalls the sharedextract_fx_observationsandndf_forward_curveonce, over all of the pair's prints, package legs included, and memoizes the result. Every print of the pair is valued against that curve. Valuation and the vol surface therefore use the same NDF curve.fx-curve:{pair}:{date},fx-market:{pair}:{date}:{min_trades}, andoption_vol'sfx-options:{market key}:{family}, which prices each option family once per market.Behaviour change
A print is now valued against the pair's full curve, which includes the print itself and package legs. Before, a curve left out the print and package legs. The test
test_fx_market_excludes_the_trades_own_printis replaced bytest_fx_market_uses_the_same_curve_as_the_vol_surfaceandtest_fx_market_builds_the_curve_once_per_pair_and_day.On the 2026-10-08 DTCC forex file, the endpoint's output is 42,762 rows, against 42,760 with the earlier leave-one-out version. Three more forwards become priceable (two CHF/EUR, one NZD/USD), and one USD/JPY NDO put no longer is. That is the effect of the shared curve near the minimum-node threshold.
Speed
On the same file, measured end to end through
GET /api/v1/cftc/swap_trades?asset_class=forex&start_date=2026-10-08&end_date=2026-10-08:swap_tradesThe earlier leave-one-out version of this PR took 24 s warm on the same request, so the shared-curve refactor keeps the speed-up.
Tests
tests/test_fx_valuation.pypasses 93/93, and the CFTC suite passes 1,227/1,227 (develop: 91 and 1,225).🤖 Generated with Claude Code