From 2ec4ae3f9808d4a2edf8aa506b7eea6d66618415 Mon Sep 17 00:00:00 2001 From: WrBug Date: Sat, 14 Feb 2026 16:01:57 +0800 Subject: [PATCH] =?UTF-8?q?refactor(cryptotail):=20=E5=8F=96=E6=B6=88=20FI?= =?UTF-8?q?XED=20=E6=A8=A1=E5=BC=8F=E9=A2=84=E7=AD=BE=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=EF=BC=8C=E6=94=B9=E4=B8=BA=E8=A7=A6=E5=8F=91=E6=97=B6=E5=86=8D?= =?UTF-8?q?=E7=AD=BE=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 移除 PeriodContext.preSignedOrderByOutcome,周期开始仅预取参数(账户、解密、费率、CLOB 等) - ensurePeriodContext 不再预签两个 outcome 的订单 - placeOrderForTrigger 统一 FIXED/RATIO 流程,均于触发时计算 size 并签名提交 - 每次触发仅对当前 outcome 签名一次,避免预签两张仅用一张的浪费 Co-authored-by: Cursor --- .../CryptoTailStrategyExecutionService.kt | 112 +++++------------- 1 file changed, 31 insertions(+), 81 deletions(-) diff --git a/backend/src/main/kotlin/com/wrbug/polymarketbot/service/cryptotail/CryptoTailStrategyExecutionService.kt b/backend/src/main/kotlin/com/wrbug/polymarketbot/service/cryptotail/CryptoTailStrategyExecutionService.kt index 8d1c204..c11d56d 100644 --- a/backend/src/main/kotlin/com/wrbug/polymarketbot/service/cryptotail/CryptoTailStrategyExecutionService.kt +++ b/backend/src/main/kotlin/com/wrbug/polymarketbot/service/cryptotail/CryptoTailStrategyExecutionService.kt @@ -26,6 +26,7 @@ import org.springframework.stereotype.Service import java.math.BigDecimal import java.math.RoundingMode import java.util.concurrent.ConcurrentHashMap +import java.util.regex.Pattern /** 尾盘策略固定下单价格(最高价 0.99),不再在触发时拉取最优价 */ private const val TRIGGER_FIXED_PRICE = "0.99" @@ -34,8 +35,8 @@ private const val TRIGGER_FIXED_PRICE = "0.99" private const val SIZE_DECIMAL_SCALE = 2 /** - * 周期内预置上下文:账户、解密凭证、费率、签名类型、CLOB 客户端;FIXED 模式含预签订单。 - * 触发时 RATIO 仅算 size 并签名提交,FIXED 直接提交预签订单。 + * 周期内预置上下文:账户、解密凭证、费率、签名类型、CLOB 客户端;不含预签订单。 + * 触发时 FIXED/RATIO 均按 outcomeIndex 计算 size 并签名提交。 */ private data class PeriodContext( val strategy: CryptoTailStrategy, @@ -48,13 +49,12 @@ private data class PeriodContext( val feeRateByTokenId: Map, val signatureType: Int, val tokenIds: List, - val marketTitle: String?, - val preSignedOrderByOutcome: Map? + val marketTitle: String? ) /** * 尾盘策略执行服务:按周期与时间窗口检查价格并下单,每周期最多触发一次。 - * 周期开始预置账户、解密、费率、签名类型、CLOB 客户端;FIXED 模式预签两张订单,触发时仅提交;RATIO 模式触发时再算 size 并签名提交。 + * 周期开始预置账户、解密、费率、签名类型、CLOB 客户端;触发时按 outcomeIndex 计算 size 并签名提交。 */ @Service class CryptoTailStrategyExecutionService( @@ -88,7 +88,7 @@ class CryptoTailStrategyExecutionService( /** * 在周期内首次需要时构建并缓存预置上下文;失败返回 null,触发流程将走完整路径。 - * 预置:账户、解密、费率、签名类型、CLOB 客户端;FIXED 时预签两个 outcome 的订单。 + * 预置:账户、解密、费率、签名类型、CLOB 客户端;不预签订单,触发时再签名。 */ private suspend fun ensurePeriodContext( strategy: CryptoTailStrategy, @@ -121,45 +121,7 @@ class CryptoTailStrategyExecutionService( } val signatureType = orderSigningService.getSignatureTypeForWalletType(account.walletType) - val preSignedOrderByOutcome: Map? = when (strategy.amountMode.uppercase()) { - "RATIO" -> null - else -> { - val amountUsdc = strategy.amountValue - if (amountUsdc < BigDecimal("1")) return null - val price = BigDecimal(TRIGGER_FIXED_PRICE) - val size = computeSize(amountUsdc, price) - val orders = mutableMapOf() - for (i in 0..1) { - if (i >= tokenIds.size) break - val tokenId = tokenIds[i] - val feeRateBps = feeRateByTokenId[tokenId] ?: "0" - try { - val signedOrder = orderSigningService.createAndSignOrder( - privateKey = decryptedKey, - makerAddress = account.proxyAddress, - tokenId = tokenId, - side = "BUY", - price = TRIGGER_FIXED_PRICE, - size = size, - signatureType = signatureType, - nonce = "0", - feeRateBps = feeRateBps, - expiration = "0" - ) - orders[i] = NewOrderRequest( - order = signedOrder, - owner = account.apiKey!!, - orderType = "FAK", - deferExec = false - ) - } catch (e: Exception) { - logger.warn("尾盘策略预签订单失败: strategyId=${strategy.id}, outcomeIndex=$i", e) - return null - } - } - orders.ifEmpty { null } - } - } + if (strategy.amountMode.uppercase() != "RATIO" && strategy.amountValue < BigDecimal("1")) return null val ctx = PeriodContext( strategy = strategy, @@ -172,8 +134,7 @@ class CryptoTailStrategyExecutionService( feeRateByTokenId = feeRateByTokenId, signatureType = signatureType, tokenIds = tokenIds, - marketTitle = marketTitle, - preSignedOrderByOutcome = preSignedOrderByOutcome + marketTitle = marketTitle ) periodContextCache[key] = ctx return ctx @@ -268,40 +229,29 @@ class CryptoTailStrategyExecutionService( return } - when { - ctx.preSignedOrderByOutcome != null -> { - val orderRequest = ctx.preSignedOrderByOutcome[outcomeIndex] - if (orderRequest != null) { - submitOrderAndSaveRecord(ctx.clobApi, strategy, periodStartUnix, marketTitle, outcomeIndex, triggerPrice, amountUsdc, orderRequest) - return - } - } - strategy.amountMode.uppercase() == "RATIO" -> { - val price = BigDecimal(TRIGGER_FIXED_PRICE) - val size = computeSize(amountUsdc, price) - val feeRateBps = ctx.feeRateByTokenId[tokenId] ?: "0" - val signedOrder = orderSigningService.createAndSignOrder( - privateKey = ctx.decryptedPrivateKey, - makerAddress = ctx.account.proxyAddress, - tokenId = tokenId, - side = "BUY", - price = TRIGGER_FIXED_PRICE, - size = size, - signatureType = ctx.signatureType, - nonce = "0", - feeRateBps = feeRateBps, - expiration = "0" - ) - val orderRequest = NewOrderRequest( - order = signedOrder, - owner = ctx.account.apiKey!!, - orderType = "FAK", - deferExec = false - ) - submitOrderAndSaveRecord(ctx.clobApi, strategy, periodStartUnix, marketTitle, outcomeIndex, triggerPrice, amountUsdc, orderRequest) - return - } - } + val price = BigDecimal(TRIGGER_FIXED_PRICE) + val size = computeSize(amountUsdc, price) + val feeRateBps = ctx.feeRateByTokenId[tokenId] ?: "0" + val signedOrder = orderSigningService.createAndSignOrder( + privateKey = ctx.decryptedPrivateKey, + makerAddress = ctx.account.proxyAddress, + tokenId = tokenId, + side = "BUY", + price = TRIGGER_FIXED_PRICE, + size = size, + signatureType = ctx.signatureType, + nonce = "0", + feeRateBps = feeRateBps, + expiration = "0" + ) + val orderRequest = NewOrderRequest( + order = signedOrder, + owner = ctx.account.apiKey!!, + orderType = "FAK", + deferExec = false + ) + submitOrderAndSaveRecord(ctx.clobApi, strategy, periodStartUnix, marketTitle, outcomeIndex, triggerPrice, amountUsdc, orderRequest) + return } placeOrderForTriggerSlowPath(strategy, periodStartUnix, marketTitle, tokenIds, outcomeIndex, triggerPrice)