fix(交易信号): 修复极小价格展示精度丢失与策略覆盖匹配失效

Motivation:
部分 meme 币等标的价格极小(如 0.00000059),原有格式化统一保留两位小数会将其显示为 0.00,导致推送消息中的价格信息失真、误导用户;同时 viper 加载配置时会将嵌套 map 的 key 统一转为小写,导致按大写策略编码配置的策略覆盖项无法命中,仓位倍数、杠杆等覆盖参数失效。

Changes:

* 新增价格展示格式化逻辑:绝对值不小于 1 的数值保留两位小数,小于 1 的数值采用最短精确表示,避免极小价格被截断为 0.00
* 策略覆盖查找改为大小写不敏感匹配,兼容 viper 将配置 key 小写化的行为,确保策略编码以任意大小写配置均可生效
* 补充极小价格展示、配置加载解析及策略覆盖匹配的单元测试
This commit is contained in:
2026-08-19 01:03:29 +08:00
parent 7651c57536
commit cd3db8d453
7 changed files with 161 additions and 21 deletions
+19 -5
View File
@@ -4,6 +4,7 @@ import (
"bytes"
"encoding/json"
"fmt"
"math"
"strconv"
"strings"
"time"
@@ -244,23 +245,23 @@ func format(env envelope, p payload, action string) string {
switch action {
case "CLOSE":
if p.Price > 0 {
lines = append(lines, fmt.Sprintf("平仓价格: %.2f", p.Price))
lines = append(lines, fmt.Sprintf("平仓价格: %s", formatPrice(p.Price)))
}
case "GAIN":
if p.Price > 0 {
lines = append(lines, fmt.Sprintf("止盈价格: %.2f", p.Price))
lines = append(lines, fmt.Sprintf("止盈价格: %s", formatPrice(p.Price)))
}
case "SELL":
if p.Price > 0 {
lines = append(lines, fmt.Sprintf("卖出价格: %.2f", p.Price))
lines = append(lines, fmt.Sprintf("卖出价格: %s", formatPrice(p.Price)))
}
default:
if p.Price > 0 {
lines = append(lines, fmt.Sprintf("开仓价格: %.2f", p.Price))
lines = append(lines, fmt.Sprintf("开仓价格: %s", formatPrice(p.Price)))
}
}
if p.LossPrice > 0 {
lines = append(lines, fmt.Sprintf("止损价格: %.2f", p.LossPrice))
lines = append(lines, fmt.Sprintf("止损价格: %s", formatPrice(p.LossPrice)))
}
if er := entryRange(p.Price, p.OpenPrice2); er != "" && p.OpenPrice2 != 0 {
lines = append(lines, fmt.Sprintf("介入区间: %s", er))
@@ -359,6 +360,19 @@ func formatFloat(f float64) string {
return strconv.FormatFloat(f, 'f', -1, 64)
}
// 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 firstNonEmpty(a, b string) string {
if strings.TrimSpace(a) != "" {
return a