Giter Site home page Giter Site logo

black_scholes_rust's Introduction

Hello! I am Daniel Stahl.

I am a leader in the data science and machine learning operations space, and I moonlight as a software engineer.

Academic background and research interest

My academic background, and my intellectual passion, is in the mathematics underlying financial models. I have published two papers in the Journal of Credit Risk and the Journal of Operational Risk extending this mathematical framework to portfolio credit and operational risks. I've made the Latex and PDFs available in my CreditRiskPaper repository and OpsRiskPaper repository. I've implemented the results of these papers in the following repositories:

I've created computationally efficient calculators for pricing options on underlyings with very complex dynamics. Examples, documentation, and related material can be found at the realoptions Github organization, as well as at finside.org The bulk of the work is done in the option_price_faas library. These calculators can be accessed from my developers site or at my rapidapi page. I also have a free web app exemplifying how the calculators may be used, and a free mobile app for Android.

Software interests

Software development is my hobby and my passion. I believe software is a craft. Software engineering requires not only a sound technical understanding, but also a feeling of pride and ownership for a product well crafted. Software should be used and re-used. My preferred development languages reflect this belief. Rust is a phenomenal language that encourages best practices, enforces memory management, and retains performance that is comparable to C++. It is my preferred language for micro-services and server-side development. Flutter and React or my two favorite languages for client-side development. React has become more and more geared towards functional programming, making client applications quick to develop and easy to maintain. Flutter takes this one step further and introduces stronger guarantees due to its fully-fledged typing system, as well as being the language that introduced the BLoC pattern for state management.

Business interests

I have spent my career in financial institutions. In my current role, I am responsible for machine learning operations and providing the tools for data scientists to safely, responsibly, and efficiently deliver robust data products for our internal and external customers. I use our internal continuous integration and continuous deliver platform and a "Gitops" style approach to enable models to be promoted to production continuously, while retaining the controls, lineage, and provenance needed for a highly regulated institution. The model development platform has been created to enable this style of promotion without the Data Scientists having to write their own continuous integration scripts. Data Scientists can focus on what they are best at: creating incredible models.

black_scholes_rust's People

Contributors

brandonros avatar cauldnz avatar changdaniel avatar danielhstahl avatar uzaaft avatar zarathustra2 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

black_scholes_rust's Issues

Maturity clarity

https://github.com/ronniec95/black_scholes/blob/92b4f0a7543e5802c2645c7e2c19f1154815e892/src/bs_f32x8_.rs#L762

I'm not smart enough to understand if the math for maturity between this library and ronniec95/black_scholes are the same but, to clarify, this repo expects maturity as days_to_expiration / 365 days a year and not days_to_expiration / 252 trading days a year, right?

What about for example:

{
    "underlying": "SPY",
    "name": "16 DEC 22 100",
    "spc": 100.0,
    "multiplier": 100.0,
    "expirationStyle": "REGULAR",
    "isEuropean": false,
    "expiration": "2022-12-17T12:00:00Z",
    "lastTradeDate": "2022-12-16T21:00:00Z",
    "settlementType": "PM"
}

Is the expiration date expiration or lastTradeDate? Or does none of this really matter because they are American style options instead of European?

Option style / maturity?

Are SPX American or European? SPX options are European-style and can therefore only be exercised at the time of expiration. There is no risk of early exercise when using European-style options which is a nice advantage for option sellers.

SPY (ETF) options are American style, meaning the option owner may choose to exercise ahead of expiration.

Option style / dividend?

According to the Black-Scholes option pricing model (its Merton's extension that accounts for dividends), there are six parameters which affect option prices:

Dividend yield was only added by Merton in Theory of Rational Option Pricing, 1973.

Not sure if dividend matters only on a certain style of option (American vs European) / if it affects the greeks since it has to be priced in even if the option isn't close to the ex-dividend date expiration wise?

Just thinking outloud/being nitpicky in the quest of making the greeks more "accurate" to the real world (aka how TD Ameritrade/other platforms price options for trading basically)

How big of a deal is a ~1.5% mismatch on calculated IV?

fn parse_date(input: &str) -> DateTime<Tz> {
    let parsed_input = chrono::DateTime::parse_from_rfc3339(&input).unwrap();
    let eastern_input = parsed_input.with_timezone(&Eastern);
    return eastern_input;
}

fn main() {
    // calculate maturity
    let now = parse_date("2022-11-18T16:00:00-05:00");
    let expiration_date = parse_date("2022-12-16T16:00:00-05:00");
    let minutes_to_expiration = expiration_date.signed_duration_since(now).num_minutes();
    let minutes_per_day = 60.0 * 24.0;
    let days_to_expiration = (minutes_to_expiration as f64) / minutes_per_day;
    let maturity = days_to_expiration / 365.0;
    // prices
    let underlying_price = 396.15; // SPY
    let strike_price = 396.0; // at the money
    let call_option_price = 9.99;
    let put_option_price = 9.77;
    // risk free rate from 10 year (TNX)
    let risk_free_rate = 0.03819;
    // iv
    let actual_call_iv = 0.2166; // Robinhood
    let actual_put_iv = 0.2419; // Robinhood
    let calculated_call_iv = black_scholes::call_iv(
        call_option_price, 
        underlying_price, 
        strike_price, 
        risk_free_rate,
        maturity
    ).unwrap();
    let calculated_put_iv = black_scholes::put_iv(
        put_option_price, 
        underlying_price, 
        strike_price, 
        risk_free_rate,
        maturity
    ).unwrap();
    println!("actual_call_iv = {}", actual_call_iv);
    println!("actual_put_iv = {}", actual_put_iv);
    println!("calculated_call_iv = {}", calculated_call_iv);
    println!("calculated_put_iv = {}", calculated_put_iv);
}
actual_call_iv = 0.2166
actual_put_iv = 0.2419
calculated_call_iv = 0.21332873734186864
calculated_put_iv = 0.23828290707877298

not sure if it's becuase of dividend yield not being "supported" in the model/in this repo, different maturity value, different risk free rate

any suggestions? let me see what thinkorswim says

WASM support

building for the wasm32-unknown-unknown target I get the following error

cargo build --target wasm32-unknown-unknown                                             
  Downloaded serde_derive v1.0.148
  Downloaded serde v1.0.148
  Downloaded syn v1.0.104
  Downloaded 3 crates (368.9 KB) in 1.11s
   Compiling autocfg v1.1.0
   Compiling proc-macro2 v1.0.47
   Compiling unicode-ident v1.0.5
   Compiling quote v1.0.21
   Compiling syn v1.0.104
   Compiling serde_derive v1.0.148
   Compiling libc v0.2.137
   Compiling serde v1.0.148
   Compiling num-traits v0.2.15
   Compiling num-integer v0.1.45
   Compiling num-bigint v0.2.6
   Compiling num-complex v0.2.4
   Compiling num-rational v0.2.4
   Compiling num-iter v0.1.43
   Compiling special v0.8.1
error[E0432]: unresolved imports `libc::c_double`, `libc::c_int`
 --> /Users/mike/.cargo/registry/src/github.com-1ecc6299db9ec823/special-0.8.1/src/math.rs:3:12
  |
3 | use libc::{c_double, c_int};
  |            ^^^^^^^^  ^^^^^ no `c_int` in the root
  |            |
  |            no `c_double` in the root

error[E0425]: cannot find function `lgamma` in module `math`
   --> /Users/mike/.cargo/registry/src/github.com-1ecc6299db9ec823/special-0.8.1/src/gamma.rs:205:36
    |
205 |         let value = unsafe { math::lgamma(self as f64, &mut sign) as Self };
    |                                    ^^^^^^ help: a function with a similar name exists: `tgamma`
...
246 | implement!(f32);
    | --------------- in this macro invocation
    |
   ::: /Users/mike/.cargo/registry/src/github.com-1ecc6299db9ec823/special-0.8.1/src/math.rs:8:5
    |
8   |     pub fn tgamma(x: c_double) -> c_double;
    |     --------------------------------------- similarly named function `tgamma` defined here
    |
    = note: this error originates in the macro `implement` (in Nightly builds, run with -Z macro-backtrace for more info)

error[E0425]: cannot find function `lgamma` in module `math`
   --> /Users/mike/.cargo/registry/src/github.com-1ecc6299db9ec823/special-0.8.1/src/gamma.rs:205:36
    |
205 |         let value = unsafe { math::lgamma(self as f64, &mut sign) as Self };
    |                                    ^^^^^^ help: a function with a similar name exists: `tgamma`
...
247 | implement!(f64);
    | --------------- in this macro invocation
    |
   ::: /Users/mike/.cargo/registry/src/github.com-1ecc6299db9ec823/special-0.8.1/src/math.rs:8:5
    |
8   |     pub fn tgamma(x: c_double) -> c_double;
    |     --------------------------------------- similarly named function `tgamma` defined here
    |
    = note: this error originates in the macro `implement` (in Nightly builds, run with -Z macro-backtrace for more info)

Some errors have detailed explanations: E0425, E0432.
For more information about an error, try `rustc --explain E0425`.
error: could not compile `special` due to 3 previous errors
warning: build failed, waiting for other jobs to finish...

which comes from the special = 0.8 dependency. This dependency is used in one function call here

(x / SQRT_2).error() * 0.5 + 0.5
and simply removing the .error() the library compiles fine.

I am wondering how critical this dependency is and maybe we could get rid of it or at least but it behind a feature flag

call_iv NaN?

image

image

fn main() {
    let option_price = 10.74;
    let underlying_price = 380.13; // SPY
    let strike = 380.0;
    let rate = 0.03938; // 10 year
    let maturity = 23.0; // 23 days to expiration (2022-10-27 -> 2022-11-18)
    let iv = black_scholes::call_iv(
        option_price, 
        underlying_price, 
        strike, 
        rate,
        maturity
    ).unwrap();
    println!("{}", iv);
}
$ cargo run
   Compiling options-rs v0.1.0 (/Users/brandonros/Desktop/options-rs)
    Finished dev [unoptimized + debuginfo] target(s) in 0.32s
     Running `target/debug/options-rs`
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: NaN', src/main.rs:13:7
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

second + third order greeks

greeks

first order

* Delta measures how option price will change if underlying price increases by $1.
* Theta measures how much an option's price will change in one day.
* Vega measures how option price will change if implied volatility rises by one percentage point.
* Rho measures how option premium will change if the risk-free interest rate increases by one percentage point.

second order

* Gamma measures how much delta will change if underlying price increases by $1.
* [Vanna](https://www.macroption.com/option-vanna/) = Also DvegaDspot or DdeltaDvol. Sensitivity of option price to small changes in [underlying price](https://www.macroption.com/underlying-price/) and [volatility](https://www.macroption.com/volatility/), sensitivity of [vega](https://www.macroption.com/option-vega/) to small changes in [underlying price](https://www.macroption.com/underlying-price/), or sensitivity of [delta](https://www.macroption.com/option-delta/) to small changes in [volatility](https://www.macroption.com/volatility/).
* [Vera](https://www.macroption.com/option-vera/) = Also rhova. Sensitivity of option price to small changes in [volatility](https://www.macroption.com/volatility/) and interest rates, sensitivity of [rho](https://www.macroption.com/option-rho/) to small changes in [volatility](https://www.macroption.com/volatility/), or sensitivity of [vega](https://www.macroption.com/option-vega/) to small changes in interest rates.
* [Veta](https://www.macroption.com/option-veta/) = Also vega decay or DvegaDtime. Sensitivity of option price to small changes in [volatility](https://www.macroption.com/volatility/) and passage of time, sensitivity of [vega](https://www.macroption.com/option-vega/) to passage of time, or sensitivity of [theta](https://www.macroption.com/option-theta/) to small changes in [volatility](https://www.macroption.com/volatility/).
* [Vomma](https://www.macroption.com/option-vomma/) = Also [vega](https://www.macroption.com/option-vega/) convexity, volga, or DvegaDvol. Sensitivity of vega to small changes in [volatility](https://www.macroption.com/volatility/).
* [Charm](https://www.macroption.com/option-charm/) = Also delta decay or DdeltaDtime. Sensitivity of option price to small changes in [underlying price](https://www.macroption.com/underlying-price/) and passage of time, sensitivity of [theta](https://www.macroption.com/option-theta/) to small changes in [underlying price](https://www.macroption.com/underlying-price/), or sensitivity of [delta](https://www.macroption.com/option-delta/) to passage of time.

third order

[Color](https://www.macroption.com/option-color/) = Also gamma decay or DgammaDtime. [Third order Greek](https://www.macroption.com/third-order-greeks/) which measures sensitivity of [gamma](https://www.macroption.com/option-gamma/) to passage of time (small changes in time to expiration).
[Speed](https://www.macroption.com/option-speed/) = Also DgammaDspot. [Third order Greek](https://www.macroption.com/third-order-greeks/) which measures sensitivity of [gamma](https://www.macroption.com/option-gamma/) to small changes in [underlying price](https://www.macroption.com/underlying-price/).
[Ultima](https://www.macroption.com/option-ultima/) = Also DvommaDvol. [Third order Greek](https://www.macroption.com/third-order-greeks/) which measures sensitivity of [vomma](https://www.macroption.com/option-vomma/) to small changes in [volatility](https://www.macroption.com/volatility/).

Proposal: Calc all greeks once & Decimals

Currently one has to call 5 functions - gamma, delta, vega, theta, sigma/iv, and the parameters of the function take a float and don't support decimals.

Going forward I would like to add support for calculating greeks with decimals as input, https://docs.rs/rust_decimal/1.10.3/rust_decimal/

This can be added as a feature so users can decide whether they want to have the decimal feature or not.

Second, it would be nice if we could do something like this:

pub struct Greeks {
    #[cfg(feature = "decimal")]
    iv: Decimal,
    #[cfg(feature = "decimal")]
    delta: Decimal,
    #[cfg(feature = "decimal")]
    gamma: Decimal,
    #[cfg(feature = "decimal")]
    theta: Decimal,
    #[cfg(feature = "decimal")]
    vega: Decimal,  

    #[cfg(not(feature = "decimal"))]
    iv: f64,
    #[cfg(not(feature = "decimal"))]
    delta: f64,
    #[cfg(not(feature = "decimal"))]
    gamma: f64,
    #[cfg(not(feature = "decimal"))]
    theta: f64,
    #[cfg(not(feature = "decimal"))]
    vega: f64,
}

impl Greeks {
    // If iv is none then we will calculate it.
    #[cfg(feature = "decimal")]
    pub fn naked(is_call: bool, stock_price: Decimal, strike: Decimal, rate: Decimal, iv: Option<Decimal>, maturity: f64) -> Self {}
    #[cfg(not(feature = "decimal"))]
    pub fn naked(is_call: bool, stock_price: f64, strike: f64, rate: f64, iv: Option<f64>, maturity: f64) -> Self {}

    pub fn from_bs_option(ot: &BsOption) {
        let is_call = ot.is_call(); 
        let stock_price = ot.stock_price(); 
        let strike = ot.strike(); 
        let rate = ot.rate(); 
        let iv = ot.iv(); 
        let maturity = ot.maturity(); 

        Self::naked(is_call, stock_price, strike, rate, iv, maturity)
    }
}

trait BsOption {
    fn is_call(&self) -> bool;

    #[cfg(feature = "decimal")]
    fn stock_price(&self) -> Decimal;
    #[cfg(feature = "decimal")]
    fn strike(&self) -> Decimal;
    #[cfg(feature = "decimal")]
    fn rate(&self) -> Decimal;
    #[cfg(feature = "decimal")]
    fn iv(&self) -> Option<Decimal>;

    #[cfg(not(feature = "decimal"))]
    fn stock_price(&self) -> f64;
    #[cfg(not(feature = "decimal"))]
    fn strike(&self) -> f64;
    #[cfg(not(feature = "decimal"))]
    fn rate(&self) -> f64;
    #[cfg(not(feature = "decimal"))]
    fn iv(&self) -> Option<f64>;

    fn maturity(&self) -> f64;
}

Benefits would be we could optimize the code - if we are interested in all greeks - in a way that we don't have to recalculate d1/d2 for instance.

Let me know what you think @danielhstahl, I can take a shot at this if you want.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.