rename trade volume to quantity and record quote quantity

This commit is contained in:
c9s 2020-07-22 12:26:27 +08:00
parent da75905aeb
commit 4a4178286a
5 changed files with 137 additions and 14 deletions

View File

@ -164,7 +164,82 @@ func (e *Exchange) QueryKLines(ctx context.Context, symbol, interval string, opt
return kLines, nil return kLines, nil
} }
func (e *Exchange) BatchQueryTrades(ctx context.Context, symbol string, startTime time.Time) (trades []types.Trade, err error) { type TradeQueryOptions struct {
StartTime *time.Time
EndTime *time.Time
Limit int
LastTradeID int64
}
func (e *Exchange) QueryTrades(ctx context.Context, symbol string, options *TradeQueryOptions) (trades []types.Trade, err error) {
req := e.Client.NewListTradesService().
Limit(1000).
Symbol(symbol)
if options.Limit > 0 {
req.Limit(options.Limit)
}
if options.StartTime != nil {
req.StartTime(options.StartTime.UnixNano() / int64(time.Millisecond))
}
if options.EndTime != nil {
req.EndTime(options.EndTime.UnixNano() / int64(time.Millisecond))
}
if options.LastTradeID > 0 {
req.FromID(options.LastTradeID)
}
remoteTrades, err := req.Do(ctx)
if err != nil {
return nil, err
}
for _, t := range remoteTrades {
// skip trade ID that is the same. however this should not happen
var side string
if t.IsBuyer {
side = "BUY"
} else {
side = "SELL"
}
// trade time
tt := time.Unix(0, t.Time*1000000)
logrus.Infof("[binance] trade: %d %s % 4s price: % 13s volume: % 11s %6s % 5s %s", t.ID, t.Symbol, side, t.Price, t.Quantity, BuyerOrSellerLabel(t), MakerOrTakerLabel(t), tt)
price, err := strconv.ParseFloat(t.Price, 64)
if err != nil {
return nil, err
}
quantity, err := strconv.ParseFloat(t.Quantity, 64)
if err != nil {
return nil, err
}
fee, err := strconv.ParseFloat(t.Commission, 64)
if err != nil {
return nil, err
}
trades = append(trades, types.Trade{
ID: t.ID,
Price: price,
Quantity: quantity,
Side: side,
IsBuyer: t.IsBuyer,
IsMaker: t.IsMaker,
Fee: fee,
FeeCurrency: t.CommissionAsset,
Time: tt,
})
}
}
func (e *Exchange) BatchQueryTrades(ctx context.Context, symbol string, startTime time.Time, options *TradeQueryOptions) (trades []types.Trade, err error) {
logrus.Infof("[binance] querying %s trades from %s", symbol, startTime) logrus.Infof("[binance] querying %s trades from %s", symbol, startTime)
var lastTradeID int64 = 0 var lastTradeID int64 = 0
@ -223,7 +298,7 @@ func (e *Exchange) BatchQueryTrades(ctx context.Context, symbol string, startTim
trades = append(trades, types.Trade{ trades = append(trades, types.Trade{
ID: t.ID, ID: t.ID,
Price: price, Price: price,
Volume: quantity, Quantity: quantity,
Side: side, Side: side,
IsBuyer: t.IsBuyer, IsBuyer: t.IsBuyer,
IsMaker: t.IsMaker, IsMaker: t.IsMaker,
@ -238,3 +313,49 @@ func (e *Exchange) BatchQueryTrades(ctx context.Context, symbol string, startTim
return trades, nil return trades, nil
} }
func convertRemoteTrade(t binance.TradeV3) (*types.Trade, error) {
// skip trade ID that is the same. however this should not happen
var side string
if t.IsBuyer {
side = "BUY"
} else {
side = "SELL"
}
// trade time
mts := time.Unix(0, t.Time*int64(time.Millisecond))
price, err := strconv.ParseFloat(t.Price, 64)
if err != nil {
return nil, err
}
quantity, err := strconv.ParseFloat(t.Quantity, 64)
if err != nil {
return nil, err
}
quoteQuantity, err := strconv.ParseFloat(t.QuoteQuantity, 64)
if err != nil {
return nil, err
}
fee, err := strconv.ParseFloat(t.Commission, 64)
if err != nil {
return nil, err
}
return &types.Trade{
ID: t.ID,
Price: price,
Quantity: quantity,
Side: side,
IsBuyer: t.IsBuyer,
IsMaker: t.IsMaker,
Fee: fee,
FeeCurrency: t.CommissionAsset,
QuoteQuantity: quoteQuantity,
Time: mts,
}, nil
}

View File

@ -93,7 +93,7 @@ func (e *ExecutionReportEvent) Trade() (*types.Trade, error) {
ID: e.TradeID, ID: e.TradeID,
Symbol: e.Symbol, Symbol: e.Symbol,
Price: util.MustParseFloat(e.LastExecutedPrice), Price: util.MustParseFloat(e.LastExecutedPrice),
Volume: util.MustParseFloat(e.LastExecutedQuantity), Quantity: util.MustParseFloat(e.LastExecutedQuantity),
Side: e.Side, Side: e.Side,
IsBuyer: e.Side == "BUY", IsBuyer: e.Side == "BUY",
IsMaker: e.IsMaker, IsMaker: e.IsMaker,

View File

@ -48,8 +48,8 @@ func (c *ProfitAndLossCalculator) Calculate() *ProfitAndLossReport {
for _, t := range trades { for _, t := range trades {
if t.IsBuyer { if t.IsBuyer {
bidVolume += t.Volume bidVolume += t.Quantity
bidAmount += t.Price * t.Volume bidAmount += t.Price * t.Quantity
// since we use USDT as the quote currency, we simply check if it matches the currency symbol // since we use USDT as the quote currency, we simply check if it matches the currency symbol
if strings.HasPrefix(t.Symbol, t.FeeCurrency) { if strings.HasPrefix(t.Symbol, t.FeeCurrency) {
@ -66,8 +66,8 @@ func (c *ProfitAndLossCalculator) Calculate() *ProfitAndLossReport {
for _, t := range trades { for _, t := range trades {
if !t.IsBuyer { if !t.IsBuyer {
profit += (t.Price - averageBidPrice) * t.Volume profit += (t.Price - averageBidPrice) * t.Quantity
askVolume += t.Volume askVolume += t.Quantity
// since we use USDT as the quote currency, we simply check if it matches the currency symbol // since we use USDT as the quote currency, we simply check if it matches the currency symbol
if strings.HasPrefix(t.Symbol, t.FeeCurrency) { if strings.HasPrefix(t.Symbol, t.FeeCurrency) {

View File

@ -119,7 +119,7 @@ func (trader *KLineRegressionTrader) RunStrategy(ctx context.Context, strategy S
trade := types.Trade{ trade := types.Trade{
ID: tradeID, ID: tradeID,
Price: price, Price: price,
Volume: volume, Quantity: volume,
Side: string(order.Side), Side: string(order.Side),
IsBuyer: order.Side == types.SideTypeBuy, IsBuyer: order.Side == types.SideTypeBuy,
IsMaker: false, IsMaker: false,

View File

@ -10,11 +10,13 @@ type Trade struct {
GID int64 `json:"gid" db:"gid"` GID int64 `json:"gid" db:"gid"`
// ID is the source trade ID // ID is the source trade ID
ID int64 `json:"id" db:"id"` ID int64 `json:"id" db:"id"`
Exchange string `json:"exchange" db:"exchange"` Exchange string `json:"exchange" db:"exchange"`
Price float64 `json:"price" db:"price"` Price float64 `json:"price" db:"price"`
Volume float64 `json:"volume" db:"volume"` Quantity float64 `json:"quantity" db:"quantity"`
Symbol string `json:"symbol" db:"symbol"` QuoteQuantity float64 `json:"quoteQuantity" db:"quote_quantity"`
Symbol string `json:"symbol" db:"symbol"`
Side string `json:"side" db:"side"` Side string `json:"side" db:"side"`
IsBuyer bool `json:"isBuyer" db:"is_buyer"` IsBuyer bool `json:"isBuyer" db:"is_buyer"`
IsMaker bool `json:"isMaker" db:"is_maker"` IsMaker bool `json:"isMaker" db:"is_maker"`
@ -48,7 +50,7 @@ func (trade Trade) SlackAttachment() slack.Attachment {
{Title: "Symbol", Value: trade.Symbol, Short: true}, {Title: "Symbol", Value: trade.Symbol, Short: true},
{Title: "Side", Value: trade.Side, Short: true}, {Title: "Side", Value: trade.Side, Short: true},
{Title: "Price", Value: market.FormatPrice(trade.Price), Short: true}, {Title: "Price", Value: market.FormatPrice(trade.Price), Short: true},
{Title: "Volume", Value: market.FormatVolume(trade.Volume), Short: true}, {Title: "Volume", Value: market.FormatVolume(trade.Quantity), Short: true},
}, },
// Footer: tradingCtx.TradeStartTime.Format(time.RFC822), // Footer: tradingCtx.TradeStartTime.Format(time.RFC822),
// FooterIcon: "", // FooterIcon: "",