bbgo_origin/pkg/bbgo/reporter.go

152 lines
3.1 KiB
Go
Raw Permalink Normal View History

2020-10-26 08:15:30 +00:00
package bbgo
import (
"regexp"
2020-10-26 08:15:30 +00:00
"github.com/robfig/cron/v3"
)
type PnLReporter interface {
Run()
}
type baseReporter struct {
notifier Notifier
cron *cron.Cron
environment *Environment
}
type PnLReporterManager struct {
baseReporter
reporters []PnLReporter
}
func NewPnLReporter(notifier Notifier) *PnLReporterManager {
return &PnLReporterManager{
baseReporter: baseReporter{
notifier: notifier,
cron: cron.New(),
},
}
}
func (manager *PnLReporterManager) AverageCostBySymbols(symbols ...string) *AverageCostPnLReporter {
reporter := &AverageCostPnLReporter{
baseReporter: manager.baseReporter,
Symbols: symbols,
}
manager.reporters = append(manager.reporters, reporter)
return reporter
}
type AverageCostPnLReporter struct {
baseReporter
Sessions []string
Symbols []string
}
func (reporter *AverageCostPnLReporter) Of(sessions ...string) *AverageCostPnLReporter {
reporter.Sessions = sessions
return reporter
}
func (reporter *AverageCostPnLReporter) When(specs ...string) *AverageCostPnLReporter {
for _, spec := range specs {
_, err := reporter.cron.AddJob(spec, reporter)
if err != nil {
panic(err)
}
}
return reporter
}
func (reporter *AverageCostPnLReporter) Run() {
2021-12-04 18:16:48 +00:00
// FIXME: this is causing cyclic import
/*
for _, sessionName := range reporter.Sessions {
session := reporter.environment.sessions[sessionName]
calculator := &pnl.AverageCostCalculator{
TradingFeeCurrency: session.Exchange.PlatformFeeCurrency(),
}
for _, symbol := range reporter.Symbols {
report := calculator.Calculate(symbol, session.Trades[symbol].Copy(), session.lastPrices[symbol])
report.Print()
}
2020-10-26 08:15:30 +00:00
}
2021-12-04 18:16:48 +00:00
*/
2020-10-26 08:15:30 +00:00
}
2020-10-27 00:48:47 +00:00
type PatternChannelRouter struct {
routes map[*regexp.Regexp]string
}
2020-10-27 01:24:59 +00:00
func NewPatternChannelRouter(routes map[string]string) *PatternChannelRouter {
router := &PatternChannelRouter{
routes: make(map[*regexp.Regexp]string),
}
if routes != nil {
router.AddRoute(routes)
}
return router
}
func (router *PatternChannelRouter) AddRoute(routes map[string]string) {
if routes == nil {
return
}
2020-10-30 21:21:17 +00:00
if router.routes == nil {
router.routes = make(map[*regexp.Regexp]string)
}
for pattern, channel := range routes {
router.routes[regexp.MustCompile(pattern)] = channel
}
}
2020-10-27 01:24:59 +00:00
func (router *PatternChannelRouter) Route(text string) (channel string, ok bool) {
for pattern, channel := range router.routes {
2020-10-27 00:48:47 +00:00
if pattern.MatchString(text) {
ok = true
return channel, ok
}
}
return channel, ok
}
type ObjectChannelHandler func(obj interface{}) (channel string, ok bool)
type ObjectChannelRouter struct {
routes []ObjectChannelHandler
}
2020-10-27 01:24:59 +00:00
func NewObjectChannelRouter() *ObjectChannelRouter {
return &ObjectChannelRouter{}
}
func (router *ObjectChannelRouter) AddRoute(f ObjectChannelHandler) {
router.routes = append(router.routes, f)
}
2020-10-27 01:24:59 +00:00
func (router *ObjectChannelRouter) Route(obj interface{}) (channel string, ok bool) {
for _, f := range router.routes {
channel, ok = f(obj)
if ok {
return
}
}
return
}
type TradeReporter struct {
*Notifiability
}
2020-10-30 21:21:17 +00:00
const TemplateOrderReport = `:handshake: {{ .Symbol }} {{ .Side }} Order Update @ {{ .Price }}`