quantitative finance in javascript
introduction
quantlib.js aims to be a COMPLETE re-implementation of C++ QuantLib in javascript language, emscripten is NOT used. it can be used in web browser or node.js environment.
get started
-
open https://quantlib.js.org/test-suite/ with morden web browser, like chrome, firefox, etc...
-
select a
specorexamplefrom menu.specsource will be displayed on left panel,specwill be run with jasmine by your web browser, and test result will be displayed on right panel
usage
load from CDN
- latest version: https://cdn.jsdelivr.net/npm/@quantlib/ql@latest/ql.mjs or https://unpkg.com/@quantlib/ql@latest/ql.mjs
- version
x.y.z: https://cdn.jsdelivr.net/npm/@quantlib/ql@x.y.z/ql.mjs or https://unpkg.com/@quantlib/ql@x.y.z/ql.mjs
install from npm
npm i @quantlib/ql
use in web page
ql.mjs is ESM format, when using in html script tag, make sure to have script type set to "module"
<script type="module">
import { Actual360, AnalyticEuropeanEngine, BlackConstantVol, BlackScholesProcess, DateExt, EuropeanExercise, EuropeanOption, FlatForward, Handle, Option, PlainVanillaPayoff, Settings, SimpleQuote, TARGET } from 'https://cdn.jsdelivr.net/npm/@quantlib/ql@latest/ql.mjs';
const today = DateExt.UTC('7,March,2014');
Settings.evaluationDate.set(today);
const payoff = new PlainVanillaPayoff(Option.Type.Call, 100.0);
const exercise = new EuropeanExercise(DateExt.UTC('7,June,2014'));
const option = new EuropeanOption(payoff, exercise);
const u = new SimpleQuote(100.0);
const r = new SimpleQuote(0.01);
const s = new SimpleQuote(0.2);
const riskFreeCurve = new FlatForward().ffInit3(0, new TARGET(), new Handle(r), new Actual360());
const volatility = new BlackConstantVol().bcvInit4(0, new TARGET(), new Handle(s), new Actual360());
const process = new BlackScholesProcess(new Handle(u), new Handle(riskFreeCurve), new Handle(volatility));
const engine = new AnalyticEuropeanEngine().init1(process);
option.setPricingEngine(engine);
const npv = option.NPV();
console.log(`NPV = ${npv}`); // 4.155543462156206
</script>what about UMD format/style javascript?
You may use javascript dynamic import
<script>
import('https://cdn.jsdelivr.net/npm/@quantlib/ql@latest/ql.mjs').then(module=>{
window.ql = module;
test();
});
function test() {
const today = ql.DateExt.UTC('7,March,2014');
ql.Settings.evaluationDate.set(today);
const payoff = new ql.PlainVanillaPayoff(ql.Option.Type.Call, 100.0);
const exercise = new ql.EuropeanExercise(ql.DateExt.UTC('7,June,2014'));
const option = new ql.EuropeanOption(payoff, exercise);
const u = new ql.SimpleQuote(100.0);
const r = new ql.SimpleQuote(0.01);
const s = new ql.SimpleQuote(0.2);
const riskFreeCurve = new ql.FlatForward().ffInit3(0, new ql.TARGET(), new ql.Handle(r), new ql.Actual360());
const volatility = new ql.BlackConstantVol().bcvInit4(0, new ql.TARGET(), new ql.Handle(s), new ql.Actual360());
const process = new ql.BlackScholesProcess(new ql.Handle(u), new ql.Handle(riskFreeCurve), new ql.Handle(volatility));
const engine = new ql.AnalyticEuropeanEngine().init1(process);
option.setPricingEngine(engine);
const npv = option.NPV();
console.log(`NPV = ${npv}`); // 4.155543462156206
}
</script>use in node.js
quantlib.js works in node.js environment. after installing with npm, pass --experimental-modules to node to use ESM javascript file
node --experimental-modules test.mjsin test.mjs
import { Actual360, AnalyticEuropeanEngine, BlackConstantVol, BlackScholesProcess, DateExt, EuropeanExercise, EuropeanOption, FlatForward, Handle, Option, PlainVanillaPayoff, Settings, SimpleQuote, TARGET } from '@quantlib/ql';
const today = DateExt.UTC('7,March,2014');
Settings.evaluationDate.set(today);
const payoff = new PlainVanillaPayoff(Option.Type.Call, 100.0);
const exercise = new EuropeanExercise(DateExt.UTC('7,June,2014'));
const option = new EuropeanOption(payoff, exercise);
const u = new SimpleQuote(100.0);
const r = new SimpleQuote(0.01);
const s = new SimpleQuote(0.2);
const riskFreeCurve = new FlatForward().ffInit3(0, new TARGET(), new Handle(r), new Actual360());
const volatility = new BlackConstantVol().bcvInit4(0, new TARGET(), new Handle(s), new Actual360());
const process = new BlackScholesProcess(new Handle(u), new Handle(riskFreeCurve), new Handle(volatility));
const engine = new AnalyticEuropeanEngine().init1(process);
option.setPricingEngine(engine);
const npv = option.NPV();
console.log(`NPV = ${npv}`); // 4.155543462156206typescript
ql.d.ts is published along with ql.mjs
write code in typescript, then compile with tsc or run with ts-node
in test.ts
import {Actual360, AnalyticEuropeanEngine, BlackConstantVol, BlackScholesProcess, BlackVolTermStructure, DateExt, EuropeanExercise, EuropeanOption, Exercise, FlatForward, GeneralizedBlackScholesProcess, Handle, Option, PlainVanillaPayoff, PricingEngine, Quote, Real, Settings, SimpleQuote, StrikedTypePayoff, TARGET, YieldTermStructure} from '@quantlib/ql';
const today: Date = DateExt.UTC('7,March,2014');
Settings.evaluationDate.set(today);
const payoff: StrikedTypePayoff =
new PlainVanillaPayoff(Option.Type.Call, 100.0);
const exercise: Exercise = new EuropeanExercise(DateExt.UTC('7,June,2014'));
const option: EuropeanOption = new EuropeanOption(payoff, exercise);
const u: Quote = new SimpleQuote(100.0);
const r: Quote = new SimpleQuote(0.01);
const s: Quote = new SimpleQuote(0.2);
const riskFreeCurve: YieldTermStructure =
new FlatForward().ffInit3(0, new TARGET(), new Handle(r), new Actual360());
const volatility: BlackVolTermStructure = new BlackConstantVol().bcvInit4(
0, new TARGET(), new Handle(s), new Actual360());
const process: GeneralizedBlackScholesProcess = new BlackScholesProcess(
new Handle(u), new Handle(riskFreeCurve), new Handle(volatility));
const engine: PricingEngine = new AnalyticEuropeanEngine().init1(process);
option.setPricingEngine(engine);
const npv: Real = option.NPV();
console.log(`NPV = ${npv}`); // 4.155543462156206release note
| version | notes |
|---|---|
| 0.3.3 | fixed most asianoption specs |
| 0.3.2 | fixed swaption, most of short-rate models specs and some other pricing specs, and part of bermudanswaption example |
| 0.3.1 | examples code cleanup, fixed 4 examples, global optimizers example DE tests passed |
| 0.3.0 | fixed 40+ pricing specs, started working on model tests |
| 0.2.7 | fixed default probability curves specs |
| 0.2.6 | fixed most european option test, tree engine cleanup |
| 0.2.5 | fixed piecewise zero spreaded term structure, brownian bridge, 4 american options specs, FD engine cleanup |
| 0.2.4 | fixed risk statistics, brownian bridge some piecewise yield curve specs |
| 0.2.3 | fixed termstructure spec, experimental Gaussian quadratures specs |
| 0.2.2 | termstructure constructor cleanup, fixed a few simple ts specs |
| 0.2.1 | add halley, halleysafe, inverseIncompleteGammaFunction from QuantLib-noBoost, fixed blackdeltacalculator |
| 0.2.0 | started working on instrument pricing specs, fixed some old test that passed before |
| 0.1.x | most math specs passed |
| 0.0.x | date&time, patterns, currency, misc specs passed |
docs
- https://quantlib.js.org/docs
- official c++ quantlib doc: https://www.quantlib.org/reference/
test-suite & example
A static report is updated regularly, so you could see the overall test status. C++ example output for reference
source code in ESM javascript:
converted from the c++ quantlib test-suite & Examples
these are the code loaded and executed in https://quantlib.js.org
credit
- C++ QuantLib project: https://quantlib.org
- C++ QuantLib-noboost: https://github.com/haozhangphd/QuantLib-noBoost
- mathjs: https://mathjs.org
- phosphor: https://github.com/phosphorjs/phosphor
- js.org: https://github.com/js-org/js.org
resource
- Google group: https://groups.google.com/d/forum/quantlibjs/
- Follow us on Twitter: @quantlibjs
- Facebook page: https://www.facebook.com/quantlibjs/
- notebook: https://observablehq.com/@quantlib