Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 37 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,43 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.17.0] - 2026-04-26

Major release adding the Black-76 closed-form pricing model for European
options on futures and forwards. The bump to `0.17.0` is required because
`PricingEngine` is now `#[non_exhaustive]` (a semver-breaking change for
downstream exhaustive matches) and the addition of
`PricingEngine::ClosedFormBlack76` shifts the implicit discriminant of
`PricingEngine::MonteCarlo` from `1` to `2`.

### Added

- `pricing::black_76`: closed-form `black_76(option) -> Result<Decimal, PricingError>`
for European options on futures / forwards. Reuses the existing `d1`
/ `d2` / `big_n` helpers; `Decimal` end-to-end via `d_mul` / `d_sub`;
`tracing::instrument` on the entry point. Only `OptionType::European`
is supported — American, Bermuda and exotics return
`PricingError::UnsupportedOptionType`.
- `pricing::Black76` trait with default `calculate_price_black_76`
(mirrors `BlackScholes`).
- `pricing::PricingEngine::ClosedFormBlack76` variant + dispatch from
`price_option`.
- `greeks::utils::calculate_d_values_black_76` `pub(crate)` helper.
- `examples/examples_pricing/`: new workspace member with binary
`black_76` (Hull canonical example, ITM commodity-futures call,
unified-API dispatch, short-side sign convention).
- `lib.rs` mermaid: `Forward-Priced` subgraph routing
`black_76 -> {Future, Forward}`.

### Changed

- `pricing::PricingEngine` is now `#[non_exhaustive]` so future engine
variants do not require a new major bump.
- `pricing::mod.rs` Core Models / Model Selection Guidelines /
Performance Considerations now include Black-76.
- `financial_types` bumped to `0.2.2` (adds `UnderlyingAssetType::Future`
and `UnderlyingAssetType::Forward`).

## [0.16.5] - 2026-04-20

Documentation-only release. Refresh the crate-level rustdoc and
Expand Down
15 changes: 8 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "optionstratlib"
version = "0.16.5"
version = "0.17.0"
edition = "2024"
authors = ["Joaquin Bejar <jb@taunais.com>"]
description = "OptionStratLib is a comprehensive Rust library for options trading and strategy development across multiple asset classes."
Expand Down Expand Up @@ -101,17 +101,18 @@ crate-type = ["cdylib", "rlib"]

[workspace]
members = [
"examples/examples_chain",
"examples/examples_curves",
"examples/examples_exotics",
"examples/examples_metrics",
"examples/examples_pricing",
"examples/examples_simulation",
"examples/examples_strategies",
"examples/examples_strategies_best",
"examples/examples_strategies_delta",
"examples/examples_strategies",
"examples/examples_surfaces",
"examples/examples_visualization",
"examples/examples_chain",
"examples/examples_volatility",
"examples/examples_curves",
"examples/examples_surfaces",
"examples/examples_metrics",
"examples/examples_exotics",
]

[workspace.dependencies]
Expand Down
2 changes: 1 addition & 1 deletion Draws/Simulation/simulator_test_montecarlo.html

Large diffs are not rendered by default.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 20 additions & 0 deletions examples/examples_metrics/Draws/Metrics/bid_ask_spread_curve.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Graph</title>
<script src="https://cdn.plot.ly/plotly-2.24.1.min.js" charset="utf-8"></script>
<style>
body { margin: 0; padding: 20px; font-family: Arial, sans-serif; }
#plotly-graph { width: 100%; height: 600px; }
</style>
</head>
<body>
<div id="plotly-graph"></div>
<script>
var plotJson = {"data":[{"type":"scatter","name":"Curve","mode":"lines","x":["380","400","420","430","440","445","450","455","460","470","480","500","520"],"y":["0.0277777777777777777777777778","0.0284360189573459715639810427","0.0239520958083832335329341317","0.0206185567010309278350515464","0.0185758513931888544891640867","0.0158730158730158730158730159","0.0104712041884816753926701571","0.0281690140845070422535211268","0.0392156862745098039215686275","0.1132075471698113207547169811","0.2222222222222222222222222222","0.6666666666666666666666666667","1.2"],"line":{"width":2.0,"color":"#1f77b4"}}],"layout":{"title":{"text":"Graph"},"showlegend":true,"width":1280,"height":720},"config":{},"frames":null};
Plotly.newPlot('plotly-graph', plotJson);
</script>
</body>
</html>
20 changes: 20 additions & 0 deletions examples/examples_metrics/Draws/Metrics/charm_curve.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Graph</title>
<script src="https://cdn.plot.ly/plotly-2.24.1.min.js" charset="utf-8"></script>
<style>
body { margin: 0; padding: 20px; font-family: Arial, sans-serif; }
#plotly-graph { width: 100%; height: 600px; }
</style>
</head>
<body>
<div id="plotly-graph"></div>
<script>
var plotJson = {"data":[{"type":"scatter","name":"Curve","mode":"lines","x":["385","390","395","400","405","410","415","420","425","430","435","440","445","450","455","460","465","470","475","480","485","490","495","500","505","510","515","520","525"],"y":["0.0004153147455346151393319792","0.0006541329381401317830517998","0.0009835900185541687128065715","0.0014045700100890783998252163","0.0018983170706241191462848458","0.0024210427895051403560533752","0.0029035442057756112572740684","0.003258026227823806993690192","0.0033924241417034588030311123","0.0032299056753572109061184429","0.0027288517444790404233382591","0.0018975322514879651228635039","0.0007985699898307314516557663","-0.000458990991271567756225489","-0.0017385348362706026262346435","-0.0029008991773418461574719786","-0.0038291485807518935473538946","-0.0044470898079479922512793718","-0.0047277481315731682913238332","-0.004691120013415697484351033","-0.0043933639600056211030912284","-0.0039113366813010035817532017","-0.0033267078505840202182882278","-0.0027130110995640517954003148","-0.0021274608944474431014086042","-0.001607791851572104620778485","-0.0011732050825697535346727448","-0.0008279246287832586434216123","-0.0005658320055212608400915492"],"line":{"width":2.0,"color":"#1f77b4"}}],"layout":{"title":{"text":"Graph"},"showlegend":true,"width":1280,"height":720},"config":{},"frames":null};
Plotly.newPlot('plotly-graph', plotJson);
</script>
</body>
</html>
20 changes: 20 additions & 0 deletions examples/examples_metrics/Draws/Metrics/charm_surface.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Graph</title>
<script src="https://cdn.plot.ly/plotly-2.24.1.min.js" charset="utf-8"></script>
<style>
body { margin: 0; padding: 20px; font-family: Arial, sans-serif; }
#plotly-graph { width: 100%; height: 600px; }
</style>
</head>
<body>
<div id="plotly-graph"></div>
<script>
var plotJson = {"data":[{"type":"surface","x":["380","387","394","401","408","415","422","429","436","443","450","457","464","471","478","485","492","499","506","513","520"],"y":["1","3","7","14","21","30","45","60"],"z":[["-0.1195433745003607488892524708","0.0826624262649251022105005347","0.040470676920600500028897207","0.0005554584489636547564762546","0.0000273965088752780726693471","0.0000273965096743513580328629","0.0000273965096743843160340012","0.0000273965096743843160340012","0.0000273965096743843160340012","0.0000273965096743843160340012","0.0000273965096743843160340012","0.0000273965096743843160340012","0.0000273965096743843160340012","0.0000273965096743843160340012","0.0000273965096743843160340012","0.0000273965096743843160340012","0.0000273965096743843160340012","0.0000273965096743843160340012","0.0000273965096743843160340012","0.0000273965096743843160340012","0.0000273965096743843160340012"],["-0.0384956319480719505731551799","0.0162468263423117133077029137","0.0360484740992538415789245442","0.0122456931198890287009031619","0.0014594321542900617110607305","0.0000956022457455764589880514","0.0000273949992271734598979931","0.0000273950084703643718887143","0.0000273950085366548683363207","0.000027395008536898985257393","0.0000273950085368994509725381","0.0000273950085368994509725381","0.0000273950085368994509725381","0.0000273950085368994509725381","0.0000273950085368994509725381","0.0000273950085368994509725381","0.0000273950085368994509725381","0.0000273950085368994509725381","0.0000273950085368994509725381","0.0000273950085368994509725381","0.0000273950085368994509725381"],["-0.0129377953709068775211481071","0.0041220275498102025386007252","0.0153379286540874339889563921","0.013325548370785470804075556","0.0064548152583747588027114854","0.0020202537998805068828035158","0.0004485740944288754018135109","0.0000903344944867281175477439","0.0000342223640979159265221156","0.0000273919982049430740059454","0.0000273920060973792835547624","0.0000273920064927051863851043","0.0000273920065081890111202533","0.0000273920065086686725462268","0.000027392006508680533285045","0.0000273920065086807798131036","0.0000273920065086807798131036","0.0000273920065086807798131036","0.0000273920065086807798131036","0.0000273920065086807798131036","0.0000273920065086807798131036"],["-0.0051448169338271569322811771","0.0011372561225585941270920574","0.0061191911902812439809508549","0.0076812147568855151707289964","0.0063594787547854146478905017","0.0040036528847837842645975873","0.0020279351267736054192839726","0.0008577253519386331444279166","0.000317205390474781814541305","0.000113671875909804417694252","0.0000495495305602961246801604","0.0000323452194808188063792343","0.0000283611161109094909543711","0.0000273867487913805966161972","0.0000273867530808516620045788","0.0000273867536688920416110304","0.0000273867537417427510478444","0.0000273867537499369225436103","0.0000273867537507774220162243","0.0000273867537508563780272881","0.000027386753750863197328972"],["-0.003026614817185624982915397","0.000441496951166585428856308","0.003360776589541706210691505","0.0048382395195176654009724097","0.0048150786288487708384413212","0.0038421267238620402093498454","0.002594576782651704826710118","0.0015269041831690395508201228","0.0008006221605838518861470428","0.0003836210630912205193783464","0.0001753697390732672455697728","0.0000832307385101670351949313","0.0000466506256337834379082585","0.0000334931181993338115327444","0.0000291722214837988545507491","0.0000278683522001848471516364","0.0000273814965164126688076027","0.0000273815008348239912538452","0.0000273815017663093933985845","0.0000273815019558282142106933","0.0000273815019922956652567867"],["-0.001924039207228313821726305","0.0001253555644454487470837929","0.0019121774822647161776419386","0.0030379790338500919904898384","0.0033956367733143142694115777","0.0031330374635782905339675108","0.0025205902042738787786971069","0.0018172974060328955088606544","0.0011949409776317477619064145","0.0007268513434548693510310558","0.0004153147455346151393319792","0.000227811479074351258995054","0.000124348525066777988406499","0.0000715018607915531264738939","0.000046332947811280771724431","0.0000350910454917470369906227","0.0000303592617491116771931078","0.000028474775147408355938877","0.0000277621047481117646185808","0.0000273747425935589547610467","0.000027374748672740724009487"],["-0.00117537861235674071338667","-0.0000511767086882421313278396","0.0009558887008252161082406648","0.00169231418338818675295679","0.002091506778288116674614746","0.0021715856208388940342722961","0.0020085313268572680418915542","0.0017008928107944838692618385","0.001340061013395386167519444","0.0009931552079144769126265499","0.0006986166937273433097944553","0.0004704831536080312186672039","0.0003063981802745685756144172","0.0001955710391411838707019399","0.0001247278392830329757002368","0.0000816219194734085955343999","0.0000565418269063850336327197","0.0000425370704703468282923213","0.0000350083985840108306537142","0.0000311017056179453720155564","0.0000291403574068105331496372"],["-0.0008430594448757576337892544","-0.0001095283323079496543942389","0.0005564763165260402086713972","0.0010783123447314697479180318","0.0014162358266953969750440528","0.0015677916933341348014517775","0.001559506284142536310711535","0.0014343738614287678582868979","0.0012394974293286662168031149","0.0010167969597045299891290958","0.0007978813642595621902787794","0.00060271731409120281282295","0.000440934529646741452151377","0.0003144471667962170235367043","0.0002203209622261584361742535","0.0001532249930133332664829748","0.0001071919419082889941872344","0.0000766819396369972310651303","0.0000570881416260591149178638","0.000044864914232566772020775","0.0000374420697050860075271951"]],"name":"Surface"}],"layout":{"title":{"text":"Graph"},"showlegend":true,"width":1280,"height":720},"config":{},"frames":null};
Plotly.newPlot('plotly-graph', plotJson);
</script>
</body>
</html>
20 changes: 20 additions & 0 deletions examples/examples_metrics/Draws/Metrics/color_curve.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Graph</title>
<script src="https://cdn.plot.ly/plotly-2.24.1.min.js" charset="utf-8"></script>
<style>
body { margin: 0; padding: 20px; font-family: Arial, sans-serif; }
#plotly-graph { width: 100%; height: 600px; }
</style>
</head>
<body>
<div id="plotly-graph"></div>
<script>
var plotJson = {"data":[{"type":"scatter","name":"Curve","mode":"lines","x":["385","390","395","400","405","410","415","420","425","430","435","440","445","450","455","460","465","470","475","480","485","490","495","500","505","510","515","520","525"],"y":["0.0000346848985303078331249415","0.0000502455845402747913373621","0.0000676026581230404427650175","0.0000839002788032098836926759","0.0000948946795285209016936331","0.0000955509419657003835789856","0.0000811943147711278142250187","0.0000490008396686600335517081","-0.0000006081578037951308094031","-0.0000631961525122853617306896","-0.0001305811124016595996409787","-0.0001922480258320790653431955","-0.0002376046287663392801003706","-0.0002584515953999514032754178","-0.000250927817240139166489991","-0.0002163521031021294252821786","-0.0001607496104966767609699938","-0.0000932745199185879950966008","-0.0000240571016982614307249336","0.000037890288638484233848379","0.000086185982324419735186747","0.0001177436559411427658968062","0.0001326070283232274994567529","0.000133187887526546234631824","0.0001232348956703894200660751","0.0001068373045647759630777533","0.0000876682667612682366290265","0.0000685499397675423465628402","0.0000513198955803442048551567"],"line":{"width":2.0,"color":"#1f77b4"}}],"layout":{"title":{"text":"Graph"},"showlegend":true,"width":1280,"height":720},"config":{},"frames":null};
Plotly.newPlot('plotly-graph', plotJson);
</script>
</body>
</html>
20 changes: 20 additions & 0 deletions examples/examples_metrics/Draws/Metrics/color_surface.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Graph</title>
<script src="https://cdn.plot.ly/plotly-2.24.1.min.js" charset="utf-8"></script>
<style>
body { margin: 0; padding: 20px; font-family: Arial, sans-serif; }
#plotly-graph { width: 100%; height: 600px; }
</style>
</head>
<body>
<div id="plotly-graph"></div>
<script>
var plotJson = {"data":[{"type":"surface","x":["380","387","394","401","408","415","422","429","436","443","450","457","464","471","478","485","492","499","506","513","520"],"y":["1","3","7","14","21","30","45","60"],"z":[["0.0113492138380559108680381799","-0.0323958266024335134210314316","0.0162911723625452022020817324","0.0004351631172846115983013289","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["-0.0038505186239357005944987953","-0.0081087191296212104185131607","0.0022363436524357265216799745","0.0028847400365536357470455744","0.0005342051401849646238009731","0.0000337541975040676959524181","0","0","0","0","0","0","0","0","0","0","0","0","0","0","0"],["-0.001931126648657940796879379","-0.0024392752265680498992710664","-0.0005779021329301322216139572","0.0008955969582544992245874215","0.0008837927033875140920595774","0.000390034150128912062227313","0.000104247826263794858269503","0.0000185656957136931208183342","0.0000023159076617588727288514","0","0","0","0","0","0","0","0","0","0","0","0"],["-0.0008164048601027685664478593","-0.0008852433532772273185797167","-0.0004845401492815291212076364","0.0000212638892813841165515422","0.0003075615026799331033666791","0.00033074325990562203188381","0.0002248949280268201792950097","0.0001149004523199629083262949","0.0000469578452946884177068817","0.000015865885712004604527165","0.0000045267721587588256403209","0.0000011075055979027197552072","0.0000002351568055469766526315","0","0","0","0","0","0","0","0"],["-0.000470358988127747010837898","-0.0004862716038168949707648291","-0.0003255837734224229014697881","-0.0000958347044248794244528102","0.0000880247256268158125794626","0.0001730239689654096862153917","0.0001724739755925721409969019","0.0001290225420622135967967644","0.0000795736526642783347638367","0.0000421427972462173742099838","0.0000196107817949884460907116","0.0000081403706878264569552977","0.000003047535205495149895381","0.0000010378538893467435531908","0.0000003237867424153220873204","0.0000000930903407402534280847","0","0","0","0","0"],["-0.0002849510453338097769172363","-0.0002864796264260145059384837","-0.0002142464379810844341099272","-0.0001049738980465899625990667","-0.0000010869954651139268866999","0.0000693370845446054977771909","0.0000992999758211762638395639","0.0000975347030826295053088931","0.0000786117497564105231601751","0.000055165997575210273079418","0.0000346848985303078331249415","0.0000198716820173678455783918","0.0000104924653254313536545827","0.0000051483869021094678944345","0.0000023627524854982613558966","0.0000010195283781108247625245","0.0000004154633691429399442535","0.0000001604991236054363610749","0.0000000589756620003539564222","0","0"],["-0.0001593082923025518005509818","-0.0001567774625384069699071422","-0.0001272227234014737389449923","-0.0000816080489842148741816457","-0.0000329483820800093324998428","0.0000081705804119091682833736","0.0000359968105963489109915703","0.0000496833429000684691125831","0.0000518044541114955430574297","0.0000464082001222604935099331","0.0000374318200438636905344051","0.0000278248905107594223072992","0.0000193277275075558149502744","0.0000126613890547562292736562","0.0000078744380565817540561809","0.0000046730750207093925956067","0.0000026570297901252452536632","0.0000014523161227388480879064","0.0000007653095624921048670473","0.0000003897616185114842708421","0.0000001922619585558203560057"],["-0.0001049263645904076856541673","-0.0001021750291638553944238811","-0.0000862590081500224110587236","-0.0000618907918608731876211409","-0.0000346217515828423322593284","-0.0000093428579155314519522387","0.0000106560092811457855024079","0.0000239521399597931618482514","0.0000307167030897240642129094","0.0000321566723926194445233644","0.0000299188239764382596732061","0.0000256196677897981545184985","0.0000205654587626377595547612","0.0000156495753575122689143448","0.0000113747377877944658649796","0.0000079400982856584360746173","0.0000053452425795223668882092","0.0000034818360215039142254713","0.0000022005665492751000456612","0.0000013525278011001250421456","0.0000008100357098550463693551"]],"name":"Surface"}],"layout":{"title":{"text":"Graph"},"showlegend":true,"width":1280,"height":720},"config":{},"frames":null};
Plotly.newPlot('plotly-graph', plotJson);
</script>
</body>
</html>
Loading
Loading