mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-13 02:23:51 +00:00
rename trade volume to quantity and record quote quantity
This commit is contained in:
parent
da75905aeb
commit
4a4178286a
|
@ -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
|
||||||
|
}
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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) {
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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: "",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user