feat(订阅): 支持 HLSS 策略止盈与介入区间格式化
Motivation: HLSS 策略信号携带的止盈价位列表与介入价位含冗余小数位,直接推送可读性差,需转换为紧凑区间并补齐推送时间,提升通知的信息密度与可读性。 Changes: * 新增止盈目标区间,将止盈价位列表去零后连接为区间 * 新增介入区间,由开仓价与介入价组合生成 * 压缩价格数值多余小数位,保留原始精度 * 注入推送时间,便于模板渲染提醒时间
This commit is contained in:
@@ -157,6 +157,80 @@ func TestConvertRendersSharedSignalTemplate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertHLSSParsesGainPricesAndOpenPrice2(t *testing.T) {
|
||||
body := []byte(`{
|
||||
"eventType": "SIGNAL_RECEIVED",
|
||||
"correlationId": "0_0_0",
|
||||
"symbol": "BTC",
|
||||
"direction": "SHORT",
|
||||
"payload": "{\"strategyCode\":\"HLSS\",\"period\":\"30m\",\"currency\":\"BTC\",\"isSale\":true,\"isClose\":false,\"price\":63150.38,\"lossPrice\":63623.3,\"gainPrices\":\"62677.470000000000000,62456.770000000000000\",\"openPrice2\":63535.02,\"totalGainTarget\":2,\"leverage\":100}",
|
||||
"eventTime": 1786860019037
|
||||
}`)
|
||||
event, data, err := Convert(body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if event != "HLSS.sell" {
|
||||
t.Fatalf("event=%q", event)
|
||||
}
|
||||
if got := asFloat(t, data["openPrice2"]); got != 63535.02 {
|
||||
t.Fatalf("openPrice2=%v", data["openPrice2"])
|
||||
}
|
||||
if data["takeProfitRange"] != "62677.47-62456.77" {
|
||||
t.Fatalf("takeProfitRange=%v", data["takeProfitRange"])
|
||||
}
|
||||
if data["entryRange"] != "63150.38-63535.02" {
|
||||
t.Fatalf("entryRange=%v", data["entryRange"])
|
||||
}
|
||||
if _, ok := data["pushedAt"].(string); !ok {
|
||||
t.Fatalf("pushedAt=%v", data["pushedAt"])
|
||||
}
|
||||
tmpl := `监控告警提醒
|
||||
|
||||
操作策略:高低点分型{{case .symbol "BTCUSDT" "BTC" "ETHUSDT" "ETH" "SOLUSDT" "SOL" "BNBUSDT" "BNB" .symbol}}-{{case .period "1h" "1小时" "4h" "4小时" "15m" "15分钟" "5m" "5分钟" "30m" "30分钟" "1d" "1日" .period}}周期{{case .side "LONG" "做多" "SHORT" "做空"}}
|
||||
|
||||
提醒时间:{{.pushedAt}}
|
||||
|
||||
{{with .takeProfitRange}}止盈目标:{{.}}
|
||||
|
||||
{{else}}{{with .takeProfitPrice}}止盈目标:{{.}}
|
||||
|
||||
{{end}}{{end}}{{with .entryRange}}介入区间:{{.}}
|
||||
|
||||
{{else}}{{with .price}}介入区间:{{.}}
|
||||
|
||||
{{end}}{{end}}{{with .stopLossPrice}}止损价位:{{.}}
|
||||
{{end}}`
|
||||
out, err := engine.NewRenderer().Render(tmpl, data)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, want := range []string{
|
||||
"监控告警提醒",
|
||||
"操作策略:高低点分型BTC-30分钟周期做空",
|
||||
"止盈目标:62677.47-62456.77",
|
||||
"介入区间:63150.38-63535.02",
|
||||
"止损价位:63623.3",
|
||||
} {
|
||||
if !strings.Contains(out, want) {
|
||||
t.Fatalf("missing %q in\n%s", want, out)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func asFloat(t *testing.T, v any) float64 {
|
||||
t.Helper()
|
||||
switch n := v.(type) {
|
||||
case float64:
|
||||
return n
|
||||
case float32:
|
||||
return float64(n)
|
||||
default:
|
||||
t.Fatalf("want float, got %T %v", v, v)
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func TestConvertInvalidJSON(t *testing.T) {
|
||||
_, _, err := Convert([]byte(`{not json`))
|
||||
if err == nil {
|
||||
|
||||
Reference in New Issue
Block a user