diff --git a/Cargo.lock b/Cargo.lock index 9602083..c2579f7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1116,7 +1116,7 @@ dependencies = [ [[package]] name = "redeem-logic-vanilla-option" -version = "0.1.1" +version = "1.0.0" dependencies = [ "anchor-lang", "rust_decimal", diff --git a/README.md b/README.md index 3995851..c3e1d2f 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ Following the Vyper suite | **Redeem Logic Lending** | Redeem Logic Plugin | `0.1.1` | `programs/redeem-logic-lending` | | **Redeem Logic Lending Fee** | Redeem Logic Plugin | `0.1.1` | `programs/redeem-logic-lending-fee` | | **Redeem Logic Farming** | Redeem Logic Plugin | `1.0.0` | `programs/redeem-logic-farming` | -| **Redeem Logic Vanilla Option** | Redeem Logic Plugin | `0.1.1` | `programs/redeem-logic-vanilla-option` | +| **Redeem Logic Vanilla Option** | Redeem Logic Plugin | `1.0.0` | `programs/redeem-logic-vanilla-option` | | **Redeem Logic Forward** | Redeem Logic Plugin | `0.1.1` | `programs/redeem-logic-forward` | | **Redeem Logic Settled Forward** | Redeem Logic Plugin | `0.1.1` | `programs/redeem-logic-settled-forward`| | **Redeem Logic Fila** | Redeem Logic Plugin | `0.1.1` | `programs/redeem-logic-fila` | diff --git a/programs/redeem-logic-vanilla-option/Cargo.toml b/programs/redeem-logic-vanilla-option/Cargo.toml index 42a134b..9c74698 100644 --- a/programs/redeem-logic-vanilla-option/Cargo.toml +++ b/programs/redeem-logic-vanilla-option/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "redeem-logic-vanilla-option" -version = "0.1.1" +version = "1.0.0" description = "Created with Anchor" edition = "2021" diff --git a/programs/redeem-logic-vanilla-option/src/lib.rs b/programs/redeem-logic-vanilla-option/src/lib.rs index 8b5cd99..be66746 100644 --- a/programs/redeem-logic-vanilla-option/src/lib.rs +++ b/programs/redeem-logic-vanilla-option/src/lib.rs @@ -1,3 +1,13 @@ +// Vyper Redeem Logic: Vanilla Option Contract +// Example: SOL/USD call option +// The notional of the contract is in base asset (e.g. SOL in a SOL/USD contract) +// Supports both linear and inverse settlement. For example for a SOL/USD contract: +// - if is_linear provide USD as collateral +// - else provide SOL +// Senior [0] is long the option, junior [1] is short +// Senior amount is the option premium paid in any case, junior amount is the collateral paid only if it expires ITM +// Learn more here: https://vyperprotocol.notion.site/Contract-Payoff-Vanilla-Option-47b362270a164d7b96732d139e4d7ee2 + use anchor_lang::prelude::*; use rust_decimal::prelude::*; use vyper_utils::redeem_logic_common::RedeemLogicErrors; @@ -13,13 +23,6 @@ solana_security_txt::security_txt! { declare_id!("8fSeRtFseNrjdf8quE2YELhuzLkHV7WEGRPA9Jz8xEVe"); -// showcasing Vyper reedem logic for vanilla options -// supports both linear and inverse settlement (=self quanto) e.g. SOL/USDC option settled in USDC vs SOL -// the option is fully collateralized, which amounts to the option writer buying back an option of the same type at bankruptcy level (i.e. call/put spread) -// senior ([0]) is option buyer, junior ([1]) is option writer -// the notional of the trade is junior_qty if inverse and junior_qty / initial_price if linear -// the premium is senior_qty and paid at expiry - #[program] pub mod redeem_logic_vanilla_option { @@ -28,25 +31,7 @@ pub mod redeem_logic_vanilla_option { pub fn initialize( ctx: Context, strike: f64, - is_call: bool, - is_linear: bool, - ) -> Result<()> { - require!(strike >= 0., RedeemLogicErrors::InvalidInput); - - let redeem_logic_config = &mut ctx.accounts.redeem_logic_config; - redeem_logic_config.owner = ctx.accounts.owner.key(); - redeem_logic_config.strike = Decimal::from_f64(strike) - .ok_or(RedeemLogicErrors::MathError)? - .serialize(); - redeem_logic_config.is_call = is_call; - redeem_logic_config.is_linear = is_linear; - - Ok(()) - } - - pub fn update( - ctx: Context, - strike: f64, + notional: u64, is_call: bool, is_linear: bool, ) -> Result<()> { @@ -56,6 +41,7 @@ pub mod redeem_logic_vanilla_option { redeem_logic_config.strike = Decimal::from_f64(strike) .ok_or(RedeemLogicErrors::MathError)? .serialize(); + redeem_logic_config.notional = notional; redeem_logic_config.is_call = is_call; redeem_logic_config.is_linear = is_linear; @@ -71,9 +57,9 @@ pub mod redeem_logic_vanilla_option { let result: RedeemLogicExecuteResult = execute_plugin( input_data.old_quantity, - Decimal::deserialize(input_data.old_reserve_fair_value[0]), Decimal::deserialize(input_data.new_reserve_fair_value[0]), Decimal::deserialize(ctx.accounts.redeem_logic_config.strike), + ctx.accounts.redeem_logic_config.notional, ctx.accounts.redeem_logic_config.is_call, ctx.accounts.redeem_logic_config.is_linear, )?; @@ -123,26 +109,12 @@ pub struct InitializeContext<'info> { #[account(init, payer = payer, space = RedeemLogicConfig::LEN)] pub redeem_logic_config: Box>, - /// CHECK: Owner of the tranche config - #[account()] - pub owner: AccountInfo<'info>, - /// Signer account #[account(mut)] pub payer: Signer<'info>, pub system_program: Program<'info, System>, } -#[derive(Accounts)] -pub struct UpdateContext<'info> { - #[account(mut, has_one = owner)] - pub redeem_logic_config: Account<'info, RedeemLogicConfig>, - - /// CHECK: Owner of the tranche config - #[account()] - pub owner: Signer<'info>, -} - #[derive(Accounts)] pub struct ExecuteContext<'info> { #[account()] @@ -151,76 +123,53 @@ pub struct ExecuteContext<'info> { #[account] pub struct RedeemLogicConfig { + pub strike: [u8; 16], + pub notional: u64, + /// true if call, false if put pub is_call: bool, /// true if linear, false if inverse pub is_linear: bool, - - pub strike: [u8; 16], - pub owner: Pubkey, } impl RedeemLogicConfig { pub const LEN: usize = 8 + // discriminator + 16 + // pub strike: [u8; 16], + 8 + // pub notional: u64, 1 + // pub is_call: bool, - 1 + // pub is_linear: bool, - 16 + // pub strike: [u8; 16], - 32 // pub owner: Pubkey, + 1 // pub is_linear: bool, ; fn dump(&self) { msg!("redeem logic config:"); + msg!("+ strike: {:?}", Decimal::deserialize(self.strike)); + msg!("+ notional: {:?}", self.notional); msg!("+ is_call: {:?}", self.is_call); msg!("+ is_linear: {:?}", self.is_linear); - msg!("+ strike: {:?}", Decimal::deserialize(self.strike)) } } #[allow(clippy::collapsible_else_if)] +#[allow(clippy::nonminimal_bool)] fn execute_plugin( old_quantity: [u64; 2], - old_spot: Decimal, new_spot: Decimal, strike: Decimal, + notional: u64, is_call: bool, is_linear: bool, ) -> Result { - require!(old_spot >= Decimal::ZERO, RedeemLogicErrors::InvalidInput); - require!(new_spot >= Decimal::ZERO, RedeemLogicErrors::InvalidInput); require!(strike >= Decimal::ZERO, RedeemLogicErrors::InvalidInput); - if old_spot == Decimal::ZERO { - return Ok(RedeemLogicExecuteResult { - new_quantity: old_quantity, - fee_quantity: 0, - }); - } - - // let senior_old_quantity = Decimal::from(old_quantity[0]); - let junior_old_quantity = Decimal::from(old_quantity[1]); - let total_old_quantity = Decimal::from(old_quantity.iter().sum::()); - - let notional = if is_linear { - junior_old_quantity / old_spot - } else { - junior_old_quantity - }; + let notional = Decimal::from(notional); - let payoff = { - if !is_linear & (new_spot == Decimal::ZERO) { - if strike == Decimal::ZERO { - if is_call { - Decimal::ONE - } else { - Decimal::ZERO - } + let payoff = notional * { + if new_spot == Decimal::ZERO && !is_linear { + if !is_call || (is_call && strike > Decimal::ZERO) { + Decimal::ZERO } else { - if is_call { - Decimal::ZERO - } else { - Decimal::ONE - } + Decimal::ONE } } else { Decimal::ZERO.max({ @@ -239,22 +188,18 @@ fn execute_plugin( } }; - let senior_new_quantity = junior_old_quantity.min(notional * payoff); - let junior_new_quantity = Decimal::ZERO.max(total_old_quantity - senior_new_quantity); + let junior_old_quantity = Decimal::from(old_quantity[1]); + let senior_new_quantity = junior_old_quantity.min(payoff); let senior_new_quantity = senior_new_quantity .floor() .to_u64() .ok_or(RedeemLogicErrors::MathError)?; - let junior_new_quantity = junior_new_quantity - .floor() - .to_u64() - .ok_or(RedeemLogicErrors::MathError)?; - let fee_quantity = old_quantity.iter().sum::() - senior_new_quantity - junior_new_quantity; + let junior_new_quantity = old_quantity.iter().sum::() - senior_new_quantity; Ok(RedeemLogicExecuteResult { new_quantity: [senior_new_quantity, junior_new_quantity], - fee_quantity, + fee_quantity: 0, }) } @@ -266,53 +211,25 @@ mod tests { #[test] fn test_linear_call_otm() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); + let old_quantity = [10_000, 100_000]; let new_spot_value = dec!(5); let strike = dec!(7); + let notional = 5_000; let is_call = true; let is_linear = true; let res = execute_plugin( old_quantity, - old_spot_value, new_spot_value, strike, + notional, is_call, is_linear, ) .unwrap(); assert_eq!(res.new_quantity[0], 0); - assert_eq!(res.new_quantity[1], 200_000); - assert_eq!(res.fee_quantity, 0); - assert_eq!( - old_quantity.iter().sum::(), - res.new_quantity.iter().sum::() + res.fee_quantity - ); - } - - #[test] - fn test_linear_call_atm() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); - let new_spot_value = dec!(5); - let strike = dec!(5); - let is_call = true; - let is_linear = true; - - let res = execute_plugin( - old_quantity, - old_spot_value, - new_spot_value, - strike, - is_call, - is_linear, - ) - .unwrap(); - - assert_eq!(res.new_quantity[0], 0); - assert_eq!(res.new_quantity[1], 200_000); + assert_eq!(res.new_quantity[1], 110_000); assert_eq!(res.fee_quantity, 0); assert_eq!( old_quantity.iter().sum::(), @@ -322,24 +239,24 @@ mod tests { #[test] fn test_linear_call_itm() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); - let new_spot_value = dec!(10); - let strike = dec!(5); + let old_quantity = [10_000, 100_000]; + let new_spot_value = dec!(5); + let strike = dec!(3); + let notional = 5_000; let is_call = true; let is_linear = true; let res = execute_plugin( old_quantity, - old_spot_value, new_spot_value, strike, + notional, is_call, is_linear, ) .unwrap(); - assert_eq!(res.new_quantity[0], 100_000); + assert_eq!(res.new_quantity[0], 10_000); assert_eq!(res.new_quantity[1], 100_000); assert_eq!(res.fee_quantity, 0); assert_eq!( @@ -349,138 +266,26 @@ mod tests { } #[test] - fn test_linear_put_otm() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); - let new_spot_value = dec!(6); - let strike = dec!(5); - let is_call = false; - let is_linear = true; - - let res = execute_plugin( - old_quantity, - old_spot_value, - new_spot_value, - strike, - is_call, - is_linear, - ) - .unwrap(); - - assert_eq!(res.new_quantity[0], 0); - assert_eq!(res.new_quantity[1], 200_000); - assert_eq!(res.fee_quantity, 0); - assert_eq!( - old_quantity.iter().sum::(), - res.new_quantity.iter().sum::() + res.fee_quantity - ); - } - - #[test] - fn test_linear_put_atm() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); - let new_spot_value = dec!(5); - let strike = dec!(5); - let is_call = false; - let is_linear = true; - - let res = execute_plugin( - old_quantity, - old_spot_value, - new_spot_value, - strike, - is_call, - is_linear, - ) - .unwrap(); - - assert_eq!(res.new_quantity[0], 0); - assert_eq!(res.new_quantity[1], 200_000); - assert_eq!(res.fee_quantity, 0); - assert_eq!( - old_quantity.iter().sum::(), - res.new_quantity.iter().sum::() + res.fee_quantity - ); - } - - #[test] - fn test_linear_put_itm() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); - let new_spot_value = dec!(3); - let strike = dec!(5); - let is_call = false; - let is_linear = true; - - let res = execute_plugin( - old_quantity, - old_spot_value, - new_spot_value, - strike, - is_call, - is_linear, - ) - .unwrap(); - - assert_eq!(res.new_quantity[0], 40_000); - assert_eq!(res.new_quantity[1], 160_000); - assert_eq!(res.fee_quantity, 0); - assert_eq!( - old_quantity.iter().sum::(), - res.new_quantity.iter().sum::() + res.fee_quantity - ); - } - - #[test] - fn test_inverse_call_otm() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); - let new_spot_value = dec!(5); - let strike = dec!(7); - let is_call = true; - let is_linear = false; - - let res = execute_plugin( - old_quantity, - old_spot_value, - new_spot_value, - strike, - is_call, - is_linear, - ) - .unwrap(); - - assert_eq!(res.new_quantity[0], 0); - assert_eq!(res.new_quantity[1], 200_000); - assert_eq!(res.fee_quantity, 0); - assert_eq!( - old_quantity.iter().sum::(), - res.new_quantity.iter().sum::() + res.fee_quantity - ); - } - - #[test] - fn test_inverse_call_atm() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); + fn test_inverse_call_itm() { + let old_quantity = [10_000, 100_000]; let new_spot_value = dec!(5); - let strike = dec!(5); + let strike = dec!(3); + let notional = 5_000; let is_call = true; let is_linear = false; let res = execute_plugin( old_quantity, - old_spot_value, new_spot_value, strike, + notional, is_call, is_linear, ) .unwrap(); - assert_eq!(res.new_quantity[0], 0); - assert_eq!(res.new_quantity[1], 200_000); + assert_eq!(res.new_quantity[0], 2_000); + assert_eq!(res.new_quantity[1], 108_000); assert_eq!(res.fee_quantity, 0); assert_eq!( old_quantity.iter().sum::(), @@ -489,26 +294,26 @@ mod tests { } #[test] - fn test_inverse_call_itm() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); - let new_spot_value = dec!(10); - let strike = dec!(5); + fn test_linear_call_deep_itm() { + let old_quantity = [10_000, 100_000]; + let new_spot_value = dec!(500); + let strike = dec!(3); + let notional = 5_000; let is_call = true; - let is_linear = false; + let is_linear = true; let res = execute_plugin( old_quantity, - old_spot_value, new_spot_value, strike, + notional, is_call, is_linear, ) .unwrap(); - assert_eq!(res.new_quantity[0], 50_000); - assert_eq!(res.new_quantity[1], 150_000); + assert_eq!(res.new_quantity[0], 100_000); + assert_eq!(res.new_quantity[1], 10_000); assert_eq!(res.fee_quantity, 0); assert_eq!( old_quantity.iter().sum::(), @@ -517,26 +322,26 @@ mod tests { } #[test] - fn test_inverse_put_otm() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); + fn test_linear_put_otm() { + let old_quantity = [10_000, 100_000]; let new_spot_value = dec!(5); let strike = dec!(3); + let notional = 5_000; let is_call = false; - let is_linear = false; + let is_linear = true; let res = execute_plugin( old_quantity, - old_spot_value, new_spot_value, strike, + notional, is_call, is_linear, ) .unwrap(); assert_eq!(res.new_quantity[0], 0); - assert_eq!(res.new_quantity[1], 200_000); + assert_eq!(res.new_quantity[1], 110_000); assert_eq!(res.fee_quantity, 0); assert_eq!( old_quantity.iter().sum::(), @@ -545,26 +350,26 @@ mod tests { } #[test] - fn test_inverse_put_atm() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); - let new_spot_value = dec!(5); + fn test_linear_put_itm() { + let old_quantity = [10_000, 100_000]; + let new_spot_value = dec!(3); let strike = dec!(5); + let notional = 5_000; let is_call = false; - let is_linear = false; + let is_linear = true; let res = execute_plugin( old_quantity, - old_spot_value, new_spot_value, strike, + notional, is_call, is_linear, ) .unwrap(); - assert_eq!(res.new_quantity[0], 0); - assert_eq!(res.new_quantity[1], 200_000); + assert_eq!(res.new_quantity[0], 10_000); + assert_eq!(res.new_quantity[1], 100_000); assert_eq!(res.fee_quantity, 0); assert_eq!( old_quantity.iter().sum::(), @@ -574,25 +379,25 @@ mod tests { #[test] fn test_inverse_put_itm() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); - let new_spot_value = dec!(2.5); + let old_quantity = [10_000, 100_000]; + let new_spot_value = dec!(3); let strike = dec!(5); + let notional = 5_000; let is_call = false; let is_linear = false; let res = execute_plugin( old_quantity, - old_spot_value, new_spot_value, strike, + notional, is_call, is_linear, ) .unwrap(); - assert_eq!(res.new_quantity[0], 100_000); - assert_eq!(res.new_quantity[1], 100_000); + assert_eq!(res.new_quantity[0], 3_333); + assert_eq!(res.new_quantity[1], 106_667); assert_eq!(res.fee_quantity, 0); assert_eq!( old_quantity.iter().sum::(), @@ -601,26 +406,26 @@ mod tests { } #[test] - fn test_zero_old_spot() { - let old_quantity = [100_000, 200_000]; - let old_spot_value = dec!(0); - let new_spot_value = dec!(2.5); - let strike = dec!(5); - let is_call = true; + fn test_linear_put_deep_itm() { + let old_quantity = [10_000, 100_000]; + let new_spot_value = dec!(3); + let strike = dec!(500); + let notional = 5_000; + let is_call = false; let is_linear = true; let res = execute_plugin( old_quantity, - old_spot_value, new_spot_value, strike, + notional, is_call, is_linear, ) .unwrap(); assert_eq!(res.new_quantity[0], 100_000); - assert_eq!(res.new_quantity[1], 200_000); + assert_eq!(res.new_quantity[1], 10_000); assert_eq!(res.fee_quantity, 0); assert_eq!( old_quantity.iter().sum::(), @@ -629,26 +434,26 @@ mod tests { } #[test] - fn test_zero_new_spot_linear_call() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); + fn test_zero_sett_linear_call_zero_strike() { + let old_quantity = [10_000, 100_000]; let new_spot_value = dec!(0); - let strike = dec!(0.5); + let strike = dec!(0); + let notional = 5_000; let is_call = true; let is_linear = true; let res = execute_plugin( old_quantity, - old_spot_value, new_spot_value, strike, + notional, is_call, is_linear, ) .unwrap(); assert_eq!(res.new_quantity[0], 0); - assert_eq!(res.new_quantity[1], 200_000); + assert_eq!(res.new_quantity[1], 110_000); assert_eq!(res.fee_quantity, 0); assert_eq!( old_quantity.iter().sum::(), @@ -657,26 +462,26 @@ mod tests { } #[test] - fn test_zero_new_spot_inverse_call() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); + fn test_zero_sett_linear_call_pos_strike() { + let old_quantity = [10_000, 100_000]; let new_spot_value = dec!(0); - let strike = dec!(0.5); + let strike = dec!(1); + let notional = 5_000; let is_call = true; - let is_linear = false; + let is_linear = true; let res = execute_plugin( old_quantity, - old_spot_value, new_spot_value, strike, + notional, is_call, is_linear, ) .unwrap(); assert_eq!(res.new_quantity[0], 0); - assert_eq!(res.new_quantity[1], 200_000); + assert_eq!(res.new_quantity[1], 110_000); assert_eq!(res.fee_quantity, 0); assert_eq!( old_quantity.iter().sum::(), @@ -685,26 +490,26 @@ mod tests { } #[test] - fn test_zero_new_spot_linear_put() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); + fn test_zero_sett_linear_put_zero_strike() { + let old_quantity = [10_000, 100_000]; let new_spot_value = dec!(0); - let strike = dec!(0.5); + let strike = dec!(0); + let notional = 5_000; let is_call = false; let is_linear = true; let res = execute_plugin( old_quantity, - old_spot_value, new_spot_value, strike, + notional, is_call, is_linear, ) .unwrap(); - assert_eq!(res.new_quantity[0], 10_000); - assert_eq!(res.new_quantity[1], 190_000); + assert_eq!(res.new_quantity[0], 0); + assert_eq!(res.new_quantity[1], 110_000); assert_eq!(res.fee_quantity, 0); assert_eq!( old_quantity.iter().sum::(), @@ -713,26 +518,26 @@ mod tests { } #[test] - fn test_zero_new_spot_inverse_put() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); + fn test_zero_sett_linear_put_pos_strike() { + let old_quantity = [10_000, 100_000]; let new_spot_value = dec!(0); - let strike = dec!(0.5); + let strike = dec!(1); + let notional = 5_000; let is_call = false; - let is_linear = false; + let is_linear = true; let res = execute_plugin( old_quantity, - old_spot_value, new_spot_value, strike, + notional, is_call, is_linear, ) .unwrap(); - assert_eq!(res.new_quantity[0], 100_000); - assert_eq!(res.new_quantity[1], 100_000); + assert_eq!(res.new_quantity[0], 5_000); + assert_eq!(res.new_quantity[1], 105_000); assert_eq!(res.fee_quantity, 0); assert_eq!( old_quantity.iter().sum::(), @@ -741,26 +546,26 @@ mod tests { } #[test] - fn test_zero_new_spot_zero_strike_linear_call() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); + fn test_zero_sett_inverse_call_zero_strike() { + let old_quantity = [10_000, 100_000]; let new_spot_value = dec!(0); let strike = dec!(0); + let notional = 5_000; let is_call = true; - let is_linear = true; + let is_linear = false; let res = execute_plugin( old_quantity, - old_spot_value, new_spot_value, strike, + notional, is_call, is_linear, ) .unwrap(); - assert_eq!(res.new_quantity[0], 0); - assert_eq!(res.new_quantity[1], 200_000); + assert_eq!(res.new_quantity[0], 5_000); + assert_eq!(res.new_quantity[1], 105_000); assert_eq!(res.fee_quantity, 0); assert_eq!( old_quantity.iter().sum::(), @@ -769,26 +574,26 @@ mod tests { } #[test] - fn test_zero_new_spot_zero_strike_inverse_call() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); + fn test_zero_sett_inverse_call_pos_strike() { + let old_quantity = [10_000, 100_000]; let new_spot_value = dec!(0); - let strike = dec!(0); + let strike = dec!(1); + let notional = 5_000; let is_call = true; let is_linear = false; let res = execute_plugin( old_quantity, - old_spot_value, new_spot_value, strike, + notional, is_call, is_linear, ) .unwrap(); - assert_eq!(res.new_quantity[0], 100_000); - assert_eq!(res.new_quantity[1], 100_000); + assert_eq!(res.new_quantity[0], 0); + assert_eq!(res.new_quantity[1], 110_000); assert_eq!(res.fee_quantity, 0); assert_eq!( old_quantity.iter().sum::(), @@ -797,26 +602,26 @@ mod tests { } #[test] - fn test_zero_new_spot_zero_strike_linear_put() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); + fn test_zero_sett_inverse_put_zero_strike() { + let old_quantity = [10_000, 100_000]; let new_spot_value = dec!(0); let strike = dec!(0); + let notional = 5_000; let is_call = false; - let is_linear = true; + let is_linear = false; let res = execute_plugin( old_quantity, - old_spot_value, new_spot_value, strike, + notional, is_call, is_linear, ) .unwrap(); assert_eq!(res.new_quantity[0], 0); - assert_eq!(res.new_quantity[1], 200_000); + assert_eq!(res.new_quantity[1], 110_000); assert_eq!(res.fee_quantity, 0); assert_eq!( old_quantity.iter().sum::(), @@ -825,58 +630,30 @@ mod tests { } #[test] - fn test_zero_new_spot_zero_strike_inverse_put() { - let old_quantity = [100_000; 2]; - let old_spot_value = dec!(5); + fn test_zero_sett_inverse_put_pos_strike() { + let old_quantity = [10_000, 100_000]; let new_spot_value = dec!(0); - let strike = dec!(0); + let strike = dec!(1); + let notional = 5_000; let is_call = false; let is_linear = false; let res = execute_plugin( old_quantity, - old_spot_value, new_spot_value, strike, + notional, is_call, is_linear, ) .unwrap(); assert_eq!(res.new_quantity[0], 0); - assert_eq!(res.new_quantity[1], 200_000); + assert_eq!(res.new_quantity[1], 110_000); assert_eq!(res.fee_quantity, 0); assert_eq!( old_quantity.iter().sum::(), res.new_quantity.iter().sum::() + res.fee_quantity ); } - - #[test] - fn test_rounding() { - let old_quantity = [13_456, 52_215]; - let old_spot_value = dec!(5); - let new_spot_value = dec!(6.698); - let strike = dec!(5.119); - let is_call = true; - let is_linear = false; - - let res = execute_plugin( - old_quantity, - old_spot_value, - new_spot_value, - strike, - is_call, - is_linear, - ) - .unwrap(); - - assert_eq!(res.new_quantity[0], 12_309); - assert_eq!(res.new_quantity[1], 53_361); - assert_eq!(res.fee_quantity, 1); - assert_eq!( - old_quantity.iter().sum::(), - res.new_quantity.iter().sum::() + res.fee_quantity - ); - } }