feat(cryptotail): 尾盘策略打印初始价差

- 周期开始预计算 AUTO 价差后打印 baseSpreadUp/baseSpreadDown
- 触发价差校验时打印初始价差、系数、有效最小价差、当前K线价差及是否通过

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
WrBug
2026-02-14 21:00:01 +08:00
co-authored by Cursor
parent 5cdcc487d4
commit bd529d9041
2 changed files with 34 additions and 9 deletions
@@ -236,7 +236,13 @@ class CryptoTailOrderbookWsService(
scope.launch {
for ((intervalSeconds, periodStartUnix) in autoPeriods) {
try {
binanceKlineAutoSpreadService.computeAndCache(intervalSeconds, periodStartUnix)
val pair = binanceKlineAutoSpreadService.computeAndCache(intervalSeconds, periodStartUnix)
if (pair != null) {
logger.info(
"周期开始初始价差: interval=${intervalSeconds}s periodStartUnix=$periodStartUnix " +
"baseSpreadUp=${pair.first.toPlainString()} baseSpreadDown=${pair.second.toPlainString()}"
)
}
} catch (e: Exception) {
logger.warn("周期开始预计算 AUTO 价差失败: interval=$intervalSeconds periodStartUnix=$periodStartUnix ${e.message}")
}
@@ -188,19 +188,37 @@ class CryptoTailStrategyExecutionService(
?: return false
val (openP, closeP) = oc
val spreadAbs = closeP.subtract(openP).abs()
val effectiveMinSpread = when (mode) {
"FIXED" -> strategy.minSpreadValue?.takeIf { it > BigDecimal.ZERO }
"AUTO" -> computeAutoEffectiveMinSpread(strategy, periodStartUnix, outcomeIndex)
else -> null
when (mode) {
"FIXED" -> {
val effectiveMinSpread = strategy.minSpreadValue?.takeIf { it > BigDecimal.ZERO }
if (effectiveMinSpread == null || effectiveMinSpread <= BigDecimal.ZERO) return true
return spreadAbs >= effectiveMinSpread
}
"AUTO" -> {
val result = computeAutoEffectiveMinSpread(strategy, periodStartUnix, outcomeIndex) ?: return true
val effectiveMinSpread = result.effectiveMinSpread
if (effectiveMinSpread <= BigDecimal.ZERO) return true
val passed = spreadAbs >= effectiveMinSpread
logger.info(
"尾盘价差校验: 初始价差(100%基准)=${result.baseSpread.toPlainString()} 系数=${result.coefficient.toPlainString()} " +
"有效最小价差=${effectiveMinSpread.toPlainString()} 当前K线价差=${spreadAbs.toPlainString()} 通过=$passed"
)
return passed
}
else -> return true
}
if (effectiveMinSpread == null || effectiveMinSpread <= BigDecimal.ZERO) return true
return spreadAbs >= effectiveMinSpread
}
/**
* AUTO 模式:取 100% 基准价差,按窗口内毫秒进度计算动态系数(100%→50%)得到有效最小价差。
*/
private fun computeAutoEffectiveMinSpread(strategy: CryptoTailStrategy, periodStartUnix: Long, outcomeIndex: Int): BigDecimal? {
private data class AutoSpreadResult(
val baseSpread: BigDecimal,
val coefficient: BigDecimal,
val effectiveMinSpread: BigDecimal
)
private fun computeAutoEffectiveMinSpread(strategy: CryptoTailStrategy, periodStartUnix: Long, outcomeIndex: Int): AutoSpreadResult? {
val baseSpread = binanceKlineAutoSpreadService.getAutoMinSpreadBase(strategy.intervalSeconds, periodStartUnix, outcomeIndex)
?: binanceKlineAutoSpreadService.computeAndCache(strategy.intervalSeconds, periodStartUnix)?.let { if (outcomeIndex == 0) it.first else it.second }
?: return null
@@ -217,7 +235,8 @@ class CryptoTailStrategyExecutionService(
.let { p -> maxOf(BigDecimal.ZERO, minOf(BigDecimal.ONE, p)) }
BigDecimal.ONE.subtract(progress.multi("0.5"))
}
return baseSpread.multi(coefficient).setScale(8, RoundingMode.HALF_UP)
val effectiveMinSpread = baseSpread.multi(coefficient).setScale(8, RoundingMode.HALF_UP)
return AutoSpreadResult(baseSpread, coefficient, effectiveMinSpread)
}
private suspend fun placeOrderForTrigger(