From 04b0edae38aae83359f059748a83b7000c8e6431 Mon Sep 17 00:00:00 2001 From: mulan xia Date: Mon, 29 Apr 2024 12:09:19 -0400 Subject: [PATCH 01/10] wip --- .../protocols/PublicProtocols.kt | 11 ++- .../state/manager/StateManagerAdaptor.kt | 3 + .../state/manager/V4StateManagerAdaptor.kt | 71 +++++++++------- .../state/manager/utils/Payloads.kt | 2 + .../v2/supervisor/SubaccountSupervisor.kt | 15 +++- .../utils/AnalyticsUtils.kt | 80 ++++++++++++++++++- 6 files changed, 146 insertions(+), 36 deletions(-) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/protocols/PublicProtocols.kt b/src/commonMain/kotlin/exchange.dydx.abacus/protocols/PublicProtocols.kt index 21f57d997..53538c9d3 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/protocols/PublicProtocols.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/protocols/PublicProtocols.kt @@ -212,12 +212,19 @@ enum class AnalyticsEvent(val rawValue: String) { // Trade Events TradePlaceOrderClick("TradePlaceOrderClick"), TradeCancelOrderClick("TradeCancelOrderClick"), - TradePlaceOrder("TradePlaceOrder"), - TradeCancelOrder("TradeCancelOrder"), + TradeTriggerOrderClick("TradeTriggerOrderClick"), + TradePlaceOrder("TradePlaceOrder"), // analytics here + TradeCancelOrder("TradeCancelOrder"), // analytics here + TradeTriggerPlaceOrder("TradeTriggerPlaceOrder"), + TradeTriggerCancelOrder("TradeTriggerCancelOrder"), TradePlaceOrderSubmissionConfirmed("TradePlaceOrderSubmissionConfirmed"), TradeCancelOrderSubmissionConfirmed("TradeCancelOrderSubmissionConfirmed"), + TradeTriggerPlaceOrderSubmissionConfirmed("TradeTriggerPlaceOrderSubmissionConfirmed"), + TradeTriggerCancelOrderSubmissionConfirmed("TradeTriggerCancelOrderSubmissionConfirmed"), TradePlaceOrderSubmissionFailed("TradePlaceOrderSubmissionFailed"), TradeCancelOrderSubmissionFailed("TradeCancelOrderSubmissionFailed"), + TradeTriggerPlaceOrderSubmissionFailed("TradeTriggerPlaceOrderSubmissionFailed"), + TradeTriggerCancelOrderSubmissionFailed("TradeTriggerCancelOrderSubmissionFailed"), TradeCancelOrderConfirmed("TradeCancelOrderConfirmed"), TradePlaceOrderConfirmed("TradePlaceOrderConfirmed"), diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt index 6ebc05891..3bb0dd667 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt @@ -1923,6 +1923,7 @@ open class StateManagerAdaptor( } return HumanReadableTriggerOrdersPayload( + marketId, placeOrderPayloads, cancelOrderPayloads, ) @@ -2152,6 +2153,7 @@ open class StateManagerAdaptor( ?: throw Exception("subaccount is null") val order = subaccount.orders?.firstOrNull { it.id == orderId } ?: throw Exception("order is null") + val type = order.type.rawValue val clientId = order.clientId ?: throw Exception("clientId is null") val orderFlags = order.orderFlags ?: throw Exception("orderFlags is null") val clobPairId = order.clobPairId ?: throw Exception("clobPairId is null") @@ -2161,6 +2163,7 @@ open class StateManagerAdaptor( return HumanReadableCancelOrderPayload( subaccountNumber, orderId, + type, clientId, orderFlags, clobPairId, diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt index 35c8d31da..826eca65f 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt @@ -1000,11 +1000,11 @@ class V4StateManagerAdaptor( callback: TransactionCallback, payload: HumanReadablePlaceOrderPayload, analyticsPayload: IMap?, + uiClickTimeMs: Double, isTriggerOrder: Boolean = false, ): HumanReadablePlaceOrderPayload { val clientId = payload.clientId val string = Json.encodeToString(payload) - val uiClickTimeMs = trackOrderClick(analyticsPayload) stopWatchingLastOrder() @@ -1025,7 +1025,7 @@ class V4StateManagerAdaptor( }, transactionCallback = { response: String? -> val error = parseTransactionResponse(response) - trackOrderSubmitted(error, analyticsPayload) + trackOrderSubmitted(error, analyticsPayload, isTriggerOrder) if (error == null) { lastOrderClientId = clientId } else { @@ -1059,12 +1059,12 @@ class V4StateManagerAdaptor( callback: TransactionCallback, payload: HumanReadableCancelOrderPayload, analyticsPayload: IMap?, + uiClickTimeMs: Double, isTriggerOrder: Boolean = false, ) { val clientId = payload.clientId val string = Json.encodeToString(payload) - val uiClickTimeMs = trackOrderClick(analyticsPayload, isCancel = true) val isShortTermOrder = payload.orderFlags == 0 stopWatchingLastOrder() @@ -1086,7 +1086,7 @@ class V4StateManagerAdaptor( }, transactionCallback = { response: String? -> val error = parseTransactionResponse(response) - trackOrderSubmitted(error, analyticsPayload, true) + trackOrderSubmitted(error, analyticsPayload, isTriggerOrder, true) if (error == null) { this.orderCanceled(orderId) } else { @@ -1115,11 +1115,11 @@ class V4StateManagerAdaptor( private fun trackOrderClick( analyticsPayload: IMap?, - isCancel: Boolean = false + analyticsEvent: AnalyticsEvent, ): Double { val uiClickTimeMs = Clock.System.now().toEpochMilliseconds().toDouble() tracking( - if (isCancel) AnalyticsEvent.TradeCancelOrderClick.rawValue else AnalyticsEvent.TradePlaceOrderClick.rawValue, + analyticsEvent.rawValue, analyticsPayload, ) return uiClickTimeMs @@ -1145,16 +1145,25 @@ class V4StateManagerAdaptor( private fun trackOrderSubmitted( error: ParsingError?, analyticsPayload: IMap?, + isTriggerOrder: Boolean, isCancel: Boolean = false, ) { if (error != null) { tracking( - if (isCancel) AnalyticsEvent.TradeCancelOrderSubmissionFailed.rawValue else AnalyticsEvent.TradePlaceOrderSubmissionFailed.rawValue, + if (isCancel) { + if (isTriggerOrder) AnalyticsEvent.TradeTriggerCancelOrderSubmissionFailed.rawValue else AnalyticsEvent.TradeCancelOrderSubmissionFailed.rawValue + } else { + if (isTriggerOrder) AnalyticsEvent.TradeTriggerPlaceOrderSubmissionFailed.rawValue else AnalyticsEvent.TradePlaceOrderSubmissionFailed.rawValue + }, ParsingHelper.merge(errorTrackingParams(error), analyticsPayload)?.toIMap(), ) } else { tracking( - if (isCancel) AnalyticsEvent.TradeCancelOrderSubmissionConfirmed.rawValue else AnalyticsEvent.TradePlaceOrderSubmissionConfirmed.rawValue, + if (isCancel) { + if (isTriggerOrder) AnalyticsEvent.TradeTriggerCancelOrderSubmissionConfirmed.rawValue else AnalyticsEvent.TradeCancelOrderSubmissionConfirmed.rawValue + } else { + if (isTriggerOrder) AnalyticsEvent.TradeTriggerPlaceOrderSubmissionConfirmed.rawValue else AnalyticsEvent.TradePlaceOrderSubmissionConfirmed.rawValue + }, analyticsPayload, ) } @@ -1164,14 +1173,18 @@ class V4StateManagerAdaptor( val payload = placeOrderPayload() val midMarketPrice = stateMachine.state?.marketOrderbook(payload.marketId)?.midPrice val analyticsPayload = analyticsUtils.placeOrderAnalyticsPayload(payload, midMarketPrice) - return submitPlaceOrder(callback, payload, analyticsPayload) + val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TradePlaceOrderClick) + + return submitPlaceOrder(callback, payload, analyticsPayload, uiClickTimeMs) } override fun commitClosePosition(callback: TransactionCallback): HumanReadablePlaceOrderPayload { val payload = closePositionPayload() val midMarketPrice = stateMachine.state?.marketOrderbook(payload.marketId)?.midPrice val analyticsPayload = analyticsUtils.placeOrderAnalyticsPayload(payload, midMarketPrice, true) - return submitPlaceOrder(callback, payload, analyticsPayload) + val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TradePlaceOrderClick) + + return submitPlaceOrder(callback, payload, analyticsPayload, uiClickTimeMs) } override fun cancelOrder(orderId: String, callback: TransactionCallback) { @@ -1182,40 +1195,42 @@ class V4StateManagerAdaptor( payload, existingOrder, ) + val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TradeCancelOrderClick) - submitCancelOrder(orderId, callback, payload, analyticsPayload) + submitCancelOrder(orderId, callback, payload, analyticsPayload, uiClickTimeMs) } override fun commitTriggerOrders(callback: TransactionCallback): HumanReadableTriggerOrdersPayload { - val payloads = triggerOrdersPayload() + val payload = triggerOrdersPayload() - payloads.cancelOrderPayloads.forEach { payload -> + // this is a diff payload that summarizes the actions to be taken + val analyticsPayload = analyticsUtils.triggerOrdersAnalyticsPayload(payload) + val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TradeTriggerOrderClick) + + payload.cancelOrderPayloads.forEach { cancelPayload -> val subaccount = stateMachine.state?.subaccount(subaccountNumber) - val existingOrder = subaccount?.orders?.firstOrNull { it.id == payload.orderId } - val analyticsPayload = analyticsUtils.cancelOrderAnalyticsPayload( - payload, + val existingOrder = subaccount?.orders?.firstOrNull { it.id == cancelPayload.orderId } + val cancelOrderAnalyticsPayload = analyticsUtils.cancelTriggerOrderAnalyticsPayload( + cancelPayload, existingOrder, - true, ) - submitCancelOrder(payload.orderId, callback, payload, analyticsPayload, true) + submitCancelOrder(cancelPayload.orderId, callback, cancelPayload, cancelOrderAnalyticsPayload, uiClickTimeMs, true) } - payloads.placeOrderPayloads.forEach { payload -> - val midMarketPrice = stateMachine.state?.marketOrderbook(payload.marketId)?.midPrice - val analyticsPayload = analyticsUtils.placeOrderAnalyticsPayload( - payload, + payload.placeOrderPayloads.forEach { placePayload -> + val midMarketPrice = stateMachine.state?.marketOrderbook(placePayload.marketId)?.midPrice + val placeOrderAnalyticsPayload = analyticsUtils.placeTriggerOrderAnalyticsPayload( + placePayload, midMarketPrice, - isClosePosition = false, - fromSlTpDialog = true, ) - submitPlaceOrder(callback, payload, analyticsPayload, true) + submitPlaceOrder(callback, placePayload, placeOrderAnalyticsPayload, uiClickTimeMs, true) } - if (payloads.cancelOrderPayloads.isEmpty() && payloads.placeOrderPayloads.isEmpty()) { - send(null, callback, payloads) + if (payload.cancelOrderPayloads.isEmpty() && payload.placeOrderPayloads.isEmpty()) { + send(null, callback, payload) } - return payloads + return payload } override fun commitTransfer(callback: TransactionCallback) { diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/utils/Payloads.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/utils/Payloads.kt index c13f994ef..657bbf329 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/utils/Payloads.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/utils/Payloads.kt @@ -62,6 +62,7 @@ data class HumanReadablePlaceOrderPayload( data class HumanReadableCancelOrderPayload( val subaccountNumber: Int, val orderId: String, + val type: String, val clientId: Int, val orderFlags: Int, val clobPairId: Int, @@ -72,6 +73,7 @@ data class HumanReadableCancelOrderPayload( @JsExport @Serializable data class HumanReadableTriggerOrdersPayload( + val marketId: String, val placeOrderPayloads: List, val cancelOrderPayloads: List, ) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt index 44416eb40..c76f020ff 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt @@ -554,7 +554,7 @@ internal class SubaccountSupervisor( val useTransactionQueue = !isShortTermOrder val onSubmitOrderTransaction = { - val submitTimeMs = trackOrderSubmit(uiClickTimeMs, analyticsPayload) + val submitTimeMs = trackOrderSubmit(uiClickTimeMs, analyticsPayload, isTriggerOrder) helper.ioImplementations.threading?.async(ThreadingType.abacus) { this.placeOrderRecords.add( PlaceOrderRecord( @@ -646,13 +646,18 @@ internal class SubaccountSupervisor( private fun trackOrderSubmit( uiClickTimeMs: Double, analyticsPayload: IMap?, + isTriggerOrder: Boolean, isCancel: Boolean = false ): Double { val submitTimeMs = Clock.System.now().toEpochMilliseconds().toDouble() val uiDelayTimeMs = submitTimeMs - uiClickTimeMs tracking( - if (isCancel) AnalyticsEvent.TradeCancelOrder.rawValue else AnalyticsEvent.TradePlaceOrder.rawValue, + if (isCancel) { + if (isTriggerOrder) AnalyticsEvent.TradeTriggerCancelOrder.rawValue else AnalyticsEvent.TradeCancelOrder.rawValue + } else { + if (isTriggerOrder) AnalyticsEvent.TradeTriggerPlaceOrder.rawValue else AnalyticsEvent.TradePlaceOrder.rawValue + }, ParsingHelper.merge(uiTrackingParams(uiDelayTimeMs), analyticsPayload) ?.toIMap(), ) @@ -699,7 +704,7 @@ internal class SubaccountSupervisor( TransactionType.CancelOrder, string, onSubmitTransaction = { - val submitTimeMs = trackOrderSubmit(uiClickTimeMs, analyticsPayload, true) + val submitTimeMs = trackOrderSubmit(uiClickTimeMs, analyticsPayload, isTriggerOrder, true) helper.ioImplementations.threading?.async(ThreadingType.abacus) { this.cancelOrderRecords.add( CancelOrderRecord( @@ -1011,7 +1016,7 @@ internal class SubaccountSupervisor( updateTriggerOrder(triggerOrders.takeProfitOrder) } - return HumanReadableTriggerOrdersPayload(placeOrderPayloads, cancelOrderPayloads) + return HumanReadableTriggerOrdersPayload(marketId, placeOrderPayloads, cancelOrderPayloads) } @Throws(Exception::class) @@ -1069,6 +1074,7 @@ internal class SubaccountSupervisor( ?: throw Exception("subaccount is null") val order = subaccount.orders?.firstOrNull { it.id == orderId } ?: throw Exception("order is null") + val type = order.type.rawValue val clientId = order.clientId ?: error("clientId is null") val orderFlags = order.orderFlags ?: error("orderFlags is null") val clobPairId = order.clobPairId ?: error("clobPairId is null") @@ -1079,6 +1085,7 @@ internal class SubaccountSupervisor( return HumanReadableCancelOrderPayload( orderSubaccountNumber, orderId, + type, clientId, orderFlags, clobPairId, diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt b/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt index 0e7227a1a..c7afaafcd 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt @@ -1,11 +1,87 @@ package exchange.dydx.abacus.utils import exchange.dydx.abacus.output.SubaccountOrder +import exchange.dydx.abacus.output.input.OrderType import exchange.dydx.abacus.state.manager.HumanReadableCancelOrderPayload import exchange.dydx.abacus.state.manager.HumanReadablePlaceOrderPayload +import exchange.dydx.abacus.state.manager.HumanReadableTriggerOrdersPayload import kollections.toIMap +enum class OrderAction(val rawValue: String) { + replace("REPLACE"), + cancel("CANCEL"), + create("CREATE"), +} + class AnalyticsUtils { + /** + * Format Trigger Orders Payload and add additional details for `TriggerOrders` Analytic Events + * @param payload HumanReadableTriggerOrdersPayload + */ + + /** + * Format Place Order Payload for `TriggerOrders` Analytic Event + * @param payload HumanReadableTriggerOrdersPayload + */ + fun triggerOrdersAnalyticsPayload( + payload: HumanReadableTriggerOrdersPayload, + ): IMap? { + val placeOrderPayloads = payload.placeOrderPayloads + val cancelOrderPayloads = payload.cancelOrderPayloads + + val stopLossOrderTypes = listOf(OrderType.stopMarket, OrderType.stopLimit) + val takeProfitOrderTypes = listOf(OrderType.takeProfitMarket, OrderType.takeProfitLimit) + + var stopLossOrderAction: OrderAction? = null + var takeProfitOrderAction: OrderAction? = null + + placeOrderPayloads.forEach { placePayload -> + val orderType = OrderType.invoke(placePayload.type) + if (stopLossOrderTypes.contains(orderType)) { + stopLossOrderAction = OrderAction.create + } else if (takeProfitOrderTypes.contains(orderType)) { + takeProfitOrderAction = OrderAction.create + } + } + + cancelOrderPayloads.forEach { cancelPayload -> + val orderType = OrderType.invoke(cancelPayload.type) + if (stopLossOrderTypes.contains(orderType)) { + stopLossOrderAction = if (stopLossOrderAction == null) OrderAction.cancel else OrderAction.replace + } else if (takeProfitOrderTypes.contains(orderType)) { + takeProfitOrderAction = if (takeProfitOrderAction == null) OrderAction.cancel else OrderAction.replace + } + } + + return iMapOf( + "marketId" to payload.marketId, + "stopLossOrderAction" to stopLossOrderAction, + "takeProfitOrderAction" to takeProfitOrderAction, + ) as IMap? + } + + /** + * xcxc + * @param payload HumanReadableTriggerOrdersPayload + */ + fun cancelTriggerOrderAnalyticsPayload( + payload: HumanReadableCancelOrderPayload, + existingOrder: SubaccountOrder?, + ): IMap? { + return cancelOrderAnalyticsPayload(payload, existingOrder, true) + } + + /** + * xcxc + * @param payload HumanReadableTriggerOrdersPayload + */ + fun placeTriggerOrderAnalyticsPayload( + payload: HumanReadablePlaceOrderPayload, + midMarketPrice: Double?, + ): IMap? { + return placeOrderAnalyticsPayload(payload, midMarketPrice, false, true) + } + /** * Format Place Order Payload and add additional details for `TradePlaceOrder` Analytic Events * @param payload HumanReadablePlaceOrderPayload @@ -17,7 +93,7 @@ class AnalyticsUtils { payload: HumanReadablePlaceOrderPayload, midMarketPrice: Double?, isClosePosition: Boolean? = false, - fromSlTpDialog: Boolean? = false, + fromSlTpDialog: Boolean? = false, // xcxc remove ): IMap? { return ParsingHelper.merge( formatPlaceOrderPayload(payload, isClosePosition, fromSlTpDialog), @@ -109,7 +185,7 @@ class AnalyticsUtils { fromSlTpDialog: Boolean? = false, ): IMap? { return iMapOf( - "fromSlTpDialog" to fromSlTpDialog, + "fromSlTpDialog" to fromSlTpDialog, // xcxc remove "subaccountNumber" to payload.subaccountNumber, "clientId" to payload.clientId, "orderId" to payload.orderId, From d396798e93da3011d9445bdb045df7d91c7f9d99 Mon Sep 17 00:00:00 2001 From: mulan xia Date: Tue, 30 Apr 2024 10:34:11 -0400 Subject: [PATCH 02/10] wip clean up --- .../TriggerOrdersInputCalculator.kt | 4 ++ .../protocols/PublicProtocols.kt | 24 ++++--- .../state/manager/StateManagerAdaptor.kt | 17 +++-- .../state/manager/V4StateManagerAdaptor.kt | 44 +++++++++---- .../state/manager/utils/Payloads.kt | 5 +- .../v2/supervisor/SubaccountSupervisor.kt | 66 +++++++++++++------ .../utils/AnalyticsUtils.kt | 39 ++--------- 7 files changed, 114 insertions(+), 85 deletions(-) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/calculator/TriggerOrdersInputCalculator.kt b/src/commonMain/kotlin/exchange.dydx.abacus/calculator/TriggerOrdersInputCalculator.kt index c89329c60..f190d50c3 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/calculator/TriggerOrdersInputCalculator.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/calculator/TriggerOrdersInputCalculator.kt @@ -13,6 +13,10 @@ import exchange.dydx.abacus.utils.mutable import exchange.dydx.abacus.utils.safeSet import kotlin.math.abs +internal object TriggerOrdersConstants { + const val TRIGGER_ORDER_DEFAULT_DURATION_DAYS = 28.0 +} + @Suppress("UNCHECKED_CAST") internal class TriggerOrdersInputCalculator(val parser: ParserProtocol) { internal fun calculate( diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/protocols/PublicProtocols.kt b/src/commonMain/kotlin/exchange.dydx.abacus/protocols/PublicProtocols.kt index 53538c9d3..7084689db 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/protocols/PublicProtocols.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/protocols/PublicProtocols.kt @@ -209,25 +209,29 @@ enum class AnalyticsEvent(val rawValue: String) { // App NetworkStatus("NetworkStatus"), - // Trade Events + // Trade TradePlaceOrderClick("TradePlaceOrderClick"), TradeCancelOrderClick("TradeCancelOrderClick"), - TradeTriggerOrderClick("TradeTriggerOrderClick"), - TradePlaceOrder("TradePlaceOrder"), // analytics here - TradeCancelOrder("TradeCancelOrder"), // analytics here - TradeTriggerPlaceOrder("TradeTriggerPlaceOrder"), - TradeTriggerCancelOrder("TradeTriggerCancelOrder"), + TradePlaceOrder("TradePlaceOrder"), + TradeCancelOrder("TradeCancelOrder"), TradePlaceOrderSubmissionConfirmed("TradePlaceOrderSubmissionConfirmed"), TradeCancelOrderSubmissionConfirmed("TradeCancelOrderSubmissionConfirmed"), - TradeTriggerPlaceOrderSubmissionConfirmed("TradeTriggerPlaceOrderSubmissionConfirmed"), - TradeTriggerCancelOrderSubmissionConfirmed("TradeTriggerCancelOrderSubmissionConfirmed"), TradePlaceOrderSubmissionFailed("TradePlaceOrderSubmissionFailed"), TradeCancelOrderSubmissionFailed("TradeCancelOrderSubmissionFailed"), - TradeTriggerPlaceOrderSubmissionFailed("TradeTriggerPlaceOrderSubmissionFailed"), - TradeTriggerCancelOrderSubmissionFailed("TradeTriggerCancelOrderSubmissionFailed"), TradeCancelOrderConfirmed("TradeCancelOrderConfirmed"), TradePlaceOrderConfirmed("TradePlaceOrderConfirmed"), + // Trigger Order + TriggerOrderClick("TriggerOrderClick"), + TriggerPlaceOrder("TriggerPlaceOrder"), + TriggerCancelOrder("TriggerCancelOrder"), + TriggerPlaceOrderSubmissionConfirmed("TriggerPlaceOrderSubmissionConfirmed"), + TriggerCancelOrderSubmissionConfirmed("TriggerCancelOrderSubmissionConfirmed"), + TriggerPlaceOrderSubmissionFailed("TriggerPlaceOrderSubmissionFailed"), + TriggerCancelOrderSubmissionFailed("TriggerCancelOrderSubmissionFailed"), + TriggerCancelOrderConfirmed("TriggerCancelOrderConfirmed"), + TriggerPlaceOrderConfirmed("TriggerPlaceOrderConfirmed"), + // Transfers TransferFaucetConfirmed("TransferFaucetConfirmed"); diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt index 3bb0dd667..58fdc3b0b 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt @@ -1,5 +1,6 @@ package exchange.dydx.abacus.state.manager +import exchange.dydx.abacus.calculator.TriggerOrdersConstants.TRIGGER_ORDER_DEFAULT_DURATION_DAYS import exchange.dydx.abacus.output.Compliance import exchange.dydx.abacus.output.ComplianceAction import exchange.dydx.abacus.output.ComplianceStatus @@ -75,6 +76,7 @@ import exchange.dydx.abacus.utils.IMap import exchange.dydx.abacus.utils.IMutableList import exchange.dydx.abacus.utils.IOImplementations import exchange.dydx.abacus.utils.JsonEncoder +import exchange.dydx.abacus.utils.Logger import exchange.dydx.abacus.utils.Parser import exchange.dydx.abacus.utils.ParsingHelper import exchange.dydx.abacus.utils.SHORT_TERM_ORDER_DURATION @@ -120,9 +122,6 @@ open class StateManagerAdaptor( var stateNotification: StateNotificationProtocol?, var dataNotification: DataNotificationProtocol?, ) { - @Suppress("LocalVariableName", "PropertyName") - private val TRIGGER_ORDER_DEFAULT_DURATION_DAYS = 28.0 - var stateMachine: TradingStateMachine = PerpTradingStateMachine( environment, uiImplementations.localizer, @@ -1880,10 +1879,12 @@ open class StateManagerAdaptor( val cancelOrderPayloads = mutableListOf() val triggerOrders = stateMachine.state?.input?.triggerOrders + val marketId = triggerOrders?.marketId ?: throw Exception("marketId is null") + val subaccountNumber = connectedSubaccountNumber ?: throw Exception("subaccountNumber is null") val subaccount = stateMachine.state?.subaccount(subaccountNumber) ?: throw Exception("subaccount is null") - - val marketId = triggerOrders?.marketId ?: throw Exception("marketId is null") + val position = subaccount.openPositions?.find { it.id == marketId } + val positionSize = position?.size?.current fun updateTriggerOrder(triggerOrder: TriggerOrder) { // Cases @@ -1924,6 +1925,7 @@ open class StateManagerAdaptor( return HumanReadableTriggerOrdersPayload( marketId, + positionSize, placeOrderPayloads, cancelOrderPayloads, ) @@ -2305,6 +2307,7 @@ open class StateManagerAdaptor( ioImplementations.threading?.async(ThreadingType.main) { ioImplementations.tracking?.log(eventName, paramsAsString) } + Logger.e { "xcxc $eventName $paramsAsString" } } private fun didSetPlaceOrderRecords() { @@ -2330,7 +2333,7 @@ open class StateManagerAdaptor( val interval = Clock.System.now().toEpochMilliseconds() .toDouble() - placeOrderRecord.timestampInMilliseconds tracking( - AnalyticsEvent.TradePlaceOrderConfirmed.rawValue, + if (placeOrderRecord.isTriggerOrder) AnalyticsEvent.TriggerPlaceOrderConfirmed.rawValue else AnalyticsEvent.TradePlaceOrderConfirmed.rawValue, ParsingHelper.merge( trackingParams(interval), orderAnalyticsPayload, @@ -2346,7 +2349,7 @@ open class StateManagerAdaptor( val interval = Clock.System.now().toEpochMilliseconds() .toDouble() - cancelOrderRecord.timestampInMilliseconds tracking( - AnalyticsEvent.TradeCancelOrderConfirmed.rawValue, + if (cancelOrderRecord.isTriggerOrder) AnalyticsEvent.TriggerCancelOrderConfirmed.rawValue else AnalyticsEvent.TradeCancelOrderConfirmed.rawValue, ParsingHelper.merge( trackingParams(interval), orderAnalyticsPayload, diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt index 826eca65f..268e39b50 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt @@ -1005,6 +1005,9 @@ class V4StateManagerAdaptor( ): HumanReadablePlaceOrderPayload { val clientId = payload.clientId val string = Json.encodeToString(payload) + val marketId = payload.marketId + val position = stateMachine.state?.subaccount(subaccountNumber)?.openPositions?.find { it.id == marketId } + val positionSize = position?.size?.current stopWatchingLastOrder() @@ -1012,13 +1015,14 @@ class V4StateManagerAdaptor( TransactionType.PlaceOrder, string, onSubmitTransaction = { - val submitTimeMs = trackOrderSubmit(uiClickTimeMs, analyticsPayload) + val submitTimeMs = trackOrderSubmit(uiClickTimeMs, analyticsPayload, isTriggerOrder) ioImplementations.threading?.async(ThreadingType.abacus) { this.placeOrderRecords.add( PlaceOrderRecord( subaccountNumber, clientId, submitTimeMs, + isTriggerOrder, ), ) } @@ -1040,6 +1044,8 @@ class V4StateManagerAdaptor( callback, if (isTriggerOrder) { HumanReadableTriggerOrdersPayload( + marketId, + positionSize, listOf(payload), emptyList(), ) @@ -1056,6 +1062,7 @@ class V4StateManagerAdaptor( private fun submitCancelOrder( orderId: String, + marketId: String?, callback: TransactionCallback, payload: HumanReadableCancelOrderPayload, analyticsPayload: IMap?, @@ -1065,6 +1072,9 @@ class V4StateManagerAdaptor( val clientId = payload.clientId val string = Json.encodeToString(payload) + val position = stateMachine.state?.subaccount(subaccountNumber)?.openPositions?.find { it.id == marketId } + val positionSize = position?.size?.current + val isShortTermOrder = payload.orderFlags == 0 stopWatchingLastOrder() @@ -1073,13 +1083,14 @@ class V4StateManagerAdaptor( TransactionType.CancelOrder, string, onSubmitTransaction = { - val submitTimeMs = trackOrderSubmit(uiClickTimeMs, analyticsPayload, true) + val submitTimeMs = trackOrderSubmit(uiClickTimeMs, analyticsPayload, isTriggerOrder, true) ioImplementations.threading?.async(ThreadingType.abacus) { this.cancelOrderRecords.add( CancelOrderRecord( subaccountNumber, clientId, submitTimeMs, + isTriggerOrder, ), ) } @@ -1101,6 +1112,8 @@ class V4StateManagerAdaptor( callback, if (isTriggerOrder) { HumanReadableTriggerOrdersPayload( + marketId, + positionSize, emptyList(), listOf(payload), ) @@ -1128,13 +1141,18 @@ class V4StateManagerAdaptor( private fun trackOrderSubmit( uiClickTimeMs: Double, analyticsPayload: IMap?, + isTriggerOrder: Boolean, isCancel: Boolean = false ): Double { val submitTimeMs = Clock.System.now().toEpochMilliseconds().toDouble() val uiDelayTimeMs = submitTimeMs - uiClickTimeMs tracking( - if (isCancel) AnalyticsEvent.TradeCancelOrder.rawValue else AnalyticsEvent.TradePlaceOrder.rawValue, + if (isCancel) { + if (isTriggerOrder) AnalyticsEvent.TriggerCancelOrder.rawValue else AnalyticsEvent.TradeCancelOrder.rawValue + } else { + if (isTriggerOrder) AnalyticsEvent.TriggerPlaceOrder.rawValue else AnalyticsEvent.TradePlaceOrder.rawValue + }, ParsingHelper.merge(uiTrackingParams(uiDelayTimeMs), analyticsPayload) ?.toIMap(), ) @@ -1151,18 +1169,18 @@ class V4StateManagerAdaptor( if (error != null) { tracking( if (isCancel) { - if (isTriggerOrder) AnalyticsEvent.TradeTriggerCancelOrderSubmissionFailed.rawValue else AnalyticsEvent.TradeCancelOrderSubmissionFailed.rawValue + if (isTriggerOrder) AnalyticsEvent.TriggerCancelOrderSubmissionFailed.rawValue else AnalyticsEvent.TradeCancelOrderSubmissionFailed.rawValue } else { - if (isTriggerOrder) AnalyticsEvent.TradeTriggerPlaceOrderSubmissionFailed.rawValue else AnalyticsEvent.TradePlaceOrderSubmissionFailed.rawValue + if (isTriggerOrder) AnalyticsEvent.TriggerPlaceOrderSubmissionFailed.rawValue else AnalyticsEvent.TradePlaceOrderSubmissionFailed.rawValue }, ParsingHelper.merge(errorTrackingParams(error), analyticsPayload)?.toIMap(), ) } else { tracking( if (isCancel) { - if (isTriggerOrder) AnalyticsEvent.TradeTriggerCancelOrderSubmissionConfirmed.rawValue else AnalyticsEvent.TradeCancelOrderSubmissionConfirmed.rawValue + if (isTriggerOrder) AnalyticsEvent.TriggerCancelOrderSubmissionConfirmed.rawValue else AnalyticsEvent.TradeCancelOrderSubmissionConfirmed.rawValue } else { - if (isTriggerOrder) AnalyticsEvent.TradeTriggerPlaceOrderSubmissionConfirmed.rawValue else AnalyticsEvent.TradePlaceOrderSubmissionConfirmed.rawValue + if (isTriggerOrder) AnalyticsEvent.TriggerPlaceOrderSubmissionConfirmed.rawValue else AnalyticsEvent.TradePlaceOrderSubmissionConfirmed.rawValue }, analyticsPayload, ) @@ -1191,13 +1209,14 @@ class V4StateManagerAdaptor( val payload = cancelOrderPayload(orderId) val subaccount = stateMachine.state?.subaccount(subaccountNumber) val existingOrder = subaccount?.orders?.firstOrNull { it.id == orderId } + val marketId = existingOrder?.marketId val analyticsPayload = analyticsUtils.cancelOrderAnalyticsPayload( payload, existingOrder, ) val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TradeCancelOrderClick) - submitCancelOrder(orderId, callback, payload, analyticsPayload, uiClickTimeMs) + submitCancelOrder(orderId, marketId, callback, payload, analyticsPayload, uiClickTimeMs) } override fun commitTriggerOrders(callback: TransactionCallback): HumanReadableTriggerOrdersPayload { @@ -1205,21 +1224,22 @@ class V4StateManagerAdaptor( // this is a diff payload that summarizes the actions to be taken val analyticsPayload = analyticsUtils.triggerOrdersAnalyticsPayload(payload) - val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TradeTriggerOrderClick) + val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TriggerOrderClick) payload.cancelOrderPayloads.forEach { cancelPayload -> val subaccount = stateMachine.state?.subaccount(subaccountNumber) val existingOrder = subaccount?.orders?.firstOrNull { it.id == cancelPayload.orderId } - val cancelOrderAnalyticsPayload = analyticsUtils.cancelTriggerOrderAnalyticsPayload( + val marketId = existingOrder?.marketId + val cancelOrderAnalyticsPayload = analyticsUtils.cancelOrderAnalyticsPayload( cancelPayload, existingOrder, ) - submitCancelOrder(cancelPayload.orderId, callback, cancelPayload, cancelOrderAnalyticsPayload, uiClickTimeMs, true) + submitCancelOrder(cancelPayload.orderId, marketId, callback, cancelPayload, cancelOrderAnalyticsPayload, uiClickTimeMs, true) } payload.placeOrderPayloads.forEach { placePayload -> val midMarketPrice = stateMachine.state?.marketOrderbook(placePayload.marketId)?.midPrice - val placeOrderAnalyticsPayload = analyticsUtils.placeTriggerOrderAnalyticsPayload( + val placeOrderAnalyticsPayload = analyticsUtils.placeOrderAnalyticsPayload( placePayload, midMarketPrice, ) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/utils/Payloads.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/utils/Payloads.kt index 657bbf329..71d20a9a1 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/utils/Payloads.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/utils/Payloads.kt @@ -18,12 +18,14 @@ data class PlaceOrderRecord( val subaccountNumber: Int, val clientId: Int, val timestampInMilliseconds: Double, + val isTriggerOrder: Boolean, ) data class CancelOrderRecord( val subaccountNumber: Int, val clientId: Int, val timestampInMilliseconds: Double, + val isTriggerOrder: Boolean, ) @JsExport @@ -73,7 +75,8 @@ data class HumanReadableCancelOrderPayload( @JsExport @Serializable data class HumanReadableTriggerOrdersPayload( - val marketId: String, + val marketId: String?, + val positionSize: Double?, val placeOrderPayloads: List, val cancelOrderPayloads: List, ) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt index 3a445c31e..56371b7da 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt @@ -1,5 +1,6 @@ package exchange.dydx.abacus.state.v2.supervisor +import exchange.dydx.abacus.calculator.TriggerOrdersConstants.TRIGGER_ORDER_DEFAULT_DURATION_DAYS import exchange.dydx.abacus.output.Notification import exchange.dydx.abacus.output.SubaccountOrder import exchange.dydx.abacus.output.TransferRecordType @@ -80,9 +81,6 @@ internal class SubaccountSupervisor( private val accountAddress: String, internal val subaccountNumber: Int ) : DynamicNetworkSupervisor(stateMachine, helper, analyticsUtils) { - @Suppress("LocalVariableName", "PropertyName") - private val TRIGGER_ORDER_DEFAULT_DURATION_DAYS = 28.0 - /* Because faucet is done at subaccount level, we need SubaccountSupervisor even before the subaccount is realized on protocol/indexer. @@ -308,7 +306,7 @@ internal class SubaccountSupervisor( val interval = Clock.System.now().toEpochMilliseconds() .toDouble() - placeOrderRecord.timestampInMilliseconds tracking( - AnalyticsEvent.TradePlaceOrderConfirmed.rawValue, + if (placeOrderRecord.isTriggerOrder) AnalyticsEvent.TriggerPlaceOrderConfirmed.rawValue else AnalyticsEvent.TradePlaceOrderConfirmed.rawValue, ParsingHelper.merge( trackingParams(interval), orderAnalyticsPayload, @@ -324,7 +322,7 @@ internal class SubaccountSupervisor( val interval = Clock.System.now().toEpochMilliseconds() .toDouble() - cancelOrderRecord.timestampInMilliseconds tracking( - AnalyticsEvent.TradeCancelOrderConfirmed.rawValue, + if (cancelOrderRecord.isTriggerOrder) AnalyticsEvent.TriggerCancelOrderConfirmed.rawValue else AnalyticsEvent.TradeCancelOrderConfirmed.rawValue, ParsingHelper.merge( trackingParams(interval), orderAnalyticsPayload, @@ -539,6 +537,10 @@ internal class SubaccountSupervisor( val transferPayloadString = if (transferPayload != null) Json.encodeToString(transferPayload) else null + val marketId = payload.marketId + val position = stateMachine.state?.subaccount(subaccountNumber)?.openPositions?.find { it.id == marketId } + val positionSize = position?.size?.current + val isShortTermOrder = when (payload.type) { "MARKET" -> true "LIMIT" -> { @@ -561,6 +563,7 @@ internal class SubaccountSupervisor( subaccountNumber, clientId, submitTimeMs, + isTriggerOrder, ), ) } @@ -568,7 +571,7 @@ internal class SubaccountSupervisor( val orderTransactionCallback = { response: String? -> val error = parseTransactionResponse(response) - trackOrderSubmitted(error, analyticsPayload) + trackOrderSubmitted(error, analyticsPayload, isTriggerOrder) if (error == null) { lastOrderClientId = clientId } else { @@ -582,6 +585,8 @@ internal class SubaccountSupervisor( callback, if (isTriggerOrder) { HumanReadableTriggerOrdersPayload( + marketId, + positionSize, listOf(payload), emptyList(), ) @@ -654,9 +659,9 @@ internal class SubaccountSupervisor( tracking( if (isCancel) { - if (isTriggerOrder) AnalyticsEvent.TradeTriggerCancelOrder.rawValue else AnalyticsEvent.TradeCancelOrder.rawValue + if (isTriggerOrder) AnalyticsEvent.TriggerCancelOrder.rawValue else AnalyticsEvent.TradeCancelOrder.rawValue } else { - if (isTriggerOrder) AnalyticsEvent.TradeTriggerPlaceOrder.rawValue else AnalyticsEvent.TradePlaceOrder.rawValue + if (isTriggerOrder) AnalyticsEvent.TriggerPlaceOrder.rawValue else AnalyticsEvent.TradePlaceOrder.rawValue }, ParsingHelper.merge(uiTrackingParams(uiDelayTimeMs), analyticsPayload) ?.toIMap(), @@ -668,16 +673,25 @@ internal class SubaccountSupervisor( private fun trackOrderSubmitted( error: ParsingError?, analyticsPayload: IMap?, + isTriggerOrder: Boolean, isCancel: Boolean = false, ) { if (error != null) { tracking( - if (isCancel) AnalyticsEvent.TradeCancelOrderSubmissionFailed.rawValue else AnalyticsEvent.TradePlaceOrderSubmissionFailed.rawValue, + if (isCancel) { + if (isTriggerOrder) AnalyticsEvent.TriggerCancelOrderSubmissionFailed.rawValue else AnalyticsEvent.TradeCancelOrderSubmissionFailed.rawValue + } else { + if (isTriggerOrder) AnalyticsEvent.TriggerPlaceOrderSubmissionFailed.rawValue else AnalyticsEvent.TradePlaceOrderSubmissionFailed.rawValue + }, ParsingHelper.merge(errorTrackingParams(error), analyticsPayload)?.toIMap(), ) } else { tracking( - if (isCancel) AnalyticsEvent.TradeCancelOrderSubmissionConfirmed.rawValue else AnalyticsEvent.TradePlaceOrderSubmissionConfirmed.rawValue, + if (isCancel) { + if (isTriggerOrder) AnalyticsEvent.TriggerCancelOrderSubmissionConfirmed.rawValue else AnalyticsEvent.TradeCancelOrderSubmissionConfirmed.rawValue + } else { + if (isTriggerOrder) AnalyticsEvent.TriggerPlaceOrderSubmissionConfirmed.rawValue else AnalyticsEvent.TradePlaceOrderSubmissionConfirmed.rawValue + }, analyticsPayload, ) } @@ -685,16 +699,18 @@ internal class SubaccountSupervisor( private fun submitCancelOrder( orderId: String, + marketId: String?, callback: TransactionCallback, payload: HumanReadableCancelOrderPayload, analyticsPayload: IMap?, + uiClickTimeMs: Double, isTriggerOrder: Boolean = false, ): HumanReadableCancelOrderPayload { val clientId = payload.clientId val string = Json.encodeToString(payload) - val uiClickTimeMs = Clock.System.now().toEpochMilliseconds().toDouble() - tracking(AnalyticsEvent.TradeCancelOrderClick.rawValue, analyticsPayload) + val position = stateMachine.state?.subaccount(subaccountNumber)?.openPositions?.find { it.id == marketId } + val positionSize = position?.size?.current stopWatchingLastOrder() @@ -711,13 +727,14 @@ internal class SubaccountSupervisor( subaccountNumber, clientId, submitTimeMs, + isTriggerOrder, ), ) } }, transactionCallback = { response: String? -> val error = parseTransactionResponse(response) - trackOrderSubmitted(error, analyticsPayload, true) + trackOrderSubmitted(error, analyticsPayload, isTriggerOrder, true) if (error == null) { this.orderCanceled(orderId) } else { @@ -731,6 +748,8 @@ internal class SubaccountSupervisor( callback, if (isTriggerOrder) { HumanReadableTriggerOrdersPayload( + marketId, + positionSize, emptyList(), listOf(payload), ) @@ -777,9 +796,11 @@ internal class SubaccountSupervisor( val payload = cancelOrderPayload(orderId) val subaccount = stateMachine.state?.subaccount(subaccountNumber) val existingOrder = subaccount?.orders?.firstOrNull { it.id == orderId } + val marketId = existingOrder?.marketId val analyticsPayload = analyticsUtils.cancelOrderAnalyticsPayload(payload, existingOrder) + val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TradeCancelOrderClick) - return submitCancelOrder(orderId, callback, payload, analyticsPayload) + return submitCancelOrder(orderId, marketId, callback, payload, analyticsPayload, uiClickTimeMs) } internal fun commitTriggerOrders( @@ -790,21 +811,22 @@ internal class SubaccountSupervisor( // this is a diff payload that summarizes the actions to be taken val analyticsPayload = analyticsUtils.triggerOrdersAnalyticsPayload(payload) - val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TradeTriggerOrderClick) + val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TriggerOrderClick) payload.cancelOrderPayloads.forEach { cancelPayload -> val subaccount = stateMachine.state?.subaccount(subaccountNumber) val existingOrder = subaccount?.orders?.firstOrNull { it.id == cancelPayload.orderId } - val cancelOrderAnalyticsPayload = analyticsUtils.cancelTriggerOrderAnalyticsPayload( + val marketId = existingOrder?.marketId + val cancelOrderAnalyticsPayload = analyticsUtils.cancelOrderAnalyticsPayload( cancelPayload, existingOrder, ) - submitCancelOrder(cancelPayload.orderId, callback, cancelPayload, cancelOrderAnalyticsPayload, true) + submitCancelOrder(cancelPayload.orderId, marketId, callback, cancelPayload, cancelOrderAnalyticsPayload, uiClickTimeMs, true) } payload.placeOrderPayloads.forEach { placePayload -> val midMarketPrice = stateMachine.state?.marketOrderbook(placePayload.marketId)?.midPrice - val placeOrderAnalyticsPayload = analyticsUtils.placeTriggerOrderAnalyticsPayload( + val placeOrderAnalyticsPayload = analyticsUtils.placeOrderAnalyticsPayload( placePayload, midMarketPrice, ) @@ -982,10 +1004,12 @@ internal class SubaccountSupervisor( val cancelOrderPayloads = mutableListOf() val triggerOrders = stateMachine.state?.input?.triggerOrders - val subaccount = stateMachine.state?.subaccount(subaccountNumber) ?: throw Exception("subaccount is null") - val marketId = triggerOrders?.marketId ?: throw Exception("marketId is null") + val subaccount = stateMachine.state?.subaccount(subaccountNumber) ?: throw Exception("subaccount is null") + val position = helper.parser.asNativeMap(helper.parser.value(subaccount, "openPositions.$marketId")) + val positionSize = helper.parser.asDouble(helper.parser.value(position, "size.current")) + fun updateTriggerOrder(triggerOrder: TriggerOrder) { // Cases // 1. Existing order -> update @@ -1023,7 +1047,7 @@ internal class SubaccountSupervisor( updateTriggerOrder(triggerOrders.takeProfitOrder) } - return HumanReadableTriggerOrdersPayload(marketId, placeOrderPayloads, cancelOrderPayloads) + return HumanReadableTriggerOrdersPayload(marketId, positionSize, placeOrderPayloads, cancelOrderPayloads) } @Throws(Exception::class) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt b/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt index c7afaafcd..976c514cf 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt @@ -55,48 +55,25 @@ class AnalyticsUtils { return iMapOf( "marketId" to payload.marketId, - "stopLossOrderAction" to stopLossOrderAction, - "takeProfitOrderAction" to takeProfitOrderAction, + "positionSize" to payload.positionSize, + "stopLossOrderAction" to stopLossOrderAction?.rawValue, + "takeProfitOrderAction" to takeProfitOrderAction?.rawValue, ) as IMap? } - /** - * xcxc - * @param payload HumanReadableTriggerOrdersPayload - */ - fun cancelTriggerOrderAnalyticsPayload( - payload: HumanReadableCancelOrderPayload, - existingOrder: SubaccountOrder?, - ): IMap? { - return cancelOrderAnalyticsPayload(payload, existingOrder, true) - } - - /** - * xcxc - * @param payload HumanReadableTriggerOrdersPayload - */ - fun placeTriggerOrderAnalyticsPayload( - payload: HumanReadablePlaceOrderPayload, - midMarketPrice: Double?, - ): IMap? { - return placeOrderAnalyticsPayload(payload, midMarketPrice, false, true) - } - /** * Format Place Order Payload and add additional details for `TradePlaceOrder` Analytic Events * @param payload HumanReadablePlaceOrderPayload * @param midMarketPrice Double? * @param isClosePosition Boolean? - * @param fromSlTpDialog Boolean? */ fun placeOrderAnalyticsPayload( payload: HumanReadablePlaceOrderPayload, midMarketPrice: Double?, isClosePosition: Boolean? = false, - fromSlTpDialog: Boolean? = false, // xcxc remove ): IMap? { return ParsingHelper.merge( - formatPlaceOrderPayload(payload, isClosePosition, fromSlTpDialog), + formatPlaceOrderPayload(payload, isClosePosition), iMapOf( "inferredTimeInForce" to calculateOrderTimeInForce(payload), "midMarketPrice" to midMarketPrice, @@ -112,7 +89,6 @@ class AnalyticsUtils { private fun formatPlaceOrderPayload( payload: HumanReadablePlaceOrderPayload, isClosePosition: Boolean? = false, - fromSlTpDialog: Boolean? = false, ): IMap? { return iMapOf( "clientId" to payload.clientId, @@ -121,7 +97,6 @@ class AnalyticsUtils { "goodTilTimeInSeconds" to payload.goodTilTimeInSeconds, "goodTilBlock" to payload.goodTilBlock, "isClosePosition" to isClosePosition, - "fromSlTpDialog" to fromSlTpDialog, "marketId" to payload.marketId, "postOnly" to payload.postOnly, "price" to payload.price, @@ -167,25 +142,21 @@ class AnalyticsUtils { * Format Cancel Order Payload and add order details for `TradeCancelOrder` Analytic Events * @param payload HumanReadableCancelOrderPayload * @param existingOrder SubaccountOrder? - * @param fromSlTpDialog Boolean */ fun cancelOrderAnalyticsPayload( payload: HumanReadableCancelOrderPayload, existingOrder: SubaccountOrder?, - fromSlTpDialog: Boolean? = false, ): IMap? { return ParsingHelper.merge( - formatCancelOrderPayload(payload, fromSlTpDialog), + formatCancelOrderPayload(payload), if (existingOrder != null) formatOrder(existingOrder) else mapOf(), )?.toIMap() } private fun formatCancelOrderPayload( payload: HumanReadableCancelOrderPayload, - fromSlTpDialog: Boolean? = false, ): IMap? { return iMapOf( - "fromSlTpDialog" to fromSlTpDialog, // xcxc remove "subaccountNumber" to payload.subaccountNumber, "clientId" to payload.clientId, "orderId" to payload.orderId, From 6e5458c4c6cc33b7b599bba09798e8219efa74ee Mon Sep 17 00:00:00 2001 From: mulan xia Date: Tue, 30 Apr 2024 14:06:16 -0400 Subject: [PATCH 03/10] bump v --- build.gradle.kts | 2 +- v4_abacus.podspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index da568286c..246c44c89 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -49,7 +49,7 @@ allprojects { } group = "exchange.dydx.abacus" -version = "1.6.50" +version = "1.6.51" repositories { google() diff --git a/v4_abacus.podspec b/v4_abacus.podspec index 88643c456..8f60f0b1a 100644 --- a/v4_abacus.podspec +++ b/v4_abacus.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'v4_abacus' - spec.version = '1.6.50' + spec.version = '1.6.51' spec.homepage = 'https://github.com/dydxprotocol/v4-abacus' spec.source = { :http=> ''} spec.authors = '' From 84461d0df3536f168b2db0b977d338dc068e177f Mon Sep 17 00:00:00 2001 From: mulan xia Date: Tue, 30 Apr 2024 14:08:38 -0400 Subject: [PATCH 04/10] bump v --- build.gradle.kts | 2 +- v4_abacus.podspec | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle.kts b/build.gradle.kts index da8104a62..a4d2e1e55 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -49,7 +49,7 @@ allprojects { } group = "exchange.dydx.abacus" -version = "1.6.52" +version = "1.6.53" repositories { google() diff --git a/v4_abacus.podspec b/v4_abacus.podspec index 8bea38bb3..945ef609f 100644 --- a/v4_abacus.podspec +++ b/v4_abacus.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'v4_abacus' - spec.version = '1.6.52' + spec.version = '1.6.53' spec.homepage = 'https://github.com/dydxprotocol/v4-abacus' spec.source = { :http=> ''} spec.authors = '' From 29b222f142673f9baa2b1833497a4d3f1f881a79 Mon Sep 17 00:00:00 2001 From: mulan xia Date: Tue, 30 Apr 2024 15:03:48 -0400 Subject: [PATCH 05/10] midway through fixing tests --- .../helper/TriggerOrderToastGeneratorTests.kt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/commonTest/kotlin/exchange.dydx.abacus/app/helper/TriggerOrderToastGeneratorTests.kt b/src/commonTest/kotlin/exchange.dydx.abacus/app/helper/TriggerOrderToastGeneratorTests.kt index c20738af3..1d3777049 100644 --- a/src/commonTest/kotlin/exchange.dydx.abacus/app/helper/TriggerOrderToastGeneratorTests.kt +++ b/src/commonTest/kotlin/exchange.dydx.abacus/app/helper/TriggerOrderToastGeneratorTests.kt @@ -69,6 +69,9 @@ class TriggerOrderToastGeneratorTests { "side": { "current": "SHORT" }, + "size": { + "current": 94.57 + }, "resources": { "sideString": {}, "sideStringKey": {}, @@ -95,6 +98,8 @@ class TriggerOrderToastGeneratorTests { toastGenerator.onTriggerOrderSubmitted( subaccountNumber = 0, payload = HumanReadableTriggerOrdersPayload( + marketId = "ETH-USD", + positionSize = 94.57, cancelOrderPayloads = emptyList(), placeOrderPayloads = emptyList(), ), @@ -105,10 +110,13 @@ class TriggerOrderToastGeneratorTests { toastGenerator.onTriggerOrderSubmitted( subaccountNumber = 0, payload = HumanReadableTriggerOrdersPayload( + marketId = "ETH-USD", + positionSize = 94.57, cancelOrderPayloads = listOf( HumanReadableCancelOrderPayload( subaccountNumber = 0, clientId = 0, + type = "TAKE_PROFIT", orderId = "existingOrderId", orderFlags = 0, clobPairId = 0, @@ -160,6 +168,8 @@ class TriggerOrderToastGeneratorTests { toastGenerator.onTriggerOrderSubmitted( subaccountNumber = 0, payload = HumanReadableTriggerOrdersPayload( + marketId = "ETH-USD", + positionSize = 94.57, cancelOrderPayloads = emptyList(), placeOrderPayloads = emptyList(), ), @@ -171,10 +181,13 @@ class TriggerOrderToastGeneratorTests { successful = true, error = null, data = HumanReadableTriggerOrdersPayload( + marketId = "ETH-USD", + positionSize = 94.57, cancelOrderPayloads = listOf( HumanReadableCancelOrderPayload( subaccountNumber = 0, clientId = 0, + type = "TAKE_PROFIT", orderId = "existingOrderId", orderFlags = 0, clobPairId = 0, @@ -198,6 +211,8 @@ class TriggerOrderToastGeneratorTests { successful = true, error = null, data = HumanReadableTriggerOrdersPayload( + marketId = "ETH-USD", + positionSize = 94.57, cancelOrderPayloads = emptyList(), placeOrderPayloads = listOf( HumanReadablePlaceOrderPayload( @@ -237,6 +252,8 @@ class TriggerOrderToastGeneratorTests { toastGenerator.onTriggerOrderSubmitted( subaccountNumber = 0, payload = HumanReadableTriggerOrdersPayload( + marketId = "ETH-USD", + positionSize = 94.57, cancelOrderPayloads = emptyList(), placeOrderPayloads = emptyList(), ), @@ -248,9 +265,12 @@ class TriggerOrderToastGeneratorTests { successful = false, error = null, data = HumanReadableTriggerOrdersPayload( + marketId = "ETH-USD", + positionSize = 94.57, cancelOrderPayloads = listOf( HumanReadableCancelOrderPayload( subaccountNumber = 0, + type = "TAKE_PROFIT", clientId = 0, orderId = "existingOrderId", orderFlags = 0, From 2d6300d5408a2c102aaa28064076fcb312169530 Mon Sep 17 00:00:00 2001 From: mulan xia Date: Tue, 30 Apr 2024 16:05:05 -0400 Subject: [PATCH 06/10] revise analytics --- .../protocols/PublicProtocols.kt | 8 -- .../state/manager/StateManagerAdaptor.kt | 37 +++--- .../state/manager/V4StateManagerAdaptor.kt | 80 +++--------- .../state/manager/utils/Payloads.kt | 4 +- .../v2/supervisor/SubaccountSupervisor.kt | 116 ++++++------------ .../utils/AnalyticsUtils.kt | 23 +++- 6 files changed, 99 insertions(+), 169 deletions(-) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/protocols/PublicProtocols.kt b/src/commonMain/kotlin/exchange.dydx.abacus/protocols/PublicProtocols.kt index 1b53cd563..8b290fc49 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/protocols/PublicProtocols.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/protocols/PublicProtocols.kt @@ -223,14 +223,6 @@ enum class AnalyticsEvent(val rawValue: String) { // Trigger Order TriggerOrderClick("TriggerOrderClick"), - TriggerPlaceOrder("TriggerPlaceOrder"), - TriggerCancelOrder("TriggerCancelOrder"), - TriggerPlaceOrderSubmissionConfirmed("TriggerPlaceOrderSubmissionConfirmed"), - TriggerCancelOrderSubmissionConfirmed("TriggerCancelOrderSubmissionConfirmed"), - TriggerPlaceOrderSubmissionFailed("TriggerPlaceOrderSubmissionFailed"), - TriggerCancelOrderSubmissionFailed("TriggerCancelOrderSubmissionFailed"), - TriggerCancelOrderConfirmed("TriggerCancelOrderConfirmed"), - TriggerPlaceOrderConfirmed("TriggerPlaceOrderConfirmed"), // Transfers TransferFaucetConfirmed("TransferFaucetConfirmed"); diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt index 2cdca16d4..29c12e751 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt @@ -1882,11 +1882,8 @@ open class StateManagerAdaptor( val subaccountNumber = connectedSubaccountNumber ?: throw Exception("subaccountNumber is null") val subaccount = stateMachine.state?.subaccount(subaccountNumber) ?: throw Exception("subaccount is null") - val position = subaccount.openPositions?.find { it.id == marketId } ?: throw ParsingException( - ParsingErrorType.MissingRequiredData, - "no open position for $marketId", - ) - val positionSize = position.size?.current + val position = subaccount.openPositions?.find { it.id == marketId } + val positionSize = position?.size?.current fun updateTriggerOrder(triggerOrder: TriggerOrder) { // Cases @@ -2298,6 +2295,12 @@ open class StateManagerAdaptor( } } + internal open fun fromSlTpParams(fromSlTp: Boolean): IMap { + return iMapOf( + "fromSlTp" to fromSlTp, + ) + } + internal open fun trackingParams(interval: Double): IMap { return iMapOf( "roundtripMs" to interval, @@ -2333,14 +2336,14 @@ open class StateManagerAdaptor( if (placeOrderRecord != null) { val interval = Clock.System.now().toEpochMilliseconds() .toDouble() - placeOrderRecord.timestampInMilliseconds + val extraParams = ParsingHelper.merge( + trackingParams(interval), + fromSlTpParams(placeOrderRecord.fromSlTp), + ) tracking( - if (placeOrderRecord.isTriggerOrder) { - AnalyticsEvent.TriggerPlaceOrderConfirmed.rawValue - } else { - AnalyticsEvent.TradePlaceOrderConfirmed.rawValue - }, + AnalyticsEvent.TradePlaceOrderConfirmed.rawValue, ParsingHelper.merge( - trackingParams(interval), + extraParams, orderAnalyticsPayload, )?.toIMap(), ) @@ -2353,14 +2356,14 @@ open class StateManagerAdaptor( if (cancelOrderRecord != null) { val interval = Clock.System.now().toEpochMilliseconds() .toDouble() - cancelOrderRecord.timestampInMilliseconds + val extraParams = ParsingHelper.merge( + trackingParams(interval), + fromSlTpParams(cancelOrderRecord.fromSlTp), + ) tracking( - if (cancelOrderRecord.isTriggerOrder) { - AnalyticsEvent.TriggerCancelOrderConfirmed.rawValue - } else { - AnalyticsEvent.TradeCancelOrderConfirmed.rawValue - }, + AnalyticsEvent.TradeCancelOrderConfirmed.rawValue, ParsingHelper.merge( - trackingParams(interval), + extraParams, orderAnalyticsPayload, )?.toIMap(), ) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt index ce397d966..6ead8fad2 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt @@ -1008,12 +1008,9 @@ class V4StateManagerAdaptor( val clientId = payload.clientId val string = Json.encodeToString(payload) val marketId = payload.marketId + val position = stateMachine.state?.subaccount(subaccountNumber)?.openPositions?.find { it.id == marketId } - ?: throw ParsingException( - ParsingErrorType.MissingRequiredData, - "no open position for $marketId", - ) - val positionSize = position.size?.current + val positionSize = position?.size?.current stopWatchingLastOrder() @@ -1021,21 +1018,21 @@ class V4StateManagerAdaptor( TransactionType.PlaceOrder, string, onSubmitTransaction = { - val submitTimeMs = trackOrderSubmit(uiClickTimeMs, analyticsPayload, isTriggerOrder) + val submitTimeMs = trackOrderSubmit(uiClickTimeMs, analyticsPayload) ioImplementations.threading?.async(ThreadingType.abacus) { this.placeOrderRecords.add( PlaceOrderRecord( subaccountNumber, clientId, submitTimeMs, - isTriggerOrder, + fromSlTp = isTriggerOrder, ), ) } }, transactionCallback = { response: String? -> val error = parseTransactionResponse(response) - trackOrderSubmitted(error, analyticsPayload, isTriggerOrder) + trackOrderSubmitted(error, analyticsPayload) if (error == null) { lastOrderClientId = clientId } else { @@ -1079,11 +1076,7 @@ class V4StateManagerAdaptor( val string = Json.encodeToString(payload) val position = stateMachine.state?.subaccount(subaccountNumber)?.openPositions?.find { it.id == marketId } - ?: throw ParsingException( - ParsingErrorType.MissingRequiredData, - "no open position for $marketId", - ) - val positionSize = position.size?.current + val positionSize = position?.size?.current val isShortTermOrder = payload.orderFlags == 0 @@ -1093,21 +1086,21 @@ class V4StateManagerAdaptor( TransactionType.CancelOrder, string, onSubmitTransaction = { - val submitTimeMs = trackOrderSubmit(uiClickTimeMs, analyticsPayload, isTriggerOrder, true) + val submitTimeMs = trackOrderSubmit(uiClickTimeMs, analyticsPayload, true) ioImplementations.threading?.async(ThreadingType.abacus) { this.cancelOrderRecords.add( CancelOrderRecord( subaccountNumber, clientId, submitTimeMs, - isTriggerOrder, + fromSlTp = isTriggerOrder, ), ) } }, transactionCallback = { response: String? -> val error = parseTransactionResponse(response) - trackOrderSubmitted(error, analyticsPayload, isTriggerOrder, true) + trackOrderSubmitted(error, analyticsPayload, true) if (error == null) { this.orderCanceled(orderId) } else { @@ -1151,28 +1144,14 @@ class V4StateManagerAdaptor( private fun trackOrderSubmit( uiClickTimeMs: Double, analyticsPayload: IMap?, - isTriggerOrder: Boolean, isCancel: Boolean = false ): Double { val submitTimeMs = Clock.System.now().toEpochMilliseconds().toDouble() val uiDelayTimeMs = submitTimeMs - uiClickTimeMs tracking( - if (isCancel) { - if (isTriggerOrder) { - AnalyticsEvent.TriggerCancelOrder.rawValue - } else { - AnalyticsEvent.TradeCancelOrder.rawValue - } - } else { - if (isTriggerOrder) { - AnalyticsEvent.TriggerPlaceOrder.rawValue - } else { - AnalyticsEvent.TradePlaceOrder.rawValue - } - }, - ParsingHelper.merge(uiTrackingParams(uiDelayTimeMs), analyticsPayload) - ?.toIMap(), + if (isCancel) AnalyticsEvent.TradeCancelOrder.rawValue else AnalyticsEvent.TradePlaceOrder.rawValue, + ParsingHelper.merge(uiTrackingParams(uiDelayTimeMs), analyticsPayload)?.toIMap(), ) return submitTimeMs @@ -1181,41 +1160,16 @@ class V4StateManagerAdaptor( private fun trackOrderSubmitted( error: ParsingError?, analyticsPayload: IMap?, - isTriggerOrder: Boolean, isCancel: Boolean = false, ) { if (error != null) { tracking( - if (isCancel) { - if (isTriggerOrder) { - AnalyticsEvent.TriggerCancelOrderSubmissionFailed.rawValue - } else { - AnalyticsEvent.TradeCancelOrderSubmissionFailed.rawValue - } - } else { - if (isTriggerOrder) { - AnalyticsEvent.TriggerPlaceOrderSubmissionFailed.rawValue - } else { - AnalyticsEvent.TradePlaceOrderSubmissionFailed.rawValue - } - }, + if (isCancel) AnalyticsEvent.TradeCancelOrderSubmissionFailed.rawValue else AnalyticsEvent.TradePlaceOrderSubmissionFailed.rawValue, ParsingHelper.merge(errorTrackingParams(error), analyticsPayload)?.toIMap(), ) } else { tracking( - if (isCancel) { - if (isTriggerOrder) { - AnalyticsEvent.TriggerCancelOrderSubmissionConfirmed.rawValue - } else { - AnalyticsEvent.TradeCancelOrderSubmissionConfirmed.rawValue - } - } else { - if (isTriggerOrder) { - AnalyticsEvent.TriggerPlaceOrderSubmissionConfirmed.rawValue - } else { - AnalyticsEvent.TradePlaceOrderSubmissionConfirmed.rawValue - } - }, + if (isCancel) AnalyticsEvent.TradeCancelOrderSubmissionConfirmed.rawValue else AnalyticsEvent.TradePlaceOrderSubmissionConfirmed.rawValue, analyticsPayload, ) } @@ -1224,7 +1178,7 @@ class V4StateManagerAdaptor( override fun commitPlaceOrder(callback: TransactionCallback): HumanReadablePlaceOrderPayload { val payload = placeOrderPayload() val midMarketPrice = stateMachine.state?.marketOrderbook(payload.marketId)?.midPrice - val analyticsPayload = analyticsUtils.placeOrderAnalyticsPayload(payload, midMarketPrice) + val analyticsPayload = analyticsUtils.placeOrderAnalyticsPayload(payload, midMarketPrice, fromSlTp = false, isClosePosition = false) val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TradePlaceOrderClick) return submitPlaceOrder(callback, payload, analyticsPayload, uiClickTimeMs) @@ -1233,7 +1187,7 @@ class V4StateManagerAdaptor( override fun commitClosePosition(callback: TransactionCallback): HumanReadablePlaceOrderPayload { val payload = closePositionPayload() val midMarketPrice = stateMachine.state?.marketOrderbook(payload.marketId)?.midPrice - val analyticsPayload = analyticsUtils.placeOrderAnalyticsPayload(payload, midMarketPrice, true) + val analyticsPayload = analyticsUtils.placeOrderAnalyticsPayload(payload, midMarketPrice, fromSlTp = false, isClosePosition = true) val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TradePlaceOrderClick) return submitPlaceOrder(callback, payload, analyticsPayload, uiClickTimeMs) @@ -1250,6 +1204,7 @@ class V4StateManagerAdaptor( val analyticsPayload = analyticsUtils.cancelOrderAnalyticsPayload( payload, existingOrder, + fromSlTp = false, ) val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TradeCancelOrderClick) @@ -1274,6 +1229,7 @@ class V4StateManagerAdaptor( val cancelOrderAnalyticsPayload = analyticsUtils.cancelOrderAnalyticsPayload( cancelPayload, existingOrder, + fromSlTp = true, ) submitCancelOrder( cancelPayload.orderId, @@ -1291,6 +1247,8 @@ class V4StateManagerAdaptor( val placeOrderAnalyticsPayload = analyticsUtils.placeOrderAnalyticsPayload( placePayload, midMarketPrice, + fromSlTp = true, + isClosePosition = false, ) submitPlaceOrder(callback, placePayload, placeOrderAnalyticsPayload, uiClickTimeMs, true) } diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/utils/Payloads.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/utils/Payloads.kt index d879d2b07..05d94be47 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/utils/Payloads.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/utils/Payloads.kt @@ -18,14 +18,14 @@ data class PlaceOrderRecord( val subaccountNumber: Int, val clientId: Int, val timestampInMilliseconds: Double, - val isTriggerOrder: Boolean, + val fromSlTp: Boolean, ) data class CancelOrderRecord( val subaccountNumber: Int, val clientId: Int, val timestampInMilliseconds: Double, - val isTriggerOrder: Boolean, + val fromSlTp: Boolean, ) @JsExport diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt index 4504dcfa9..ad0f5b3c8 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt @@ -305,14 +305,14 @@ internal class SubaccountSupervisor( if (placeOrderRecord != null) { val interval = Clock.System.now().toEpochMilliseconds() .toDouble() - placeOrderRecord.timestampInMilliseconds + val extraParams = ParsingHelper.merge( + trackingParams(interval), + fromSlTpParams(placeOrderRecord.fromSlTp), + ) tracking( - if (placeOrderRecord.isTriggerOrder) { - AnalyticsEvent.TriggerPlaceOrderConfirmed.rawValue - } else { - AnalyticsEvent.TradePlaceOrderConfirmed.rawValue - }, + AnalyticsEvent.TradePlaceOrderConfirmed.rawValue, ParsingHelper.merge( - trackingParams(interval), + extraParams, orderAnalyticsPayload, )?.toIMap(), ) @@ -325,14 +325,14 @@ internal class SubaccountSupervisor( if (cancelOrderRecord != null) { val interval = Clock.System.now().toEpochMilliseconds() .toDouble() - cancelOrderRecord.timestampInMilliseconds + val extraParams = ParsingHelper.merge( + trackingParams(interval), + fromSlTpParams(cancelOrderRecord.fromSlTp), + ) tracking( - if (cancelOrderRecord.isTriggerOrder) { - AnalyticsEvent.TriggerCancelOrderConfirmed.rawValue - } else { - AnalyticsEvent.TradeCancelOrderConfirmed.rawValue - }, + AnalyticsEvent.TradeCancelOrderConfirmed.rawValue, ParsingHelper.merge( - trackingParams(interval), + extraParams, orderAnalyticsPayload, )?.toIMap(), ) @@ -343,6 +343,12 @@ internal class SubaccountSupervisor( } } + private fun fromSlTpParams(fromSlTp: Boolean): IMap { + return iMapOf( + "fromSlTp" to fromSlTp, + ) + } + private fun trackingParams(interval: Double): IMap { return iMapOf( "roundtripMs" to interval, @@ -547,11 +553,7 @@ internal class SubaccountSupervisor( val marketId = payload.marketId val position = stateMachine.state?.subaccount(subaccountNumber)?.openPositions?.find { it.id == marketId } - ?: throw ParsingException( - ParsingErrorType.MissingRequiredData, - "no open position for $marketId", - ) - val positionSize = position.size?.current + val positionSize = position?.size?.current val isShortTermOrder = when (payload.type) { "MARKET" -> true @@ -568,14 +570,14 @@ internal class SubaccountSupervisor( val useTransactionQueue = !isShortTermOrder val onSubmitOrderTransaction = { - val submitTimeMs = trackOrderSubmit(uiClickTimeMs, analyticsPayload, isTriggerOrder) + val submitTimeMs = trackOrderSubmit(uiClickTimeMs, analyticsPayload) helper.ioImplementations.threading?.async(ThreadingType.abacus) { this.placeOrderRecords.add( PlaceOrderRecord( subaccountNumber, clientId, submitTimeMs, - isTriggerOrder, + fromSlTp = isTriggerOrder, ), ) } @@ -583,7 +585,7 @@ internal class SubaccountSupervisor( val orderTransactionCallback = { response: String? -> val error = parseTransactionResponse(response) - trackOrderSubmitted(error, analyticsPayload, isTriggerOrder) + trackOrderSubmitted(error, analyticsPayload) if (error == null) { lastOrderClientId = clientId } else { @@ -663,28 +665,14 @@ internal class SubaccountSupervisor( private fun trackOrderSubmit( uiClickTimeMs: Double, analyticsPayload: IMap?, - isTriggerOrder: Boolean, isCancel: Boolean = false ): Double { val submitTimeMs = Clock.System.now().toEpochMilliseconds().toDouble() val uiDelayTimeMs = submitTimeMs - uiClickTimeMs tracking( - if (isCancel) { - if (isTriggerOrder) { - AnalyticsEvent.TriggerCancelOrder.rawValue - } else { - AnalyticsEvent.TradeCancelOrder.rawValue - } - } else { - if (isTriggerOrder) { - AnalyticsEvent.TriggerPlaceOrder.rawValue - } else { - AnalyticsEvent.TradePlaceOrder.rawValue - } - }, - ParsingHelper.merge(uiTrackingParams(uiDelayTimeMs), analyticsPayload) - ?.toIMap(), + if (isCancel) AnalyticsEvent.TradeCancelOrder.rawValue else AnalyticsEvent.TradePlaceOrder.rawValue, + ParsingHelper.merge(uiTrackingParams(uiDelayTimeMs), analyticsPayload)?.toIMap(), ) return submitTimeMs @@ -693,41 +681,16 @@ internal class SubaccountSupervisor( private fun trackOrderSubmitted( error: ParsingError?, analyticsPayload: IMap?, - isTriggerOrder: Boolean, isCancel: Boolean = false, ) { if (error != null) { tracking( - if (isCancel) { - if (isTriggerOrder) { - AnalyticsEvent.TriggerCancelOrderSubmissionFailed.rawValue - } else { - AnalyticsEvent.TradeCancelOrderSubmissionFailed.rawValue - } - } else { - if (isTriggerOrder) { - AnalyticsEvent.TriggerPlaceOrderSubmissionFailed.rawValue - } else { - AnalyticsEvent.TradePlaceOrderSubmissionFailed.rawValue - } - }, + if (isCancel) AnalyticsEvent.TradeCancelOrderSubmissionFailed.rawValue else AnalyticsEvent.TradePlaceOrderSubmissionFailed.rawValue, ParsingHelper.merge(errorTrackingParams(error), analyticsPayload)?.toIMap(), ) } else { tracking( - if (isCancel) { - if (isTriggerOrder) { - AnalyticsEvent.TriggerCancelOrderSubmissionConfirmed.rawValue - } else { - AnalyticsEvent.TradeCancelOrderSubmissionConfirmed.rawValue - } - } else { - if (isTriggerOrder) { - AnalyticsEvent.TriggerPlaceOrderSubmissionConfirmed.rawValue - } else { - AnalyticsEvent.TradePlaceOrderSubmissionConfirmed.rawValue - } - }, + if (isCancel) AnalyticsEvent.TradeCancelOrderSubmissionConfirmed.rawValue else AnalyticsEvent.TradePlaceOrderSubmissionConfirmed.rawValue, analyticsPayload, ) } @@ -746,11 +709,7 @@ internal class SubaccountSupervisor( val string = Json.encodeToString(payload) val position = stateMachine.state?.subaccount(subaccountNumber)?.openPositions?.find { it.id == marketId } - ?: throw ParsingException( - ParsingErrorType.MissingRequiredData, - "no open position for $marketId", - ) - val positionSize = position.size?.current + val positionSize = position?.size?.current stopWatchingLastOrder() @@ -760,21 +719,21 @@ internal class SubaccountSupervisor( TransactionType.CancelOrder, string, onSubmitTransaction = { - val submitTimeMs = trackOrderSubmit(uiClickTimeMs, analyticsPayload, isTriggerOrder, true) + val submitTimeMs = trackOrderSubmit(uiClickTimeMs, analyticsPayload, true) helper.ioImplementations.threading?.async(ThreadingType.abacus) { this.cancelOrderRecords.add( CancelOrderRecord( subaccountNumber, clientId, submitTimeMs, - isTriggerOrder, + fromSlTp = isTriggerOrder, ), ) } }, transactionCallback = { response: String? -> val error = parseTransactionResponse(response) - trackOrderSubmitted(error, analyticsPayload, isTriggerOrder, true) + trackOrderSubmitted(error, analyticsPayload, true) if (error == null) { this.orderCanceled(orderId) } else { @@ -810,7 +769,7 @@ internal class SubaccountSupervisor( ): HumanReadablePlaceOrderPayload { val orderPayload = placeOrderPayload(currentHeight) val midMarketPrice = stateMachine.state?.marketOrderbook(orderPayload.marketId)?.midPrice - val analyticsPayload = analyticsUtils.placeOrderAnalyticsPayload(orderPayload, midMarketPrice, false) + val analyticsPayload = analyticsUtils.placeOrderAnalyticsPayload(orderPayload, midMarketPrice, fromSlTp = false, isClosePosition = false) val isIsolatedMarginOrder = helper.parser.asInt(orderPayload.subaccountNumber) != subaccountNumber val transferPayload = @@ -826,7 +785,7 @@ internal class SubaccountSupervisor( ): HumanReadablePlaceOrderPayload { val payload = closePositionPayload(currentHeight) val midMarketPrice = stateMachine.state?.marketOrderbook(payload.marketId)?.midPrice - val analyticsPayload = analyticsUtils.placeOrderAnalyticsPayload(payload, midMarketPrice, true) + val analyticsPayload = analyticsUtils.placeOrderAnalyticsPayload(payload, midMarketPrice, fromSlTp = false, isClosePosition = true) val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TradePlaceOrderClick) return submitPlaceOrder(callback, payload, analyticsPayload, uiClickTimeMs) @@ -840,7 +799,7 @@ internal class SubaccountSupervisor( "no existing order to be cancelled for $orderId", ) val marketId = existingOrder.marketId - val analyticsPayload = analyticsUtils.cancelOrderAnalyticsPayload(payload, existingOrder) + val analyticsPayload = analyticsUtils.cancelOrderAnalyticsPayload(payload, existingOrder, fromSlTp = false) val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TradeCancelOrderClick) return submitCancelOrder(orderId, marketId, callback, payload, analyticsPayload, uiClickTimeMs) @@ -867,6 +826,7 @@ internal class SubaccountSupervisor( val cancelOrderAnalyticsPayload = analyticsUtils.cancelOrderAnalyticsPayload( cancelPayload, existingOrder, + fromSlTp = true, ) submitCancelOrder( cancelPayload.orderId, @@ -884,6 +844,8 @@ internal class SubaccountSupervisor( val placeOrderAnalyticsPayload = analyticsUtils.placeOrderAnalyticsPayload( placePayload, midMarketPrice, + fromSlTp = true, + isClosePosition = false, ) submitPlaceOrder(callback, placePayload, placeOrderAnalyticsPayload, uiClickTimeMs, true) } @@ -1063,11 +1025,7 @@ internal class SubaccountSupervisor( val subaccount = stateMachine.state?.subaccount(subaccountNumber) val position = subaccount?.openPositions?.find { it.id == marketId } - ?: throw ParsingException( - ParsingErrorType.MissingRequiredData, - "no open position for $marketId", - ) - val positionSize = position.size?.current + val positionSize = position?.size?.current fun updateTriggerOrder(triggerOrder: TriggerOrder) { // Cases diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt b/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt index 5f07be767..8079afd79 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt @@ -42,14 +42,21 @@ class AnalyticsUtils { val stopLossOrderTypes = listOf(OrderType.stopMarket, OrderType.stopLimit) val takeProfitOrderTypes = listOf(OrderType.takeProfitMarket, OrderType.takeProfitLimit) + var stopLossOrderCancelClientId: Int? = null + var stopLossOrderPlaceClientId: Int? = null + var takeProfitOrderCancelClientId: Int? = null + var takeProfitOrderPlaceClientId: Int? = null + var stopLossOrderAction: TriggerOrderAction? = null var takeProfitOrderAction: TriggerOrderAction? = null placeOrderPayloads.forEach { placePayload -> val orderType = OrderType.invoke(placePayload.type) if (stopLossOrderTypes.contains(orderType)) { + stopLossOrderPlaceClientId = placePayload.clientId stopLossOrderAction = TriggerOrderAction.CREATE } else if (takeProfitOrderTypes.contains(orderType)) { + takeProfitOrderPlaceClientId = placePayload.clientId takeProfitOrderAction = TriggerOrderAction.CREATE } } @@ -57,12 +64,14 @@ class AnalyticsUtils { cancelOrderPayloads.forEach { cancelPayload -> val orderType = OrderType.invoke(cancelPayload.type) if (stopLossOrderTypes.contains(orderType)) { + stopLossOrderCancelClientId = cancelPayload.clientId stopLossOrderAction = if (stopLossOrderAction == null) { TriggerOrderAction.CANCEL } else { TriggerOrderAction.REPLACE } } else if (takeProfitOrderTypes.contains(orderType)) { + takeProfitOrderCancelClientId = cancelPayload.clientId takeProfitOrderAction = if (takeProfitOrderAction == null) { TriggerOrderAction.CANCEL } else { @@ -75,7 +84,11 @@ class AnalyticsUtils { "marketId" to payload.marketId, "positionSize" to payload.positionSize, "stopLossOrderAction" to stopLossOrderAction?.rawValue, + "stopLossOrderCancelClientId" to stopLossOrderCancelClientId, + "stopLossOrderPlaceClientId" to stopLossOrderPlaceClientId, "takeProfitOrderAction" to takeProfitOrderAction?.rawValue, + "takeProfitOrderCancelClientId" to takeProfitOrderCancelClientId, + "takeProfitOrderPlaceClientId" to takeProfitOrderPlaceClientId, ) as IMap? } @@ -88,10 +101,11 @@ class AnalyticsUtils { fun placeOrderAnalyticsPayload( payload: HumanReadablePlaceOrderPayload, midMarketPrice: Double?, + fromSlTp: Boolean? = false, isClosePosition: Boolean? = false, ): IMap? { return ParsingHelper.merge( - formatPlaceOrderPayload(payload, isClosePosition), + formatPlaceOrderPayload(payload, fromSlTp, isClosePosition), iMapOf( "inferredTimeInForce" to calculateOrderTimeInForce(payload), "midMarketPrice" to midMarketPrice, @@ -106,6 +120,7 @@ class AnalyticsUtils { */ private fun formatPlaceOrderPayload( payload: HumanReadablePlaceOrderPayload, + fromSlTp: Boolean? = false, isClosePosition: Boolean? = false, ): IMap? { return iMapOf( @@ -114,6 +129,7 @@ class AnalyticsUtils { "execution" to payload.execution, "goodTilTimeInSeconds" to payload.goodTilTimeInSeconds, "goodTilBlock" to payload.goodTilBlock, + "fromSlTp" to fromSlTp, "isClosePosition" to isClosePosition, "marketId" to payload.marketId, "postOnly" to payload.postOnly, @@ -164,15 +180,17 @@ class AnalyticsUtils { fun cancelOrderAnalyticsPayload( payload: HumanReadableCancelOrderPayload, existingOrder: SubaccountOrder?, + fromSlTp: Boolean? = false, ): IMap? { return ParsingHelper.merge( - formatCancelOrderPayload(payload), + formatCancelOrderPayload(payload, fromSlTp), if (existingOrder != null) formatOrder(existingOrder) else mapOf(), )?.toIMap() } private fun formatCancelOrderPayload( payload: HumanReadableCancelOrderPayload, + fromSlTp: Boolean? = false, ): IMap? { return iMapOf( "subaccountNumber" to payload.subaccountNumber, @@ -182,6 +200,7 @@ class AnalyticsUtils { "clobPairId" to payload.clobPairId, "goodTilBlock" to payload.goodTilBlock, "goodTilBlockTime" to payload.goodTilBlockTime, + "fromSlTp" to fromSlTp, ) as IMap? } From 77b47434c8e897827286fad2d155fb2e46d5ee5d Mon Sep 17 00:00:00 2001 From: mulan xia Date: Tue, 30 Apr 2024 16:30:03 -0400 Subject: [PATCH 07/10] review comments --- .../state/manager/StateManagerAdaptor.kt | 7 +++---- .../state/manager/V4StateManagerAdaptor.kt | 2 +- .../state/v2/supervisor/NetworkSupervisor.kt | 2 +- .../state/v2/supervisor/SubaccountSupervisor.kt | 7 +++---- .../exchange.dydx.abacus/utils/AnalyticsUtils.kt | 13 ++++--------- 5 files changed, 12 insertions(+), 19 deletions(-) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt index 29c12e751..6fa4398a6 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt @@ -1876,10 +1876,9 @@ open class StateManagerAdaptor( fun triggerOrdersPayload(): HumanReadableTriggerOrdersPayload { val placeOrderPayloads = mutableListOf() val cancelOrderPayloads = mutableListOf() - val triggerOrders = stateMachine.state?.input?.triggerOrders - - val marketId = triggerOrders?.marketId ?: throw Exception("marketId is null") + val triggerOrders = requireNotNull(stateMachine.state?.input?.triggerOrders) { "triggerOrders input was null" } + val marketId = requireNotNull(triggerOrders.marketId) { "triggerOrders.marektId was null" } val subaccountNumber = connectedSubaccountNumber ?: throw Exception("subaccountNumber is null") val subaccount = stateMachine.state?.subaccount(subaccountNumber) ?: throw Exception("subaccount is null") val position = subaccount.openPositions?.find { it.id == marketId } @@ -2307,7 +2306,7 @@ open class StateManagerAdaptor( ) } - internal fun tracking(eventName: String, params: IMap?) { + internal fun tracking(eventName: String, params: IMap?) { val paramsAsString = jsonEncoder.encode(params) ioImplementations.threading?.async(ThreadingType.main) { ioImplementations.tracking?.log(eventName, paramsAsString) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt index 6ead8fad2..b779c1952 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt @@ -1130,7 +1130,7 @@ class V4StateManagerAdaptor( } private fun trackOrderClick( - analyticsPayload: IMap?, + analyticsPayload: IMap?, analyticsEvent: AnalyticsEvent, ): Double { val uiClickTimeMs = Clock.System.now().toEpochMilliseconds().toDouble() diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/NetworkSupervisor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/NetworkSupervisor.kt index 8748551d4..475a8a847 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/NetworkSupervisor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/NetworkSupervisor.kt @@ -81,7 +81,7 @@ internal open class NetworkSupervisor( } } - internal fun tracking(eventName: String, params: IMap?) { + internal fun tracking(eventName: String, params: IMap?) { val paramsAsString = helper.jsonEncoder.encode(params) helper.ioImplementations.threading?.async(ThreadingType.main) { helper.ioImplementations.tracking?.log(eventName, paramsAsString) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt index ad0f5b3c8..663f2fe1c 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt @@ -651,7 +651,7 @@ internal class SubaccountSupervisor( } private fun trackOrderClick( - analyticsPayload: IMap?, + analyticsPayload: IMap?, analyticsEvent: AnalyticsEvent, ): Double { val uiClickTimeMs = Clock.System.now().toEpochMilliseconds().toDouble() @@ -1019,10 +1019,9 @@ internal class SubaccountSupervisor( fun triggerOrdersPayload(currentHeight: Int?): HumanReadableTriggerOrdersPayload { val placeOrderPayloads = mutableListOf() val cancelOrderPayloads = mutableListOf() - val triggerOrders = stateMachine.state?.input?.triggerOrders - - val marketId = triggerOrders?.marketId ?: throw Exception("marketId is null") + val triggerOrders = requireNotNull(stateMachine.state?.input?.triggerOrders) { "triggerOrders input was null" } + val marketId = requireNotNull(triggerOrders.marketId) { "triggerOrders.marketId was null" } val subaccount = stateMachine.state?.subaccount(subaccountNumber) val position = subaccount?.openPositions?.find { it.id == marketId } val positionSize = position?.size?.current diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt b/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt index 8079afd79..c64b73ee0 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt @@ -16,11 +16,6 @@ enum class TriggerOrderAction(val rawValue: String) { CANCEL("CANCEL"), CREATE("CREATE"), ; - - companion object { - operator fun invoke(rawValue: String?) = - TriggerOrderAction.values().firstOrNull { it.rawValue == rawValue } - } } class AnalyticsUtils { @@ -35,7 +30,7 @@ class AnalyticsUtils { */ fun triggerOrdersAnalyticsPayload( payload: HumanReadableTriggerOrdersPayload, - ): IMap? { + ): IMap? { val placeOrderPayloads = payload.placeOrderPayloads val cancelOrderPayloads = payload.cancelOrderPayloads @@ -51,7 +46,7 @@ class AnalyticsUtils { var takeProfitOrderAction: TriggerOrderAction? = null placeOrderPayloads.forEach { placePayload -> - val orderType = OrderType.invoke(placePayload.type) + val orderType = OrderType(placePayload.type) if (stopLossOrderTypes.contains(orderType)) { stopLossOrderPlaceClientId = placePayload.clientId stopLossOrderAction = TriggerOrderAction.CREATE @@ -62,7 +57,7 @@ class AnalyticsUtils { } cancelOrderPayloads.forEach { cancelPayload -> - val orderType = OrderType.invoke(cancelPayload.type) + val orderType = OrderType(cancelPayload.type) if (stopLossOrderTypes.contains(orderType)) { stopLossOrderCancelClientId = cancelPayload.clientId stopLossOrderAction = if (stopLossOrderAction == null) { @@ -89,7 +84,7 @@ class AnalyticsUtils { "takeProfitOrderAction" to takeProfitOrderAction?.rawValue, "takeProfitOrderCancelClientId" to takeProfitOrderCancelClientId, "takeProfitOrderPlaceClientId" to takeProfitOrderPlaceClientId, - ) as IMap? + ) } /** From d9311ee82f7bcfe49a9307a5f303c9e7f35cbdc3 Mon Sep 17 00:00:00 2001 From: mulan xia Date: Tue, 30 Apr 2024 16:46:49 -0400 Subject: [PATCH 08/10] rename fromSlTp to fromSlTpDialog --- .../state/manager/StateManagerAdaptor.kt | 8 +++---- .../state/manager/V4StateManagerAdaptor.kt | 14 ++++++------ .../state/manager/utils/Payloads.kt | 4 ++-- .../v2/supervisor/SubaccountSupervisor.kt | 22 +++++++++---------- .../utils/AnalyticsUtils.kt | 16 +++++++------- 5 files changed, 32 insertions(+), 32 deletions(-) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt index 6fa4398a6..e5b8b27c0 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/StateManagerAdaptor.kt @@ -2294,9 +2294,9 @@ open class StateManagerAdaptor( } } - internal open fun fromSlTpParams(fromSlTp: Boolean): IMap { + internal open fun fromSlTpDialogParams(fromSlTpDialog: Boolean): IMap { return iMapOf( - "fromSlTp" to fromSlTp, + "fromSlTpDialog" to fromSlTpDialog, ) } @@ -2337,7 +2337,7 @@ open class StateManagerAdaptor( .toDouble() - placeOrderRecord.timestampInMilliseconds val extraParams = ParsingHelper.merge( trackingParams(interval), - fromSlTpParams(placeOrderRecord.fromSlTp), + fromSlTpDialogParams(placeOrderRecord.fromSlTpDialog), ) tracking( AnalyticsEvent.TradePlaceOrderConfirmed.rawValue, @@ -2357,7 +2357,7 @@ open class StateManagerAdaptor( .toDouble() - cancelOrderRecord.timestampInMilliseconds val extraParams = ParsingHelper.merge( trackingParams(interval), - fromSlTpParams(cancelOrderRecord.fromSlTp), + fromSlTpDialogParams(cancelOrderRecord.fromSlTpDialog), ) tracking( AnalyticsEvent.TradeCancelOrderConfirmed.rawValue, diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt index b779c1952..443a0d5f2 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/V4StateManagerAdaptor.kt @@ -1025,7 +1025,7 @@ class V4StateManagerAdaptor( subaccountNumber, clientId, submitTimeMs, - fromSlTp = isTriggerOrder, + fromSlTpDialog = isTriggerOrder, ), ) } @@ -1093,7 +1093,7 @@ class V4StateManagerAdaptor( subaccountNumber, clientId, submitTimeMs, - fromSlTp = isTriggerOrder, + fromSlTpDialog = isTriggerOrder, ), ) } @@ -1178,7 +1178,7 @@ class V4StateManagerAdaptor( override fun commitPlaceOrder(callback: TransactionCallback): HumanReadablePlaceOrderPayload { val payload = placeOrderPayload() val midMarketPrice = stateMachine.state?.marketOrderbook(payload.marketId)?.midPrice - val analyticsPayload = analyticsUtils.placeOrderAnalyticsPayload(payload, midMarketPrice, fromSlTp = false, isClosePosition = false) + val analyticsPayload = analyticsUtils.placeOrderAnalyticsPayload(payload, midMarketPrice, fromSlTpDialog = false, isClosePosition = false) val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TradePlaceOrderClick) return submitPlaceOrder(callback, payload, analyticsPayload, uiClickTimeMs) @@ -1187,7 +1187,7 @@ class V4StateManagerAdaptor( override fun commitClosePosition(callback: TransactionCallback): HumanReadablePlaceOrderPayload { val payload = closePositionPayload() val midMarketPrice = stateMachine.state?.marketOrderbook(payload.marketId)?.midPrice - val analyticsPayload = analyticsUtils.placeOrderAnalyticsPayload(payload, midMarketPrice, fromSlTp = false, isClosePosition = true) + val analyticsPayload = analyticsUtils.placeOrderAnalyticsPayload(payload, midMarketPrice, fromSlTpDialog = false, isClosePosition = true) val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TradePlaceOrderClick) return submitPlaceOrder(callback, payload, analyticsPayload, uiClickTimeMs) @@ -1204,7 +1204,7 @@ class V4StateManagerAdaptor( val analyticsPayload = analyticsUtils.cancelOrderAnalyticsPayload( payload, existingOrder, - fromSlTp = false, + fromSlTpDialog = false, ) val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TradeCancelOrderClick) @@ -1229,7 +1229,7 @@ class V4StateManagerAdaptor( val cancelOrderAnalyticsPayload = analyticsUtils.cancelOrderAnalyticsPayload( cancelPayload, existingOrder, - fromSlTp = true, + fromSlTpDialog = true, ) submitCancelOrder( cancelPayload.orderId, @@ -1247,7 +1247,7 @@ class V4StateManagerAdaptor( val placeOrderAnalyticsPayload = analyticsUtils.placeOrderAnalyticsPayload( placePayload, midMarketPrice, - fromSlTp = true, + fromSlTpDialog = true, isClosePosition = false, ) submitPlaceOrder(callback, placePayload, placeOrderAnalyticsPayload, uiClickTimeMs, true) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/utils/Payloads.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/utils/Payloads.kt index 05d94be47..5bfac942b 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/utils/Payloads.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/manager/utils/Payloads.kt @@ -18,14 +18,14 @@ data class PlaceOrderRecord( val subaccountNumber: Int, val clientId: Int, val timestampInMilliseconds: Double, - val fromSlTp: Boolean, + val fromSlTpDialog: Boolean, ) data class CancelOrderRecord( val subaccountNumber: Int, val clientId: Int, val timestampInMilliseconds: Double, - val fromSlTp: Boolean, + val fromSlTpDialog: Boolean, ) @JsExport diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt index 663f2fe1c..119926137 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/state/v2/supervisor/SubaccountSupervisor.kt @@ -307,7 +307,7 @@ internal class SubaccountSupervisor( .toDouble() - placeOrderRecord.timestampInMilliseconds val extraParams = ParsingHelper.merge( trackingParams(interval), - fromSlTpParams(placeOrderRecord.fromSlTp), + fromSlTpDialogParams(placeOrderRecord.fromSlTpDialog), ) tracking( AnalyticsEvent.TradePlaceOrderConfirmed.rawValue, @@ -327,7 +327,7 @@ internal class SubaccountSupervisor( .toDouble() - cancelOrderRecord.timestampInMilliseconds val extraParams = ParsingHelper.merge( trackingParams(interval), - fromSlTpParams(cancelOrderRecord.fromSlTp), + fromSlTpDialogParams(cancelOrderRecord.fromSlTpDialog), ) tracking( AnalyticsEvent.TradeCancelOrderConfirmed.rawValue, @@ -343,9 +343,9 @@ internal class SubaccountSupervisor( } } - private fun fromSlTpParams(fromSlTp: Boolean): IMap { + private fun fromSlTpDialogParams(fromSlTpDialog: Boolean): IMap { return iMapOf( - "fromSlTp" to fromSlTp, + "fromSlTpDialog" to fromSlTpDialog, ) } @@ -577,7 +577,7 @@ internal class SubaccountSupervisor( subaccountNumber, clientId, submitTimeMs, - fromSlTp = isTriggerOrder, + fromSlTpDialog = isTriggerOrder, ), ) } @@ -726,7 +726,7 @@ internal class SubaccountSupervisor( subaccountNumber, clientId, submitTimeMs, - fromSlTp = isTriggerOrder, + fromSlTpDialog = isTriggerOrder, ), ) } @@ -769,7 +769,7 @@ internal class SubaccountSupervisor( ): HumanReadablePlaceOrderPayload { val orderPayload = placeOrderPayload(currentHeight) val midMarketPrice = stateMachine.state?.marketOrderbook(orderPayload.marketId)?.midPrice - val analyticsPayload = analyticsUtils.placeOrderAnalyticsPayload(orderPayload, midMarketPrice, fromSlTp = false, isClosePosition = false) + val analyticsPayload = analyticsUtils.placeOrderAnalyticsPayload(orderPayload, midMarketPrice, fromSlTpDialog = false, isClosePosition = false) val isIsolatedMarginOrder = helper.parser.asInt(orderPayload.subaccountNumber) != subaccountNumber val transferPayload = @@ -785,7 +785,7 @@ internal class SubaccountSupervisor( ): HumanReadablePlaceOrderPayload { val payload = closePositionPayload(currentHeight) val midMarketPrice = stateMachine.state?.marketOrderbook(payload.marketId)?.midPrice - val analyticsPayload = analyticsUtils.placeOrderAnalyticsPayload(payload, midMarketPrice, fromSlTp = false, isClosePosition = true) + val analyticsPayload = analyticsUtils.placeOrderAnalyticsPayload(payload, midMarketPrice, fromSlTpDialog = false, isClosePosition = true) val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TradePlaceOrderClick) return submitPlaceOrder(callback, payload, analyticsPayload, uiClickTimeMs) @@ -799,7 +799,7 @@ internal class SubaccountSupervisor( "no existing order to be cancelled for $orderId", ) val marketId = existingOrder.marketId - val analyticsPayload = analyticsUtils.cancelOrderAnalyticsPayload(payload, existingOrder, fromSlTp = false) + val analyticsPayload = analyticsUtils.cancelOrderAnalyticsPayload(payload, existingOrder, fromSlTpDialog = false) val uiClickTimeMs = trackOrderClick(analyticsPayload, AnalyticsEvent.TradeCancelOrderClick) return submitCancelOrder(orderId, marketId, callback, payload, analyticsPayload, uiClickTimeMs) @@ -826,7 +826,7 @@ internal class SubaccountSupervisor( val cancelOrderAnalyticsPayload = analyticsUtils.cancelOrderAnalyticsPayload( cancelPayload, existingOrder, - fromSlTp = true, + fromSlTpDialog = true, ) submitCancelOrder( cancelPayload.orderId, @@ -844,7 +844,7 @@ internal class SubaccountSupervisor( val placeOrderAnalyticsPayload = analyticsUtils.placeOrderAnalyticsPayload( placePayload, midMarketPrice, - fromSlTp = true, + fromSlTpDialog = true, isClosePosition = false, ) submitPlaceOrder(callback, placePayload, placeOrderAnalyticsPayload, uiClickTimeMs, true) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt b/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt index c64b73ee0..839589ce5 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt @@ -96,11 +96,11 @@ class AnalyticsUtils { fun placeOrderAnalyticsPayload( payload: HumanReadablePlaceOrderPayload, midMarketPrice: Double?, - fromSlTp: Boolean? = false, + fromSlTpDialog: Boolean? = false, isClosePosition: Boolean? = false, ): IMap? { return ParsingHelper.merge( - formatPlaceOrderPayload(payload, fromSlTp, isClosePosition), + formatPlaceOrderPayload(payload, fromSlTpDialog, isClosePosition), iMapOf( "inferredTimeInForce" to calculateOrderTimeInForce(payload), "midMarketPrice" to midMarketPrice, @@ -115,7 +115,7 @@ class AnalyticsUtils { */ private fun formatPlaceOrderPayload( payload: HumanReadablePlaceOrderPayload, - fromSlTp: Boolean? = false, + fromSlTpDialog: Boolean? = false, isClosePosition: Boolean? = false, ): IMap? { return iMapOf( @@ -124,7 +124,7 @@ class AnalyticsUtils { "execution" to payload.execution, "goodTilTimeInSeconds" to payload.goodTilTimeInSeconds, "goodTilBlock" to payload.goodTilBlock, - "fromSlTp" to fromSlTp, + "fromSlTpDialog" to fromSlTpDialog, "isClosePosition" to isClosePosition, "marketId" to payload.marketId, "postOnly" to payload.postOnly, @@ -175,17 +175,17 @@ class AnalyticsUtils { fun cancelOrderAnalyticsPayload( payload: HumanReadableCancelOrderPayload, existingOrder: SubaccountOrder?, - fromSlTp: Boolean? = false, + fromSlTpDialog: Boolean? = false, ): IMap? { return ParsingHelper.merge( - formatCancelOrderPayload(payload, fromSlTp), + formatCancelOrderPayload(payload, fromSlTpDialog), if (existingOrder != null) formatOrder(existingOrder) else mapOf(), )?.toIMap() } private fun formatCancelOrderPayload( payload: HumanReadableCancelOrderPayload, - fromSlTp: Boolean? = false, + fromSlTpDialog: Boolean? = false, ): IMap? { return iMapOf( "subaccountNumber" to payload.subaccountNumber, @@ -195,7 +195,7 @@ class AnalyticsUtils { "clobPairId" to payload.clobPairId, "goodTilBlock" to payload.goodTilBlock, "goodTilBlockTime" to payload.goodTilBlockTime, - "fromSlTp" to fromSlTp, + "fromSlTpDialog" to fromSlTpDialog, ) as IMap? } From 815d909a622a07562473593e4076f744d7c4b026 Mon Sep 17 00:00:00 2001 From: mulan xia Date: Tue, 30 Apr 2024 17:02:40 -0400 Subject: [PATCH 09/10] add notation for frunctions --- .../exchange.dydx.abacus/utils/AnalyticsUtils.kt | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt b/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt index 839589ce5..dba6d6502 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/utils/AnalyticsUtils.kt @@ -91,6 +91,7 @@ class AnalyticsUtils { * Format Place Order Payload and add additional details for `TradePlaceOrder` Analytic Events * @param payload HumanReadablePlaceOrderPayload * @param midMarketPrice Double? + * @param fromSlTpDialog Boolean? * @param isClosePosition Boolean? */ fun placeOrderAnalyticsPayload( @@ -111,7 +112,8 @@ class AnalyticsUtils { /** * Format Place Order Payload for `TradePlaceOrder` Analytic Event * @param payload HumanReadablePlaceOrderPayload - * @param isClosePosition Boolean + * @param fromSlTpDialog Boolean? + * @param isClosePosition Boolean? */ private fun formatPlaceOrderPayload( payload: HumanReadablePlaceOrderPayload, @@ -171,6 +173,7 @@ class AnalyticsUtils { * Format Cancel Order Payload and add order details for `TradeCancelOrder` Analytic Events * @param payload HumanReadableCancelOrderPayload * @param existingOrder SubaccountOrder? + * @param fromSlTpDialog Boolean? */ fun cancelOrderAnalyticsPayload( payload: HumanReadableCancelOrderPayload, @@ -183,11 +186,17 @@ class AnalyticsUtils { )?.toIMap() } + /** + * Format Cancel Order Payload for `TradeCancelOrder` Analytic Event + * @param payload HumanReadableCancelOrderPayload + * @param fromSlTpDialog Boolean? + */ private fun formatCancelOrderPayload( payload: HumanReadableCancelOrderPayload, fromSlTpDialog: Boolean? = false, ): IMap? { return iMapOf( + "fromSlTpDialog" to fromSlTpDialog, "subaccountNumber" to payload.subaccountNumber, "clientId" to payload.clientId, "orderId" to payload.orderId, @@ -195,7 +204,6 @@ class AnalyticsUtils { "clobPairId" to payload.clobPairId, "goodTilBlock" to payload.goodTilBlock, "goodTilBlockTime" to payload.goodTilBlockTime, - "fromSlTpDialog" to fromSlTpDialog, ) as IMap? } From ff5deb1c69f2d86daef53715d7e009436e5156ce Mon Sep 17 00:00:00 2001 From: moo-onthelawn <70078372+moo-onthelawn@users.noreply.github.com> Date: Wed, 1 May 2024 10:20:28 -0400 Subject: [PATCH 10/10] bumped time (#330) --- .../calculator/TriggerOrdersInputCalculator.kt | 2 +- .../exchange.dydx.abacus/app/manager/V4TransactionTests.kt | 2 +- .../exchange.dydx.abacus/app/manager/v2/V4TransactionTests.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/commonMain/kotlin/exchange.dydx.abacus/calculator/TriggerOrdersInputCalculator.kt b/src/commonMain/kotlin/exchange.dydx.abacus/calculator/TriggerOrdersInputCalculator.kt index f190d50c3..e24cbcb29 100644 --- a/src/commonMain/kotlin/exchange.dydx.abacus/calculator/TriggerOrdersInputCalculator.kt +++ b/src/commonMain/kotlin/exchange.dydx.abacus/calculator/TriggerOrdersInputCalculator.kt @@ -14,7 +14,7 @@ import exchange.dydx.abacus.utils.safeSet import kotlin.math.abs internal object TriggerOrdersConstants { - const val TRIGGER_ORDER_DEFAULT_DURATION_DAYS = 28.0 + const val TRIGGER_ORDER_DEFAULT_DURATION_DAYS = 90.0 } @Suppress("UNCHECKED_CAST") diff --git a/src/commonTest/kotlin/exchange.dydx.abacus/app/manager/V4TransactionTests.kt b/src/commonTest/kotlin/exchange.dydx.abacus/app/manager/V4TransactionTests.kt index 4607f50b4..23f375ade 100644 --- a/src/commonTest/kotlin/exchange.dydx.abacus/app/manager/V4TransactionTests.kt +++ b/src/commonTest/kotlin/exchange.dydx.abacus/app/manager/V4TransactionTests.kt @@ -221,7 +221,7 @@ class V4TransactionTests : NetworkTests() { fun validateLimitOrderDefaults(payload: HumanReadablePlaceOrderPayload) { assertEquals(payload.execution, "DEFAULT") assertEquals(payload.timeInForce, null) - assertEquals(payload.goodTilTimeInSeconds, 2419200) + assertEquals(payload.goodTilTimeInSeconds, 7776000) assertEquals(payload.reduceOnly, true) assertEquals(payload.postOnly, false) } diff --git a/src/commonTest/kotlin/exchange.dydx.abacus/app/manager/v2/V4TransactionTests.kt b/src/commonTest/kotlin/exchange.dydx.abacus/app/manager/v2/V4TransactionTests.kt index 405ca6a56..207ef6ae8 100644 --- a/src/commonTest/kotlin/exchange.dydx.abacus/app/manager/v2/V4TransactionTests.kt +++ b/src/commonTest/kotlin/exchange.dydx.abacus/app/manager/v2/V4TransactionTests.kt @@ -244,7 +244,7 @@ class V4TransactionTests : NetworkTests() { fun validateLimitOrderDefaults(payload: HumanReadablePlaceOrderPayload) { assertEquals(payload.execution, "DEFAULT") assertEquals(payload.timeInForce, null) - assertEquals(payload.goodTilTimeInSeconds, 2419200) + assertEquals(payload.goodTilTimeInSeconds, 7776000) assertEquals(payload.reduceOnly, true) assertEquals(payload.postOnly, false) }