From 938e612c42fd93853fd0c9d99ae7c216aace28f7 Mon Sep 17 00:00:00 2001 From: c9s Date: Fri, 5 Aug 2022 00:53:26 +0800 Subject: [PATCH] util: move emoji and pnl related functions to util --- pkg/types/kline.go | 12 ++-- pkg/types/profit.go | 88 +++++--------------------- pkg/types/side.go | 8 ++- pkg/{types/color.go => util/colors.go} | 2 +- pkg/util/emoji.go | 63 ++++++++++++++++++ 5 files changed, 91 insertions(+), 82 deletions(-) rename pkg/{types/color.go => util/colors.go} (85%) create mode 100644 pkg/util/emoji.go diff --git a/pkg/types/kline.go b/pkg/types/kline.go index 6906a1c97..5444c8e3d 100644 --- a/pkg/types/kline.go +++ b/pkg/types/kline.go @@ -214,11 +214,11 @@ func (k KLine) GetChange() fixedpoint.Value { func (k KLine) Color() string { if k.Direction() > 0 { - return GreenColor + return util.GreenColor } else if k.Direction() < 0 { - return RedColor + return util.RedColor } - return GrayColor + return util.GrayColor } func (k KLine) String() string { @@ -368,11 +368,11 @@ func (k KLineWindow) GetTrend() int { func (k KLineWindow) Color() string { if k.GetTrend() > 0 { - return GreenColor + return util.GreenColor } else if k.GetTrend() < 0 { - return RedColor + return util.RedColor } - return GrayColor + return util.GrayColor } // Mid price diff --git a/pkg/types/profit.go b/pkg/types/profit.go index 3bfb4e68a..73da1ed21 100644 --- a/pkg/types/profit.go +++ b/pkg/types/profit.go @@ -64,17 +64,17 @@ type Profit struct { } func (p *Profit) SlackAttachment() slack.Attachment { - var color = pnlColor(p.Profit) + var color = util.PnLColor(p.Profit) var title = fmt.Sprintf("%s PnL ", p.Symbol) - title += pnlEmojiMargin(p.Profit, p.ProfitMargin, defaultPnlLevelResolution) + " " - title += pnlSignString(p.Profit) + " " + p.QuoteCurrency + title += util.PnLEmojiMargin(p.Profit, p.ProfitMargin, util.DefaultPnLLevelResolution) + " " + title += util.PnLSignString(p.Profit) + " " + p.QuoteCurrency var fields []slack.AttachmentField if !p.NetProfit.IsZero() { fields = append(fields, slack.AttachmentField{ Title: "Net Profit", - Value: pnlSignString(p.NetProfit) + " " + p.QuoteCurrency, + Value: util.PnLSignString(p.NetProfit) + " " + p.QuoteCurrency, Short: true, }) } @@ -130,9 +130,9 @@ func (p *Profit) SlackAttachment() slack.Attachment { func (p *Profit) PlainText() string { var emoji string if !p.ProfitMargin.IsZero() { - emoji = pnlEmojiMargin(p.Profit, p.ProfitMargin, defaultPnlLevelResolution) + emoji = util.PnLEmojiMargin(p.Profit, p.ProfitMargin, util.DefaultPnLLevelResolution) } else { - emoji = pnlEmojiSimple(p.Profit) + emoji = util.PnLEmojiSimple(p.Profit) } return fmt.Sprintf("%s trade profit %s %s %s (%s), net profit =~ %s %s (%s)", @@ -145,62 +145,6 @@ func (p *Profit) PlainText() string { ) } -var lossEmoji = "🔥" -var profitEmoji = "💰" -var defaultPnlLevelResolution = fixedpoint.NewFromFloat(0.001) - -func pnlColor(pnl fixedpoint.Value) string { - if pnl.Sign() > 0 { - return GreenColor - } - return RedColor -} - -func pnlSignString(pnl fixedpoint.Value) string { - if pnl.Sign() > 0 { - return "+" + pnl.String() - } - return pnl.String() -} - -func pnlEmojiSimple(pnl fixedpoint.Value) string { - if pnl.Sign() < 0 { - return lossEmoji - } - - if pnl.IsZero() { - return "" - } - - return profitEmoji -} - -func pnlEmojiMargin(pnl, margin, resolution fixedpoint.Value) (out string) { - if margin.IsZero() { - return pnlEmojiSimple(pnl) - } - - if pnl.Sign() < 0 { - out = lossEmoji - level := (margin.Neg()).Div(resolution).Int() - for i := 1; i < level; i++ { - out += lossEmoji - } - return out - } - - if pnl.IsZero() { - return out - } - - out = profitEmoji - level := margin.Div(resolution).Int() - for i := 1; i < level; i++ { - out += profitEmoji - } - return out -} - type ProfitStats struct { Symbol string `json:"symbol"` QuoteCurrency string `json:"quoteCurrency"` @@ -303,8 +247,8 @@ func (s *ProfitStats) PlainText() string { } func (s *ProfitStats) SlackAttachment() slack.Attachment { - var color = pnlColor(s.AccumulatedPnL) - var title = fmt.Sprintf("%s Accumulated PnL %s %s", s.Symbol, pnlSignString(s.AccumulatedPnL), s.QuoteCurrency) + var color = util.PnLColor(s.AccumulatedPnL) + var title = fmt.Sprintf("%s Accumulated PnL %s %s", s.Symbol, util.PnLSignString(s.AccumulatedPnL), s.QuoteCurrency) since := time.Unix(s.AccumulatedSince, 0).Local() title += " Since " + since.Format(time.RFC822) @@ -314,7 +258,7 @@ func (s *ProfitStats) SlackAttachment() slack.Attachment { if !s.TodayPnL.IsZero() { fields = append(fields, slack.AttachmentField{ Title: "P&L Today", - Value: pnlSignString(s.TodayPnL) + " " + s.QuoteCurrency, + Value: util.PnLSignString(s.TodayPnL) + " " + s.QuoteCurrency, Short: true, }) } @@ -322,7 +266,7 @@ func (s *ProfitStats) SlackAttachment() slack.Attachment { if !s.TodayNetProfit.IsZero() { fields = append(fields, slack.AttachmentField{ Title: "Net Profit Today", - Value: pnlSignString(s.TodayNetProfit) + " " + s.QuoteCurrency, + Value: util.PnLSignString(s.TodayNetProfit) + " " + s.QuoteCurrency, Short: true, }) } @@ -330,7 +274,7 @@ func (s *ProfitStats) SlackAttachment() slack.Attachment { if !s.TodayGrossProfit.IsZero() { fields = append(fields, slack.AttachmentField{ Title: "Gross Profit Today", - Value: pnlSignString(s.TodayGrossProfit) + " " + s.QuoteCurrency, + Value: util.PnLSignString(s.TodayGrossProfit) + " " + s.QuoteCurrency, Short: true, }) } @@ -338,7 +282,7 @@ func (s *ProfitStats) SlackAttachment() slack.Attachment { if !s.TodayGrossLoss.IsZero() { fields = append(fields, slack.AttachmentField{ Title: "Gross Loss Today", - Value: pnlSignString(s.TodayGrossLoss) + " " + s.QuoteCurrency, + Value: util.PnLSignString(s.TodayGrossLoss) + " " + s.QuoteCurrency, Short: true, }) } @@ -346,28 +290,28 @@ func (s *ProfitStats) SlackAttachment() slack.Attachment { if !s.AccumulatedPnL.IsZero() { fields = append(fields, slack.AttachmentField{ Title: "Accumulated P&L", - Value: pnlSignString(s.AccumulatedPnL) + " " + s.QuoteCurrency, + Value: util.PnLSignString(s.AccumulatedPnL) + " " + s.QuoteCurrency, }) } if !s.AccumulatedGrossProfit.IsZero() { fields = append(fields, slack.AttachmentField{ Title: "Accumulated Gross Profit", - Value: pnlSignString(s.AccumulatedGrossProfit) + " " + s.QuoteCurrency, + Value: util.PnLSignString(s.AccumulatedGrossProfit) + " " + s.QuoteCurrency, }) } if !s.AccumulatedGrossLoss.IsZero() { fields = append(fields, slack.AttachmentField{ Title: "Accumulated Gross Loss", - Value: pnlSignString(s.AccumulatedGrossLoss) + " " + s.QuoteCurrency, + Value: util.PnLSignString(s.AccumulatedGrossLoss) + " " + s.QuoteCurrency, }) } if !s.AccumulatedNetProfit.IsZero() { fields = append(fields, slack.AttachmentField{ Title: "Accumulated Net Profit", - Value: pnlSignString(s.AccumulatedNetProfit) + " " + s.QuoteCurrency, + Value: util.PnLSignString(s.AccumulatedNetProfit) + " " + s.QuoteCurrency, }) } diff --git a/pkg/types/side.go b/pkg/types/side.go index 46c916aed..4eef24665 100644 --- a/pkg/types/side.go +++ b/pkg/types/side.go @@ -5,6 +5,8 @@ import ( "strings" "github.com/pkg/errors" + + "github.com/c9s/bbgo/pkg/util" ) // SideType define side type of order @@ -74,14 +76,14 @@ func (side SideType) String() string { func (side SideType) Color() string { if side == SideTypeBuy { - return GreenColor + return util.GreenColor } if side == SideTypeSell { - return RedColor + return util.RedColor } - return GrayColor + return util.GrayColor } func SideToColorName(side SideType) string { diff --git a/pkg/types/color.go b/pkg/util/colors.go similarity index 85% rename from pkg/types/color.go rename to pkg/util/colors.go index ac8324aa2..b17b407eb 100644 --- a/pkg/types/color.go +++ b/pkg/util/colors.go @@ -1,4 +1,4 @@ -package types +package util const GreenColor = "#228B22" const RedColor = "#800000" diff --git a/pkg/util/emoji.go b/pkg/util/emoji.go new file mode 100644 index 000000000..354718252 --- /dev/null +++ b/pkg/util/emoji.go @@ -0,0 +1,63 @@ +package util + +import ( + "github.com/c9s/bbgo/pkg/fixedpoint" +) + +var LossEmoji = "🔥" +var ProfitEmoji = "💰" +var DefaultPnLLevelResolution = fixedpoint.NewFromFloat(0.001) + +func PnLColor(pnl fixedpoint.Value) string { + if pnl.Sign() > 0 { + return GreenColor + } + return RedColor +} + +func PnLSignString(pnl fixedpoint.Value) string { + if pnl.Sign() > 0 { + return "+" + pnl.String() + } + return pnl.String() +} + + +func PnLEmojiSimple(pnl fixedpoint.Value) string { + if pnl.Sign() < 0 { + return LossEmoji + } + + if pnl.IsZero() { + return "" + } + + return ProfitEmoji +} + +func PnLEmojiMargin(pnl, margin, resolution fixedpoint.Value) (out string) { + if margin.IsZero() { + return PnLEmojiSimple(pnl) + } + + if pnl.Sign() < 0 { + out = LossEmoji + level := (margin.Neg()).Div(resolution).Int() + for i := 1; i < level; i++ { + out += LossEmoji + } + return out + } + + if pnl.IsZero() { + return out + } + + out = ProfitEmoji + level := margin.Div(resolution).Int() + for i := 1; i < level; i++ { + out += ProfitEmoji + } + return out +} +