fix(价格展示): 修复模板渲染时极小价格被折叠为 0.00 的问题
Motivation: 此前的修复仅覆盖直接拼接文案的场景,跟单等基于模板渲染的推送场景中,%.2f 格式化仍会把 PEPE 等 Meme 币的极小价格(如 0.00000059)折叠为 0.00,导致交易通知丢失真实价格、误导用户。 Changes: * 抽取共享的价格显示逻辑到统一显示层,两个订阅者改为复用,移除重复实现 * 新增 Decimal 类型,渲染时以副本方式包装模板数据,使模板内 printf 风格格式化保留极小价格精度且不出现科学计数法,同时不修改调用方原始数据 * 渲染引擎空值判断改用反射实现,覆盖全部整型、无符号整型与浮点类型 * 补充转换到渲染的端到端回归测试,覆盖极小价格精度、科学计数法与数据不可变性
This commit is contained in:
@@ -2,10 +2,9 @@ package tradesignal
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"aiaa-notification-service/internal/display"
|
||||
"aiaa-notification-service/internal/tz"
|
||||
)
|
||||
|
||||
@@ -31,7 +30,7 @@ func Format(signal *Signal, opts ...FormatOptions) string {
|
||||
action := strings.ToUpper(signal.Action)
|
||||
switch action {
|
||||
case "OPEN":
|
||||
lines = append(lines, fmt.Sprintf("开仓价格: %s", formatPrice(signal.Price)))
|
||||
lines = append(lines, fmt.Sprintf("开仓价格: %s", display.FormatPrice(signal.Price)))
|
||||
if line := sizeLine("OPEN", signal.Quantity, signal.AmountMarginRatio); line != "" {
|
||||
lines = append(lines, line)
|
||||
}
|
||||
@@ -40,23 +39,23 @@ func Format(signal *Signal, opts ...FormatOptions) string {
|
||||
lines = append(lines, fmt.Sprintf("杠杆: %dx", signal.Leverage))
|
||||
}
|
||||
if signal.TakeProfitPrice != nil {
|
||||
lines = append(lines, fmt.Sprintf("止盈价格: %s", formatPrice(*signal.TakeProfitPrice)))
|
||||
lines = append(lines, fmt.Sprintf("止盈价格: %s", display.FormatPrice(*signal.TakeProfitPrice)))
|
||||
}
|
||||
if signal.StopLossPrice != nil {
|
||||
lines = append(lines, fmt.Sprintf("止损价格: %s", formatPrice(*signal.StopLossPrice)))
|
||||
lines = append(lines, fmt.Sprintf("止损价格: %s", display.FormatPrice(*signal.StopLossPrice)))
|
||||
}
|
||||
case "CLOSE":
|
||||
lines = append(lines, fmt.Sprintf("平仓价格: %s", formatPrice(signal.Price)))
|
||||
lines = append(lines, fmt.Sprintf("平仓价格: %s", display.FormatPrice(signal.Price)))
|
||||
lines = append(lines, closeSizeLine(signal.Quantity, signal.PosMarginRatio))
|
||||
lines = appendAvgPrice(lines, opt.AvgPrice)
|
||||
if signal.PnL != nil {
|
||||
lines = append(lines, fmt.Sprintf("平仓盈亏: %s", formatPrice(*signal.PnL)))
|
||||
lines = append(lines, fmt.Sprintf("平仓盈亏: %s", display.FormatPrice(*signal.PnL)))
|
||||
}
|
||||
if signal.AccountBalance != nil {
|
||||
lines = append(lines, fmt.Sprintf("账户余额:%s", formatPrice(*signal.AccountBalance)))
|
||||
lines = append(lines, fmt.Sprintf("账户余额:%s", display.FormatPrice(*signal.AccountBalance)))
|
||||
}
|
||||
case "ADD":
|
||||
lines = append(lines, fmt.Sprintf("加仓价格: %s", formatPrice(signal.Price)))
|
||||
lines = append(lines, fmt.Sprintf("加仓价格: %s", display.FormatPrice(signal.Price)))
|
||||
if line := sizeLine("ADD", signal.Quantity, signal.AmountMarginRatio); line != "" {
|
||||
lines = append(lines, line)
|
||||
}
|
||||
@@ -65,19 +64,19 @@ func Format(signal *Signal, opts ...FormatOptions) string {
|
||||
lines = append(lines, fmt.Sprintf("杠杆: %dx", signal.Leverage))
|
||||
}
|
||||
case "REDUCE":
|
||||
lines = append(lines, fmt.Sprintf("减仓价格: %s", formatPrice(signal.Price)))
|
||||
lines = append(lines, fmt.Sprintf("减仓价格: %s", display.FormatPrice(signal.Price)))
|
||||
if line := sizeLine("REDUCE", signal.Quantity, signal.PosMarginRatio); line != "" {
|
||||
lines = append(lines, line)
|
||||
}
|
||||
lines = appendAvgPrice(lines, opt.AvgPrice)
|
||||
if signal.PnL != nil {
|
||||
lines = append(lines, fmt.Sprintf("减仓盈亏: %s", formatPrice(*signal.PnL)))
|
||||
lines = append(lines, fmt.Sprintf("减仓盈亏: %s", display.FormatPrice(*signal.PnL)))
|
||||
}
|
||||
if signal.AccountBalance != nil {
|
||||
lines = append(lines, fmt.Sprintf("账户余额:%s", formatPrice(*signal.AccountBalance)))
|
||||
lines = append(lines, fmt.Sprintf("账户余额:%s", display.FormatPrice(*signal.AccountBalance)))
|
||||
}
|
||||
default:
|
||||
lines = append(lines, fmt.Sprintf("价格: %s", formatPrice(signal.Price)))
|
||||
lines = append(lines, fmt.Sprintf("价格: %s", display.FormatPrice(signal.Price)))
|
||||
if line := sizeLine("", signal.Quantity, signal.AmountMarginRatio); line != "" {
|
||||
lines = append(lines, line)
|
||||
}
|
||||
@@ -129,7 +128,7 @@ func appendAvgPrice(lines []string, avgPrice *float64) []string {
|
||||
if avgPrice == nil || *avgPrice <= 0 {
|
||||
return lines
|
||||
}
|
||||
return append(lines, fmt.Sprintf("平均单价: %s", formatPrice(*avgPrice)))
|
||||
return append(lines, fmt.Sprintf("平均单价: %s", display.FormatPrice(*avgPrice)))
|
||||
}
|
||||
|
||||
func closeSizeLine(quantity, posMarginRatio *float64) string {
|
||||
@@ -190,19 +189,6 @@ func formatPercent(ratio float64) string {
|
||||
return fmt.Sprintf("%.2f%%", ratio*100)
|
||||
}
|
||||
|
||||
// formatPrice renders a price for display. Values >= 1 keep two decimals for
|
||||
// readability; smaller values use the shortest exact representation so tiny
|
||||
// prices like 0.00000059 are not collapsed to 0.00.
|
||||
func formatPrice(v float64) string {
|
||||
if v == 0 {
|
||||
return "0.00"
|
||||
}
|
||||
if math.Abs(v) >= 1 {
|
||||
return strconv.FormatFloat(v, 'f', 2, 64)
|
||||
}
|
||||
return strconv.FormatFloat(v, 'f', -1, 64)
|
||||
}
|
||||
|
||||
func trimQuote(symbol string) string {
|
||||
symbol = strings.ToUpper(symbol)
|
||||
for _, suffix := range []string{"USDT", "USDC", "BUSD", "USD"} {
|
||||
|
||||
Reference in New Issue
Block a user