package view import ( "fmt" "math" "strings" "time" "github.com/jedib0t/go-pretty/v6/table" "golang.org/x/text/language" "golang.org/x/text/message" "me.thuanle/bbot/internal/helper/binancex" "me.thuanle/bbot/internal/services/tele/view/helper" "me.thuanle/bbot/internal/utils/timex" ) func RenderPrice(price float64) string { mFmt := message.NewPrinter(language.AmericanEnglish) switch { case price > 1000: return mFmt.Sprintf("%0.0f", price) case price > 100: return mFmt.Sprintf("%0.1f", price) case price > 10: return mFmt.Sprintf("%0.2f", price) case price > 1: return mFmt.Sprintf("%0.3f", price) case price > 0.1: return mFmt.Sprintf("%0.4f", price) case price > 0.01: return mFmt.Sprintf("%0.5f", price) case price > 0.001: return mFmt.Sprintf("%0.6f", price) case price > 0.0001: return mFmt.Sprintf("%0.7f", price) default: return mFmt.Sprintf("%0.8f", price) } } func RenderOnPriceMessage(symbol string, spotPrice float64, futurePrice float64, fundrate float64, fundtime int64, marginRate float64) string { return fmt.Sprintf( "%s\n"+ " Spot: %s - Future: %s \n"+ " Fund rate: %.4f%% %s in %s\n"+ " Margin rate: %.3f%%", RenderSymbolInfo(symbol), RenderPrice(spotPrice), RenderPrice(futurePrice), fundrate*100, IconOfFundingFeeDirection(fundrate), timex.CdMinuteStringTime(time.UnixMilli(fundtime)), marginRate*365*100, ) } func RenderOnAlphaPriceMessage(symbol string, price float64, change24h float64) string { icon := "🟢" if change24h < 0 { icon = "🔴" } return fmt.Sprintf( "🅰️ %s\n"+ " Price: $%s\n"+ " 24h: %s%.2f%%", symbol, RenderPrice(price), icon, change24h, ) } type RichTokenMessageInput struct { Token string HasSpot bool SpotPrice float64 HasFuture bool FuturePrice float64 FundingRate float64 FundingTimeMs int64 HasAlpha bool AlphaPrice float64 HasAlpha24h bool Alpha24hChange float64 HasMarginAPR bool MarginAPRPercent float64 } func RenderRichTokenMessage(in RichTokenMessageInput) string { rows := []string{fmt.Sprintf("🪙 %s", strings.ToUpper(in.Token))} if in.HasSpot { rows = append(rows, fmt.Sprintf("💵 Spot: $%s", RenderPrice(in.SpotPrice))) } if in.HasFuture { rows = append(rows, fmt.Sprintf("📈 Future: $%s", RenderPrice(in.FuturePrice))) } if in.HasAlpha { rows = append(rows, fmt.Sprintf("🅰️ Alpha: $%s", RenderPrice(in.AlphaPrice))) } if in.HasSpot && in.HasFuture && in.SpotPrice > 0 { delta := in.FuturePrice - in.SpotPrice deltaPct := delta / in.SpotPrice * 100 sign := "+" if delta < 0 { sign = "-" } rows = append(rows, fmt.Sprintf("🧭 Basis: %s$%s (%+.2f%%)", sign, RenderPrice(math.Abs(delta)), deltaPct)) } if in.HasFuture { rows = append(rows, fmt.Sprintf("💸 Funding: %.4f%% %s in %s", in.FundingRate*100, IconOfFundingFeeDirection(in.FundingRate), timex.CdMinuteStringTime(time.UnixMilli(in.FundingTimeMs)), )) } if in.HasMarginAPR { rows = append(rows, fmt.Sprintf("🏦 Margin: %.3f%% APR", in.MarginAPRPercent)) } if in.HasAlpha24h { icon := "🟢" if in.Alpha24hChange < 0 { icon = "🔴" } rows = append(rows, fmt.Sprintf("📊 Alpha 24h: %s%+.2f%%", icon, in.Alpha24hChange)) } return strings.Join(rows, "\n") } func RenderOnGetTopPricesMessage(symbols []string, price []float64, fundRate []float64) string { t := helper.NewNoBorderTableWriter("", "Price", "Fund") mFmt := message.NewPrinter(language.AmericanEnglish) for i, symbol := range symbols { t.AppendRow(table.Row{ binancex.Symbol2Token(symbol), mFmt.Sprintf("%.2f", price[i]), mFmt.Sprintf("%.3f%%", fundRate[i]*100), }) } return t.Render() }