Skip to content

Commit

Permalink
feat: unallocated usdc in vault positions table (#712)
Browse files Browse the repository at this point in the history
  • Loading branch information
tyleroooo authored Oct 15, 2024
1 parent d7ec961 commit 98b2a5b
Show file tree
Hide file tree
Showing 4 changed files with 159 additions and 12 deletions.
2 changes: 1 addition & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ allprojects {
}

group = "exchange.dydx.abacus"
version = "1.12.27"
version = "1.12.28"

repositories {
google()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,25 +145,54 @@ object VaultCalculator {
)
}

private fun maybeAddUsdcRow(positions: List<VaultPosition>, vaultTvl: Double?): List<VaultPosition> {
if (vaultTvl != null) {
val usdcTotal = vaultTvl - positions.sumOf { it.marginUsdc ?: 0.0 }

// add a usdc row
return positions + VaultPosition(
marketId = "USDC-USD",
marginUsdc = usdcTotal,
equityUsdc = usdcTotal,
currentLeverageMultiple = 1.0,
currentPosition = CurrentPosition(
asset = usdcTotal,
usdc = usdcTotal,
),
thirtyDayPnl = ThirtyDayPnl(
percent = 0.0,
absolute = 0.0,
sparklinePoints = null,
),
)
}
return positions
}

fun calculateVaultPositions(
positions: IndexerMegavaultPositionResponse?,
histories: IndexerVaultsHistoricalPnlResponse?,
markets: IMap<String, PerpetualMarket>?
markets: IMap<String, PerpetualMarket>?,
vaultTvl: Double?,
): VaultPositions? {
if (positions?.positions == null) {
return null
}

val historiesMap = histories?.vaultsPnl?.associateBy { it.ticker }

var processedPositions = positions.positions.mapNotNull {
calculateVaultPosition(
it,
historiesMap?.get(it.ticker),
markets?.get(it.ticker),
)
}

processedPositions = maybeAddUsdcRow(processedPositions, vaultTvl)

return VaultPositions(
positions = positions.positions.mapNotNull {
calculateVaultPosition(
it,
historiesMap?.get(it.ticker),
markets?.get(it.ticker),
)
}.toIList(),
positions = processedPositions.toIList(),
)
}

Expand All @@ -175,7 +204,7 @@ object VaultCalculator {
return null
}

val positions: List<VaultPosition>? = vault.positions?.mapNotNull { position ->
var positions: List<VaultPosition> = vault.positions.mapNotNull { position ->
val ticker = position.ticker ?: return@mapNotNull null
val history = vault.pnls.get(ticker)
val market = markets?.get(ticker)
Expand All @@ -188,7 +217,10 @@ object VaultCalculator {
perpetualMarket = market,
)
}
return VaultPositions(positions = positions?.toIList())

positions = maybeAddUsdcRow(positions, vault.details?.totalValue)

return VaultPositions(positions = positions.toIList())
}

fun calculateVaultPosition(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,21 @@
package exchange.dydx.abacus.functional.vault

import exchange.dydx.abacus.functional.vault.VaultCalculator.calculateVaultPosition
import exchange.dydx.abacus.functional.vault.VaultCalculator.calculateVaultPositions
import exchange.dydx.abacus.functional.vault.VaultCalculator.calculateVaultSummary
import exchange.dydx.abacus.output.PerpetualMarket
import exchange.dydx.abacus.utils.NUM_PARENT_SUBACCOUNTS
import exchange.dydx.abacus.utils.iMapOf
import indexer.codegen.IndexerAssetPositionResponseObject
import indexer.codegen.IndexerMegavaultHistoricalPnlResponse
import indexer.codegen.IndexerMegavaultPositionResponse
import indexer.codegen.IndexerPerpetualPositionResponseObject
import indexer.codegen.IndexerPerpetualPositionStatus
import indexer.codegen.IndexerPnlTicksResponseObject
import indexer.codegen.IndexerPositionSide
import indexer.codegen.IndexerVaultHistoricalPnl
import indexer.codegen.IndexerVaultPosition
import indexer.codegen.IndexerVaultsHistoricalPnlResponse
import kollections.iListOf
import kotlinx.datetime.Instant
import kotlin.test.Test
Expand Down Expand Up @@ -207,4 +211,115 @@ class VaultTests {

assertEquals(expectedVaultPosition, vaultPosition)
}

@Test
fun shouldCalculateVaultPositionsCorrectly() {
val position = IndexerVaultPosition(
ticker = "BTC-USD",
assetPosition = IndexerAssetPositionResponseObject(
symbol = "USDC",
side = IndexerPositionSide.SHORT,
size = "40000.0",
assetId = "0",
subaccountNumber = NUM_PARENT_SUBACCOUNTS,
),
perpetualPosition = IndexerPerpetualPositionResponseObject(
market = "BTC-USD",
status = IndexerPerpetualPositionStatus.OPEN,
side = IndexerPositionSide.LONG,
size = "1.0",
maxSize = null,
entryPrice = "50000.0",
realizedPnl = null,
createdAt = "2023-08-01T00:00:00Z",
createdAtHeight = "1000",
sumOpen = null,
sumClose = null,
netFunding = null,
unrealizedPnl = "5000.0",
closedAt = null,
exitPrice = null,
subaccountNumber = NUM_PARENT_SUBACCOUNTS,
),
equity = "15000.0",
)

val history = IndexerVaultHistoricalPnl(
ticker = "BTC-USD",
historicalPnl = arrayOf(
IndexerPnlTicksResponseObject(
id = "1",
equity = "10500.0",
totalPnl = "500.0",
netTransfers = "0.0",
createdAt = Instant.fromEpochMilliseconds(1659465600000).toString(),
),
IndexerPnlTicksResponseObject(
id = "2",
equity = "10000.0",
totalPnl = "0.0",
netTransfers = "0.0",
createdAt = Instant.fromEpochMilliseconds(1659379200000).toString(),
),
),
)

val market = PerpetualMarket(
id = "BTC-USD",
assetId = "0",
market = "BTC-USD",
displayId = null,
oraclePrice = 55000.0,
marketCaps = null,
priceChange24H = null,
priceChange24HPercent = null,
status = null,
configs = null,
perpetual = null,
)

val vaultPositions = calculateVaultPositions(
IndexerMegavaultPositionResponse(positions = arrayOf(position)),
IndexerVaultsHistoricalPnlResponse(vaultsPnl = arrayOf(history)),
iMapOf("BTC-USD" to market),
21000.0,
)

val expectedVaultPosition = VaultPosition(
marketId = "BTC-USD",
marginUsdc = 15000.0,
currentLeverageMultiple = 55.0 / 15.0,
currentPosition = CurrentPosition(
asset = 1.0,
usdc = 55000.0,
),
thirtyDayPnl = ThirtyDayPnl(
percent = 0.05,
absolute = 500.0,
sparklinePoints = iListOf(0.0, 500.0),
),
)

assertEquals(
iListOf(
expectedVaultPosition,
VaultPosition(
marketId = "USDC-USD",
marginUsdc = 6000.0,
equityUsdc = 6000.0,
currentLeverageMultiple = 1.0,
currentPosition = CurrentPosition(
asset = 6000.0,
usdc = 6000.0,
),
thirtyDayPnl = ThirtyDayPnl(
percent = 0.0,
absolute = 0.0,
sparklinePoints = null,
),
),
),
vaultPositions?.positions,
)
}
}
2 changes: 1 addition & 1 deletion v4_abacus.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |spec|
spec.name = 'v4_abacus'
spec.version = '1.12.27'
spec.version = '1.12.28'
spec.homepage = 'https://github.com/dydxprotocol/v4-abacus'
spec.source = { :http=> ''}
spec.authors = ''
Expand Down

0 comments on commit 98b2a5b

Please sign in to comment.