-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create Input for Adjusting Isolated Position's Margin (#326)
* draft new Input * adjustIsolatedMarginInput: state, tests, calculators * update documentation and nit * update summary * spotlessApply * remove newline * bump version * linter get what linter wants * detekt rule * fix validation * force enum usage instead of converting to string * spotlessApply * string -> enum * kotlin enum feedback * built-in kotlin enum for input field * bump verison, update test * Update accessors due to built-in enum change * update docs
- Loading branch information
Showing
21 changed files
with
1,028 additions
and
47 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# AdjustIsolatedMarginInput | ||
|
||
data class AdjustIsolatedMarginInput( | ||
 val type: String?, // "ADD" or "REMOVE" | ||
 val amount: Double?, | ||
 val childSubaccountNumber: Int?, | ||
) | ||
|
||
## type | ||
|
||
ADD - Add margin to the child's isolated margin account from the parent's cross margin account | ||
REMOVE - Remove margin from the child's isolated margin account to the parent's cross margin account | ||
|
||
## amount | ||
|
||
Amount of USDC to remove or add | ||
|
||
## childSubaccountNumber | ||
|
||
Subaccount number for the child whose margin is to be adjusted | ||
|
136 changes: 136 additions & 0 deletions
136
src/commonMain/kotlin/exchange.dydx.abacus/calculator/AdjustIsolatedMarginInputCalculator.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
package exchange.dydx.abacus.calculator | ||
|
||
import exchange.dydx.abacus.output.input.IsolatedMarginAdjustmentType | ||
import exchange.dydx.abacus.protocols.ParserProtocol | ||
import exchange.dydx.abacus.utils.Numeric | ||
import exchange.dydx.abacus.utils.mutable | ||
import exchange.dydx.abacus.utils.safeSet | ||
|
||
@Suppress("UNCHECKED_CAST") | ||
internal class AdjustIsolatedMarginInputCalculator(val parser: ParserProtocol) { | ||
private val subaccountTransformer = SubaccountTransformer() | ||
|
||
internal fun calculate( | ||
state: Map<String, Any>, | ||
parentSubaccountNumber: Int?, | ||
): Map<String, Any> { | ||
val wallet = parser.asNativeMap(state["wallet"]) | ||
val isolatedMarginAdjustment = parser.asNativeMap(state["adjustIsolatedMargin"]) | ||
val childSubaccountNumber = parser.asInt(isolatedMarginAdjustment?.get("ChildSubaccountNumber")) | ||
val type = parser.asString(isolatedMarginAdjustment?.get("Type"))?.let { | ||
IsolatedMarginAdjustmentType.valueOf(it) | ||
} ?: IsolatedMarginAdjustmentType.Add | ||
|
||
return if (wallet != null && isolatedMarginAdjustment != null && type != null) { | ||
val modified = state.mutable() | ||
val parentTransferDelta = getModifiedTransferDelta(isolatedMarginAdjustment, true) | ||
val childTransferDelta = getModifiedTransferDelta(isolatedMarginAdjustment, false) | ||
|
||
val walletPostParentSubaccountTransfer = | ||
subaccountTransformer.applyIsolatedMarginAdjustmentToWallet( | ||
wallet, | ||
subaccountNumber = parentSubaccountNumber, | ||
parentTransferDelta, | ||
parser, | ||
"postOrder", | ||
) | ||
|
||
val walletPostChildSubaccountTransfer = | ||
subaccountTransformer.applyIsolatedMarginAdjustmentToWallet( | ||
wallet = walletPostParentSubaccountTransfer, | ||
subaccountNumber = childSubaccountNumber, | ||
childTransferDelta, | ||
parser, | ||
"postOrder", | ||
) | ||
|
||
val modifiedParentSubaccount = parser.asNativeMap(parser.value(walletPostChildSubaccountTransfer, "accounts.subaccounts.$parentSubaccountNumber")) | ||
val modifiedChildSubaccount = parser.asNativeMap(parser.value(walletPostChildSubaccountTransfer, "accounts.subaccounts.$childSubaccountNumber")) | ||
val modifiedIsolatedMarginAdjustment = finalize(isolatedMarginAdjustment, modifiedParentSubaccount, modifiedChildSubaccount, type) | ||
|
||
modified["adjustIsolatedMargin"] = modifiedIsolatedMarginAdjustment | ||
modified["wallet"] = walletPostChildSubaccountTransfer | ||
modified | ||
} else { | ||
state | ||
} | ||
} | ||
|
||
private fun getModifiedTransferDelta( | ||
isolatedMarginAdjustment: Map<String, Any>, | ||
isParentSubaccount: Boolean, | ||
): Map<String, Double> { | ||
val type = parser.asString(isolatedMarginAdjustment["Type"])?.let { | ||
IsolatedMarginAdjustmentType.valueOf(it) | ||
} ?: IsolatedMarginAdjustmentType.Add | ||
val amount = parser.asDouble(isolatedMarginAdjustment["Amount"]) | ||
|
||
when (type) { | ||
IsolatedMarginAdjustmentType.Add -> { | ||
val multiplier = | ||
if (isParentSubaccount) Numeric.double.NEGATIVE else Numeric.double.POSITIVE | ||
val usdcSize = (amount ?: Numeric.double.ZERO) * multiplier | ||
|
||
return mapOf( | ||
"usdcSize" to usdcSize, | ||
) | ||
} | ||
|
||
IsolatedMarginAdjustmentType.Remove -> { | ||
val multiplier = | ||
if (isParentSubaccount) Numeric.double.POSITIVE else Numeric.double.NEGATIVE | ||
val usdcSize = (amount ?: Numeric.double.ZERO) * multiplier | ||
|
||
return mapOf( | ||
"usdcSize" to usdcSize, | ||
) | ||
} | ||
} | ||
} | ||
|
||
private fun summaryForType( | ||
parentSubaccount: Map<String, Any>?, | ||
childSubaccount: Map<String, Any>?, | ||
type: IsolatedMarginAdjustmentType, | ||
): Map<String, Any> { | ||
val summary = mutableMapOf<String, Any>() | ||
val crossCollateral = parser.asDouble(parser.value(parentSubaccount, "freeCollateral.postOrder")) | ||
val crossMarginUsage = parser.asDouble(parser.value(parentSubaccount, "marginUsage.postOrder")) | ||
val openPositions = parser.asNativeMap(childSubaccount?.get("openPositions")) | ||
val marketId = openPositions?.keys?.firstOrNull() | ||
val positionMargin = parser.asDouble(parser.value(childSubaccount, "freeCollateral.postOrder")) | ||
val positionLeverage = parser.asDouble(parser.value(childSubaccount, "openPositions.$marketId.leverage.postOrder")) | ||
val liquidationPrice = parser.asDouble(parser.value(childSubaccount, "openPositions.$marketId.liquidationPrice.postOrder")) | ||
|
||
when (type) { | ||
IsolatedMarginAdjustmentType.Add -> { | ||
summary.safeSet("crossFreeCollateral", crossCollateral) | ||
summary.safeSet("crossMarginUsage", crossMarginUsage) | ||
summary.safeSet("positionMargin", positionMargin) | ||
summary.safeSet("positionLeverage", positionLeverage) | ||
summary.safeSet("liquidationPrice", liquidationPrice) | ||
} | ||
|
||
IsolatedMarginAdjustmentType.Remove -> { | ||
summary.safeSet("crossFreeCollateral", crossCollateral) | ||
summary.safeSet("crossMarginUsage", crossMarginUsage) | ||
summary.safeSet("positionMargin", positionMargin) | ||
summary.safeSet("positionLeverage", positionLeverage) | ||
summary.safeSet("liquidationPrice", liquidationPrice) | ||
} | ||
} | ||
|
||
return summary | ||
} | ||
|
||
private fun finalize( | ||
isolatedMarginAdjustment: Map<String, Any>, | ||
parentSubaccount: Map<String, Any>?, | ||
childSubaccount: Map<String, Any>?, | ||
type: IsolatedMarginAdjustmentType, | ||
): Map<String, Any> { | ||
val modified = isolatedMarginAdjustment.mutable() | ||
modified.safeSet("summary", summaryForType(parentSubaccount, childSubaccount, type)) | ||
return modified | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.