Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

program: flag to set max leverage for spot orders #346

Merged
merged 5 commits into from
Feb 6, 2023
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
54 changes: 38 additions & 16 deletions programs/drift/src/controller/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,6 @@ pub fn place_perp_order(

// Increment open orders for existing position
let (existing_position_direction, order_base_asset_amount) = {
let market_position = &mut user.perp_positions[position_index];
market_position.open_orders += 1;

validate!(
params.base_asset_amount >= market.amm.order_step_size,
ErrorCode::OrderAmountTooSmall,
Expand All @@ -186,8 +183,22 @@ pub fn place_perp_order(
market.amm.order_step_size
)?;

let base_asset_amount =
standardize_base_asset_amount(params.base_asset_amount, market.amm.order_step_size)?;
let base_asset_amount = if params.base_asset_amount == u64::MAX {
calculate_max_perp_order_size(
user,
position_index,
params.market_index,
params.direction,
perp_market_map,
spot_market_map,
oracle_map,
)?
} else {
standardize_base_asset_amount(params.base_asset_amount, market.amm.order_step_size)?
};

let market_position = &mut user.perp_positions[position_index];
market_position.open_orders += 1;

if !matches!(
&params.order_type,
Expand Down Expand Up @@ -2626,6 +2637,7 @@ pub fn place_spot_order(
let market_index = params.market_index;
let spot_market = &spot_market_map.get_ref(&market_index)?;
let force_reduce_only = spot_market.is_reduce_only()?;
let step_size = spot_market.order_step_size;

validate!(
!matches!(spot_market.status, MarketStatus::Initialized),
Expand All @@ -2639,36 +2651,46 @@ pub fn place_spot_order(

let oracle_price_data = *oracle_map.get_price_data(&spot_market.oracle)?;
let (worst_case_token_amount_before, _) = user.spot_positions[spot_position_index]
.get_worst_case_token_amounts(spot_market, &oracle_price_data, None)?;
.get_worst_case_token_amounts(spot_market, &oracle_price_data, None, None)?;

let balance_type = user.spot_positions[spot_position_index].balance_type;
let token_amount = user.spot_positions[spot_position_index].get_token_amount(spot_market)?;
let signed_token_amount = get_signed_token_amount(token_amount, &balance_type)?;

// Increment open orders for existing position
let (existing_position_direction, order_base_asset_amount) = {
let spot_position = &mut user.spot_positions[spot_position_index];
spot_position.open_orders += 1;

validate!(
params.base_asset_amount >= spot_market.order_step_size,
params.base_asset_amount >= step_size,
ErrorCode::InvalidOrderSizeTooSmall,
"params.base_asset_amount={} cannot be below spot_market.order_step_size={}",
params.base_asset_amount,
spot_market.order_step_size
step_size
)?;

let base_asset_amount =
standardize_base_asset_amount(params.base_asset_amount, spot_market.order_step_size)?;
let base_asset_amount = if params.base_asset_amount == u64::MAX {
calculate_max_spot_order_size(
user,
params.market_index,
params.direction,
perp_market_map,
spot_market_map,
oracle_map,
)?
} else {
standardize_base_asset_amount(params.base_asset_amount, step_size)?
};

validate!(
is_multiple_of_step_size(base_asset_amount, spot_market.order_step_size)?,
is_multiple_of_step_size(base_asset_amount, step_size)?,
ErrorCode::InvalidOrderNotStepSizeMultiple,
"Order base asset amount ({}), is not a multiple of step size ({})",
base_asset_amount,
spot_market.order_step_size
step_size
)?;

let spot_position = &mut user.spot_positions[spot_position_index];
spot_position.open_orders += 1;

if !matches!(
&params.order_type,
OrderType::TriggerMarket | OrderType::TriggerLimit
Expand Down Expand Up @@ -2754,7 +2776,7 @@ pub fn place_spot_order(
user.orders[new_order_index] = new_order;

let (worst_case_token_amount_after, _) = user.spot_positions[spot_position_index]
.get_worst_case_token_amounts(spot_market, &oracle_price_data, None)?;
.get_worst_case_token_amounts(spot_market, &oracle_price_data, None, None)?;

let order_risk_decreasing =
is_spot_order_risk_decreasing(&user.orders[new_order_index], &balance_type, token_amount)?;
Expand Down
23 changes: 19 additions & 4 deletions programs/drift/src/math/margin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use crate::state::user::{PerpPosition, SpotPosition, User};
use num_integer::Roots;
use solana_program::msg;
use std::cmp::{max, min, Ordering};
use std::ops::Neg;

#[cfg(test)]
mod tests;
Expand Down Expand Up @@ -332,11 +333,21 @@ pub fn calculate_margin_requirement_and_total_collateral_and_liability_info(
}
}
} else {
let signed_token_amount = spot_position.get_signed_token_amount(&spot_market)?;
let (worst_case_token_amount, worst_cast_quote_token_amount): (i128, i128) =
spot_position.get_worst_case_token_amounts(
&spot_market,
oracle_price_data,
None,
if strict {
Some(
spot_market
.historical_oracle_data
.last_oracle_price_twap_5min,
)
} else {
None
},
Some(signed_token_amount),
)?;

if worst_case_token_amount == 0 {
Expand All @@ -349,9 +360,9 @@ pub fn calculate_margin_requirement_and_total_collateral_and_liability_info(
)?;
}

let worst_case_token_value = if strict {
let signed_token_value = if strict {
get_strict_token_value(
worst_case_token_amount,
signed_token_amount,
spot_market.decimals,
oracle_price_data,
spot_market
Expand All @@ -360,12 +371,16 @@ pub fn calculate_margin_requirement_and_total_collateral_and_liability_info(
)?
} else {
get_token_value(
worst_case_token_amount,
signed_token_amount,
spot_market.decimals,
oracle_price_data.price,
)?
};

// the worst case token value is the deposit/borrow amount * oracle + worst case order size * oracle
let worst_case_token_value =
signed_token_value.safe_add(worst_cast_quote_token_amount.neg())?;

margin_requirement =
margin_requirement.safe_add(spot_position.margin_requirement_for_open_orders()?)?;

Expand Down
Loading