diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/calculator/MarginCalculator.kt b/src/commonMain/kotlin/exchange.dydx.abacus/calculator/MarginCalculator.kt index a5cbe7ade..c746b3aae 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/calculator/MarginCalculator.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/calculator/MarginCalculator.kt @@ -22,6 +22,7 @@ import exchange.dydx.abacus.utils.NUM_PARENT_SUBACCOUNTS import exchange.dydx.abacus.utils.Numeric import kollections.iListOf import kotlin.math.max +import kotlin.math.min internal object MarginCalculator { fun findExistingPosition( @@ -775,8 +776,7 @@ internal object MarginCalculator { // Cap targetLeverage to 98% of max leverage val adjustedTargetLeverage = if (maxLeverageForMarket != null) { - val cappedLeverage = maxLeverageForMarket * MAX_LEVERAGE_BUFFER_PERCENT - cappedLeverage + maxLeverageForMarket * MAX_LEVERAGE_BUFFER_PERCENT } else { null } diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/calculator/SubaccountCalculator.kt b/src/commonMain/kotlin/exchange.dydx.abacus/calculator/SubaccountCalculator.kt index 05e2f828f..a0a57b2fd 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/calculator/SubaccountCalculator.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/calculator/SubaccountCalculator.kt @@ -6,6 +6,7 @@ import exchange.dydx.abacus.utils.Numeric import exchange.dydx.abacus.utils.mutable import exchange.dydx.abacus.utils.safeSet import kotlin.math.max +import exchange.dydx.abacus.utils.Logger internal enum class CalculationPeriod(val rawValue: String) { current("current"), diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/calculator/TradeInputCalculator.kt b/src/commonMain/kotlin/exchange.dydx.abacus/calculator/TradeInputCalculator.kt index da00dbc6d..e38f838ab 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/calculator/TradeInputCalculator.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/calculator/TradeInputCalculator.kt @@ -60,8 +60,6 @@ internal class TradeInputCalculator( ): Map { val account = parser.asNativeMap(state["account"]) - val subaccount = parser.asNativeMap(parser.value(account, "subaccounts.$subaccountNumber")) - val user = parser.asNativeMap(state["user"]) ?: mapOf() val markets = parser.asNativeMap(state["markets"]) val rewardsParams = parser.asNativeMap(state["rewardsParams"]) @@ -72,6 +70,14 @@ internal class TradeInputCalculator( subaccountNumber, ) + val marginMode = parser.asString(parser.value(trade, "marginMode"))?.let { MarginMode.invoke(it) } + val subaccount = if (marginMode == MarginMode.Cross) { + parser.asNativeMap(parser.value(account, "subaccounts.$subaccountNumber")) + } else { + // TODO: incorrect for isolated trades; fix CT-1092 + parser.asNativeMap(parser.value(account, "groupedSubaccounts.$subaccountNumber")) + } + val marketId = parser.asString(trade?.get("marketId")) val type = parser.asString(trade?.get("type")) val market = if (marketId != null) parser.asNativeMap(markets?.get(marketId)) else null @@ -1691,6 +1697,8 @@ internal class TradeInputCalculator( val freeCollateral = parser.asDouble(parser.value(subaccount, "freeCollateral.current")) ?: Numeric.double.ZERO val positionNotionalTotal = parser.asDouble(parser.value(position, "notionalTotal.current")) ?: Numeric.double.ZERO + // xcxc update + return if (equity != null && equity > Numeric.double.ZERO) { (freeCollateral + positionNotionalTotal / maxMarketLeverage) * maxMarketLeverage / equity } else { diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine+TradeInput.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine+TradeInput.kt index 1aea1a75e..a7327ac9f 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine+TradeInput.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine+TradeInput.kt @@ -272,7 +272,7 @@ fun TradingStateMachine.trade( changes = StateChanges( iListOf(Changes.subaccount, Changes.input), null, - iListOf(subaccountNumber), + subaccountNumbers, ) } else { error = ParsingError( @@ -386,7 +386,7 @@ fun TradingStateMachine.trade( changes = StateChanges( iListOf(Changes.wallet, Changes.subaccount, Changes.input), null, - subaccountNumbers, + iListOf(subaccountNumber), ) } if (sizeChanged) { diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine.kt index 76fef1d92..1302240c8 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/model/TradingStateMachine.kt @@ -91,6 +91,7 @@ import kotlinx.serialization.json.jsonObject import kotlin.math.max import kotlin.math.min import kotlin.time.Duration.Companion.days +import exchange.dydx.abacus.output.input.MarginMode @Suppress("UNCHECKED_CAST") @JsExport @@ -628,7 +629,6 @@ open class TradingStateMachine( internal fun updateStateChanges(changes: StateChanges): StateChanges { if (changes.changes.contains(Changes.input)) { val subaccountNumber = changes.subaccountNumbers?.firstOrNull() - val childSubaccountNumber = changes.subaccountNumbers?.lastOrNull() val subaccount = if (subaccountNumber != null) { parser.asNativeMap( @@ -657,11 +657,11 @@ open class TradingStateMachine( ) } - if (subaccountNumber != null && childSubaccountNumber != null) { + if (subaccountNumber != null) { if (staticTyping) { when (internalState.input.currentType) { InputType.TRADE -> { - calculateTrade(childSubaccountNumber) + calculateTrade(subaccountNumber) } InputType.TRANSFER -> { calculateTransfer(subaccountNumber) @@ -680,7 +680,7 @@ open class TradingStateMachine( } else { when (this.input?.get("current")) { "trade" -> { - calculateTrade(childSubaccountNumber) + calculateTrade(subaccountNumber) } "closePosition" -> { @@ -1071,13 +1071,20 @@ open class TradingStateMachine( val marketId = parser.asString(parser.value(modified, "trade.marketId")) if (subaccountNumber != null && marketId != null) { + val marginMode = parser.asString(parser.value(modified, "marginMode"))?.let { MarginMode.invoke(it) } + val subaccount = if (marginMode == MarginMode.Cross) { + parser.asNativeMap(parser.value(this.account, "subaccounts.$subaccountNumber")) + } else { + parser.asNativeMap(parser.value(this.account, "groupedSubaccounts.$subaccountNumber")) + } val leverage = parser.asDouble( parser.value( - this.account, - "subaccounts.$subaccountNumber.openPositions.$marketId.leverage.postOrder", + subaccount, + "openPositions.$marketId.leverage.postOrder", ), ) + Logger.e { "xcxc $marketId on $subaccountNumber has leverage $leverage"} modified.safeSet("trade.size.leverage", leverage) } else { modified.safeSet("trade.size.leverage", null)