fix: 修复仓位轮询检查逻辑和时区问题
- 修复仓位轮询检查:当仓位不存在时,只有当订单创建时间超过2分钟才认为仓位被出售,避免刚创建的订单被误判 - 修复时区问题:所有时间格式化使用系统时区,移除硬编码的时区配置 - DateUtils 添加 formatDateTime() 函数,使用 ZoneId.systemDefault() - TelegramNotificationService 所有时间格式化使用 DateUtils.formatDateTime() - Dockerfile 和启动脚本移除时区配置,自动使用系统时区
This commit is contained in:
+3
-3
@@ -22,9 +22,9 @@ FROM eclipse-temurin:17-jre-jammy
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
# 安装必要的工具
|
||||
# 安装必要的工具和时区数据
|
||||
RUN apt-get update && \
|
||||
apt-get install -y curl && \
|
||||
apt-get install -y curl tzdata && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
# 从构建阶段复制 JAR 文件
|
||||
@@ -43,6 +43,6 @@ EXPOSE 8000
|
||||
HEALTHCHECK --interval=30s --timeout=3s --start-period=40s --retries=3 \
|
||||
CMD curl -f http://localhost:8000/api/system/health || exit 1
|
||||
|
||||
# 启动应用
|
||||
# 启动应用(自动使用系统时区)
|
||||
ENTRYPOINT ["java", "-jar", "app.jar"]
|
||||
|
||||
|
||||
+6
-6
@@ -373,22 +373,22 @@ class PositionCheckService(
|
||||
|
||||
if (position == null) {
|
||||
// 仓位不存在,检查订单创建时间
|
||||
// 只有当订单创建时间超过30秒时,才认为仓位被出售了
|
||||
// 只有当订单创建时间超过2分钟时,才认为仓位被出售了
|
||||
// 这样可以避免刚创建的订单因为API延迟而被误判为已卖出
|
||||
val now = System.currentTimeMillis()
|
||||
val ordersToMarkAsSold = orders.filter { order ->
|
||||
val orderAge = now - order.createdAt
|
||||
orderAge > 30000 // 30秒 = 30000毫秒
|
||||
orderAge > 120000 // 2分钟 = 120000毫秒
|
||||
}
|
||||
|
||||
if (ordersToMarkAsSold.isNotEmpty()) {
|
||||
// 有订单创建时间超过30秒,认为仓位已被出售
|
||||
// 有订单创建时间超过2分钟,认为仓位已被出售
|
||||
val currentPrice = getCurrentMarketPrice(marketId, outcomeIndex)
|
||||
updateOrdersAsSold(ordersToMarkAsSold, currentPrice, copyTrading.id, marketId, outcomeIndex)
|
||||
logger.debug("仓位不存在且订单创建时间超过30秒,标记为已卖出: marketId=$marketId, outcomeIndex=$outcomeIndex, orderCount=${ordersToMarkAsSold.size}")
|
||||
logger.debug("仓位不存在且订单创建时间超过2分钟,标记为已卖出: marketId=$marketId, outcomeIndex=$outcomeIndex, orderCount=${ordersToMarkAsSold.size}")
|
||||
} else {
|
||||
// 订单创建时间不足30秒,可能是刚创建的订单,暂时不处理
|
||||
logger.debug("仓位不存在但订单创建时间不足30秒,暂不标记为已卖出: marketId=$marketId, outcomeIndex=$outcomeIndex, orderCount=${orders.size}, oldestOrderAge=${orders.minOfOrNull { now - it.createdAt }?.let { "${it}ms" } ?: "N/A"}")
|
||||
// 订单创建时间不足2分钟,可能是刚创建的订单,暂时不处理
|
||||
logger.debug("仓位不存在但订单创建时间不足2分钟,暂不标记为已卖出: marketId=$marketId, outcomeIndex=$outcomeIndex, orderCount=${orders.size}, oldestOrderAge=${orders.minOfOrNull { now - it.createdAt }?.let { "${it}ms" } ?: "N/A"}")
|
||||
}
|
||||
} else {
|
||||
// 有仓位,按订单下单顺序(FIFO)更新状态
|
||||
|
||||
+5
-4
@@ -7,6 +7,7 @@ import com.wrbug.polymarketbot.dto.NotificationConfigData
|
||||
import com.wrbug.polymarketbot.dto.TelegramConfigData
|
||||
import com.wrbug.polymarketbot.util.createClient
|
||||
import com.wrbug.polymarketbot.util.toSafeBigDecimal
|
||||
import com.wrbug.polymarketbot.util.DateUtils
|
||||
import kotlinx.coroutines.*
|
||||
import okhttp3.MediaType.Companion.toMediaType
|
||||
import okhttp3.OkHttpClient
|
||||
@@ -308,7 +309,7 @@ class TelegramNotificationService(
|
||||
}
|
||||
}
|
||||
|
||||
val time = java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(java.util.Date())
|
||||
val time = DateUtils.formatDateTime()
|
||||
|
||||
// 转义 HTML 特殊字符
|
||||
val escapedMarketTitle = marketTitle.replace("<", "<").replace(">", ">")
|
||||
@@ -639,7 +640,7 @@ class TelegramNotificationService(
|
||||
""
|
||||
}
|
||||
|
||||
val time = java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(java.util.Date())
|
||||
val time = DateUtils.formatDateTime()
|
||||
|
||||
// 转义 HTML 特殊字符
|
||||
val escapedMarketTitle = marketTitle.replace("<", "<").replace(">", ">")
|
||||
@@ -760,7 +761,7 @@ class TelegramNotificationService(
|
||||
}
|
||||
}
|
||||
|
||||
val time = java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(java.util.Date())
|
||||
val time = DateUtils.formatDateTime()
|
||||
|
||||
// 错误信息已经是后端返回的 msg,不需要截断(但为了安全,限制长度)
|
||||
val shortErrorMessage = if (errorMessage.length > 500) {
|
||||
@@ -901,7 +902,7 @@ class TelegramNotificationService(
|
||||
}
|
||||
}
|
||||
|
||||
val time = java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(java.util.Date())
|
||||
val time = DateUtils.formatDateTime()
|
||||
|
||||
// 转义 HTML 特殊字符
|
||||
val escapedAccountInfo = accountInfo.replace("<", "<").replace(">", ">")
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package com.wrbug.polymarketbot.util
|
||||
|
||||
import java.time.Instant
|
||||
import java.time.ZoneId
|
||||
import java.time.ZonedDateTime
|
||||
import java.time.format.DateTimeFormatter
|
||||
import java.time.format.DateTimeParseException
|
||||
|
||||
@@ -15,6 +17,13 @@ object DateUtils {
|
||||
*/
|
||||
private val isoFormatter = DateTimeFormatter.ISO_DATE_TIME
|
||||
|
||||
/**
|
||||
* 使用系统时区的日期时间格式化器(用于显示)
|
||||
* 格式:yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
private val displayFormatter: DateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
|
||||
.withZone(ZoneId.systemDefault())
|
||||
|
||||
/**
|
||||
* 将 ISO 8601 格式的日期字符串转换为时间戳(毫秒)
|
||||
* @param dateString ISO 8601 格式的日期字符串,如 "2020-11-04T00:00:00Z"
|
||||
@@ -61,5 +70,19 @@ object DateUtils {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将时间戳(毫秒)格式化为可读的日期时间字符串(使用系统时区)
|
||||
* @param timestamp 时间戳(毫秒),如果为 null 则使用当前时间
|
||||
* @return 格式化的日期时间字符串,格式:yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
fun formatDateTime(timestamp: Long? = null): String {
|
||||
val instant = if (timestamp != null) {
|
||||
Instant.ofEpochMilli(timestamp)
|
||||
} else {
|
||||
Instant.now()
|
||||
}
|
||||
return displayFormatter.format(instant)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -54,6 +54,7 @@ trap cleanup SIGTERM SIGINT
|
||||
|
||||
# 启动后端服务(以 appuser 用户运行,后台运行)
|
||||
echo "启动后端服务..."
|
||||
# 自动使用系统时区
|
||||
java -jar /app/app.jar --spring.profiles.active=${SPRING_PROFILES_ACTIVE:-prod} &
|
||||
BACKEND_PID=$!
|
||||
|
||||
|
||||
Reference in New Issue
Block a user