From 8e0778a095aa013c5d4a6030d87b85f43f0e3da6 Mon Sep 17 00:00:00 2001 From: c9s Date: Sat, 6 Feb 2021 16:05:21 +0800 Subject: [PATCH] fix trading volume query for sqlite3 --- pkg/service/order.go | 13 ++++++-- pkg/service/trade.go | 66 ++++++++++++++++++++++++++++++++++++--- pkg/service/trade_test.go | 6 ++-- 3 files changed, 76 insertions(+), 9 deletions(-) diff --git a/pkg/service/order.go b/pkg/service/order.go index 3ff86124e..c0cdde8cc 100644 --- a/pkg/service/order.go +++ b/pkg/service/order.go @@ -139,10 +139,19 @@ func (s *OrderService) scanRows(rows *sqlx.Rows) (orders []types.Order, err erro return orders, rows.Err() } -func (s *OrderService) Insert(order types.Order) error { - _, err := s.DB.NamedExec(` +func (s *OrderService) Insert(order types.Order) (err error) { + if s.DB.DriverName() == "mysql" { + _, err = s.DB.NamedExec(` INSERT INTO orders (exchange, order_id, client_order_id, order_type, status, symbol, price, stop_price, quantity, executed_quantity, side, is_working, time_in_force, created_at, updated_at, is_margin, is_isolated) VALUES (:exchange, :order_id, :client_order_id, :order_type, :status, :symbol, :price, :stop_price, :quantity, :executed_quantity, :side, :is_working, :time_in_force, :created_at, :updated_at, :is_margin, :is_isolated) ON DUPLICATE KEY UPDATE status=:status, executed_quantity=:executed_quantity, is_working=:is_working, updated_at=:updated_at`, order) + return err + } + + _, err = s.DB.NamedExec(` + INSERT INTO orders (exchange, order_id, client_order_id, order_type, status, symbol, price, stop_price, quantity, executed_quantity, side, is_working, time_in_force, created_at, updated_at, is_margin, is_isolated) + VALUES (:exchange, :order_id, :client_order_id, :order_type, :status, :symbol, :price, :stop_price, :quantity, :executed_quantity, :side, :is_working, :time_in_force, :created_at, :updated_at, :is_margin, :is_isolated) + `, order) + return err } diff --git a/pkg/service/trade.go b/pkg/service/trade.go index e607cc668..c1a2d2d60 100644 --- a/pkg/service/trade.go +++ b/pkg/service/trade.go @@ -44,7 +44,15 @@ func (s *TradeService) QueryTradingVolume(startTime time.Time, options TradingVo "start_time": startTime, } - sql := queryTradingVolumeSQL(options) + sql := "" + driverName := s.DB.DriverName() + if driverName == "mysql" { + sql = generateMysqlTradingVolumeQuerySQL(options) + } else { + sql = generateSqliteTradingVolumeSQL(options) + } + + log.Info(sql) rows, err := s.DB.NamedQuery(sql, args) if err != nil { @@ -72,14 +80,65 @@ func (s *TradeService) QueryTradingVolume(startTime time.Time, options TradingVo return records, rows.Err() } -func queryTradingVolumeSQL(options TradingVolumeQueryOptions) string { + +func generateSqliteTradingVolumeSQL(options TradingVolumeQueryOptions) string { var sel []string var groupBys []string var orderBys []string where := []string{"traded_at > :start_time"} - switch options.GroupByPeriod { + switch options.GroupByPeriod { case "month": + sel = append(sel, "strftime('%Y',traded_at) AS year", "strftime('%m',traded_at) AS month") + groupBys = append([]string{"month", "year"}, groupBys...) + orderBys = append(orderBys, "year ASC", "month ASC") + + case "year": + sel = append(sel, "strftime('%Y',traded_at) AS year") + groupBys = append([]string{"year"}, groupBys...) + orderBys = append(orderBys, "year ASC") + + case "day": + fallthrough + + default: + sel = append(sel, "strftime('%Y',traded_at) AS year", "strftime('%m',traded_at) AS month", "strftime('%d',traded_at) AS day") + groupBys = append([]string{"day", "month", "year"}, groupBys...) + orderBys = append(orderBys, "year ASC", "month ASC", "day ASC") + } + + switch options.SegmentBy { + case "symbol": + sel = append(sel, "symbol") + groupBys = append([]string{"symbol"}, groupBys...) + orderBys = append(orderBys, "symbol") + case "exchange": + sel = append(sel, "exchange") + groupBys = append([]string{"exchange"}, groupBys...) + orderBys = append(orderBys, "exchange") + } + + sel = append(sel, "SUM(quantity * price) AS quote_volume") + sql := `SELECT ` + strings.Join(sel, ", ") + ` FROM trades` + + ` WHERE ` + strings.Join(where, " AND ") + + ` GROUP BY ` + strings.Join(groupBys, ", ") + + ` ORDER BY ` + strings.Join(orderBys, ", ") + + return sql +} + + +func generateMysqlTradingVolumeQuerySQL(options TradingVolumeQueryOptions) string { + var sel []string + var groupBys []string + var orderBys []string + where := []string{"traded_at > :start_time"} + + switch options.GroupByPeriod { + case "month": + + + sel = append(sel, "YEAR(traded_at) AS year", "MONTH(traded_at) AS month") groupBys = append([]string{"MONTH(traded_at)", "YEAR(traded_at)"}, groupBys...) orderBys = append(orderBys, "year ASC", "month ASC") @@ -115,7 +174,6 @@ func queryTradingVolumeSQL(options TradingVolumeQueryOptions) string { ` GROUP BY ` + strings.Join(groupBys, ", ") + ` ORDER BY ` + strings.Join(orderBys, ", ") - log.Info(sql) return sql } diff --git a/pkg/service/trade_test.go b/pkg/service/trade_test.go index 35e4e486d..25e9b8bef 100644 --- a/pkg/service/trade_test.go +++ b/pkg/service/trade_test.go @@ -11,15 +11,15 @@ func Test_queryTradingVolumeSQL(t *testing.T) { o := TradingVolumeQueryOptions{ GroupByPeriod: "month", } - assert.Equal(t, "SELECT YEAR(traded_at) AS year, MONTH(traded_at) AS month, SUM(quantity * price) AS quote_volume FROM trades WHERE traded_at > :start_time GROUP BY MONTH(traded_at), YEAR(traded_at) ORDER BY year ASC, month ASC", queryTradingVolumeSQL(o)) + assert.Equal(t, "SELECT YEAR(traded_at) AS year, MONTH(traded_at) AS month, SUM(quantity * price) AS quote_volume FROM trades WHERE traded_at > :start_time GROUP BY MONTH(traded_at), YEAR(traded_at) ORDER BY year ASC, month ASC", generateMysqlTradingVolumeQuerySQL(o)) o.GroupByPeriod = "year" - assert.Equal(t, "SELECT YEAR(traded_at) AS year, SUM(quantity * price) AS quote_volume FROM trades WHERE traded_at > :start_time GROUP BY YEAR(traded_at) ORDER BY year ASC", queryTradingVolumeSQL(o)) + assert.Equal(t, "SELECT YEAR(traded_at) AS year, SUM(quantity * price) AS quote_volume FROM trades WHERE traded_at > :start_time GROUP BY YEAR(traded_at) ORDER BY year ASC", generateMysqlTradingVolumeQuerySQL(o)) expectedDefaultSQL := "SELECT YEAR(traded_at) AS year, MONTH(traded_at) AS month, DAY(traded_at) AS day, SUM(quantity * price) AS quote_volume FROM trades WHERE traded_at > :start_time GROUP BY DAY(traded_at), MONTH(traded_at), YEAR(traded_at) ORDER BY year ASC, month ASC, day ASC" for _, s := range []string{"", "day"} { o.GroupByPeriod = s - assert.Equal(t, expectedDefaultSQL, queryTradingVolumeSQL(o)) + assert.Equal(t, expectedDefaultSQL, generateMysqlTradingVolumeQuerySQL(o)) } })