Exchanges: enrich order history with avg executed price, cost, and more (#792)

* Exchanges: enrich order history with avg executed price, cost, and more

* Fix division by zero in order detail enrichment

* Remove DateCompleted from Bithumb OrderData and fix OrderDate parsing

* Fixes on order detail fields and rename EnrichOrderDetail to CalculateCostsAndAmounts

* BTSE order history populate name and id

* Calculate average executed price for market order or when order amount is zero

* Minor fixes on infer order amounts, costs, and times

* Attach InferAmountsCostsAndTimes to Order.Detail

* Binance: fix order status

* Always use order.StringToOrderStatus() and ensure order has at least one of executed/remaining amount set
This commit is contained in:
khcchiu
2021-10-26 08:22:30 +08:00
committed by GitHub
parent 6345014612
commit 8617b50ff6
33 changed files with 556 additions and 259 deletions

View File

@@ -376,6 +376,7 @@ func (a *Alphapoint) GetActiveOrders(ctx context.Context, req *order.GetOrdersRe
orderDetail := order.Detail{
Amount: resp[x].OpenOrders[y].QtyTotal,
Exchange: a.Name,
ExecutedAmount: resp[x].OpenOrders[y].QtyTotal - resp[x].OpenOrders[y].QtyRemaining,
AccountID: strconv.FormatInt(int64(resp[x].OpenOrders[y].AccountID), 10),
ID: strconv.FormatInt(int64(resp[x].OpenOrders[y].ServerOrderID), 10),
Price: resp[x].OpenOrders[y].Price,
@@ -423,6 +424,7 @@ func (a *Alphapoint) GetOrderHistory(ctx context.Context, req *order.GetOrdersRe
Amount: resp[x].OpenOrders[y].QtyTotal,
AccountID: strconv.FormatInt(int64(resp[x].OpenOrders[y].AccountID), 10),
Exchange: a.Name,
ExecutedAmount: resp[x].OpenOrders[y].QtyTotal - resp[x].OpenOrders[y].QtyRemaining,
ID: strconv.FormatInt(int64(resp[x].OpenOrders[y].ServerOrderID), 10),
Price: resp[x].OpenOrders[y].Price,
RemainingAmount: resp[x].OpenOrders[y].QtyRemaining,

View File

@@ -1130,7 +1130,7 @@ func (b *Binance) GetOrderInfo(ctx context.Context, orderID string, pair currenc
orderSide := order.Side(resp.Side)
status, err := order.StringToOrderStatus(resp.Status)
if err != nil {
return respData, err
log.Errorf(log.ExchangeSys, "%s %v", b.Name, err)
}
orderType := order.Limit
if resp.Type == "MARKET" {
@@ -1295,6 +1295,10 @@ func (b *Binance) GetActiveOrders(ctx context.Context, req *order.GetOrdersReque
for x := range resp {
orderSide := order.Side(strings.ToUpper(resp[x].Side))
orderType := order.Type(strings.ToUpper(resp[x].Type))
orderStatus, err := order.StringToOrderStatus(resp[i].Status)
if err != nil {
log.Errorf(log.ExchangeSys, "%s %v", b.Name, err)
}
orders = append(orders, order.Detail{
Amount: resp[x].OrigQty,
Date: resp[x].Time,
@@ -1304,7 +1308,7 @@ func (b *Binance) GetActiveOrders(ctx context.Context, req *order.GetOrdersReque
Side: orderSide,
Type: orderType,
Price: resp[x].Price,
Status: order.Status(resp[x].Status),
Status: orderStatus,
Pair: req.Pairs[i],
AssetType: req.AssetType,
LastUpdated: resp[x].UpdateTime,
@@ -1411,22 +1415,39 @@ func (b *Binance) GetOrderHistory(ctx context.Context, req *order.GetOrdersReque
for i := range resp {
orderSide := order.Side(strings.ToUpper(resp[i].Side))
orderType := order.Type(strings.ToUpper(resp[i].Type))
orderStatus, err := order.StringToOrderStatus(resp[i].Status)
if err != nil {
log.Errorf(log.ExchangeSys, "%s %v", b.Name, err)
}
// New orders are covered in GetOpenOrders
if resp[i].Status == "NEW" {
if orderStatus == order.New {
continue
}
orders = append(orders, order.Detail{
Amount: resp[i].OrigQty,
Date: resp[i].Time,
Exchange: b.Name,
ID: strconv.FormatInt(resp[i].OrderID, 10),
Side: orderSide,
Type: orderType,
Price: resp[i].Price,
Pair: req.Pairs[x],
Status: order.Status(resp[i].Status),
})
var cost float64
// For some historical orders cummulativeQuoteQty will be < 0,
// meaning the data is not available at this time.
if resp[i].CummulativeQuoteQty > 0 {
cost = resp[i].CummulativeQuoteQty
}
detail := order.Detail{
Amount: resp[i].OrigQty,
ExecutedAmount: resp[i].ExecutedQty,
RemainingAmount: resp[i].OrigQty - resp[i].ExecutedQty,
Cost: cost,
CostAsset: req.Pairs[x].Quote,
Date: resp[i].Time,
LastUpdated: resp[i].UpdateTime,
Exchange: b.Name,
ID: strconv.FormatInt(resp[i].OrderID, 10),
Side: orderSide,
Type: orderType,
Price: resp[i].Price,
Pair: req.Pairs[x],
Status: orderStatus,
}
detail.InferCostsAndTimes()
orders = append(orders, detail)
}
}
case asset.CoinMarginedFutures:

View File

@@ -956,16 +956,18 @@ func (b *Bitfinex) GetOrderHistory(ctx context.Context, req *order.GetOrdersRequ
}
orderDetail := order.Detail{
Amount: resp[i].OriginalAmount,
Date: orderDate,
Exchange: b.Name,
ID: strconv.FormatInt(resp[i].ID, 10),
Side: orderSide,
Price: resp[i].Price,
RemainingAmount: resp[i].RemainingAmount,
ExecutedAmount: resp[i].ExecutedAmount,
Pair: pair,
Amount: resp[i].OriginalAmount,
Date: orderDate,
Exchange: b.Name,
ID: strconv.FormatInt(resp[i].ID, 10),
Side: orderSide,
Price: resp[i].Price,
AverageExecutedPrice: resp[i].AverageExecutionPrice,
RemainingAmount: resp[i].RemainingAmount,
ExecutedAmount: resp[i].ExecutedAmount,
Pair: pair,
}
orderDetail.InferCostsAndTimes()
switch {
case resp[i].IsLive:

View File

@@ -127,18 +127,17 @@ type Orders struct {
// OrderData contains all individual order details
type OrderData struct {
OrderID string `json:"order_id"`
OrderCurrency string `json:"order_currency"`
OrderDate int64 `json:"order_date"`
PaymentCurrency string `json:"payment_currency"`
Type string `json:"type"`
Status string `json:"status"`
Units float64 `json:"units,string"`
UnitsRemaining float64 `json:"units_remaining,string"`
Price float64 `json:"price,string"`
Fee float64 `json:"fee,string"`
Total float64 `json:"total,string"`
DateCompleted int64 `json:"date_completed"`
OrderID string `json:"order_id"`
OrderCurrency string `json:"order_currency"`
OrderDate bithumbTime `json:"order_date"`
PaymentCurrency string `json:"payment_currency"`
Type string `json:"type"`
Status string `json:"status"`
Units float64 `json:"units,string"`
UnitsRemaining float64 `json:"units_remaining,string"`
Price float64 `json:"price,string"`
Fee float64 `json:"fee,string"`
Total float64 `json:"total,string"`
}
// UserTransactions holds users full transaction list

View File

@@ -692,12 +692,12 @@ func (b *Bithumb) GetActiveOrders(ctx context.Context, req *order.GetOrdersReque
continue
}
orderDate := time.Unix(resp.Data[i].OrderDate, 0)
orderDetail := order.Detail{
Amount: resp.Data[i].Units,
Exchange: b.Name,
ExecutedAmount: resp.Data[i].Units - resp.Data[i].UnitsRemaining,
ID: resp.Data[i].OrderID,
Date: orderDate,
Date: resp.Data[i].OrderDate.Time(),
Price: resp.Data[i].Price,
RemainingAmount: resp.Data[i].UnitsRemaining,
Status: order.Active,
@@ -750,14 +750,14 @@ func (b *Bithumb) GetOrderHistory(ctx context.Context, req *order.GetOrdersReque
continue
}
orderDate := time.Unix(resp.Data[i].OrderDate, 0)
orderDetail := order.Detail{
Amount: resp.Data[i].Units,
ExecutedAmount: resp.Data[i].Units - resp.Data[i].UnitsRemaining,
RemainingAmount: resp.Data[i].UnitsRemaining,
Exchange: b.Name,
ID: resp.Data[i].OrderID,
Date: orderDate,
Date: resp.Data[i].OrderDate.Time(),
Price: resp.Data[i].Price,
RemainingAmount: resp.Data[i].UnitsRemaining,
Pair: currency.NewPairWithDelimiter(resp.Data[i].OrderCurrency,
resp.Data[i].PaymentCurrency,
format.Delimiter),
@@ -769,6 +769,7 @@ func (b *Bithumb) GetOrderHistory(ctx context.Context, req *order.GetOrdersReque
orderDetail.Side = order.Sell
}
orderDetail.InferCostsAndTimes()
orders = append(orders, orderDetail)
}
}

View File

@@ -291,18 +291,18 @@ type Order struct {
ClOrdID string `json:"clOrdID"`
ClOrdLinkID string `json:"clOrdLinkID"`
ContingencyType string `json:"contingencyType"`
CumQty int64 `json:"cumQty"`
CumQty float64 `json:"cumQty"`
Currency string `json:"currency"`
DisplayQuantity int64 `json:"displayQty"`
ExDestination string `json:"exDestination"`
ExecInst string `json:"execInst"`
LeavesQty int64 `json:"leavesQty"`
LeavesQty float64 `json:"leavesQty"`
MultiLegReportingType string `json:"multiLegReportingType"`
OrdRejReason string `json:"ordRejReason"`
OrdStatus string `json:"ordStatus"`
OrdType int64 `json:"ordType,string"`
OrderID string `json:"orderID"`
OrderQty int64 `json:"orderQty"`
OrderQty float64 `json:"orderQty"`
PegOffsetValue float64 `json:"pegOffsetValue"`
PegPriceType string `json:"pegPriceType"`
Price float64 `json:"price"`
@@ -316,7 +316,7 @@ type Order struct {
Text string `json:"text"`
TimeInForce string `json:"timeInForce"`
Timestamp time.Time `json:"timestamp"`
TransactTime string `json:"transactTime"`
TransactTime time.Time `json:"transactTime"`
Triggered string `json:"triggered"`
WorkingIndicator bool `json:"workingIndicator"`
}

View File

@@ -748,20 +748,26 @@ func (b *Bitmex) GetActiveOrders(ctx context.Context, req *order.GetOrdersReques
for i := range resp {
orderSide := orderSideMap[resp[i].Side]
orderStatus, err := order.StringToOrderStatus(resp[i].OrdStatus)
if err != nil {
log.Errorf(log.ExchangeSys, "%s %v", b.Name, err)
}
orderType := orderTypeMap[resp[i].OrdType]
if orderType == "" {
orderType = order.UnknownType
}
orderDetail := order.Detail{
Date: resp[i].Timestamp,
Price: resp[i].Price,
Amount: float64(resp[i].OrderQty),
Exchange: b.Name,
ID: resp[i].OrderID,
Side: orderSide,
Type: orderType,
Status: order.Status(resp[i].OrdStatus),
Date: resp[i].Timestamp,
Price: resp[i].Price,
Amount: resp[i].OrderQty,
ExecutedAmount: resp[i].CumQty,
RemainingAmount: resp[i].LeavesQty,
Exchange: b.Name,
ID: resp[i].OrderID,
Side: orderSide,
Status: orderStatus,
Type: orderType,
Pair: currency.NewPairWithDelimiter(resp[i].Symbol,
resp[i].SettlCurrency,
format.Delimiter),
@@ -799,23 +805,32 @@ func (b *Bitmex) GetOrderHistory(ctx context.Context, req *order.GetOrdersReques
for i := range resp {
orderSide := orderSideMap[resp[i].Side]
orderStatus, err := order.StringToOrderStatus(resp[i].OrdStatus)
if err != nil {
log.Errorf(log.ExchangeSys, "%s %v", b.Name, err)
}
orderType := orderTypeMap[resp[i].OrdType]
if orderType == "" {
orderType = order.UnknownType
}
pair := currency.NewPairWithDelimiter(resp[i].Symbol, resp[i].SettlCurrency, format.Delimiter)
orderDetail := order.Detail{
Price: resp[i].Price,
Amount: float64(resp[i].OrderQty),
Exchange: b.Name,
ID: resp[i].OrderID,
Side: orderSide,
Type: orderType,
Status: order.Status(resp[i].OrdStatus),
Pair: currency.NewPairWithDelimiter(resp[i].Symbol,
resp[i].SettlCurrency,
format.Delimiter),
Price: resp[i].Price,
AverageExecutedPrice: resp[i].AvgPx,
Amount: resp[i].OrderQty,
ExecutedAmount: resp[i].CumQty,
RemainingAmount: resp[i].LeavesQty,
Date: resp[i].TransactTime,
CloseTime: resp[i].Timestamp,
Exchange: b.Name,
ID: resp[i].OrderID,
Side: orderSide,
Status: orderStatus,
Type: orderType,
Pair: pair,
}
orderDetail.InferCostsAndTimes()
orders = append(orders, orderDetail)
}

View File

@@ -856,12 +856,13 @@ func (b *Bittrex) GetOrderHistory(ctx context.Context, req *order.GetOrdersReque
continue
}
resp = append(resp, order.Detail{
detail := order.Detail{
Amount: orderData[i].Quantity,
RemainingAmount: orderData[i].Quantity - orderData[i].FillQuantity,
ExecutedAmount: orderData[i].FillQuantity,
RemainingAmount: orderData[i].Quantity - orderData[i].FillQuantity,
Price: orderData[i].Limit,
Date: orderData[i].CreatedAt,
CloseTime: orderData[i].ClosedAt,
ID: orderData[i].ID,
Exchange: b.Name,
Type: orderType,
@@ -869,7 +870,9 @@ func (b *Bittrex) GetOrderHistory(ctx context.Context, req *order.GetOrdersReque
Status: orderStatus,
Fee: orderData[i].Commission,
Pair: pair,
})
}
detail.InferCostsAndTimes()
resp = append(resp, detail)
}
order.FilterOrdersByType(&resp, req.Type)

View File

@@ -864,7 +864,10 @@ func (b *BTCMarkets) GetOrderHistory(ctx context.Context, req *order.GetOrdersRe
tempResp.ID = tempData.Orders[c].OrderID
tempResp.Date = tempData.Orders[c].CreationTime
tempResp.Price = tempData.Orders[c].Price
tempResp.ExecutedAmount = tempData.Orders[c].Amount
tempResp.Amount = tempData.Orders[c].Amount
tempResp.ExecutedAmount = tempData.Orders[c].Amount - tempData.Orders[c].OpenAmount
tempResp.RemainingAmount = tempData.Orders[c].OpenAmount
tempResp.InferCostsAndTimes()
resp = append(resp, tempResp)
}
}

View File

@@ -648,7 +648,9 @@ func (b *BTSE) GetOrderInfo(ctx context.Context, orderID string, pair currency.P
od.Type = orderIntToType(o[i].OrderType)
od.Price = o[i].Price
od.Status = order.Status(o[i].OrderState)
if od.Status, err = order.StringToOrderStatus(o[i].OrderState); err != nil {
log.Errorf(log.ExchangeSys, "%s %v", b.Name, err)
}
th, err := b.TradeHistory(ctx,
"",
@@ -782,6 +784,11 @@ func (b *BTSE) GetActiveOrders(ctx context.Context, req *order.GetOrdersRequest)
side = order.Sell
}
status, err := order.StringToOrderStatus(resp[i].OrderState)
if err != nil {
log.Errorf(log.ExchangeSys, "%s %v", b.Name, err)
}
p, err := currency.NewPairDelimiter(resp[i].Symbol,
format.Delimiter)
if err != nil {
@@ -792,14 +799,16 @@ func (b *BTSE) GetActiveOrders(ctx context.Context, req *order.GetOrdersRequest)
}
openOrder := order.Detail{
Pair: p,
Exchange: b.Name,
Amount: resp[i].Size,
ID: resp[i].OrderID,
Date: time.Unix(resp[i].Timestamp, 0),
Side: side,
Price: resp[i].Price,
Status: order.Status(resp[i].OrderState),
Pair: p,
Exchange: b.Name,
Amount: resp[i].Size,
ExecutedAmount: resp[i].FilledSize,
RemainingAmount: resp[i].Size - resp[i].FilledSize,
ID: resp[i].OrderID,
Date: time.Unix(resp[i].Timestamp, 0),
Side: side,
Price: resp[i].Price,
Status: status,
}
if resp[i].OrderType == 77 {
@@ -886,24 +895,26 @@ func (b *BTSE) GetOrderHistory(ctx context.Context, getOrdersRequest *order.GetO
if !matchType(currentOrder[y].OrderType, orderDeref.Type) {
continue
}
orderStatus, err := order.StringToOrderStatus(currentOrder[x].OrderState)
if err != nil {
log.Errorf(log.ExchangeSys, "%s %v", b.Name, err)
}
orderTime := time.UnixMilli(currentOrder[y].Timestamp)
tempOrder := order.Detail{
Price: currentOrder[y].Price,
Amount: currentOrder[y].Size,
Side: order.Side(currentOrder[y].Side),
Pair: orderDeref.Pairs[x],
}
switch currentOrder[x].OrderState {
case "STATUS_ACTIVE":
tempOrder.Status = order.Active
case "ORDER_CANCELLED":
tempOrder.Status = order.Cancelled
case "ORDER_FULLY_TRANSACTED":
tempOrder.Status = order.Filled
case "ORDER_PARTIALLY_TRANSACTED":
tempOrder.Status = order.PartiallyFilled
default:
tempOrder.Status = order.UnknownStatus
ID: currentOrder[y].OrderID,
ClientID: currentOrder[y].ClOrderID,
Exchange: b.Name,
Price: currentOrder[y].Price,
AverageExecutedPrice: currentOrder[y].AverageFillPrice,
Amount: currentOrder[y].Size,
ExecutedAmount: currentOrder[y].FilledSize,
RemainingAmount: currentOrder[y].Size - currentOrder[y].FilledSize,
Date: orderTime,
Side: order.Side(currentOrder[y].Side),
Status: orderStatus,
Pair: orderDeref.Pairs[x],
}
tempOrder.InferCostsAndTimes()
resp = append(resp, tempOrder)
}
}

View File

@@ -125,7 +125,7 @@ type GeneralizedOrderResponse struct {
Funds float64 `json:"funds,string"`
SpecifiedFunds float64 `json:"specified_funds,string"`
DoneReason string `json:"done_reason"`
DoneAt string `json:"done_at"`
DoneAt time.Time `json:"done_at"`
}
// Funding holds funding data

View File

@@ -588,10 +588,6 @@ func (c *CoinbasePro) GetOrderInfo(ctx context.Context, orderID string, pair cur
if errGo != nil {
return order.Detail{}, fmt.Errorf("error retrieving order %s : %s", orderID, errGo)
}
od, errOd := time.Parse(time.RFC3339, genOrderDetail.DoneAt)
if errOd != nil {
return order.Detail{}, fmt.Errorf("error parsing order done at time: %s", errOd)
}
os, errOs := order.StringToOrderStatus(genOrderDetail.Status)
if errOs != nil {
return order.Detail{}, fmt.Errorf("error parsing order status: %s", errOs)
@@ -615,7 +611,7 @@ func (c *CoinbasePro) GetOrderInfo(ctx context.Context, orderID string, pair cur
Pair: p,
Side: ss,
Type: tt,
Date: od,
Date: genOrderDetail.DoneAt,
Status: os,
Price: genOrderDetail.Price,
Amount: genOrderDetail.Size,
@@ -828,20 +824,31 @@ func (c *CoinbasePro) GetOrderHistory(ctx context.Context, req *order.GetOrdersR
return nil, err
}
orderSide := order.Side(strings.ToUpper(respOrders[i].Side))
orderStatus, err := order.StringToOrderStatus(respOrders[i].Status)
if err != nil {
log.Errorf(log.ExchangeSys, "%s %v", c.Name, err)
}
orderType := order.Type(strings.ToUpper(respOrders[i].Type))
orders = append(orders, order.Detail{
ID: respOrders[i].ID,
Amount: respOrders[i].Size,
ExecutedAmount: respOrders[i].FilledSize,
Type: orderType,
Date: respOrders[i].CreatedAt,
Fee: respOrders[i].FillFees,
FeeAsset: curr.Quote,
Side: orderSide,
Pair: curr,
Price: respOrders[i].Price,
Exchange: c.Name,
})
detail := order.Detail{
ID: respOrders[i].ID,
Amount: respOrders[i].Size,
ExecutedAmount: respOrders[i].FilledSize,
RemainingAmount: respOrders[i].Size - respOrders[i].FilledSize,
Cost: respOrders[i].ExecutedValue,
CostAsset: curr.Quote,
Type: orderType,
Date: respOrders[i].CreatedAt,
CloseTime: respOrders[i].DoneAt,
Fee: respOrders[i].FillFees,
FeeAsset: curr.Quote,
Side: orderSide,
Status: orderStatus,
Pair: curr,
Price: respOrders[i].Price,
Exchange: c.Name,
}
detail.InferCostsAndTimes()
orders = append(orders, detail)
}
order.FilterOrdersByType(&orders, req.Type)

View File

@@ -774,7 +774,9 @@ func (c *Coinbene) GetActiveOrders(ctx context.Context, getOrdersRequest *order.
tempResp.Side = order.Sell
}
tempResp.Date = tempData[y].OrderTime
tempResp.Status = order.Status(tempData[y].OrderStatus)
if tempResp.Status, err = order.StringToOrderStatus(tempData[y].OrderStatus); err != nil {
log.Errorf(log.ExchangeSys, "%s %v", c.Name, err)
}
tempResp.Price = tempData[y].OrderPrice
tempResp.Amount = tempData[y].Amount
tempResp.ExecutedAmount = tempData[y].FilledAmount
@@ -831,12 +833,18 @@ func (c *Coinbene) GetOrderHistory(ctx context.Context, getOrdersRequest *order.
tempResp.Side = order.Sell
}
tempResp.Date = tempData[y].OrderTime
tempResp.Status = order.Status(tempData[y].OrderStatus)
if tempResp.Status, err = order.StringToOrderStatus(tempData[y].OrderStatus); err != nil {
log.Errorf(log.ExchangeSys, "%s %v", c.Name, err)
}
tempResp.Price = tempData[y].OrderPrice
tempResp.AverageExecutedPrice = tempData[y].AvgPrice
tempResp.Amount = tempData[y].Amount
tempResp.ExecutedAmount = tempData[y].FilledAmount
tempResp.RemainingAmount = tempData[y].Amount - tempData[y].FilledAmount
tempResp.Cost = tempData[y].Quantity
tempResp.CostAsset = tempResp.Pair.Quote
tempResp.Fee = tempData[y].TotalFee
tempResp.InferCostsAndTimes()
resp = append(resp, tempResp)
}
}

View File

@@ -977,7 +977,7 @@ func (c *COINUT) GetOrderHistory(ctx context.Context, req *order.GetOrdersReques
return nil, err
}
allOrders = append(allOrders, order.Detail{
detail := order.Detail{
Exchange: c.Name,
ID: strconv.FormatInt(trades.Trades[x].OrderID, 10),
Pair: p,
@@ -986,9 +986,11 @@ func (c *COINUT) GetOrderHistory(ctx context.Context, req *order.GetOrdersReques
Status: order.Filled,
Price: trades.Trades[x].Price,
Amount: trades.Trades[x].Quantity,
ExecutedAmount: trades.Trades[x].Quantity,
ExecutedAmount: trades.Trades[x].Quantity - trades.Trades[x].OpenQuantity,
RemainingAmount: trades.Trades[x].OpenQuantity,
})
}
detail.InferCostsAndTimes()
allOrders = append(allOrders, detail)
}
if len(trades.Trades) < 100 {
break

View File

@@ -670,21 +670,26 @@ func (e *EXMO) GetOrderHistory(ctx context.Context, req *order.GetOrdersRequest)
var orders []order.Detail
for i := range allTrades {
symbol, err := currency.NewPairDelimiter(allTrades[i].Pair, "_")
pair, err := currency.NewPairDelimiter(allTrades[i].Pair, "_")
if err != nil {
return nil, err
}
orderDate := time.Unix(allTrades[i].Date, 0)
orderSide := order.Side(strings.ToUpper(allTrades[i].Type))
orders = append(orders, order.Detail{
ID: strconv.FormatInt(allTrades[i].TradeID, 10),
Amount: allTrades[i].Quantity,
Date: orderDate,
Price: allTrades[i].Price,
Side: orderSide,
Exchange: e.Name,
Pair: symbol,
})
detail := order.Detail{
ID: strconv.FormatInt(allTrades[i].TradeID, 10),
Amount: allTrades[i].Quantity,
ExecutedAmount: allTrades[i].Quantity,
Cost: allTrades[i].Amount,
CostAsset: pair.Quote,
Date: orderDate,
Price: allTrades[i].Price,
Side: orderSide,
Exchange: e.Name,
Pair: pair,
}
detail.InferCostsAndTimes()
orders = append(orders, detail)
}
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)

View File

@@ -1016,6 +1016,7 @@ func (f *FTX) GetOrderHistory(ctx context.Context, getOrdersRequest *order.GetOr
tempResp.ID = strconv.FormatInt(orderData[y].ID, 10)
tempResp.Amount = orderData[y].Size
tempResp.AssetType = assetType
tempResp.AverageExecutedPrice = orderData[y].AvgFillPrice
tempResp.ClientOrderID = orderData[y].ClientID
tempResp.Date = orderData[y].CreatedAt
tempResp.Exchange = f.Name
@@ -1080,6 +1081,7 @@ func (f *FTX) GetOrderHistory(ctx context.Context, getOrdersRequest *order.GetOr
tempResp.Side = orderVars.Side
tempResp.Type = orderVars.OrderType
tempResp.Fee = orderVars.Fee
tempResp.InferCostsAndTimes()
resp = append(resp, tempResp)
}
}

View File

@@ -605,7 +605,9 @@ func (g *Gateio) GetOrderInfo(ctx context.Context, orderID string, pair currency
orderDetail.ExecutedAmount = orders.Orders[x].FilledAmount
orderDetail.Amount = orders.Orders[x].InitialAmount
orderDetail.Date = time.Unix(orders.Orders[x].Timestamp, 0)
orderDetail.Status = order.Status(orders.Orders[x].Status)
if orderDetail.Status, err = order.StringToOrderStatus(orders.Orders[x].Status); err != nil {
log.Errorf(log.ExchangeSys, "%s %v", g.Name, err)
}
orderDetail.Price = orders.Orders[x].Rate
orderDetail.Pair, err = currency.NewPairDelimiter(orders.Orders[x].CurrencyPair,
format.Delimiter)
@@ -763,17 +765,22 @@ func (g *Gateio) GetActiveOrders(ctx context.Context, req *order.GetOrdersReques
return nil, err
}
side := order.Side(strings.ToUpper(resp.Orders[i].Type))
status, err := order.StringToOrderStatus(resp.Orders[i].Status)
if err != nil {
log.Errorf(log.ExchangeSys, "%s %v", g.Name, err)
}
orderDate := time.Unix(resp.Orders[i].Timestamp, 0)
orders = append(orders, order.Detail{
ID: resp.Orders[i].OrderNumber,
Amount: resp.Orders[i].Amount,
Price: resp.Orders[i].Rate,
ExecutedAmount: resp.Orders[i].Amount - resp.Orders[i].FilledAmount,
RemainingAmount: resp.Orders[i].FilledAmount,
Price: resp.Orders[i].Rate,
Date: orderDate,
Side: side,
Exchange: g.Name,
Pair: symbol,
Status: order.Status(resp.Orders[i].Status),
Status: status,
})
}
}
@@ -805,22 +812,26 @@ func (g *Gateio) GetOrderHistory(ctx context.Context, req *order.GetOrdersReques
var orders []order.Detail
for i := range trades {
var symbol currency.Pair
symbol, err = currency.NewPairDelimiter(trades[i].Pair, format.Delimiter)
var pair currency.Pair
pair, err = currency.NewPairDelimiter(trades[i].Pair, format.Delimiter)
if err != nil {
return nil, err
}
side := order.Side(strings.ToUpper(trades[i].Type))
orderDate := time.Unix(trades[i].TimeUnix, 0)
orders = append(orders, order.Detail{
ID: strconv.FormatInt(trades[i].OrderID, 10),
Amount: trades[i].Amount,
Price: trades[i].Rate,
Date: orderDate,
Side: side,
Exchange: g.Name,
Pair: symbol,
})
detail := order.Detail{
ID: strconv.FormatInt(trades[i].OrderID, 10),
Amount: trades[i].Amount,
ExecutedAmount: trades[i].Amount,
Price: trades[i].Rate,
AverageExecutedPrice: trades[i].Rate,
Date: orderDate,
Side: side,
Exchange: g.Name,
Pair: pair,
}
detail.InferCostsAndTimes()
orders = append(orders, detail)
}
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)

View File

@@ -757,18 +757,24 @@ func (g *Gemini) GetOrderHistory(ctx context.Context, req *order.GetOrdersReques
side := order.Side(strings.ToUpper(trades[i].Type))
orderDate := time.Unix(trades[i].Timestamp, 0)
orders = append(orders, order.Detail{
Amount: trades[i].Amount,
ID: strconv.FormatInt(trades[i].OrderID, 10),
Exchange: g.Name,
Date: orderDate,
Side: side,
Fee: trades[i].FeeAmount,
Price: trades[i].Price,
Pair: currency.NewPairWithDelimiter(trades[i].BaseCurrency,
detail := order.Detail{
ID: strconv.FormatInt(trades[i].OrderID, 10),
Amount: trades[i].Amount,
ExecutedAmount: trades[i].Amount,
Exchange: g.Name,
Date: orderDate,
Side: side,
Fee: trades[i].FeeAmount,
Price: trades[i].Price,
AverageExecutedPrice: trades[i].Price,
Pair: currency.NewPairWithDelimiter(
trades[i].BaseCurrency,
trades[i].QuoteCurrency,
format.Delimiter),
})
format.Delimiter,
),
}
detail.InferCostsAndTimes()
orders = append(orders, detail)
}
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)

View File

@@ -184,6 +184,7 @@ type OrderHistoryResponse struct {
Type string `json:"type"`
TimeInForce string `json:"timeInForce"`
Price float64 `json:"price,string"`
AvgPrice float64 `json:"avgPrice,string"`
Quantity float64 `json:"quantity,string"`
PostOnly bool `json:"postOnly"`
CumQuantity float64 `json:"cumQuantity,string"`

View File

@@ -768,22 +768,33 @@ func (h *HitBTC) GetOrderHistory(ctx context.Context, req *order.GetOrdersReques
var orders []order.Detail
for i := range allOrders {
var symbol currency.Pair
symbol, err = currency.NewPairDelimiter(allOrders[i].Symbol,
var pair currency.Pair
pair, err = currency.NewPairDelimiter(allOrders[i].Symbol,
format.Delimiter)
if err != nil {
return nil, err
}
side := order.Side(strings.ToUpper(allOrders[i].Side))
orders = append(orders, order.Detail{
ID: allOrders[i].ID,
Amount: allOrders[i].Quantity,
Exchange: h.Name,
Price: allOrders[i].Price,
Date: allOrders[i].CreatedAt,
Side: side,
Pair: symbol,
})
status, err := order.StringToOrderStatus(allOrders[i].Status)
if err != nil {
log.Errorf(log.ExchangeSys, "%s %v", h.Name, err)
}
detail := order.Detail{
ID: allOrders[i].ID,
Amount: allOrders[i].Quantity,
ExecutedAmount: allOrders[i].CumQuantity,
RemainingAmount: allOrders[i].Quantity - allOrders[i].CumQuantity,
Exchange: h.Name,
Price: allOrders[i].Price,
AverageExecutedPrice: allOrders[i].AvgPrice,
Date: allOrders[i].CreatedAt,
LastUpdated: allOrders[i].UpdatedAt,
Side: side,
Status: status,
Pair: pair,
}
detail.InferCostsAndTimes()
orders = append(orders, detail)
}
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)

View File

@@ -1384,18 +1384,18 @@ func (h *HUOBI) GetActiveOrders(ctx context.Context, req *order.GetOrdersRequest
}
for x := range resp {
orderDetail := order.Detail{
ID: strconv.FormatInt(resp[x].ID, 10),
Price: resp[x].Price,
Amount: resp[x].Amount,
Pair: req.Pairs[i],
Exchange: h.Name,
ExecutedAmount: resp[x].FilledAmount,
Date: time.UnixMilli(resp[x].CreatedAt),
Status: order.Status(resp[x].State),
AccountID: strconv.FormatInt(resp[x].AccountID, 10),
Fee: resp[x].FilledFees,
ID: strconv.FormatInt(resp[x].ID, 10),
Price: resp[x].Price,
Amount: resp[x].Amount,
ExecutedAmount: resp[x].FilledAmount,
RemainingAmount: resp[x].Amount - resp[x].FilledAmount,
Pair: req.Pairs[i],
Exchange: h.Name,
Date: time.UnixMilli(resp[x].CreatedAt),
AccountID: strconv.FormatInt(resp[x].AccountID, 10),
Fee: resp[x].FilledFees,
}
setOrderSideAndType(resp[x].Type, &orderDetail)
setOrderSideStatusAndType(resp[x].State, resp[x].Type, &orderDetail)
orders = append(orders, orderDetail)
}
}
@@ -1520,18 +1520,22 @@ func (h *HUOBI) GetOrderHistory(ctx context.Context, req *order.GetOrdersRequest
}
for x := range resp {
orderDetail := order.Detail{
ID: strconv.FormatInt(resp[x].ID, 10),
Price: resp[x].Price,
Amount: resp[x].Amount,
Pair: req.Pairs[i],
Exchange: h.Name,
ExecutedAmount: resp[x].FilledAmount,
Date: time.UnixMilli(resp[x].CreatedAt),
Status: order.Status(resp[x].State),
AccountID: strconv.FormatInt(resp[x].AccountID, 10),
Fee: resp[x].FilledFees,
ID: strconv.FormatInt(resp[x].ID, 10),
Price: resp[x].Price,
Amount: resp[x].Amount,
ExecutedAmount: resp[x].FilledAmount,
RemainingAmount: resp[x].Amount - resp[x].FilledAmount,
Cost: resp[x].FilledCashAmount,
CostAsset: req.Pairs[i].Quote,
Pair: req.Pairs[i],
Exchange: h.Name,
Date: time.UnixMilli(resp[x].CreatedAt),
CloseTime: time.UnixMilli(resp[x].FinishedAt),
AccountID: strconv.FormatInt(resp[x].AccountID, 10),
Fee: resp[x].FilledFees,
}
setOrderSideAndType(resp[x].Type, &orderDetail)
setOrderSideStatusAndType(resp[x].State, resp[x].Type, &orderDetail)
orderDetail.InferCostsAndTimes()
orders = append(orders, orderDetail)
}
}
@@ -1648,7 +1652,12 @@ func (h *HUOBI) GetOrderHistory(ctx context.Context, req *order.GetOrdersRequest
return orders, nil
}
func setOrderSideAndType(requestType string, orderDetail *order.Detail) {
func setOrderSideStatusAndType(orderState, requestType string, orderDetail *order.Detail) {
var err error
if orderDetail.Status, err = order.StringToOrderStatus(orderState); err != nil {
log.Errorf(log.ExchangeSys, "%s %v", orderDetail.Exchange, err)
}
switch SpotNewOrderRequestParamsType(requestType) {
case SpotNewOrderRequestTypeBuyMarket:
orderDetail.Side = order.Buy

View File

@@ -614,6 +614,10 @@ func (i *ItBit) GetOrderHistory(ctx context.Context, req *order.GetOrdersRequest
}
side := order.Side(strings.ToUpper(allOrders[j].Side))
status, err := order.StringToOrderStatus(allOrders[j].Status)
if err != nil {
log.Errorf(log.ExchangeSys, "%s %v", i.Name, err)
}
orderDate, err := time.Parse(time.RFC3339, allOrders[j].CreatedTime)
if err != nil {
log.Errorf(log.ExchangeSys,
@@ -624,16 +628,21 @@ func (i *ItBit) GetOrderHistory(ctx context.Context, req *order.GetOrdersRequest
allOrders[j].CreatedTime)
}
orders = append(orders, order.Detail{
ID: allOrders[j].ID,
Side: side,
Amount: allOrders[j].Amount,
ExecutedAmount: allOrders[j].AmountFilled,
RemainingAmount: (allOrders[j].Amount - allOrders[j].AmountFilled),
Exchange: i.Name,
Date: orderDate,
Pair: symbol,
})
detail := order.Detail{
ID: allOrders[j].ID,
Side: side,
Status: status,
Amount: allOrders[j].Amount,
ExecutedAmount: allOrders[j].AmountFilled,
RemainingAmount: allOrders[j].Amount - allOrders[j].AmountFilled,
Price: allOrders[j].Price,
AverageExecutedPrice: allOrders[j].VolumeWeightedAveragePrice,
Exchange: i.Name,
Date: orderDate,
Pair: symbol,
}
detail.InferCostsAndTimes()
orders = append(orders, detail)
}
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)

View File

@@ -904,7 +904,7 @@ func (k *Kraken) GetOrderInfo(ctx context.Context, orderID string, pair currency
}
status, err := order.StringToOrderStatus(orderInfo.Status)
if err != nil {
return orderDetail, err
log.Errorf(log.ExchangeSys, "%s %v", k.Name, err)
}
oType, err := order.StringToOrderType(orderInfo.Description.OrderType)
if err != nil {
@@ -1225,20 +1225,29 @@ func (k *Kraken) GetOrderHistory(ctx context.Context, getOrdersRequest *order.Ge
}
side := order.Side(strings.ToUpper(resp.Closed[i].Description.Type))
status, err := order.StringToOrderStatus(resp.Closed[i].Status)
if err != nil {
log.Errorf(log.ExchangeSys, "%s %v", k.Name, err)
}
orderType := order.Type(strings.ToUpper(resp.Closed[i].Description.OrderType))
orders = append(orders, order.Detail{
detail := order.Detail{
ID: i,
Amount: resp.Closed[i].Volume,
RemainingAmount: (resp.Closed[i].Volume - resp.Closed[i].VolumeExecuted),
ExecutedAmount: resp.Closed[i].VolumeExecuted,
RemainingAmount: resp.Closed[i].Volume - resp.Closed[i].VolumeExecuted,
Cost: resp.Closed[i].Cost,
CostAsset: p.Quote,
Exchange: k.Name,
Date: convert.TimeFromUnixTimestampDecimal(resp.Closed[i].OpenTime),
CloseTime: convert.TimeFromUnixTimestampDecimal(resp.Closed[i].CloseTime),
Price: resp.Closed[i].Description.Price,
Side: side,
Status: status,
Type: orderType,
Pair: p,
})
}
detail.InferCostsAndTimes()
orders = append(orders, detail)
}
case asset.Futures:
var orderHistory FuturesRecentOrdersData

View File

@@ -790,10 +790,11 @@ func (l *Lbank) GetOrderHistory(ctx context.Context, getOrdersRequest *order.Get
resp.Status = "Invalid Order Status"
}
resp.Price = tempResp.Orders[x].Price
resp.AverageExecutedPrice = tempResp.Orders[x].AvgPrice
resp.Amount = tempResp.Orders[x].Amount
resp.Date = time.Unix(tempResp.Orders[x].CreateTime, 0)
resp.ExecutedAmount = tempResp.Orders[x].DealAmount
resp.RemainingAmount = tempResp.Orders[x].Price - tempResp.Orders[x].DealAmount
resp.RemainingAmount = tempResp.Orders[x].Amount - tempResp.Orders[x].DealAmount
resp.Fee, err = l.GetFeeByType(ctx,
&exchange.FeeBuilder{
FeeType: exchange.CryptocurrencyTradeFee,
@@ -802,6 +803,7 @@ func (l *Lbank) GetOrderHistory(ctx context.Context, getOrdersRequest *order.Get
if err != nil {
resp.Fee = lbankFeeNotFound
}
resp.InferCostsAndTimes()
finalResp = append(finalResp, resp)
b++
}

View File

@@ -638,6 +638,11 @@ func (l *LocalBitcoins) GetOrderHistory(ctx context.Context, getOrdersRequest *o
status = "Closed"
}
orderStatus, err := order.StringToOrderStatus(status)
if err != nil {
log.Errorf(log.ExchangeSys, "%s %v", l.Name, err)
}
orders = append(orders, order.Detail{
Amount: allTrades[i].Data.AmountBTC,
Price: allTrades[i].Data.Amount,
@@ -645,7 +650,7 @@ func (l *LocalBitcoins) GetOrderHistory(ctx context.Context, getOrdersRequest *o
Date: orderDate,
Fee: allTrades[i].Data.FeeBTC,
Side: side,
Status: order.Status(status),
Status: orderStatus,
Pair: currency.NewPairWithDelimiter(currency.BTC.String(),
allTrades[i].Data.Currency,
format.Delimiter),

View File

@@ -319,6 +319,7 @@ type GetSpotOrderResponse struct {
Notional string `json:"notional"`
OrderID string `json:"order_id"`
Price float64 `json:"price,string"`
PriceAvg float64 `json:"price_avg,string"`
Side string `json:"side"`
Size float64 `json:"size,string"`
Status string `json:"status"`

View File

@@ -408,16 +408,20 @@ func (o *OKGroup) GetOrderInfo(ctx context.Context, orderID string, pair currenc
return resp, err
}
status, err := order.StringToOrderStatus(mOrder.Status)
if err != nil {
log.Errorf(log.ExchangeSys, "%s %v", o.Name, err)
}
resp = order.Detail{
Amount: mOrder.Size,
Pair: p,
Exchange: o.Name,
Date: mOrder.Timestamp,
ExecutedAmount: mOrder.FilledSize,
Status: order.Status(mOrder.Status),
Status: status,
Side: order.Side(mOrder.Side),
}
return
return resp, nil
}
// GetDepositAddress returns a deposit address for a specified currency
@@ -501,6 +505,11 @@ func (o *OKGroup) GetActiveOrders(ctx context.Context, req *order.GetOrdersReque
return resp, err
}
for i := range spotOpenOrders {
var status order.Status
status, err = order.StringToOrderStatus(spotOpenOrders[i].Status)
if err != nil {
log.Errorf(log.ExchangeSys, "%s %v", o.Name, err)
}
resp = append(resp, order.Detail{
ID: spotOpenOrders[i].OrderID,
Price: spotOpenOrders[i].Price,
@@ -511,7 +520,7 @@ func (o *OKGroup) GetActiveOrders(ctx context.Context, req *order.GetOrdersReque
Type: order.Type(spotOpenOrders[i].Type),
ExecutedAmount: spotOpenOrders[i].FilledSize,
Date: spotOpenOrders[i].Timestamp,
Status: order.Status(spotOpenOrders[i].Status),
Status: status,
})
}
}
@@ -532,8 +541,8 @@ func (o *OKGroup) GetOrderHistory(ctx context.Context, req *order.GetOrdersReque
if err != nil {
return nil, err
}
var spotOpenOrders []GetSpotOrderResponse
spotOpenOrders, err = o.GetSpotOrders(ctx,
var spotOrders []GetSpotOrderResponse
spotOrders, err = o.GetSpotOrders(ctx,
GetSpotOrdersRequest{
Status: strings.Join([]string{"filled", "cancelled", "failure"}, "|"),
InstrumentID: fPair.String(),
@@ -541,19 +550,28 @@ func (o *OKGroup) GetOrderHistory(ctx context.Context, req *order.GetOrdersReque
if err != nil {
return resp, err
}
for i := range spotOpenOrders {
resp = append(resp, order.Detail{
ID: spotOpenOrders[i].OrderID,
Price: spotOpenOrders[i].Price,
Amount: spotOpenOrders[i].Size,
Pair: req.Pairs[x],
Exchange: o.Name,
Side: order.Side(spotOpenOrders[i].Side),
Type: order.Type(spotOpenOrders[i].Type),
ExecutedAmount: spotOpenOrders[i].FilledSize,
Date: spotOpenOrders[i].Timestamp,
Status: order.Status(spotOpenOrders[i].Status),
})
for i := range spotOrders {
var status order.Status
status, err = order.StringToOrderStatus(spotOrders[i].Status)
if err != nil {
log.Errorf(log.ExchangeSys, "%s %v", o.Name, err)
}
detail := order.Detail{
ID: spotOrders[i].OrderID,
Price: spotOrders[i].Price,
AverageExecutedPrice: spotOrders[i].PriceAvg,
Amount: spotOrders[i].Size,
ExecutedAmount: spotOrders[i].FilledSize,
RemainingAmount: spotOrders[i].Size - spotOrders[i].FilledSize,
Pair: req.Pairs[x],
Exchange: o.Name,
Side: order.Side(spotOrders[i].Side),
Type: order.Type(spotOrders[i].Type),
Date: spotOrders[i].Timestamp,
Status: status,
}
detail.InferCostsAndTimes()
resp = append(resp, detail)
}
}
return resp, err

View File

@@ -144,6 +144,90 @@ func TestOrderTypes(t *testing.T) {
}
}
func TestInferCostsAndTimes(t *testing.T) {
t.Parallel()
var detail Detail
detail.InferCostsAndTimes()
if detail.Amount != detail.ExecutedAmount+detail.RemainingAmount {
t.Errorf(
"Order detail amounts not equals. Expected 0, received %f",
detail.Amount-(detail.ExecutedAmount+detail.RemainingAmount),
)
}
detail.CloseTime = time.Now()
detail.InferCostsAndTimes()
if detail.LastUpdated != detail.CloseTime {
t.Errorf(
"Order last updated not equals close time. Expected %s, received %s",
detail.CloseTime,
detail.LastUpdated,
)
}
detail.Amount = 1
detail.ExecutedAmount = 1
detail.InferCostsAndTimes()
if detail.AverageExecutedPrice != 0 {
t.Errorf(
"Unexpected AverageExecutedPrice. Expected 0, received %f",
detail.AverageExecutedPrice,
)
}
detail.Amount = 1
detail.ExecutedAmount = 1
detail.InferCostsAndTimes()
if detail.Cost != 0 {
t.Errorf(
"Unexpected Cost. Expected 0, received %f",
detail.Cost,
)
}
detail.ExecutedAmount = 0
detail.Amount = 1
detail.RemainingAmount = 1
detail.InferCostsAndTimes()
if detail.Amount != detail.ExecutedAmount+detail.RemainingAmount {
t.Errorf(
"Order detail amounts not equals. Expected 0, received %f",
detail.Amount-(detail.ExecutedAmount+detail.RemainingAmount),
)
}
detail.RemainingAmount = 0
detail.Amount = 1
detail.ExecutedAmount = 1
detail.Price = 2
detail.InferCostsAndTimes()
if detail.AverageExecutedPrice != 2 {
t.Errorf(
"Unexpected AverageExecutedPrice. Expected 2, received %f",
detail.AverageExecutedPrice,
)
}
detail = Detail{Amount: 1, ExecutedAmount: 2, Cost: 3, Price: 0}
detail.InferCostsAndTimes()
if detail.AverageExecutedPrice != 1.5 {
t.Errorf(
"Unexpected AverageExecutedPrice. Expected 1.5, received %f",
detail.AverageExecutedPrice,
)
}
detail = Detail{Amount: 1, ExecutedAmount: 2, AverageExecutedPrice: 3}
detail.InferCostsAndTimes()
if detail.Cost != 6 {
t.Errorf(
"Unexpected Cost. Expected 6, received %f",
detail.Cost,
)
}
}
func TestFilterOrdersByType(t *testing.T) {
t.Parallel()

View File

@@ -488,6 +488,36 @@ func (s Status) String() string {
return string(s)
}
// InferCostsAndTimes infer order costs using execution information and times when available
func (d *Detail) InferCostsAndTimes() {
if d.CostAsset.IsEmpty() {
d.CostAsset = d.Pair.Quote
}
if d.LastUpdated.IsZero() {
if d.CloseTime.IsZero() {
d.LastUpdated = d.Date
} else {
d.LastUpdated = d.CloseTime
}
}
if d.ExecutedAmount <= 0 {
return
}
if d.AverageExecutedPrice == 0 {
if d.Cost != 0 {
d.AverageExecutedPrice = d.Cost / d.ExecutedAmount
} else {
d.AverageExecutedPrice = d.Price
}
}
if d.Cost == 0 {
d.Cost = d.AverageExecutedPrice * d.ExecutedAmount
}
}
// FilterOrdersBySide removes any order details that don't match the
// order status provided
func FilterOrdersBySide(orders *[]Detail, side Side) {
@@ -743,7 +773,8 @@ func StringToOrderStatus(status string) (Status, error) {
case strings.EqualFold(status, New.String()),
strings.EqualFold(status, "placed"):
return New, nil
case strings.EqualFold(status, Active.String()):
case strings.EqualFold(status, Active.String()),
strings.EqualFold(status, "STATUS_ACTIVE"): // BTSE case
return Active, nil
case strings.EqualFold(status, PartiallyFilled.String()),
strings.EqualFold(status, "partially matched"),
@@ -751,18 +782,20 @@ func StringToOrderStatus(status string) (Status, error) {
return PartiallyFilled, nil
case strings.EqualFold(status, Filled.String()),
strings.EqualFold(status, "fully matched"),
strings.EqualFold(status, "fully filled"):
strings.EqualFold(status, "fully filled"),
strings.EqualFold(status, "ORDER_FULLY_TRANSACTED"): // BTSE case
return Filled, nil
case strings.EqualFold(status, PartiallyCancelled.String()),
strings.EqualFold(status, "partially cancelled"):
strings.EqualFold(status, "partially cancelled"),
strings.EqualFold(status, "ORDER_PARTIALLY_TRANSACTED"): // BTSE case
return PartiallyCancelled, nil
case strings.EqualFold(status, Open.String()):
return Open, nil
case strings.EqualFold(status, Closed.String()):
return Closed, nil
case strings.EqualFold(status, Cancelled.String()):
return Cancelled, nil
case strings.EqualFold(status, "CANCELED"): // Kraken case
case strings.EqualFold(status, Cancelled.String()),
strings.EqualFold(status, "CANCELED"), // Binance and Kraken case
strings.EqualFold(status, "ORDER_CANCELLED"): // BTSE case
return Cancelled, nil
case strings.EqualFold(status, PendingCancel.String()),
strings.EqualFold(status, "pending cancel"),

View File

@@ -668,7 +668,9 @@ func (p *Poloniex) GetOrderInfo(ctx context.Context, orderID string, pair curren
return orderInfo, err
}
orderInfo.Status, _ = order.StringToOrderStatus(resp.Status)
if orderInfo.Status, err = order.StringToOrderStatus(resp.Status); err != nil {
log.Errorf(log.ExchangeSys, "%s %v", p.Name, err)
}
orderInfo.Price = resp.Rate
orderInfo.Amount = resp.Amount
orderInfo.Cost = resp.Total
@@ -874,8 +876,8 @@ func (p *Poloniex) GetOrderHistory(ctx context.Context, req *order.GetOrdersRequ
var orders []order.Detail
for key := range resp.Data {
var symbol currency.Pair
symbol, err = currency.NewPairDelimiter(key, format.Delimiter)
var pair currency.Pair
pair, err = currency.NewPairDelimiter(key, format.Delimiter)
if err != nil {
return nil, err
}
@@ -893,15 +895,20 @@ func (p *Poloniex) GetOrderHistory(ctx context.Context, req *order.GetOrdersRequ
resp.Data[key][i].Date)
}
orders = append(orders, order.Detail{
ID: strconv.FormatInt(resp.Data[key][i].GlobalTradeID, 10),
Side: orderSide,
Amount: resp.Data[key][i].Amount,
Date: orderDate,
Price: resp.Data[key][i].Rate,
Pair: symbol,
Exchange: p.Name,
})
detail := order.Detail{
ID: strconv.FormatInt(resp.Data[key][i].GlobalTradeID, 10),
Side: orderSide,
Amount: resp.Data[key][i].Amount,
ExecutedAmount: resp.Data[key][i].Amount,
Date: orderDate,
Price: resp.Data[key][i].Rate,
AverageExecutedPrice: resp.Data[key][i].Rate,
Pair: pair,
Status: order.Filled,
Exchange: p.Name,
}
detail.InferCostsAndTimes()
orders = append(orders, detail)
}
}

View File

@@ -635,22 +635,27 @@ func (y *Yobit) GetOrderHistory(ctx context.Context, req *order.GetOrdersRequest
var orders []order.Detail
for i := range allOrders {
var symbol currency.Pair
symbol, err = currency.NewPairDelimiter(allOrders[i].Pair, format.Delimiter)
var pair currency.Pair
pair, err = currency.NewPairDelimiter(allOrders[i].Pair, format.Delimiter)
if err != nil {
return nil, err
}
orderDate := time.Unix(int64(allOrders[i].Timestamp), 0)
side := order.Side(strings.ToUpper(allOrders[i].Type))
orders = append(orders, order.Detail{
ID: strconv.FormatFloat(allOrders[i].OrderID, 'f', -1, 64),
Amount: allOrders[i].Amount,
Price: allOrders[i].Rate,
Side: side,
Date: orderDate,
Pair: symbol,
Exchange: y.Name,
})
detail := order.Detail{
ID: strconv.FormatFloat(allOrders[i].OrderID, 'f', -1, 64),
Amount: allOrders[i].Amount,
ExecutedAmount: allOrders[i].Amount,
Price: allOrders[i].Rate,
AverageExecutedPrice: allOrders[i].Rate,
Side: side,
Status: order.Filled,
Date: orderDate,
Pair: pair,
Exchange: y.Name,
}
detail.InferCostsAndTimes()
orders = append(orders, detail)
}
order.FilterOrdersBySide(&orders, req.Side)

View File

@@ -40,7 +40,7 @@ type Order struct {
Price float64 `json:"price"`
Status int `json:"status"`
TotalAmount float64 `json:"total_amount"`
TradeAmount int `json:"trade_amount"`
TradeAmount float64 `json:"trade_amount"`
TradeDate int `json:"trade_date"`
TradeMoney float64 `json:"trade_money"`
Type int64 `json:"type"`

View File

@@ -812,23 +812,28 @@ func (z *ZB) GetOrderHistory(ctx context.Context, req *order.GetOrdersRequest) (
}
for i := range allOrders {
var symbol currency.Pair
symbol, err = currency.NewPairDelimiter(allOrders[i].Currency,
var pair currency.Pair
pair, err = currency.NewPairDelimiter(allOrders[i].Currency,
format.Delimiter)
if err != nil {
return nil, err
}
orderDate := time.Unix(int64(allOrders[i].TradeDate), 0)
orderSide := orderSideMap[allOrders[i].Type]
orders = append(orders, order.Detail{
ID: strconv.FormatInt(allOrders[i].ID, 10),
Amount: allOrders[i].TotalAmount,
Exchange: z.Name,
Date: orderDate,
Price: allOrders[i].Price,
Side: orderSide,
Pair: symbol,
})
detail := order.Detail{
ID: strconv.FormatInt(allOrders[i].ID, 10),
Amount: allOrders[i].TotalAmount,
ExecutedAmount: allOrders[i].TradeAmount,
RemainingAmount: allOrders[i].TotalAmount - allOrders[i].TradeAmount,
Exchange: z.Name,
Date: orderDate,
Price: allOrders[i].Price,
AverageExecutedPrice: allOrders[i].TradePrice,
Side: orderSide,
Pair: pair,
}
detail.InferCostsAndTimes()
orders = append(orders, detail)
}
order.FilterOrdersByTimeRange(&orders, req.StartTime, req.EndTime)