From 934a882360452e58fc07999f1c64f450eb85d451 Mon Sep 17 00:00:00 2001 From: Peyman Date: Mon, 29 Nov 2021 17:40:44 +0330 Subject: [PATCH 1/3] clean up trade manager --- .../core/service/TradeManagerImpl.kt | 311 ++++++++++-------- 1 file changed, 174 insertions(+), 137 deletions(-) diff --git a/accountant/accountant-core/src/main/kotlin/co/nilin/opex/accountant/core/service/TradeManagerImpl.kt b/accountant/accountant-core/src/main/kotlin/co/nilin/opex/accountant/core/service/TradeManagerImpl.kt index e407b3adb..e10a95670 100644 --- a/accountant/accountant-core/src/main/kotlin/co/nilin/opex/accountant/core/service/TradeManagerImpl.kt +++ b/accountant/accountant-core/src/main/kotlin/co/nilin/opex/accountant/core/service/TradeManagerImpl.kt @@ -3,6 +3,7 @@ package co.nilin.opex.accountant.core.service import co.nilin.opex.accountant.core.api.TradeManager import co.nilin.opex.accountant.core.inout.RichTrade import co.nilin.opex.accountant.core.model.FinancialAction +import co.nilin.opex.accountant.core.model.Order import co.nilin.opex.accountant.core.spi.* import co.nilin.opex.matching.engine.core.eventh.events.TradeEvent import co.nilin.opex.matching.engine.core.model.OrderDirection @@ -12,15 +13,15 @@ import java.math.BigDecimal import java.time.LocalDateTime open class TradeManagerImpl( - val pairStaticRateLoader: PairStaticRateLoader, - val financeActionPersister: FinancialActionPersister, - val financeActionLoader: FinancialActionLoader, - val orderPersister: OrderPersister, - val tempEventPersister: TempEventPersister, - val richTradePublisher: RichTradePublisher, - val walletProxy: WalletProxy, - val platformCoin: String, - val platformAddress: String + private val pairStaticRateLoader: PairStaticRateLoader, + private val financeActionPersister: FinancialActionPersister, + private val financeActionLoader: FinancialActionLoader, + private val orderPersister: OrderPersister, + private val tempEventPersister: TempEventPersister, + private val richTradePublisher: RichTradePublisher, + private val walletProxy: WalletProxy, + private val platformCoin: String, + private val platformAddress: String ) : TradeManager { private val log = LoggerFactory.getLogger(TradeManagerImpl::class.java) @@ -33,6 +34,7 @@ open class TradeManagerImpl( val takerOrder = orderPersister.load(trade.takerOuid) //maker order by ouid val makerOrder = orderPersister.load(trade.makerOuid) + if (takerOrder == null || makerOrder == null) { if (takerOrder == null) { tempEventPersister.saveTempEvent(trade.takerOuid, trade) @@ -42,38 +44,16 @@ open class TradeManagerImpl( } return emptyList() } + //check taker uuid - // //check maker uuid - // - val leftSidePCRate = pairStaticRateLoader.calculateStaticRate(platformCoin, trade.pair.leftSideName) - val rightSidePCRate = pairStaticRateLoader.calculateStaticRate(platformCoin, trade.pair.rightSideName) - val takerMatchedAmount = if (takerOrder.direction == OrderDirection.ASK) { - trade.matchedQuantity.toBigDecimal().multiply(takerOrder.leftSideFraction.toBigDecimal()) - } else { - trade.matchedQuantity.toBigDecimal().multiply(takerOrder.leftSideFraction.toBigDecimal()) - .multiply(trade.makerPrice.toBigDecimal()).multiply(takerOrder.rightSideFraction.toBigDecimal()) - } + val takerMatchedAmount = calculateMatchedAmount(trade, takerOrder) + val takerPCFeeCoefficient = getPCFeeCoefficient(trade, takerOrder) - val takerPCFeeCoefficient: Double = if (takerOrder.direction == OrderDirection.ASK) { - leftSidePCRate ?: 0.0 - } else { - rightSidePCRate ?: 0.0 - } + val makerMatchedAmount = calculateMatchedAmount(trade, makerOrder) + val makerPCFeeCoefficient = getPCFeeCoefficient(trade, makerOrder) - val makerMatchedAmount = if (makerOrder.direction == OrderDirection.ASK) { - trade.matchedQuantity.toBigDecimal().multiply(makerOrder.leftSideFraction.toBigDecimal()) - } else { - trade.matchedQuantity.toBigDecimal().multiply(makerOrder.leftSideFraction.toBigDecimal()) - .multiply(trade.makerPrice.toBigDecimal()).multiply(makerOrder.rightSideFraction.toBigDecimal()) - } - - val makerPCFeeCoefficient: Double = if (makerOrder.direction == OrderDirection.ASK) { - leftSidePCRate ?: 0.0 - } else { - rightSidePCRate ?: 0.0 - } log.info("trade event configs loaded ") //lookup for taker parent fa val takerParentFinancialAction = financeActionLoader.findLast(trade.takerUuid, trade.takerOuid) @@ -85,42 +65,170 @@ open class TradeManagerImpl( //calculate maker fee val makerFee = makerOrder.makerFee - val makerTotalFeeWithPlatformCoin = takerMatchedAmount - .multiply(makerFee.toBigDecimal()) - .multiply(makerPCFeeCoefficient.toBigDecimal()) + val makerTotalFeeWithPlatformCoin = calcFeeWithPlatformCoin(makerMatchedAmount, makerFee, makerPCFeeCoefficient) + //check if maker uuid can pay the fee with platform coin //create fa for transfer taker uuid symbol exchange wallet to maker symbol main wallet /* - amount for sell (ask): match_quantity (if not pay by platform coin then - maker fee) - amount for buy (bid): match_quantity * maker price (if not pay by platform coin then - maker fee) + * amount for sell (ask): match_quantity (if not pay by platform coin then - maker fee) + * amount for buy (bid): match_quantity * maker price (if not pay by platform coin then - maker fee) + */ + val takerTransferAction = + createTransferAction(trade, takerParentFinancialAction, takerOrder, takerMatchedAmount) + log.info("trade event takerTransferAction {}", takerTransferAction) + financialActions.add(takerTransferAction) + + val makerFeeAction = createMakerFeeAction( + trade, + makerParentFinancialAction, + makerTotalFeeWithPlatformCoin, + makerFee, + takerOrder, + takerMatchedAmount + ) + log.info("trade event makerFeeAction {}", makerFeeAction) + financialActions.add(makerFeeAction) + + //update taker order status + takerOrder.remainedTransferAmount -= takerMatchedAmount + if (takerOrder.filledQuantity == takerOrder.quantity) { + takerOrder.status = 1 + } + orderPersister.save(takerOrder) + log.info("taker order saved {}", takerOrder) + + //calculate taker fee + val takerFee = takerOrder.takerFee + val takerTotalFeeWithPlatformCoin = calcFeeWithPlatformCoin(takerMatchedAmount, takerFee, takerPCFeeCoefficient) + + //create fa for transfer makeruuid symbol exchange wallet to taker symbol main wallet + /* + amount for sell (ask): match_quantity (if not pay by platform coin then - taker fee) + amount for buy (bid): match_quantity * maker price (if not pay by platform coin then - taker fee) */ - val takerTransferAction = FinancialAction( + val makerTransferAction = + createTransferAction(trade, makerParentFinancialAction, makerOrder, makerMatchedAmount) + log.info("trade event makerTransferAction {}", makerTransferAction) + financialActions.add(makerTransferAction) + + //check if taker uuid can pay the fee with platform coin + val takerFeeAction = createTakerFeeAction( + trade, takerParentFinancialAction, + takerTotalFeeWithPlatformCoin, + takerFee, + makerOrder, + makerMatchedAmount + ) + + log.info("trade event takerFeeAction {}", takerFeeAction) + financialActions.add(takerFeeAction) + //update maker order status + makerOrder.remainedTransferAmount -= makerMatchedAmount + if (makerOrder.filledQuantity == makerOrder.quantity) { + makerOrder.status = 1 + } + orderPersister.save(makerOrder) + log.info("maker order saved {}", makerOrder) + richTradePublisher.publish( + RichTrade( + trade.tradeId, + trade.pair.toString(), + trade.takerOuid, + trade.takerUuid, + trade.takerOrderId, + trade.takerDirection, + trade.takerPrice.toBigDecimal().multiply(takerOrder.rightSideFraction.toBigDecimal()), + takerOrder.origQuantity, + takerOrder.origPrice.multiply(takerOrder.origQuantity), + trade.takerRemainedQuantity.toBigDecimal().multiply(takerOrder.leftSideFraction.toBigDecimal()), + takerFeeAction.amount, + takerFeeAction.symbol, + trade.makerOuid, + trade.makerUuid, + trade.makerOrderId, + trade.makerDirection, + trade.makerPrice.toBigDecimal().multiply(makerOrder.rightSideFraction.toBigDecimal()), + makerOrder.origQuantity, + makerOrder.origPrice.multiply(makerOrder.origQuantity), + trade.makerRemainedQuantity.toBigDecimal().multiply(makerOrder.leftSideFraction.toBigDecimal()), + makerFeeAction.amount, + makerFeeAction.symbol, + trade.matchedQuantity.toBigDecimal().multiply(makerOrder.leftSideFraction.toBigDecimal()), + trade.eventDate + ) + + ) + return financeActionPersister.persist(financialActions) + } + + private fun calculateMatchedAmount(trade: TradeEvent, order: Order): BigDecimal { + return if (order.direction == OrderDirection.ASK) { + trade.matchedQuantity.toBigDecimal().multiply(order.leftSideFraction.toBigDecimal()) + } else { + trade.matchedQuantity.toBigDecimal().multiply(order.leftSideFraction.toBigDecimal()) + .multiply(trade.makerPrice.toBigDecimal()).multiply(order.rightSideFraction.toBigDecimal()) + } + } + + private suspend fun getPCFeeCoefficient(trade: TradeEvent, order: Order): Double { + val leftSidePCRate = pairStaticRateLoader.calculateStaticRate(platformCoin, trade.pair.leftSideName) + val rightSidePCRate = pairStaticRateLoader.calculateStaticRate(platformCoin, trade.pair.rightSideName) + return if (order.direction == OrderDirection.ASK) { + leftSidePCRate ?: 0.0 + } else { + rightSidePCRate ?: 0.0 + } + } + + private fun calcFeeWithPlatformCoin( + matchedAmount: BigDecimal, + fee: Double, + coefficient: Double + ): BigDecimal { + return matchedAmount.multiply(fee.toBigDecimal()).multiply(coefficient.toBigDecimal()) + } + + private fun createTransferAction( + trade: TradeEvent, + parentAction: FinancialAction?, + order: Order, + matchedAmount: BigDecimal + ): FinancialAction { + return FinancialAction( + parentAction, TradeEvent::class.simpleName!!, trade.takerOuid, - if (takerOrder.direction == OrderDirection.ASK) { + if (order.direction == OrderDirection.ASK) { trade.pair.leftSideName } else { trade.pair.rightSideName }, - takerMatchedAmount, + matchedAmount, trade.takerUuid, "exchange", trade.makerUuid, "main", LocalDateTime.now() ) - log.info("trade event takerTransferAction {}", takerTransferAction) - financialActions.add(takerTransferAction) - val makerFeeAction = if (makerTotalFeeWithPlatformCoin > BigDecimal.ZERO && - walletProxy.canFulfil(platformCoin, "main", trade.makerUuid, makerTotalFeeWithPlatformCoin) - ) { + } + + private suspend fun createMakerFeeAction( + trade: TradeEvent, + parentAction: FinancialAction?, + totalFee: BigDecimal, + makerFee: Double, + takerOrder: Order, + takerMatchedAmount: BigDecimal, + ): FinancialAction { + val canFulfill = walletProxy.canFulfil(platformCoin, "main", trade.makerUuid, totalFee) + return if (totalFee > BigDecimal.ZERO && canFulfill) { FinancialAction( - makerParentFinancialAction, + parentAction, TradeEvent::class.simpleName!!, trade.takerOuid, platformCoin, - makerTotalFeeWithPlatformCoin, + totalFee, trade.makerUuid, "main", platformAddress, @@ -129,7 +237,7 @@ open class TradeManagerImpl( ) } else { FinancialAction( - makerParentFinancialAction, + parentAction, TradeEvent::class.simpleName!!, trade.takerOuid, if (takerOrder.direction == OrderDirection.ASK) { @@ -145,51 +253,20 @@ open class TradeManagerImpl( LocalDateTime.now() ) } - log.info("trade event makerFeeAction {}", makerFeeAction) - financialActions.add(makerFeeAction) - //update taker order status - takerOrder.remainedTransferAmount -= takerMatchedAmount - if (takerOrder.filledQuantity == takerOrder.quantity) { - takerOrder.status = 1 - } - orderPersister.save(takerOrder) - log.info("taker order saved {}", takerOrder) - - //calculate taker fee - val takerFee = takerOrder.takerFee - val takerTotalFeeWithPlatformCoin = takerMatchedAmount - .multiply(takerFee.toBigDecimal()) - .multiply(takerPCFeeCoefficient.toBigDecimal()) + } - //create fa for transfer makeruuid symbol exchange wallet to taker symbol main wallet - /* - amount for sell (ask): match_quantity (if not pay by platform coin then - taker fee) - amount for buy (bid): match_quantity * maker price (if not pay by platform coin then - taker fee) - */ - val makerTransferAction = FinancialAction( - makerParentFinancialAction, - TradeEvent::class.simpleName!!, - trade.makerOuid, - if (makerOrder.direction == OrderDirection.ASK) { - trade.pair.leftSideName - } else { - trade.pair.rightSideName - }, - makerMatchedAmount, - trade.makerUuid, - "exchange", - trade.takerUuid, - "main", - LocalDateTime.now() - ) - log.info("trade event makerTransferAction {}", makerTransferAction) - financialActions.add(makerTransferAction) - //check if taker uuid can pay the fee with platform coin - val takerFeeAction = if (takerTotalFeeWithPlatformCoin > BigDecimal.ZERO && - walletProxy.canFulfil(platformCoin, "main", trade.takerUuid, takerTotalFeeWithPlatformCoin) - ) { + private suspend fun createTakerFeeAction( + trade: TradeEvent, + parentAction: FinancialAction?, + totalFee: BigDecimal, + takerFee: Double, + makerOrder: Order, + makerMatchedAmount: BigDecimal, + ): FinancialAction { + val canFulfill = walletProxy.canFulfil(platformCoin, "main", trade.takerUuid, totalFee) + return if (totalFee > BigDecimal.ZERO && canFulfill) { FinancialAction( - takerParentFinancialAction, + parentAction, TradeEvent::class.simpleName!!, trade.makerOuid, if (makerOrder.direction == OrderDirection.ASK) { @@ -197,7 +274,7 @@ open class TradeManagerImpl( } else { trade.pair.rightSideName }, - takerTotalFeeWithPlatformCoin, + totalFee, trade.takerUuid, "main", platformAddress, @@ -206,7 +283,7 @@ open class TradeManagerImpl( ) } else { FinancialAction( - takerParentFinancialAction, + parentAction, TradeEvent::class.simpleName!!, trade.makerOuid, if (makerOrder.direction == OrderDirection.ASK) { @@ -221,46 +298,6 @@ open class TradeManagerImpl( "exchange", LocalDateTime.now() ) - - } - log.info("trade event takerFeeAction {}", takerFeeAction) - financialActions.add(takerFeeAction) - //update maker order status - makerOrder.remainedTransferAmount -= makerMatchedAmount - if (makerOrder.filledQuantity == makerOrder.quantity) { - makerOrder.status = 1 } - orderPersister.save(makerOrder) - log.info("maker order saved {}", makerOrder) - richTradePublisher.publish( - RichTrade( - trade.tradeId, - trade.pair.toString(), - trade.takerOuid, - trade.takerUuid, - trade.takerOrderId, - trade.takerDirection, - trade.takerPrice.toBigDecimal().multiply(takerOrder.rightSideFraction.toBigDecimal()), - takerOrder.origQuantity, - takerOrder.origPrice.multiply(takerOrder.origQuantity), - trade.takerRemainedQuantity.toBigDecimal().multiply(takerOrder.leftSideFraction.toBigDecimal()), - takerFeeAction.amount, - takerFeeAction.symbol, - trade.makerOuid, - trade.makerUuid, - trade.makerOrderId, - trade.makerDirection, - trade.makerPrice.toBigDecimal().multiply(makerOrder.rightSideFraction.toBigDecimal()), - makerOrder.origQuantity, - makerOrder.origPrice.multiply(makerOrder.origQuantity), - trade.makerRemainedQuantity.toBigDecimal().multiply(makerOrder.leftSideFraction.toBigDecimal()), - makerFeeAction.amount, - makerFeeAction.symbol, - trade.matchedQuantity.toBigDecimal().multiply(makerOrder.leftSideFraction.toBigDecimal()), - trade.eventDate - ) - - ) - return financeActionPersister.persist(financialActions) } } \ No newline at end of file From 46c90d8d55ef8e089e4e32d5f996fdcf55a8016d Mon Sep 17 00:00:00 2001 From: Peyman Date: Tue, 30 Nov 2021 12:22:49 +0330 Subject: [PATCH 2/3] #157: add serializer for event-log and wallet --- .../eventlog/ports/kafka/listener/config/EventlogKafkaConfig.kt | 1 + .../main/kotlin/co/nilin/opex/auth/gateway/config/KafkaConfig.kt | 1 + .../opex/wallet/ports/kafka/listener/config/WalletKafkaConfig.kt | 1 + 3 files changed, 3 insertions(+) diff --git a/eventlog/eventlog-ports/eventlog-eventlistener-kafka/src/main/kotlin/co/nilin/opex/eventlog/ports/kafka/listener/config/EventlogKafkaConfig.kt b/eventlog/eventlog-ports/eventlog-eventlistener-kafka/src/main/kotlin/co/nilin/opex/eventlog/ports/kafka/listener/config/EventlogKafkaConfig.kt index d1b9e8545..d149a2fb0 100644 --- a/eventlog/eventlog-ports/eventlog-eventlistener-kafka/src/main/kotlin/co/nilin/opex/eventlog/ports/kafka/listener/config/EventlogKafkaConfig.kt +++ b/eventlog/eventlog-ports/eventlog-eventlistener-kafka/src/main/kotlin/co/nilin/opex/eventlog/ports/kafka/listener/config/EventlogKafkaConfig.kt @@ -39,6 +39,7 @@ class EventlogKafkaConfig { props[ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG] = StringDeserializer::class.java props[ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG] = JsonDeserializer::class.java props[JsonDeserializer.TRUSTED_PACKAGES] = "co.nilin.opex.*" + props[JsonDeserializer.TYPE_MAPPINGS] = "order_request:co.nilin.opex.eventlog.ports.kafka.listener.inout.OrderSubmitRequest" return props } diff --git a/user-management/keycloak-gateway/src/main/kotlin/co/nilin/opex/auth/gateway/config/KafkaConfig.kt b/user-management/keycloak-gateway/src/main/kotlin/co/nilin/opex/auth/gateway/config/KafkaConfig.kt index d600f89bd..f7c43d672 100644 --- a/user-management/keycloak-gateway/src/main/kotlin/co/nilin/opex/auth/gateway/config/KafkaConfig.kt +++ b/user-management/keycloak-gateway/src/main/kotlin/co/nilin/opex/auth/gateway/config/KafkaConfig.kt @@ -26,6 +26,7 @@ class KafkaConfig { props[ProducerConfig.BOOTSTRAP_SERVERS_CONFIG] = bootstrapServers props[ProducerConfig.KEY_SERIALIZER_CLASS_CONFIG] = StringSerializer::class.java props[ProducerConfig.VALUE_SERIALIZER_CLASS_CONFIG] = JsonSerializer::class.java + props[JsonSerializer.TYPE_MAPPINGS] = "user_created_event:co.nilin.opex.auth.gateway.model.UserCreatedEvent" return props } diff --git a/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/config/WalletKafkaConfig.kt b/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/config/WalletKafkaConfig.kt index 7d48625ef..39d363755 100644 --- a/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/config/WalletKafkaConfig.kt +++ b/wallet/wallet-ports/wallet-eventlistener-kafka/src/main/kotlin/co/nilin/opex/wallet/ports/kafka/listener/config/WalletKafkaConfig.kt @@ -37,6 +37,7 @@ class WalletKafkaConfig { props[ConsumerConfig.KEY_DESERIALIZER_CLASS_CONFIG] = StringDeserializer::class.java props[ConsumerConfig.VALUE_DESERIALIZER_CLASS_CONFIG] = JsonDeserializer::class.java props[JsonDeserializer.TRUSTED_PACKAGES] = "co.nilin.opex.*" + props[JsonDeserializer.TYPE_MAPPINGS] = "user_created_event:co.nilin.opex.wallet.ports.kafka.listener.model.UserCreatedEvent" return props } From 3eb2f859a4dde782454eaedb418c9b3726af6386 Mon Sep 17 00:00:00 2001 From: Peyman Date: Tue, 30 Nov 2021 12:32:47 +0330 Subject: [PATCH 3/3] revert TradeManagerImpl changes --- .../core/service/TradeManagerImpl.kt | 311 ++++++++---------- 1 file changed, 137 insertions(+), 174 deletions(-) diff --git a/accountant/accountant-core/src/main/kotlin/co/nilin/opex/accountant/core/service/TradeManagerImpl.kt b/accountant/accountant-core/src/main/kotlin/co/nilin/opex/accountant/core/service/TradeManagerImpl.kt index e10a95670..e407b3adb 100644 --- a/accountant/accountant-core/src/main/kotlin/co/nilin/opex/accountant/core/service/TradeManagerImpl.kt +++ b/accountant/accountant-core/src/main/kotlin/co/nilin/opex/accountant/core/service/TradeManagerImpl.kt @@ -3,7 +3,6 @@ package co.nilin.opex.accountant.core.service import co.nilin.opex.accountant.core.api.TradeManager import co.nilin.opex.accountant.core.inout.RichTrade import co.nilin.opex.accountant.core.model.FinancialAction -import co.nilin.opex.accountant.core.model.Order import co.nilin.opex.accountant.core.spi.* import co.nilin.opex.matching.engine.core.eventh.events.TradeEvent import co.nilin.opex.matching.engine.core.model.OrderDirection @@ -13,15 +12,15 @@ import java.math.BigDecimal import java.time.LocalDateTime open class TradeManagerImpl( - private val pairStaticRateLoader: PairStaticRateLoader, - private val financeActionPersister: FinancialActionPersister, - private val financeActionLoader: FinancialActionLoader, - private val orderPersister: OrderPersister, - private val tempEventPersister: TempEventPersister, - private val richTradePublisher: RichTradePublisher, - private val walletProxy: WalletProxy, - private val platformCoin: String, - private val platformAddress: String + val pairStaticRateLoader: PairStaticRateLoader, + val financeActionPersister: FinancialActionPersister, + val financeActionLoader: FinancialActionLoader, + val orderPersister: OrderPersister, + val tempEventPersister: TempEventPersister, + val richTradePublisher: RichTradePublisher, + val walletProxy: WalletProxy, + val platformCoin: String, + val platformAddress: String ) : TradeManager { private val log = LoggerFactory.getLogger(TradeManagerImpl::class.java) @@ -34,7 +33,6 @@ open class TradeManagerImpl( val takerOrder = orderPersister.load(trade.takerOuid) //maker order by ouid val makerOrder = orderPersister.load(trade.makerOuid) - if (takerOrder == null || makerOrder == null) { if (takerOrder == null) { tempEventPersister.saveTempEvent(trade.takerOuid, trade) @@ -44,16 +42,38 @@ open class TradeManagerImpl( } return emptyList() } - //check taker uuid + // //check maker uuid + // + val leftSidePCRate = pairStaticRateLoader.calculateStaticRate(platformCoin, trade.pair.leftSideName) + val rightSidePCRate = pairStaticRateLoader.calculateStaticRate(platformCoin, trade.pair.rightSideName) - val takerMatchedAmount = calculateMatchedAmount(trade, takerOrder) - val takerPCFeeCoefficient = getPCFeeCoefficient(trade, takerOrder) + val takerMatchedAmount = if (takerOrder.direction == OrderDirection.ASK) { + trade.matchedQuantity.toBigDecimal().multiply(takerOrder.leftSideFraction.toBigDecimal()) + } else { + trade.matchedQuantity.toBigDecimal().multiply(takerOrder.leftSideFraction.toBigDecimal()) + .multiply(trade.makerPrice.toBigDecimal()).multiply(takerOrder.rightSideFraction.toBigDecimal()) + } - val makerMatchedAmount = calculateMatchedAmount(trade, makerOrder) - val makerPCFeeCoefficient = getPCFeeCoefficient(trade, makerOrder) + val takerPCFeeCoefficient: Double = if (takerOrder.direction == OrderDirection.ASK) { + leftSidePCRate ?: 0.0 + } else { + rightSidePCRate ?: 0.0 + } + val makerMatchedAmount = if (makerOrder.direction == OrderDirection.ASK) { + trade.matchedQuantity.toBigDecimal().multiply(makerOrder.leftSideFraction.toBigDecimal()) + } else { + trade.matchedQuantity.toBigDecimal().multiply(makerOrder.leftSideFraction.toBigDecimal()) + .multiply(trade.makerPrice.toBigDecimal()).multiply(makerOrder.rightSideFraction.toBigDecimal()) + } + + val makerPCFeeCoefficient: Double = if (makerOrder.direction == OrderDirection.ASK) { + leftSidePCRate ?: 0.0 + } else { + rightSidePCRate ?: 0.0 + } log.info("trade event configs loaded ") //lookup for taker parent fa val takerParentFinancialAction = financeActionLoader.findLast(trade.takerUuid, trade.takerOuid) @@ -65,170 +85,42 @@ open class TradeManagerImpl( //calculate maker fee val makerFee = makerOrder.makerFee - val makerTotalFeeWithPlatformCoin = calcFeeWithPlatformCoin(makerMatchedAmount, makerFee, makerPCFeeCoefficient) - + val makerTotalFeeWithPlatformCoin = takerMatchedAmount + .multiply(makerFee.toBigDecimal()) + .multiply(makerPCFeeCoefficient.toBigDecimal()) //check if maker uuid can pay the fee with platform coin //create fa for transfer taker uuid symbol exchange wallet to maker symbol main wallet /* - * amount for sell (ask): match_quantity (if not pay by platform coin then - maker fee) - * amount for buy (bid): match_quantity * maker price (if not pay by platform coin then - maker fee) - */ - val takerTransferAction = - createTransferAction(trade, takerParentFinancialAction, takerOrder, takerMatchedAmount) - log.info("trade event takerTransferAction {}", takerTransferAction) - financialActions.add(takerTransferAction) - - val makerFeeAction = createMakerFeeAction( - trade, - makerParentFinancialAction, - makerTotalFeeWithPlatformCoin, - makerFee, - takerOrder, - takerMatchedAmount - ) - log.info("trade event makerFeeAction {}", makerFeeAction) - financialActions.add(makerFeeAction) - - //update taker order status - takerOrder.remainedTransferAmount -= takerMatchedAmount - if (takerOrder.filledQuantity == takerOrder.quantity) { - takerOrder.status = 1 - } - orderPersister.save(takerOrder) - log.info("taker order saved {}", takerOrder) - - //calculate taker fee - val takerFee = takerOrder.takerFee - val takerTotalFeeWithPlatformCoin = calcFeeWithPlatformCoin(takerMatchedAmount, takerFee, takerPCFeeCoefficient) - - //create fa for transfer makeruuid symbol exchange wallet to taker symbol main wallet - /* - amount for sell (ask): match_quantity (if not pay by platform coin then - taker fee) - amount for buy (bid): match_quantity * maker price (if not pay by platform coin then - taker fee) + amount for sell (ask): match_quantity (if not pay by platform coin then - maker fee) + amount for buy (bid): match_quantity * maker price (if not pay by platform coin then - maker fee) */ - val makerTransferAction = - createTransferAction(trade, makerParentFinancialAction, makerOrder, makerMatchedAmount) - log.info("trade event makerTransferAction {}", makerTransferAction) - financialActions.add(makerTransferAction) - - //check if taker uuid can pay the fee with platform coin - val takerFeeAction = createTakerFeeAction( - trade, + val takerTransferAction = FinancialAction( takerParentFinancialAction, - takerTotalFeeWithPlatformCoin, - takerFee, - makerOrder, - makerMatchedAmount - ) - - log.info("trade event takerFeeAction {}", takerFeeAction) - financialActions.add(takerFeeAction) - //update maker order status - makerOrder.remainedTransferAmount -= makerMatchedAmount - if (makerOrder.filledQuantity == makerOrder.quantity) { - makerOrder.status = 1 - } - orderPersister.save(makerOrder) - log.info("maker order saved {}", makerOrder) - richTradePublisher.publish( - RichTrade( - trade.tradeId, - trade.pair.toString(), - trade.takerOuid, - trade.takerUuid, - trade.takerOrderId, - trade.takerDirection, - trade.takerPrice.toBigDecimal().multiply(takerOrder.rightSideFraction.toBigDecimal()), - takerOrder.origQuantity, - takerOrder.origPrice.multiply(takerOrder.origQuantity), - trade.takerRemainedQuantity.toBigDecimal().multiply(takerOrder.leftSideFraction.toBigDecimal()), - takerFeeAction.amount, - takerFeeAction.symbol, - trade.makerOuid, - trade.makerUuid, - trade.makerOrderId, - trade.makerDirection, - trade.makerPrice.toBigDecimal().multiply(makerOrder.rightSideFraction.toBigDecimal()), - makerOrder.origQuantity, - makerOrder.origPrice.multiply(makerOrder.origQuantity), - trade.makerRemainedQuantity.toBigDecimal().multiply(makerOrder.leftSideFraction.toBigDecimal()), - makerFeeAction.amount, - makerFeeAction.symbol, - trade.matchedQuantity.toBigDecimal().multiply(makerOrder.leftSideFraction.toBigDecimal()), - trade.eventDate - ) - - ) - return financeActionPersister.persist(financialActions) - } - - private fun calculateMatchedAmount(trade: TradeEvent, order: Order): BigDecimal { - return if (order.direction == OrderDirection.ASK) { - trade.matchedQuantity.toBigDecimal().multiply(order.leftSideFraction.toBigDecimal()) - } else { - trade.matchedQuantity.toBigDecimal().multiply(order.leftSideFraction.toBigDecimal()) - .multiply(trade.makerPrice.toBigDecimal()).multiply(order.rightSideFraction.toBigDecimal()) - } - } - - private suspend fun getPCFeeCoefficient(trade: TradeEvent, order: Order): Double { - val leftSidePCRate = pairStaticRateLoader.calculateStaticRate(platformCoin, trade.pair.leftSideName) - val rightSidePCRate = pairStaticRateLoader.calculateStaticRate(platformCoin, trade.pair.rightSideName) - return if (order.direction == OrderDirection.ASK) { - leftSidePCRate ?: 0.0 - } else { - rightSidePCRate ?: 0.0 - } - } - - private fun calcFeeWithPlatformCoin( - matchedAmount: BigDecimal, - fee: Double, - coefficient: Double - ): BigDecimal { - return matchedAmount.multiply(fee.toBigDecimal()).multiply(coefficient.toBigDecimal()) - } - - private fun createTransferAction( - trade: TradeEvent, - parentAction: FinancialAction?, - order: Order, - matchedAmount: BigDecimal - ): FinancialAction { - return FinancialAction( - parentAction, TradeEvent::class.simpleName!!, trade.takerOuid, - if (order.direction == OrderDirection.ASK) { + if (takerOrder.direction == OrderDirection.ASK) { trade.pair.leftSideName } else { trade.pair.rightSideName }, - matchedAmount, + takerMatchedAmount, trade.takerUuid, "exchange", trade.makerUuid, "main", LocalDateTime.now() ) - } - - private suspend fun createMakerFeeAction( - trade: TradeEvent, - parentAction: FinancialAction?, - totalFee: BigDecimal, - makerFee: Double, - takerOrder: Order, - takerMatchedAmount: BigDecimal, - ): FinancialAction { - val canFulfill = walletProxy.canFulfil(platformCoin, "main", trade.makerUuid, totalFee) - return if (totalFee > BigDecimal.ZERO && canFulfill) { + log.info("trade event takerTransferAction {}", takerTransferAction) + financialActions.add(takerTransferAction) + val makerFeeAction = if (makerTotalFeeWithPlatformCoin > BigDecimal.ZERO && + walletProxy.canFulfil(platformCoin, "main", trade.makerUuid, makerTotalFeeWithPlatformCoin) + ) { FinancialAction( - parentAction, + makerParentFinancialAction, TradeEvent::class.simpleName!!, trade.takerOuid, platformCoin, - totalFee, + makerTotalFeeWithPlatformCoin, trade.makerUuid, "main", platformAddress, @@ -237,7 +129,7 @@ open class TradeManagerImpl( ) } else { FinancialAction( - parentAction, + makerParentFinancialAction, TradeEvent::class.simpleName!!, trade.takerOuid, if (takerOrder.direction == OrderDirection.ASK) { @@ -253,20 +145,51 @@ open class TradeManagerImpl( LocalDateTime.now() ) } - } + log.info("trade event makerFeeAction {}", makerFeeAction) + financialActions.add(makerFeeAction) + //update taker order status + takerOrder.remainedTransferAmount -= takerMatchedAmount + if (takerOrder.filledQuantity == takerOrder.quantity) { + takerOrder.status = 1 + } + orderPersister.save(takerOrder) + log.info("taker order saved {}", takerOrder) + + //calculate taker fee + val takerFee = takerOrder.takerFee + val takerTotalFeeWithPlatformCoin = takerMatchedAmount + .multiply(takerFee.toBigDecimal()) + .multiply(takerPCFeeCoefficient.toBigDecimal()) - private suspend fun createTakerFeeAction( - trade: TradeEvent, - parentAction: FinancialAction?, - totalFee: BigDecimal, - takerFee: Double, - makerOrder: Order, - makerMatchedAmount: BigDecimal, - ): FinancialAction { - val canFulfill = walletProxy.canFulfil(platformCoin, "main", trade.takerUuid, totalFee) - return if (totalFee > BigDecimal.ZERO && canFulfill) { + //create fa for transfer makeruuid symbol exchange wallet to taker symbol main wallet + /* + amount for sell (ask): match_quantity (if not pay by platform coin then - taker fee) + amount for buy (bid): match_quantity * maker price (if not pay by platform coin then - taker fee) + */ + val makerTransferAction = FinancialAction( + makerParentFinancialAction, + TradeEvent::class.simpleName!!, + trade.makerOuid, + if (makerOrder.direction == OrderDirection.ASK) { + trade.pair.leftSideName + } else { + trade.pair.rightSideName + }, + makerMatchedAmount, + trade.makerUuid, + "exchange", + trade.takerUuid, + "main", + LocalDateTime.now() + ) + log.info("trade event makerTransferAction {}", makerTransferAction) + financialActions.add(makerTransferAction) + //check if taker uuid can pay the fee with platform coin + val takerFeeAction = if (takerTotalFeeWithPlatformCoin > BigDecimal.ZERO && + walletProxy.canFulfil(platformCoin, "main", trade.takerUuid, takerTotalFeeWithPlatformCoin) + ) { FinancialAction( - parentAction, + takerParentFinancialAction, TradeEvent::class.simpleName!!, trade.makerOuid, if (makerOrder.direction == OrderDirection.ASK) { @@ -274,7 +197,7 @@ open class TradeManagerImpl( } else { trade.pair.rightSideName }, - totalFee, + takerTotalFeeWithPlatformCoin, trade.takerUuid, "main", platformAddress, @@ -283,7 +206,7 @@ open class TradeManagerImpl( ) } else { FinancialAction( - parentAction, + takerParentFinancialAction, TradeEvent::class.simpleName!!, trade.makerOuid, if (makerOrder.direction == OrderDirection.ASK) { @@ -298,6 +221,46 @@ open class TradeManagerImpl( "exchange", LocalDateTime.now() ) + + } + log.info("trade event takerFeeAction {}", takerFeeAction) + financialActions.add(takerFeeAction) + //update maker order status + makerOrder.remainedTransferAmount -= makerMatchedAmount + if (makerOrder.filledQuantity == makerOrder.quantity) { + makerOrder.status = 1 } + orderPersister.save(makerOrder) + log.info("maker order saved {}", makerOrder) + richTradePublisher.publish( + RichTrade( + trade.tradeId, + trade.pair.toString(), + trade.takerOuid, + trade.takerUuid, + trade.takerOrderId, + trade.takerDirection, + trade.takerPrice.toBigDecimal().multiply(takerOrder.rightSideFraction.toBigDecimal()), + takerOrder.origQuantity, + takerOrder.origPrice.multiply(takerOrder.origQuantity), + trade.takerRemainedQuantity.toBigDecimal().multiply(takerOrder.leftSideFraction.toBigDecimal()), + takerFeeAction.amount, + takerFeeAction.symbol, + trade.makerOuid, + trade.makerUuid, + trade.makerOrderId, + trade.makerDirection, + trade.makerPrice.toBigDecimal().multiply(makerOrder.rightSideFraction.toBigDecimal()), + makerOrder.origQuantity, + makerOrder.origPrice.multiply(makerOrder.origQuantity), + trade.makerRemainedQuantity.toBigDecimal().multiply(makerOrder.leftSideFraction.toBigDecimal()), + makerFeeAction.amount, + makerFeeAction.symbol, + trade.matchedQuantity.toBigDecimal().multiply(makerOrder.leftSideFraction.toBigDecimal()), + trade.eventDate + ) + + ) + return financeActionPersister.persist(financialActions) } } \ No newline at end of file