Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

exchanges/order: Added TimeInForce type and values #1382

Open
wants to merge 25 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5412e91
Added TimeInForce type and updated related files
samuael Oct 29, 2023
0bbd6fb
Linter issue fix and minor coinbasepro type update
samuael Oct 29, 2023
b786e75
Bitrex consts update
samuael Oct 29, 2023
afa9695
added unit test and minor changes in bittrex
samuael Oct 30, 2023
cb2619b
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Nov 5, 2023
da4b3cb
Unit tests update
samuael Nov 15, 2023
e41ab86
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Nov 15, 2023
c9b88ab
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Nov 23, 2023
e11beef
Fix minor linter issues
samuael Nov 23, 2023
9add848
Update TestStringToTimeInForce unit test
samuael Nov 27, 2023
aecc942
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Nov 27, 2023
3a7ac71
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Nov 29, 2023
44f1cbb
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Dec 6, 2023
964ed95
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Dec 22, 2023
05b4921
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Dec 27, 2023
2179454
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Dec 31, 2023
3043702
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Jan 2, 2024
45b3596
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Jan 16, 2024
318152b
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Jan 24, 2024
cede5cb
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Jan 29, 2024
3aa605a
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Feb 28, 2024
6dd27b9
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Mar 6, 2024
6b3e010
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Mar 13, 2024
d82cc0c
fix conflict with gateio timeInForce
samuael Mar 18, 2024
b453062
Merge branch 'master' of http://github.com/thrasher-corp/gocryptotrad…
samuael Mar 18, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
40 changes: 20 additions & 20 deletions cmd/exchange_wrapper_standards/exchange_wrapper_standards_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -420,29 +420,29 @@ func generateMethodArg(ctx context.Context, t *testing.T, argGenerator *MethodAr
input = reflect.ValueOf(req)
case argGenerator.MethodInputType.AssignableTo(orderSubmitParam):
input = reflect.ValueOf(&order.Submit{
Exchange: exchName,
Type: order.Limit,
Side: order.Buy,
Pair: argGenerator.AssetParams.Pair,
AssetType: argGenerator.AssetParams.Asset,
Price: 1337,
Amount: 1,
ClientID: "1337",
ClientOrderID: "13371337",
ImmediateOrCancel: true,
Exchange: exchName,
Type: order.Limit,
Side: order.Buy,
Pair: argGenerator.AssetParams.Pair,
AssetType: argGenerator.AssetParams.Asset,
Price: 1337,
Amount: 1,
ClientID: "1337",
ClientOrderID: "13371337",
TimeInForce: order.IOC,
})
case argGenerator.MethodInputType.AssignableTo(orderModifyParam):
input = reflect.ValueOf(&order.Modify{
Exchange: exchName,
Type: order.Limit,
Side: order.Buy,
Pair: argGenerator.AssetParams.Pair,
AssetType: argGenerator.AssetParams.Asset,
Price: 1337,
Amount: 1,
ClientOrderID: "13371337",
OrderID: "1337",
ImmediateOrCancel: true,
Exchange: exchName,
Type: order.Limit,
Side: order.Buy,
Pair: argGenerator.AssetParams.Pair,
AssetType: argGenerator.AssetParams.Asset,
Price: 1337,
Amount: 1,
ClientOrderID: "13371337",
OrderID: "1337",
TimeInForce: order.IOC,
})
case argGenerator.MethodInputType.AssignableTo(orderCancelParam):
input = reflect.ValueOf(&order.Cancel{
Expand Down
8 changes: 4 additions & 4 deletions engine/order_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -404,10 +404,10 @@ func (m *OrderManager) Modify(ctx context.Context, mod *order.Modify) (*order.Mo

// Populate additional Modify fields as some of them are required by various
// exchange implementations.
mod.Pair = det.Pair // Used by Bithumb.
mod.Side = det.Side // Used by Bithumb.
mod.PostOnly = det.PostOnly // Used by Poloniex.
mod.ImmediateOrCancel = det.ImmediateOrCancel // Used by Poloniex.
mod.Pair = det.Pair // Used by Bithumb.
mod.Side = det.Side // Used by Bithumb.
mod.PostOnly = det.PostOnly // Used by Poloniex.
mod.TimeInForce = det.TimeInForce

// Following is just a precaution to not modify orders by mistake if exchange
// implementations do not check fields of the Modify struct for zero values.
Expand Down
2 changes: 1 addition & 1 deletion exchanges/binance/binance.go
Original file line number Diff line number Diff line change
Expand Up @@ -629,7 +629,7 @@ func (b *Binance) newOrder(ctx context.Context, api string, o *NewOrderRequest,
params.Set("price", strconv.FormatFloat(o.Price, 'f', -1, 64))
}
if o.TimeInForce != "" {
params.Set("timeInForce", string(o.TimeInForce))
params.Set("timeInForce", o.TimeInForce)
}

if o.NewClientOrderID != "" {
Expand Down
2 changes: 1 addition & 1 deletion exchanges/binance/binance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1443,7 +1443,7 @@ func TestNewOrderTest(t *testing.T) {
TradeType: BinanceRequestParamsOrderLimit,
Price: 0.0025,
Quantity: 100000,
TimeInForce: BinanceRequestParamsTimeGTC,
TimeInForce: order.GoodTillCancel.String(),
}

err := b.NewOrderTest(context.Background(), req)
Expand Down
2 changes: 1 addition & 1 deletion exchanges/binance/binance_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,7 @@ type NewOrderRequest struct {
TradeType RequestParamsOrderType
// TimeInForce specifies how long the order remains in effect.
// Examples are (Good Till Cancel (GTC), Immediate or Cancel (IOC) and Fill Or Kill (FOK))
TimeInForce RequestParamsTimeForceType
TimeInForce string
// Quantity is the total base qty spent or received in an order.
Quantity float64
// QuoteOrderQty is the total quote qty spent or received in a MARKET order.
Expand Down
6 changes: 3 additions & 3 deletions exchanges/binance/binance_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -990,15 +990,15 @@ func (b *Binance) SubmitOrder(ctx context.Context, s *order.Submit) (*order.Subm
} else {
sideType = order.Sell.String()
}
timeInForce := BinanceRequestParamsTimeGTC
timeInForce := order.GoodTillCancel.String()
var requestParamsOrderType RequestParamsOrderType
switch s.Type {
case order.Market:
timeInForce = ""
requestParamsOrderType = BinanceRequestParamsOrderMarket
case order.Limit:
if s.ImmediateOrCancel {
timeInForce = BinanceRequestParamsTimeIOC
if s.TimeInForce == order.IOC {
timeInForce = order.IOC.String()
}
requestParamsOrderType = BinanceRequestParamsOrderLimit
default:
Expand Down
10 changes: 5 additions & 5 deletions exchanges/bittrex/bittrex_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,11 @@ type TimeInForce string

// All order status types
const (
GoodTilCancelled TimeInForce = "GOOD_TIL_CANCELLED"
ImmediateOrCancel TimeInForce = "IMMEDIATE_OR_CANCEL"
FillOrKill TimeInForce = "FILL_OR_KILL"
PostOnlyGoodTilCancelled TimeInForce = "POST_ONLY_GOOD_TIL_CANCELLED"
BuyNow TimeInForce = "BUY_NOW"
GoodTilCancelled = "GOOD_TIL_CANCELLED"
ImmediateOrCancel = "IMMEDIATE_OR_CANCEL"
FillOrKill = "FILL_OR_KILL"
PostOnlyGoodTilCancelled = "POST_ONLY_GOOD_TIL_CANCELLED"
shazbert marked this conversation as resolved.
Show resolved Hide resolved
BuyNow = "BUY_NOW"
)

// OrderData holds order data
Expand Down
38 changes: 22 additions & 16 deletions exchanges/bittrex/bittrex_websocket.go
Original file line number Diff line number Diff line change
Expand Up @@ -602,23 +602,29 @@ func (b *Bittrex) WsProcessUpdateOrder(data *OrderUpdateMessage) error {
Err: err,
}
}

timeInForce, err := order.StringToTimeInForce(data.Delta.TimeInForce)
if err != nil {
b.Websocket.DataHandler <- order.ClassificationError{
Exchange: b.Name,
OrderID: data.Delta.ID,
Err: err,
}
}
b.Websocket.DataHandler <- &order.Detail{
ImmediateOrCancel: data.Delta.TimeInForce == string(ImmediateOrCancel),
FillOrKill: data.Delta.TimeInForce == string(GoodTilCancelled),
PostOnly: data.Delta.TimeInForce == string(PostOnlyGoodTilCancelled),
Price: data.Delta.Limit,
Amount: data.Delta.Quantity,
RemainingAmount: data.Delta.Quantity - data.Delta.FillQuantity,
ExecutedAmount: data.Delta.FillQuantity,
Exchange: b.Name,
OrderID: data.Delta.ID,
Type: orderType,
Side: orderSide,
Status: orderStatus,
AssetType: asset.Spot,
Date: data.Delta.CreatedAt,
Pair: pair,
TimeInForce: timeInForce,
PostOnly: data.Delta.TimeInForce == PostOnlyGoodTilCancelled,
Price: data.Delta.Limit,
Amount: data.Delta.Quantity,
RemainingAmount: data.Delta.Quantity - data.Delta.FillQuantity,
ExecutedAmount: data.Delta.FillQuantity,
Exchange: b.Name,
OrderID: data.Delta.ID,
Type: orderType,
Side: orderSide,
Status: orderStatus,
AssetType: asset.Spot,
Date: data.Delta.CreatedAt,
Pair: pair,
}
return nil
}
28 changes: 14 additions & 14 deletions exchanges/bittrex/bittrex_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -698,9 +698,9 @@ func (b *Bittrex) GetOrderInfo(ctx context.Context, orderID string, _ currency.P

// ConstructOrderDetail constructs an order detail item from the underlying data
func (b *Bittrex) ConstructOrderDetail(orderData *OrderData) (*order.Detail, error) {
immediateOrCancel := false
if orderData.TimeInForce == string(ImmediateOrCancel) {
immediateOrCancel = true
timeInForce, err := order.StringToTimeInForce(orderData.TimeInForce)
if err != nil {
timeInForce = order.UnknownTIF
}

format, err := b.GetPairFormat(asset.Spot, false)
Expand Down Expand Up @@ -743,17 +743,17 @@ func (b *Bittrex) ConstructOrderDetail(orderData *OrderData) (*order.Detail, err
}

return &order.Detail{
ImmediateOrCancel: immediateOrCancel,
Amount: orderData.Quantity,
ExecutedAmount: orderData.FillQuantity,
RemainingAmount: orderData.Quantity - orderData.FillQuantity,
Price: orderData.Limit,
Date: orderData.CreatedAt,
OrderID: orderData.ID,
Exchange: b.Name,
Type: orderType,
Pair: orderPair,
Status: orderStatus,
TimeInForce: timeInForce,
Amount: orderData.Quantity,
ExecutedAmount: orderData.FillQuantity,
RemainingAmount: orderData.Quantity - orderData.FillQuantity,
Price: orderData.Limit,
Date: orderData.CreatedAt,
OrderID: orderData.ID,
Exchange: b.Name,
Type: orderType,
Pair: orderPair,
Status: orderStatus,
}, nil
}

Expand Down
11 changes: 5 additions & 6 deletions exchanges/btcmarkets/btcmarkets.go
Original file line number Diff line number Diff line change
Expand Up @@ -376,13 +376,12 @@ func (b *BTCMarkets) formatOrderSide(o order.Side) (string, error) {

// getTimeInForce returns a string depending on the options in order.Submit
func (b *BTCMarkets) getTimeInForce(s *order.Submit) string {
if s.ImmediateOrCancel {
return immediateOrCancel
}
if s.FillOrKill {
return fillOrKill
switch s.TimeInForce {
case order.IOC, order.FOK:
return s.TimeInForce.String()
default:
return "" // GTC (good till cancelled, default value)
}
return "" // GTC (good till cancelled, default value)
}

// NewOrder requests a new order and returns an ID
Expand Down
4 changes: 2 additions & 2 deletions exchanges/btcmarkets/btcmarkets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -987,12 +987,12 @@ func TestGetTimeInForce(t *testing.T) {
t.Fatal("unexpected value")
}

f = b.getTimeInForce(&order.Submit{ImmediateOrCancel: true})
f = b.getTimeInForce(&order.Submit{TimeInForce: order.IOC})
if f != immediateOrCancel {
t.Fatalf("received: '%v' but expected: '%v'", f, immediateOrCancel)
}

f = b.getTimeInForce(&order.Submit{FillOrKill: true})
f = b.getTimeInForce(&order.Submit{TimeInForce: order.FOK})
if f != fillOrKill {
t.Fatalf("received: '%v' but expected: '%v'", f, fillOrKill)
}
Expand Down
2 changes: 1 addition & 1 deletion exchanges/coinbasepro/coinbasepro.go
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ func (c *CoinbasePro) GetHolds(ctx context.Context, accountID string) ([]Account
// timeInforce - [optional] GTC, GTT, IOC, or FOK (default is GTC)
// cancelAfter - [optional] min, hour, day * Requires time_in_force to be GTT
// postOnly - [optional] Post only flag Invalid when time_in_force is IOC or FOK
func (c *CoinbasePro) PlaceLimitOrder(ctx context.Context, clientRef string, price, amount float64, side string, timeInforce RequestParamsTimeForceType, cancelAfter, productID, stp string, postOnly bool) (string, error) {
func (c *CoinbasePro) PlaceLimitOrder(ctx context.Context, clientRef, side, timeInforce, cancelAfter, productID, stp string, price, amount float64, postOnly bool) (string, error) {
resp := GeneralizedOrderResponse{}
req := make(map[string]interface{})
req["type"] = order.Limit.Lower()
Expand Down
4 changes: 2 additions & 2 deletions exchanges/coinbasepro/coinbasepro_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,8 +196,8 @@ func TestAuthRequests(t *testing.T) {
t.Error("Expecting error")
}
orderResponse, err := c.PlaceLimitOrder(context.Background(),
"", 0.001, 0.001,
order.Buy.Lower(), "", "", testPair.String(), "", false)
"",
order.Buy.Lower(), "", "", testPair.String(), "", 0.001, 0.001, false)
if orderResponse != "" {
t.Error("Expecting no data returned")
}
Expand Down
11 changes: 0 additions & 11 deletions exchanges/coinbasepro/coinbasepro_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -489,17 +489,6 @@ type wsStatus struct {
Type string `json:"type"`
}

// RequestParamsTimeForceType Time in force
type RequestParamsTimeForceType string

var (
// CoinbaseRequestParamsTimeGTC GTC
CoinbaseRequestParamsTimeGTC = RequestParamsTimeForceType("GTC")

// CoinbaseRequestParamsTimeIOC IOC
CoinbaseRequestParamsTimeIOC = RequestParamsTimeForceType("IOC")
)

// TransferHistory returns wallet transfer history
type TransferHistory struct {
ID string `json:"id"`
Expand Down
10 changes: 5 additions & 5 deletions exchanges/coinbasepro/coinbasepro_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -563,19 +563,19 @@ func (c *CoinbasePro) SubmitOrder(ctx context.Context, s *order.Submit) (*order.
fPair.String(),
"")
case order.Limit:
timeInForce := CoinbaseRequestParamsTimeGTC
if s.ImmediateOrCancel {
timeInForce = CoinbaseRequestParamsTimeIOC
timeInForce := order.GoodTillCancel.String()
if s.TimeInForce == order.IOC {
timeInForce = order.IOC.String()
}
orderID, err = c.PlaceLimitOrder(ctx,
"",
s.Price,
s.Amount,
s.Side.Lower(),
timeInForce,
"",
fPair.String(),
"",
s.Price,
s.Amount,
false)
default:
err = fmt.Errorf("%w %v", order.ErrUnsupportedOrderType, s.Type)
Expand Down
2 changes: 1 addition & 1 deletion exchanges/huobi/huobi_wrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -1058,7 +1058,7 @@ func (h *HUOBI) SubmitOrder(ctx context.Context, s *order.Submit) (*order.Submit
// It is important to note that the above methods will not guarantee the order to be filled in 100%.
// The system will obtain the optimal N price at that moment and place the order.
oType = "optimal_20"
if s.ImmediateOrCancel {
if s.TimeInForce == order.IOC {
oType = "optimal_20_ioc"
}
case order.Limit:
Expand Down
2 changes: 1 addition & 1 deletion exchanges/kraken/kraken.go
Original file line number Diff line number Diff line change
Expand Up @@ -920,7 +920,7 @@ func (k *Kraken) AddOrder(ctx context.Context, symbol currency.Pair, side, order
}

if args.TimeInForce != "" {
params.Set("timeinforce", string(args.TimeInForce))
params.Set("timeinforce", args.TimeInForce)
}

if err := k.SendAuthenticatedHTTPRequest(ctx, exchange.RestSpot, krakenOrderPlace, params, &response); err != nil {
Expand Down
50 changes: 20 additions & 30 deletions exchanges/kraken/kraken_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ type AddOrderOptions struct {
ClosePrice float64
ClosePrice2 float64
Validate bool
TimeInForce RequestParamsTimeForceType
TimeInForce string
}

// CancelOrderResponse type
Expand Down Expand Up @@ -675,25 +675,25 @@ type WsOpenOrderDescription struct {

// WsAddOrderRequest request type for ws adding order
type WsAddOrderRequest struct {
Event string `json:"event"`
Token string `json:"token"`
RequestID int64 `json:"reqid,omitempty"` // Optional, client originated ID reflected in response message.
OrderType string `json:"ordertype"`
OrderSide string `json:"type"`
Pair string `json:"pair"`
Price float64 `json:"price,string,omitempty"` // optional
Price2 float64 `json:"price2,string,omitempty"` // optional
Volume float64 `json:"volume,string,omitempty"`
Leverage float64 `json:"leverage,omitempty"` // optional
OFlags string `json:"oflags,omitempty"` // optional
StartTime string `json:"starttm,omitempty"` // optional
ExpireTime string `json:"expiretm,omitempty"` // optional
UserReferenceID string `json:"userref,omitempty"` // optional
Validate string `json:"validate,omitempty"` // optional
CloseOrderType string `json:"close[ordertype],omitempty"` // optional
ClosePrice float64 `json:"close[price],omitempty"` // optional
ClosePrice2 float64 `json:"close[price2],omitempty"` // optional
TimeInForce RequestParamsTimeForceType `json:"timeinforce,omitempty"` // optional
Event string `json:"event"`
Token string `json:"token"`
RequestID int64 `json:"reqid,omitempty"` // Optional, client originated ID reflected in response message.
OrderType string `json:"ordertype"`
OrderSide string `json:"type"`
Pair string `json:"pair"`
Price float64 `json:"price,string,omitempty"` // optional
Price2 float64 `json:"price2,string,omitempty"` // optional
Volume float64 `json:"volume,string,omitempty"`
Leverage float64 `json:"leverage,omitempty"` // optional
OFlags string `json:"oflags,omitempty"` // optional
StartTime string `json:"starttm,omitempty"` // optional
ExpireTime string `json:"expiretm,omitempty"` // optional
UserReferenceID string `json:"userref,omitempty"` // optional
Validate string `json:"validate,omitempty"` // optional
CloseOrderType string `json:"close[ordertype],omitempty"` // optional
ClosePrice float64 `json:"close[price],omitempty"` // optional
ClosePrice2 float64 `json:"close[price2],omitempty"` // optional
TimeInForce string `json:"timeinforce,omitempty"` // optional
}

// WsAddOrderResponse response data for ws order
Expand Down Expand Up @@ -730,13 +730,3 @@ type OrderVars struct {
OrderType order.Type
Fee float64
}

// RequestParamsTimeForceType Time in force
type RequestParamsTimeForceType string

var (
// RequestParamsTimeGTC GTC
RequestParamsTimeGTC = RequestParamsTimeForceType("GTC")
// RequestParamsTimeIOC IOC
RequestParamsTimeIOC = RequestParamsTimeForceType("IOC")
)