feat(通知模板): 支持缺字段按空值渲染与空行省略
Motivation: 统一 crypto-strategy 与 trade-signal 两类交易信号的模板字段,使同一套通知模板可复用;字段缺失或为空时不再导致渲染报错或输出空行,通知内容更整洁。 Changes: * 渲染器缺失字段改为按空值处理,新增 line 函数实现空值整行省略 * crypto-strategy 信号补充止盈价、止损价、平均价、收益额等模板字段 * trade-signal 信号保留原始报文中的额外字段以适配统一模板 * 修复结构化日志将 error 作为值直接输出导致的格式问题
This commit is contained in:
@@ -35,6 +35,7 @@ type payload struct {
|
||||
|
||||
type remark struct {
|
||||
OrderID string `json:"orderId"`
|
||||
Revenue string `json:"revenue"`
|
||||
}
|
||||
|
||||
type Converter struct{}
|
||||
@@ -60,31 +61,39 @@ func Convert(body []byte) (string, map[string]interface{}, error) {
|
||||
text := format(env, p, action)
|
||||
|
||||
data := map[string]interface{}{
|
||||
"eventType": env.EventType,
|
||||
"correlationId": env.CorrelationID,
|
||||
"symbol": firstNonEmpty(env.Symbol, p.Currency),
|
||||
"direction": env.Direction,
|
||||
"side": strings.ToUpper(env.Direction),
|
||||
"action": action,
|
||||
"eventTime": env.EventTime,
|
||||
"strategyCode": p.StrategyCode,
|
||||
"period": p.Period,
|
||||
"currency": p.Currency,
|
||||
"isSale": p.IsSale,
|
||||
"isClose": p.IsClose,
|
||||
"isGain": p.IsGain,
|
||||
"gainTarget": p.GainTarget,
|
||||
"price": p.Price,
|
||||
"lossPrice": p.LossPrice,
|
||||
"gainPrices": p.GainPrices,
|
||||
"leverage": p.Leverage,
|
||||
"formatted": text,
|
||||
"eventType": env.EventType,
|
||||
"correlationId": env.CorrelationID,
|
||||
"symbol": firstNonEmpty(env.Symbol, p.Currency),
|
||||
"direction": env.Direction,
|
||||
"side": strings.ToUpper(env.Direction),
|
||||
"action": action,
|
||||
"eventTime": env.EventTime,
|
||||
"strategyCode": p.StrategyCode,
|
||||
"period": p.Period,
|
||||
"currency": p.Currency,
|
||||
"isSale": p.IsSale,
|
||||
"isClose": p.IsClose,
|
||||
"isGain": p.IsGain,
|
||||
"gainTarget": p.GainTarget,
|
||||
"price": p.Price,
|
||||
"lossPrice": p.LossPrice,
|
||||
"gainPrices": p.GainPrices,
|
||||
"leverage": p.Leverage,
|
||||
"formatted": text,
|
||||
"stopLossPrice": p.LossPrice,
|
||||
"takeProfitPrice": takeProfitPrice(p),
|
||||
"totalAvgPx": "",
|
||||
}
|
||||
if p.TotalGainTarget != 0 {
|
||||
data["totalGainTarget"] = p.TotalGainTarget
|
||||
}
|
||||
if oid := parseOrderID(p.Remark); oid != "" {
|
||||
data["orderId"] = oid
|
||||
if r := parseRemark(p.Remark); r.OrderID != "" || r.Revenue != "" {
|
||||
if r.OrderID != "" {
|
||||
data["orderId"] = r.OrderID
|
||||
}
|
||||
if r.Revenue != "" {
|
||||
data["revenue"] = r.Revenue
|
||||
}
|
||||
}
|
||||
return event, data, nil
|
||||
}
|
||||
@@ -128,16 +137,26 @@ func inferAction(p payload) string {
|
||||
}
|
||||
}
|
||||
|
||||
func parseOrderID(raw string) string {
|
||||
func takeProfitPrice(p payload) interface{} {
|
||||
if gp := strings.TrimSpace(p.GainPrices); gp != "" {
|
||||
return gp
|
||||
}
|
||||
if p.IsGain && p.Price > 0 {
|
||||
return p.Price
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
func parseRemark(raw string) remark {
|
||||
raw = strings.TrimSpace(raw)
|
||||
if raw == "" {
|
||||
return ""
|
||||
return remark{}
|
||||
}
|
||||
var r remark
|
||||
if err := json.Unmarshal([]byte(raw), &r); err != nil {
|
||||
return ""
|
||||
return remark{}
|
||||
}
|
||||
return r.OrderID
|
||||
return r
|
||||
}
|
||||
|
||||
func format(env envelope, p payload, action string) string {
|
||||
|
||||
Reference in New Issue
Block a user