fix trading volume query for sqlite3

This commit is contained in:
c9s 2021-02-06 16:05:21 +08:00
parent b12b882891
commit 8e0778a095
3 changed files with 76 additions and 9 deletions

View File

@ -139,10 +139,19 @@ func (s *OrderService) scanRows(rows *sqlx.Rows) (orders []types.Order, err erro
return orders, rows.Err() return orders, rows.Err()
} }
func (s *OrderService) Insert(order types.Order) error { func (s *OrderService) Insert(order types.Order) (err error) {
_, err := s.DB.NamedExec(` 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) 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) 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) 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 return err
} }

View File

@ -44,7 +44,15 @@ func (s *TradeService) QueryTradingVolume(startTime time.Time, options TradingVo
"start_time": startTime, "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) rows, err := s.DB.NamedQuery(sql, args)
if err != nil { if err != nil {
@ -72,14 +80,65 @@ func (s *TradeService) QueryTradingVolume(startTime time.Time, options TradingVo
return records, rows.Err() return records, rows.Err()
} }
func queryTradingVolumeSQL(options TradingVolumeQueryOptions) string {
func generateSqliteTradingVolumeSQL(options TradingVolumeQueryOptions) string {
var sel []string var sel []string
var groupBys []string var groupBys []string
var orderBys []string var orderBys []string
where := []string{"traded_at > :start_time"} where := []string{"traded_at > :start_time"}
switch options.GroupByPeriod {
switch options.GroupByPeriod {
case "month": 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") sel = append(sel, "YEAR(traded_at) AS year", "MONTH(traded_at) AS month")
groupBys = append([]string{"MONTH(traded_at)", "YEAR(traded_at)"}, groupBys...) groupBys = append([]string{"MONTH(traded_at)", "YEAR(traded_at)"}, groupBys...)
orderBys = append(orderBys, "year ASC", "month ASC") orderBys = append(orderBys, "year ASC", "month ASC")
@ -115,7 +174,6 @@ func queryTradingVolumeSQL(options TradingVolumeQueryOptions) string {
` GROUP BY ` + strings.Join(groupBys, ", ") + ` GROUP BY ` + strings.Join(groupBys, ", ") +
` ORDER BY ` + strings.Join(orderBys, ", ") ` ORDER BY ` + strings.Join(orderBys, ", ")
log.Info(sql)
return sql return sql
} }

View File

@ -11,15 +11,15 @@ func Test_queryTradingVolumeSQL(t *testing.T) {
o := TradingVolumeQueryOptions{ o := TradingVolumeQueryOptions{
GroupByPeriod: "month", 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" 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" 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"} { for _, s := range []string{"", "day"} {
o.GroupByPeriod = s o.GroupByPeriod = s
assert.Equal(t, expectedDefaultSQL, queryTradingVolumeSQL(o)) assert.Equal(t, expectedDefaultSQL, generateMysqlTradingVolumeQuerySQL(o))
} }
}) })