Skip to content

Commit

Permalink
Add parsing logic for new markets in v4_markets channel update. (#734)
Browse files Browse the repository at this point in the history
  • Loading branch information
ruixhuang authored Oct 25, 2024
1 parent c926adc commit 24acfc3
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 10 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.13.13"
version = "1.13.14"

repositories {
google()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package exchange.dydx.abacus.processor.markets

import com.ionspin.kotlin.bignum.decimal.toBigDecimal
import exchange.dydx.abacus.output.MarketConfigs
import exchange.dydx.abacus.output.MarketConfigsV4
import exchange.dydx.abacus.output.MarketPerpetual
Expand All @@ -26,6 +27,7 @@ import kollections.toIList
import numberOfDecimals
import kotlin.math.max
import kotlin.math.min
import kotlin.math.pow
import kotlin.time.Duration.Companion.seconds

internal interface MarketProcessorProtocol : BaseProcessorProtocol {
Expand Down Expand Up @@ -262,8 +264,28 @@ internal class MarketProcessor(
private fun createConfigs(
payload: IndexerCompositeMarketObject,
): MarketConfigs {
val stepSize = parser.asDouble(payload.stepSize)
val tickSize = parser.asDouble(payload.tickSize)
var stepSize = parser.asDouble(payload.stepSize)
var tickSize = parser.asDouble(payload.tickSize)

val atomicResolution = parser.asInt(payload.atomicResolution)
val stepBaseQuantums = parser.asInt(payload.stepBaseQuantums)
val quantumConversionExponent = parser.asInt(payload.quantumConversionExponent)
val subticksPerTick = parser.asInt(payload.subticksPerTick)
if (stepSize == null) {
if (atomicResolution != null && stepBaseQuantums != null) {
stepSize = getStepSize(stepBaseQuantums, atomicResolution)
} else {
stepSize = fallbackStepSize
}
}
if (tickSize == null) {
if (subticksPerTick != null && quantumConversionExponent != null && atomicResolution != null) {
tickSize = getTickSize(subticksPerTick, quantumConversionExponent, atomicResolution)
} else {
tickSize = fallbackTickSize
}
}

return MarketConfigs(
clobPairId = payload.clobPairId,
largeSize = null,
Expand Down Expand Up @@ -493,15 +515,68 @@ internal class MarketProcessor(
parser.asDouble(payload["basePositionSize"]),
) // v4
}

// calculate stepSize and tickSize if not provided
val stepSize = parser.asDouble(configs["stepSize"])
val tickSize = parser.asDouble(configs["tickSize"])
val atomicResolution = parser.asInt(parser.value(configsV4, "atomicResolution"))
val stepBaseQuantums = parser.asInt(parser.value(configsV4, "stepBaseQuantums"))
val quantumConversionExponent = parser.asInt(parser.value(configsV4, "quantumConversionExponent"))
if (stepSize == null) {
if (atomicResolution != null && stepBaseQuantums != null) {
val stepSize = getStepSize(stepBaseQuantums, atomicResolution)
configs.safeSet("stepSize", stepSize)
} else {
configs.safeSet("stepSize", fallbackStepSize)
}
}
if (tickSize == null) {
val subticksPerTick = parser.asInt(parser.value(configsV4, "subticksPerTick"))
if (subticksPerTick != null && quantumConversionExponent != null && atomicResolution != null) {
val tickSize = getTickSize(subticksPerTick, quantumConversionExponent, atomicResolution)
configs.safeSet("tickSize", tickSize)
} else {
configs.safeSet("tickSize", fallbackTickSize)
}
}
return configs
}

private fun getStepSize(
stepBaseQuantums: Int,
atomicResolution: Int,
): Double {
val stepSize = stepBaseQuantums.toBigDecimal().times(10.0.toBigDecimal().pow(atomicResolution))
return parser.asDouble(stepSize) ?: fallbackStepSize
}

private fun getTickSize(
subticksPerTick: Int,
quantumConversionExponent: Int,
atomicResolution: Int
): Double {
val quoteCurrencyAtomicResolution = -6
val tickSize = subticksPerTick.toBigDecimal().times(
10.0.toBigDecimal().pow(quantumConversionExponent),
).times(
10.0.toBigDecimal().pow(quoteCurrencyAtomicResolution),
).divide(
10.0.toBigDecimal().pow(atomicResolution),
)
return parser.asDouble(tickSize) ?: fallbackTickSize
}

private fun perpetual(
existing: Map<String, Any>?,
payload: Map<String, Any>,
oraclePrice: Double?,
): Map<String, Any> {
val perpetual = transform(existing, payload, perpetualKeyMap)
val openInterest = parser.asDouble(perpetual["openInterest"])
if (openInterest == null) {
perpetual.safeSet("openInterest", 0.0)
perpetual.safeSet("openInterestUSDC", 0.0)
}
oraclePrice?.let {
parser.asDouble(perpetual["openInterest"])?.let {
perpetual["openInterestUSDC"] = it * oraclePrice
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,11 +189,20 @@ internal class MarketsProcessor(
for ((market, data) in narrowedPayload) {
val marketPayload = parser.asNativeMap(data)
if (marketPayload != null) {
val receivedMarket = marketProcessorDeprecated!!.receivedDeltaDeprecated(
parser.asNativeMap(existing?.get(market)),
marketPayload,
)
markets[market] = receivedMarket
if (marketPayload["clobPairId"] != null) {
// new permissionless market
val receivedMarket = marketProcessorDeprecated!!.received(
parser.asNativeMap(existing?.get(market)),
marketPayload,
)
markets[market] = receivedMarket
} else {
val receivedMarket = marketProcessorDeprecated!!.receivedDeltaDeprecated(
parser.asNativeMap(existing?.get(market)),
marketPayload,
)
markets[market] = receivedMarket
}
}
}
return markets
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,12 @@ class V4MarketsTests : V4BaseTests() {
assertEquals(ethMarket?.perpetualMarket?.perpetual?.volume24H, 626131271.611287094)
assertEquals(ethMarket?.perpetualMarket?.perpetual?.trades24H, 1214631.0)
assertEquals(ethMarket?.perpetualMarket?.perpetual?.nextFundingRate, 0.0)

val mlnMarket = markets["MLN-USD"]
assertEquals(mlnMarket?.perpetualMarket?.oraclePrice, null)
assertEquals(mlnMarket?.perpetualMarket?.perpetual?.openInterest, null)
assertEquals(mlnMarket?.perpetualMarket?.configs?.stepSize, 0.1)
assertEquals(mlnMarket?.perpetualMarket?.configs?.tickSize, 0.01)
} else {
test(
{
Expand Down Expand Up @@ -475,7 +481,26 @@ class V4MarketsTests : V4BaseTests() {
"nextFundingRate":0.0,
"trades24H":1214631
}
},
"MLN-USD":{
"market":"MLN-USD",
"status":{
"canTrade":true,
"canReduce":true
},
"configs":{
"stepSize":0.1,
"tickSize":0.01,
"initialMarginFraction":0.05,
"clobPairId":111
},
"perpetual":{
"openInterest":0.0,
"openInterestLowerCap": 500000.0,
"openInterestUpperCap": 1000000.0
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2791,7 +2791,22 @@ internal class MarketsChannelMock {
"volume24H":"626131271.611287094",
"trades24H":1214631,
"openInterest":"67603.376057"
}
},
"MLN-USD": {
"id": "111",
"clobPairId": "111",
"ticker": "MLN-USD",
"marketId": 111,
"status": "ACTIVE",
"quantumConversionExponent": -9,
"atomicResolution": -7,
"subticksPerTick": 1000000,
"stepBaseQuantums": 1000000,
"initialMarginFraction": "0.05",
"maintenanceMarginFraction": "0.03",
"openInterestLowerCap": "500000",
"openInterestUpperCap": "1000000"
}
}
}
]
Expand Down
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.13.13'
spec.version = '1.13.14'
spec.homepage = 'https://github.com/dydxprotocol/v4-abacus'
spec.source = { :http=> ''}
spec.authors = ''
Expand Down

0 comments on commit 24acfc3

Please sign in to comment.