v9.2.1 Update
Summary
50% of the spread and price impact is now charged on trade opening and closing instead of 100% on trade opening
Existing trades don't pay any spread or impact on close (since they already paid in full on open), and they keep paying 100% spread when partial adding
Spread and price impact on close use the reverse direction as opening spread (makes price lower for longs and higher for shorts)
Price impact on close uses the opposite side depth and opposite side price impact OI (= cumulative vol now)
Price impact OI windows now use new cumulative volume logic (much shorter windows duration possible because more accurate, opening a long / closing a short uses/adds to long windows, opening a short / closing a long uses/adds to short windows, new cumulative factor which will be set to 1 to start with but can be used to adjust weight of price impact OI in price impact formula), we never remove any OI from windows anymore (logic much simpler, no longer need to move trade OI to current window for partials)
Closing price impact higher for short-term trades (depending on protection factor blocks duration and protection factor multiplier per pair), only when net PnL is positive
Liquidation price now takes into account the closing spread (not the price impact) for trades opened after v9.2 and uses new logic for the liquidation pnl % threshold (closer pnl % threshold as leverage increases, more aggressive for higher leverages similarly to MMR)
Existing trades aren't affected by the new liquidation threshold logic, liquidation parameters for trades are stored on opening so they can't change for an open trade even when a group's liquidation parameters are updated, however a trade's liquidation params are refreshed to current value when position size is increased using partials
New stop loss max distance is
liqPnlThresholdP - 10%
(eg. -70% PnL when trade liq pnl % threshold is -80%)Added max slippage on close (market close, partial close, tp/sl) mechanism: by default 1% for all opened trades, can be adjusted after trade is open
Extracted cancel reason logic for limit/stop/tp/sl/liq callbacks into getters, will be used by EA-lookbacks to check ability to execute at past chain state
LIQ triggers no longer turned into SL triggers when SL is closer otherwise user could set very low max closing slippage and would never be able to be liquidated if price went past his SL and LIQ price, trigger bots will prioritize SL over LIQ when possible
Full Changelog
core/facets/GNSPairsStorage.sol (update)
Added
initializeGroupLiquidationParams
,setGroupLiquidationParams
,getGroupLiquidationParams
, andgetPairLiquidationParams
core/facets/GNSPriceAggregator.sol (update)
getPrice
now accepts_tradeId
instead of_trader
core/facets/GNSPriceImpact.sol (update)
Added
initializePairFactors
,setProtectionCloseFactors
,setProtectionCloseFactorBlocks
,setCumulativeFactors
,getPairFactors
Removed
removePriceImpactOpenInterest
,getTradeLastWindowOiUsd
,getTradePriceImpactInfo
addPriceImpactOpenInterest
now accepts_open
argumentgetTradePriceImpact
now accepts_isPnlPositive
,_open
,_lastPosIncreaseBlock
, and_contractsVersion
arguments
core/facets/GNSTradingCallbacks.sol (update)
Added
validateTriggerOpenOrderCallback
andvalidateTriggerCloseOrderCallback
getters
core/facets/GNSTradingInteractions.sol (update)
New
updateMaxClosingSlippageP
functioncloseTradeMarket
anddecreasePositionSize
now accept_expectedPrice
argument (used for max slippage check in callbacks)
core/facets/GNSTradingStorage.sol (update)
New
updateTradeMaxClosingSlippageP
functionupdateTradePosition
now accepts_isPartialIncrease
argumentAdded
getTradeLiquidationParams
,getTradesLiquidationParams
,getAllTradesLiquidationParams
, andgetCurrentContractsVersion
interfaces/IGeneralErrors.sol (update)
Added
WrongOrderType()
error
interfaces/libraries/IPairsStorageUtils.sol (update)
Added new function definitions
Added
GroupLiquidationParamsUpdated
eventAdded
MaxLiqSpreadPTooHigh
,WrongLiqParamsThresholds
,WrongLiqParamsLeverages
,StartLiqThresholdTooHigh
,EndLiqThresholdTooLow
,StartLeverageTooLow
,EndLeverageTooHigh
interfaces/libraries/IPriceAggregatorUtils.sol (update)
Adjusted
getPrice
function definitionUpdated
PriceRequested
event: now emitstradeId
instead oftrader
interfaces/libraries/IPriceImpactUtils.sol (update)
Added new function definitions
Removed deprecated function definitions
Adjusted
addPriceImpactOpenInterest
andgetTradePriceImpact
functions definitionsAdded
ProtectionCloseFactorUpdated
,ProtectionCloseFactorBlocksUpdated
, andCumulativeFactorUpdated
eventsRemoved
isPartial
fromPriceImpactOpenInterestAdded
eventRemoved
PriceImpactOpenInterestRemoved
event
interfaces/libraries/ITradingCallbacksUtils.sol (update)
Added
validateTriggerOpenOrderCallback
andvalidateTriggerCloseOrderCallback
functions definitions
interfaces/libraries/ITradingCommonUtils.sol (update)
Added
TradePriceImpactInput
struct to avoid stack too deep ingetTradeClosingPriceImpact
interfaces/libraries/ITradingInteractionsUtils.sol (update)
Added
updateMaxClosingSlippageP
function definitionAdjusted
closeTradeMarket
anddecreasePositionSize
functions definitionsRemoved
WrongOrderType()
error
interfaces/libraries/ITradingStorageUtils.sol (update)
Added new function definitions
Adjusted
updateTradePosition
function definitionTradeStored
event now also emits the trade liquidation paramsTradePositionUpdated
now emitsisPartialIncrease
New
TradeMaxClosingSlippagePUpdated
event
interfaces/libraries/IUpdatePositionSizeUtils.sol (update)
Added
long
andcollateralPriceUsd
properties toPositionSizeIncreaseExecuted
andPositionSizeDecreaseExecuted
events
interfaces/types/IBorrowingFees.sol (update)
LiqPriceInput
struct has newliquidationParams
property
interfaces/types/IPairsStorage.sol (update)
Added
groupLiquidationParams
mapping and correspondingGroupLiquidationParams
struct__gap
length decreased from 41 to 40
interfaces/types/IPriceImpact.sol (update)
Added
pairFactors
mapping__gap
length decreased from 46 to 45Added
_open
property toOiWindowUpdate
structNew
PairFactors
struct
interfaces/types/ITradingStorage.sol (update)
Added
tradeLiquidationParams
mapping__gap
length decreased from 39 to 38New
ContractsVersion
enumTradeInfo
struct now hascontractsVersion
andlastPosIncreaseBlock
properties, and__placeholder
was reduced fromuint48
touint8
interfaces/types/IUpdatePositionSize.sol (update)
Added
expectedPrice
property toDecreasePositionSizeInput
structAdded
priceAfterImpact
property toDecreasePositionSizeValues
struct
libraries/ArrayGetters.sol (update)
Added
getTradesLiquidationParams
andgetAllTradesLiquidationParams
getters
libraries/BorrowingFeesUtils.sol (update)
getTradeLiquidationPrice
: calculateclosingFeesCollateral
using newTradingCommonUtils.getTotalClosingFeesCollateral
helper, pass input liquidation params, trade contracts version, and pair spread % to_getTradeLiquidationPrice
_getTradeLiquidationPrice
: new_liquidationParams
,_contractsVersion
, and_pairSpreadP
arguments,_collateralPrecisionDelta
is now uint256 (saves one var to avoid stack too deep), calculateliqPnlThresholdP
using newTradingCommonUtils.getLiqPnlThresholdP
helper, incollateralLiqNegativePnlInt
calculation divide by1e10
because of new liq threshold precision, if trade opened after v9.2 make liquidation price distance lower by closing spread (= 1/2 pair spread %, capped atmaxLiqSpreadP
)
libraries/ConstantsUtils.sol (update)
Replaced
MAX_SL_P
bySL_LIQ_BUFFER_P=10%
, renamedLIQ_THRESHOLD_P
toLEGACY_LIQ_THRESHOLD_P
, addedMIN_LIQ_THRESHOLD_P=50%
/MAX_LIQ_SPREAD_P=0.05%
/DEFAULT_MAX_CLOSING_SLIPPAGE_P=1%
libraries/PairsStorageUtils.sol (update)
New
initializeGroupLiquidationParams
function: initializes group liquidation params for all existing groupsNew
setGroupLiquidationParams
function: used to update a group's liquidation params (only affects trades opened after the change)New
getGroupLiquidationParams
andgetPairLiquidationParams
getters
libraries/PriceAggregatorUtils.sol (update)
getPrice
: now accepts_tradeId
argument instead of_trader
, passestrader
/index
/orderType
data tolinkRequest
libraries/PriceImpactUtils.sol (update)
MAX_WINDOWS_DURATION
lowered from 30 days to 10 minutes,MIN_WINDOWS_DURATION
lowered from 10 minutes to 1 minuteNew
initializePairFactors
function that initializes pairs factorsNew
setProtectionCloseFactors
to set the protection close factors for a set of pairsNew
setProtectionCloseFactorBlocks
to set the protection close factor duration in blocks for a set of pairsNew
setCumulativeFactors
to set the cumulative factors for a set of pairsaddPriceImpactOpenInterest
: Removed partials logic that moved previous trade OI to current window if not expired, changed logic to decide if adds to long or short part of window (opening a long / closing a short adds to long window, opening a short / closing a long adds to short window), removedlastWindowOiUsd
update (deprecated)Removed
removePriceImpactOpenInterest
andgetTradeLastWindowOiUsd
getTradePriceImpact
: new_isPnlPositive
/_open
/_lastPosIncreaseBlock
/_contractsVersion
arguments, now loadspairFactors
for pair, uses opposite side depth when_open = false
, uses opposite side price impact OI when_open = false
, passes_open
,protectionCloseFactor
(only when_isPnlPositive
is true,_open
is false,protectionCloseFactor
isn't zero, and protection close factor didn't expire, otherwise passes1e10
),cumulativeFactor
(when not zero, otherwise passes1e10
), and_contractsVersion
to_getTradePriceImpact
Removed
getTradePriceImpactInfo
(deprecated)New
getPairFactors
getter_getTradePriceImpact
: new_open
,_protectionCloseFactor
,_cumulativeFactor
,_contractsVersion
arguments, returns early 0 price impact if trade opened before v9.2 and_open = false
(no closing price impact for trades opened before v9.2 since they paid it fully on open), multiplies_startOpenInterestUsd
by_cumulativeFactor
, multiplies by_protectionCloseFactor
instead of1e10
inpriceImpactP
calculation and divides result by 2 if trade opened after v9.2 (charge half price impact if trade opened after v9.2 since they paid half on open already, for trades opened before v9.2 charges full opening price impact), sets_long
to!_long
if_open
is false to invert the price impact direction on close
libraries/TradingCallbacksUtils.sol (update)
closeTradeMarketCallback
: use new_getTradeInfo
getter, AddTradingCommonUtils.getTradeClosingPriceImpact
call, added max slippage cancel reason check (uses default max slippage % iftradeInfo.maxSlippageP
not set), usepriceAfterImpact
(= market price + closing spread and price impact) instead of_a.price
to calculatev.profitP
, emitpriceAfterImpact
andpriceImpactP
in eventexecuteTriggerOpenOrderCallback
: moved all cancel reason and spread/price impact logic tovalidateTriggerOpenOrderCallback
executeTriggerCloseOrderCallback
: moved all cancel reason and spread/price impact logic tovalidateTriggerCloseOrderCallback
, emitpriceImpactP
inLimitExecuted
eventvalidateTriggerOpenOrderCallback
: new getter that contains the extracted cancel reason logic ofexecuteTriggerOpenOrderCallback
validateTriggerCloseOrderCallback
: new getter that contains the extracted cancel reason logic ofexecuteTriggerCloseOrderCallback
, for SLs and TPs (not liquidations) setv.executionPrice
toTradingCommonUtils.getTradeClosingPriceImpact
result to take into account closing spread and impact, added max slippage cancel reason check for everything but liquidations (uses default max slippage % iftradeInfo.maxSlippageP
not set)_openTradePrep
: no logic change, just use newTradingCommonUtils.getTradeOpeningPriceImpact
helper to calculate opening price impactNew
_getTradeInfo
getter
libraries/TradingCommonUtils.sol (update)
getMarketExecutionPrice
: new_open
/_contractsVersion
arguments, returns early with 0 spread if_open = false
and_contractsVersion = before v9.2
, divides spread by 2 if_contractsVersion >= v9.2
, inverts spread direction when_open
= falsegetTradeValuePure
: combined_borrowingFeeCollateral
and_closingFeeCollateral
into_feesCollateral
to avoid stack too deep, added_liqPnlThresholdP
argument,collateralLiqThreshold
is nowuint256
and uses_liqPnlThresholdP
instead ofConstantsUtils.LIQ_THRESHOLD_P
and is adjusted for1e10
precision, addedint256
conversion forcollateralLiqThreshold
in return statementgetLiqPnlThresholdP
: new pure function that returns the corresponding liquidation PnL threshold percentage to use depending on a trade's liquidation params and leverage; uses new logic (linearly decreasing liq pnl threshold as leverage increases, capped between two values)getTradeLiquidationPrice
: pass the stored trade's liquidation paramsgetTradeValueCollateral
: passborrowingFeesCollateral + _closingFeesCollateral
togetTradeValuePure
instead of passing them separately, and also passgetTradeLiqPnlThresholdP(_trade)
getTradeOpeningPriceImpact
: New view helper to calculate the price impact % and price after spread + price impact for trade openings / partial addsgetTradeClosingPriceImpact
: New view helper that returns the closing price impact %, price after closing spread and impact, and net trade value used to determine whether net pnl is positive or not; returns early 0% price impact for trades opened before v9.2, otherwise calculates net trade value (taking into account pnl, spread, price impact, closing fees, and borrowing fees) without protection factor and compares it to the initial trade collateral to determine the_isPnlPositive
value passed togetTradePriceImpact
which determines the final returnedpriceImpactP
andpriceAfterImpact
valuesgetTradeLiqPnlThresholdP
: new getter that returns the value ofgetLiqPnlThresholdP
by passing the trade's stored liquidation params and its leveragegetTotalClosingFeesCollateral
: new getter that returns a trade's closing fee based on its_collateralIndex
/_pairIndex
/_positionSizeCollateral
, used inBorrowingFeesUtils.getTradeLiquidationPrice
/TradingCommonUtils.getTradeClosingPriceImpact
/DecreasePositionSizeUtils.validateRequest
Renamed
addOiCollateral
toupdateOi
, now accepts_open
argument and passes it tohandleTradeBorrowingCallback
andaddPriceImpactOpenInterest
Renamed
addTradeOiCollateral
toupdateOiTrade
, now accepts_open
argument and passes it toupdateOi
Removed
removeOiCollateral
andremoveTradeOiCollateral
handleOiDelta
now usesupdateOi
, passes_open = true
when_newPositionSizeCollateral > existingPositionSizeCollateral
and_open = false
when_newPositionSizeCollateral < existingPositionSizeCollateral
libraries/TradingInteractionsUtils.sol (update)
New
updateMaxClosingSlippageP
function that simply callsGNSTradingStorage.updateTradeMaxClosingSlippageP
closeTradeMarket
: now accepts_expectedPrice
, reverts if_expectedPrice
is 0, setspendingOrder.trade.openPrice
to_expectedPrice
, passes trade id togetPrice
decreasePositionSize
: now accepts_expectedPrice
, passes it torequestDecreasePositionSize
triggerOrder
: no longer turn LIQ orders into SL orders when SL is closer, usesTradingCommonUtils.getTradeOpeningPriceImpact
to calculatepriceImpactP
_openTrade
: usesTradingCommonUtils.getTradeOpeningPriceImpact
to calculatepriceImpactP
, passes trade id togetPrice
_getPriceTriggerOrder
: passes trade id togetPrice
libraries/TradingStorageUtils.sol (update)
storeTrade
: Fetches the corresponding pair's liquidation params and stores them into the newtradeLiquidationParams
mapping, limits the trade SL distance using the new_limitTradeSlDistance
helper, sets_tradeInfo.contractsVersion
to the current version usinggetCurrentContractsVersion()
, sets_tradeInfo.lastPosIncreaseBlock
to current block, no longer sets_tradeInfo.lastOiUpdateTs = 0
because corresponding logic was deprecated, callsupdateOiTrade
with_open = true
instead ofaddTradeOiCollateral
, emits the trade's liquidation paramsNew
updateTradeMaxClosingSlippageP
setterupdateTradePosition
/updateOpenOrderDetails
/updateTradeSl
: limit the trade's SL distance using the new_limitTradeSlDistance
helper instead of_limitSlDistance
updateTradePosition
: new_isPartialIncrease
argument, sets the trade's stored liquidation params to the current pair liquidation params when_isPartialIncrease = true
and setsi.lastPosIncreaseBlock
to current block, emits_isPartialIncrease
inTradePositionUpdated
eventcloseTrade
: callsupdateOiTrade
with_open = false
instead ofremoveTradeOiCollateral
getTradeLiquidationParams
: new getter to return the newtradeLiquidationParams
mapping valuesgetCurrentContractsVersion
: new getter to return the current contracts version (will need to be updated at each significant update)_limitSlDistance
: accepts new_liqPnlThresholdP
argument, calculatesminSlP
as_liqPnlThresholdP - ConstantsUtils.SL_LIQ_BUFFER_P
, uses calculatedminSlP
instead ofConstantsUtils.MAX_SL_P
, adjustments done for1e10
precision ofminSlP
_limitTradeSlDistance
: new view wrapper accepting_trade
and_newSl
arguments; returns a trade's capped SL distance based on its open price, leverage, new stop loss value, whether it's a long or a short, and based on its liquidation pnl % threshold fetched usingTradingCommonUtils.getTradeLiqPnlThresholdP(_trade)
libraries/updateLeverage/UpdateLeverageLifecycles.sol (update)
_initiateRequest
: small adjustment to avoid stack too deep, now passes trade id togetPrice
_prepareCallbackValues
: pass stored trade liquidation params invalues.liqPrice
calculation_handleCallback
: pass_isPartialIncrease = false
toupdateTradePosition
libraries/updatePositionSize/DecreasePositionSizeUtils.sol (update)
validateRequest
: calculateclosingFeesCollateral
using newTradingCommonUtils.getTotalClosingFeesCollateral
helper, revert ifinput.expectedPrice
is 0prepareCallbackValues
: addedvalues.priceAfterImpact
calculation using newTradingCommonUtils.getTradeClosingPriceImpact
helper,values.existingPnlCollateral
now usesuint64(values.priceAfterImpact)
instead of_answer.price
validateCallback
: now accepts_pendingOrder
(to fetch expected price), added max slippage calculations and corresponding cancel reason check (uses default max slippage % iftradeInfo.maxSlippageP
not set)updateTradeSuccess
: pass_isPartialIncrease = false
toupdateTradePosition
libraries/updatePositionSize/IncreasePositionSizeUtils.sol (update)
prepareCallbackValues
: UsesTradingCommonUtils.getTradeOpeningPriceImpact
to calculatevalues.priceAfterImpact
, passes current pair liquidation params togetTradeLiquidationPrice
forvalues.newLiqPrice
calculation (already checks using new liquidation params since trade liquidation params will be refreshed on success callback)updateTradeSuccess
: pass_isPartialIncrease = true
toupdateTradePosition
libraries/updatePositionSize/UpdatePositionSizeLifecycles.sol (update)
requestDecreasePositionSize
: passes_input.expectedPrice
to_initiateRequest
_initiateRequest
: passes trade id togetPrice
executeIncreasePositionSizeMarket
/executeDecreasePositionSizeMarket
: pass trade long and current collateral/usd price to eventexecuteDecreasePositionSizeMarket
: pass_order
toDecreasePositionSizeUtils.validateCallback