ronniec95 / black_scholes

A SIMD based black scholes pricer using the http://crates.io/wide crate
https://mushfaqueronniechowdhury.medium.com/probably-the-fastest-black-scholes-pricer-in-world-34103e97f7eb
64 stars 7 forks source link

Calcuating greeks #3

Closed cholcombe973 closed 2 years ago

cholcombe973 commented 2 years ago

First off thank you so much for writing this crate! If it wasn't for this I wouldn't even know where to start. I'm working on trying to calculate some greeks and seeing if it matches data the nasdaq is producing. I'm using the $1000 2022-01-28 PUT for tesla as an example. Using the following code:

    use black_scholes_pricer::put_greeks;
    use chrono::NaiveDate;

    let expiry = NaiveDate::from_ymd(2022, 1, 28);
    let today = NaiveDate::from_ymd(2021, 12, 25);
    let days_until_expire = expiry.signed_duration_since(today).num_days();
    println!("Days until expire: {}", days_until_expire);
    let greeks = put_greeks(
        &[52.0],
        &[1000.0],
        &[days_until_expire as f32 / 252.0],
        &[0.0],
        &[0.62578],
        &[0.0],
    );
    println!("{:?}", greeks);

I get this output:

Days until expire: 34
Greeks { pv: [948.0, NaN, NaN, NaN, NaN, NaN, NaN, NaN], delta: [-1.0, NaN, NaN, NaN, NaN, NaN, NaN, NaN], theta: [-3409717700000000000000000000000000000.0, NaN, NaN, NaN, NaN, NaN, NaN, NaN], gamma: [-6440186000000000000000000000000000.0, NaN, NaN, NaN, NaN, NaN, NaN, NaN], rho: [-134.92064, NaN, NaN, NaN, NaN, NaN, NaN, NaN], vega: [1470297200000000000000000000000000000.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] }

If I modify the inputs and remove the division by 252 from the days_util_expire and actually gets pretty close to the nasdaq output.

Greeks { pv: [987.7166, NaN, NaN, NaN, NaN, NaN, NaN, NaN], delta: [-0.15524423, NaN, NaN, NaN, NaN, NaN, NaN, NaN], theta: [-1.8617551, NaN, NaN, NaN, NaN, NaN, NaN, NaN], gamma: [-0.0035164347, NaN, NaN, NaN, NaN, NaN, NaN, NaN], rho: [-33856.836, NaN, NaN, NaN, NaN, NaN, NaN, NaN], vega: [202.30647, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] }

I'm likely not understanding something about how to use this function.

image
ronniec95 commented 2 years ago

Hi

You have a spot price of 52 and a strike of 1000? Do you not mean spot: 1067 strike: 1000?

pub fn put_greeks( spot: &[f32], // This should be the spot price of the underlying, not of the option strike: &[f32], volatility: &[f32], risk_free_rate: &[f32], dividend_yield: &[f32], years_to_expiry: &[f32], )

The PV is 948 in your example which indicates a delta of 1 which is the same as shorting the stock.

cholcombe973 commented 2 years ago

Ok that makes more sense! I changed the code around to this:

    let expiry = NaiveDate::from_ymd(2022, 1, 28);
    let today = NaiveDate::from_ymd(2021, 12, 25);
    let days_until_expire = expiry.signed_duration_since(today).num_days();
    let days_until_expire = days_until_expire as f32 / 365.0;
    let bs_price = black_scholes_pricer::bs_single::bs_price(
        black_scholes_pricer::bs::OptionDir::PUT,
        1067.64,
        1000.0,
        days_until_expire as f32,
        0.01,
        0.62578,
        0.0,
    );
    println!("BS Price: {}", bs_price);
    let greeks = black_scholes_pricer::put_greeks(
        &[1067.64],
        &[1000.0],
        &[days_until_expire as f32],
        &[0.01],
        &[0.62578],
        &[0.0],
    );
  println!("{:?}", greeks);
BS Price: 49.0159
Greeks { pv: [49.0159, NaN, NaN, NaN, NaN, NaN, NaN, NaN], delta: [-0.3288607, NaN, NaN, NaN, NaN, NaN, NaN, NaN], theta: [-477.68066, NaN, NaN, NaN, NaN, NaN, NaN, NaN], gamma: [-0.002158228, NaN, NaN, NaN, NaN, NaN, NaN, NaN], rho: [-37.27152, NaN, NaN, NaN, NaN, NaN, NaN, NaN], vega: [143.40182, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0] }

That actually gets pretty close! The theta and vega values doesn't make sense to me though. Do I need to do some post processing with those values?

cholcombe973 commented 2 years ago

I did some further research and it looks like the theta value is represented in years so it needs to be divided by the number trading days to get the theta per calendar day. Is that also true for your library? Edit: Dividing that out it looks pretty close. It might be worth just making a little documentation note on the functions saying the value is a yearly value and should be divided out for people like myself that are new to this. :)

ronniec95 commented 2 years ago

Hi Chris

Yes on the theta. The reason is that you may have options with different basis , 252, 360, 365. Rather than assuming I give a base value and let the user decide. The other way would be to take an extra parameter and use that for all calculations.

Am open to suggestions? It might make it more explicit actually?

Also the Vega is for 1 option so you may want to multiply by 100.

Let me know what you think?

On Fri, 31 Dec 2021, 02:52 Chris Holcombe, @.***> wrote:

I did some further research and it looks like the theta value is represented in years so it needs to be divided by the number trading days to get the theta per calendar day. Is that also true for your library?

— Reply to this email directly, view it on GitHub https://github.com/ronniec95/black_scholes/issues/3#issuecomment-1003247655, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAGY5WHOGQGXIHXRCU4RENDUTULH5ANCNFSM5KYOWHTQ . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

You are receiving this because you commented.Message ID: @.***>

cholcombe973 commented 2 years ago

Thanks for the clarification! That makes sense. Yeah I think taking an optional parameter would be fine or just adding a note to the documentation to the Greeks struct saying this is the raw theta/vega values and you'll need to process as needed to suite your situation.

ronniec95 commented 2 years ago

Yeah I think I'll do that for all the methods actually