Skip to content

Commit

Permalink
Potential order loss (#387)
Browse files Browse the repository at this point in the history
Co-authored-by: Kelvin Lau <[email protected]>
  • Loading branch information
xjcaa and Kelvin Lau authored Apr 19, 2024
1 parent 9b107ce commit ed09606
Show file tree
Hide file tree
Showing 8 changed files with 146 additions and 13 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
All notable changes to this project will be documented in this file.
Version changes are pinned to SDK releases.

## [1.28.0]

- Add potential order loss to account margining.
- Add 10% oracle deviation protection to orders.

## [1.26.4]

- Respect Exchange.skipRpcConfirmation everywhere. ([#384](https://github.com/zetamarkets/sdk/pull/384))
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@zetamarkets/sdk",
"repository": "https://github.com/zetamarkets/sdk/",
"version": "1.27.3",
"version": "1.28.0",
"description": "Zeta SDK",
"main": "dist/index.js",
"types": "dist/index.d.ts",
Expand Down
27 changes: 25 additions & 2 deletions src/idl/zeta.json
Original file line number Diff line number Diff line change
Expand Up @@ -8174,12 +8174,30 @@
"name": "rebateRebalanceAmount",
"type": "u64"
},
{
"name": "potentialOrderLoss",
"type": {
"array": [
"u64",
15
]
}
},
{
"name": "potentialOrderLossPadding",
"type": {
"array": [
"u64",
10
]
}
},
{
"name": "padding",
"type": {
"array": [
"u8",
1976
1776
]
}
}
Expand Down Expand Up @@ -9721,7 +9739,7 @@
"name": "STRK"
},
{
"name": "TNSR"
"name": "W"
},
{
"name": "UNDEFINED"
Expand Down Expand Up @@ -11255,6 +11273,11 @@
"code": 6169,
"name": "InvalidOracleUpdate",
"msg": "Invalid oracle update"
},
{
"code": 6170,
"name": "OrderPriceTooFarFromMarkPrice",
"msg": "Order price too far from mark price"
}
]
}
2 changes: 2 additions & 0 deletions src/program-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,8 @@ export interface CrossMarginAccount {
productLedgersPadding: Array<ProductLedger>;
triggerOrderBits: anchor.BN;
rebateRebalanceAmount: anchor.BN;
potentialOrderLoss: Array<anchor.BN>;
potentialOrderLossPadding: Array<anchor.BN>;
padding: Array<number>;
}

Expand Down
18 changes: 17 additions & 1 deletion src/risk-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ export function collectRiskMaps(
mmMap: Map<Asset, Number>,
mmioMap: Map<Asset, Number>,
upnlMap: Map<Asset, Number>,
unpaidFundingMap: Map<Asset, Number>
unpaidFundingMap: Map<Asset, Number>,
potentialOrderLossMap: Map<Asset, Number>
): Map<Asset, types.AssetRiskState> {
let allAssets = assets.allAssets();
let collectedRiskState = new Map();
Expand All @@ -40,6 +41,7 @@ export function collectRiskMaps(
maintenanceMarginIncludingOrders: mmioMap.get(a),
unrealizedPnl: upnlMap.get(a),
unpaidFunding: unpaidFundingMap.get(a),
potentialOrderLoss: potentialOrderLossMap.get(a),
});
}
return collectedRiskState;
Expand Down Expand Up @@ -326,6 +328,20 @@ export function addFakeCancelToAccount(

const nativeOrderSize = convertDecimalToNativeLotSize(order.size);

let totalOrders =
marginAccount.productLedgers[assetIndex].orderState.closingOrders +
marginAccount.productLedgers[assetIndex].orderState.openingOrders[0] +
marginAccount.productLedgers[assetIndex].orderState.openingOrders[1];

if (totalOrders == nativeOrderSize) {
marginAccount.potentialOrderLoss[assetIndex] = 0;
} else {
let totalMaxLoss = marginAccount.potentialOrderLoss[assetIndex];
let maxLossPerLot = totalMaxLoss / totalOrders;
let averageMaxLoss = maxLossPerLot * nativeOrderSize;
marginAccount.potentialOrderLoss[assetIndex] -= averageMaxLoss;
}

const cancelOpening = Math.min(
marginAccount.productLedgers[assetIndex].orderState.openingOrders[
bidAskIndex
Expand Down
49 changes: 44 additions & 5 deletions src/risk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,23 @@ export class RiskCalculator {
}
}

public getPotentialOrderLoss(
account: CrossMarginAccount
): Map<Asset, number> {
const i_list = [...Array(constants.ACTIVE_PERP_MARKETS).keys()];

const potentialOrderLossMap: Map<Asset, number> = new Map();
for (var i of i_list) {
const asset = assets.indexToAsset(i);
const potentialOrderLoss = convertNativeIntegerToDecimal(
account.potentialOrderLoss[i].toNumber()
);
potentialOrderLossMap.set(asset, potentialOrderLoss);
}

return potentialOrderLossMap;
}

/**
* Returns the total initial margin requirement for a given account.
* This includes initial margin on positions which is used for
Expand Down Expand Up @@ -675,6 +692,9 @@ export class RiskCalculator {
): types.CrossMarginAccountState {
let balance = convertNativeBNToDecimal(marginAccount.balance);
let accType = types.ProgramAccountType.CrossMarginAccount;

let potentialOrderLoss = this.getPotentialOrderLoss(marginAccount);

let unrealizedPnl = this.calculateUnrealizedPnl(
marginAccount,
accType
Expand Down Expand Up @@ -703,6 +723,10 @@ export class RiskCalculator {
accType
) as Map<Asset, number>;

let potentialOrderLossTotal = Array.from(
potentialOrderLoss.values()
).reduce((a, b) => a + b, 0);

let upnlTotal = Array.from(unrealizedPnl.values()).reduce(
(a, b) => a + b,
0
Expand All @@ -725,16 +749,28 @@ export class RiskCalculator {

let equity: number = balance + upnlTotal + unpaidFundingTotal;
let availableBalanceInitial: number =
balance + upnlTotal + unpaidFundingTotal - imTotal;
balance +
upnlTotal +
unpaidFundingTotal -
imTotal -
potentialOrderLossTotal;
let availableBalanceWithdrawable: number =
balance +
Math.min(0, upnlTotal) +
unpaidFundingTotal -
imSkipConcessionTotal;
let availableBalanceMaintenance: number =
balance + upnlTotal + unpaidFundingTotal - mmTotal;
balance +
upnlTotal +
unpaidFundingTotal -
mmTotal -
potentialOrderLossTotal;
let availableBalanceMaintenanceIncludingOrders: number =
balance + upnlTotal + unpaidFundingTotal - mmioTotal;
balance +
upnlTotal +
unpaidFundingTotal -
mmioTotal -
potentialOrderLossTotal;
return {
balance,
equity,
Expand All @@ -748,14 +784,16 @@ export class RiskCalculator {
maintenanceMargin,
maintenanceMarginIncludingOrders,
unrealizedPnl,
unpaidFunding
unpaidFunding,
potentialOrderLoss
),
initialMarginTotal: imTotal,
initalMarginSkipConcessionTotal: imSkipConcessionTotal,
maintenanceMarginTotal: mmTotal,
maintenanceMarginIncludingOrdersTotal: mmioTotal,
unrealizedPnlTotal: upnlTotal,
unpaidFundingTotal: unpaidFundingTotal,
potentialOrderLossTotal,
};
}

Expand Down Expand Up @@ -868,7 +906,8 @@ export class RiskCalculator {
).values()
).reduce((a, b) => a + b, 0) +
state.unpaidFundingTotal -
state.maintenanceMarginIncludingOrdersTotal;
state.maintenanceMarginIncludingOrdersTotal -
state.potentialOrderLossTotal;

let fee =
(getFeeBps(isTaker, marginAccount.accountType) / 10000) * tradePrice;
Expand Down
2 changes: 2 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,7 @@ export interface AssetRiskState {
maintenanceMarginIncludingOrders: number;
unrealizedPnl: number;
unpaidFunding: number;
potentialOrderLoss: number;
}

export interface CrossMarginAccountState {
Expand All @@ -300,6 +301,7 @@ export interface CrossMarginAccountState {
maintenanceMarginIncludingOrdersTotal: number;
unrealizedPnlTotal: number;
unpaidFundingTotal: number;
potentialOrderLossTotal: number;
}

export interface CancelArgs {
Expand Down
54 changes: 50 additions & 4 deletions src/types/zeta.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8174,12 +8174,30 @@ export type Zeta = {
"name": "rebateRebalanceAmount",
"type": "u64"
},
{
"name": "potentialOrderLoss",
"type": {
"array": [
"u64",
15
]
}
},
{
"name": "potentialOrderLossPadding",
"type": {
"array": [
"u64",
10
]
}
},
{
"name": "padding",
"type": {
"array": [
"u8",
1976
1776
]
}
}
Expand Down Expand Up @@ -9721,7 +9739,7 @@ export type Zeta = {
"name": "STRK"
},
{
"name": "TNSR"
"name": "W"
},
{
"name": "UNDEFINED"
Expand Down Expand Up @@ -11255,6 +11273,11 @@ export type Zeta = {
"code": 6169,
"name": "InvalidOracleUpdate",
"msg": "Invalid oracle update"
},
{
"code": 6170,
"name": "OrderPriceTooFarFromMarkPrice",
"msg": "Order price too far from mark price"
}
]
};
Expand Down Expand Up @@ -19435,12 +19458,30 @@ export const IDL: Zeta = {
"name": "rebateRebalanceAmount",
"type": "u64"
},
{
"name": "potentialOrderLoss",
"type": {
"array": [
"u64",
15
]
}
},
{
"name": "potentialOrderLossPadding",
"type": {
"array": [
"u64",
10
]
}
},
{
"name": "padding",
"type": {
"array": [
"u8",
1976
1776
]
}
}
Expand Down Expand Up @@ -20982,7 +21023,7 @@ export const IDL: Zeta = {
"name": "STRK"
},
{
"name": "TNSR"
"name": "W"
},
{
"name": "UNDEFINED"
Expand Down Expand Up @@ -22516,6 +22557,11 @@ export const IDL: Zeta = {
"code": 6169,
"name": "InvalidOracleUpdate",
"msg": "Invalid oracle update"
},
{
"code": 6170,
"name": "OrderPriceTooFarFromMarkPrice",
"msg": "Order price too far from mark price"
}
]
};

0 comments on commit ed09606

Please sign in to comment.