mirror of
https://github.com/d0zingcat/gocryptotrader.git
synced 2026-05-13 23:16:45 +00:00
exchanges: Order types update (#1850)
* Added TimeInForce type and updated related files * Linter issue fix and minor coinbasepro type update * Bitrex consts update * added unit test and minor changes in bittrex * Unit tests update * Fix minor linter issues * Update TestStringToTimeInForce unit test * fix conflict with gateio timeInForce * Update order tests * Complete updating the order unit tests * update kucoin and deribit wrapper to match the time in force change * fix time-in-force related test errors * linter issue fix * time in force constants, functions and unit tests update * shift tif policies to TimeInForce * Update time-in-force, related functions, and unit tests * fix linter issue and time-in-force processing * added a good till crossing tif value * order type fix and fix related tim-in-force entries * update time-in-force unmarshaling and unit test * update order type to support time-in-force and hybrid order type representation * added tests for type and time-in-force check from order type * fix time-in-force error in gateio * fix minor unit test issues * linter issue fix * update based on review comments * add unit test and fix missing issues * minor fix and added benchmark unit test * change GTT to GTC for limit * fix linter issue * linter issues fix * update order types declaration and handling by endpoints * added time-in-force value to place order param * fix minor issues based on review comment and move tif code to separate files * update on exchanges linked to time-in-force * resolve missing review comments * minor linter issues fix * added time-in-force handler and update timeInForce parametered endpoint * minor fixes based on review * nits fix * update based on review * linter fix * rm getTimeInForce func and minor change to time-in-force * minor change * update based on review comments * wrappers and time-in-force calling approach * minor change * update gateio string to timeInForce conversion and unit test * fix types to string conversion * fix build errors * update on order types handling and unit tests * fix linter issue * order type unit tests update * order types string as constant replacement and unit tests update * update order type-string functions unit test
This commit is contained in:
@@ -2226,7 +2226,7 @@ func TestGetActiveOrders(t *testing.T) {
|
||||
Side: order.Buy,
|
||||
}
|
||||
|
||||
getOrdersRequest.Type = order.OptimalLimitIOC
|
||||
getOrdersRequest.Type = order.OptimalLimit
|
||||
_, err = ku.GetActiveOrders(t.Context(), &getOrdersRequest)
|
||||
require.ErrorIs(t, err, order.ErrUnsupportedOrderType)
|
||||
|
||||
|
||||
@@ -24,49 +24,64 @@ func orderTypeFromString(orderType string) (order.Type, order.TimeInForce, error
|
||||
case orderIOC:
|
||||
return order.Limit, order.ImmediateOrCancel, nil
|
||||
case orderOptimalLimitIOC:
|
||||
return order.OptimalLimitIOC, order.ImmediateOrCancel, nil
|
||||
case "mmp":
|
||||
return order.OptimalLimit, order.ImmediateOrCancel, nil
|
||||
case orderMarketMakerProtection:
|
||||
return order.MarketMakerProtection, order.UnknownTIF, nil
|
||||
case "mmp_and_post_only":
|
||||
return order.MarketMakerProtectionAndPostOnly, order.PostOnly, nil
|
||||
case "twap":
|
||||
case orderMarketMakerProtectionAndPostOnly:
|
||||
return order.MarketMakerProtection, order.PostOnly, nil
|
||||
case orderTWAP:
|
||||
return order.TWAP, order.UnknownTIF, nil
|
||||
case "move_order_stop":
|
||||
case orderMoveOrderStop:
|
||||
return order.TrailingStop, order.UnknownTIF, nil
|
||||
case "chase":
|
||||
case orderChase:
|
||||
return order.Chase, order.UnknownTIF, nil
|
||||
default:
|
||||
return order.UnknownType, order.UnknownTIF, fmt.Errorf("%w %v", order.ErrTypeIsInvalid, orderType)
|
||||
return order.UnknownType, order.UnknownTIF, fmt.Errorf("%w %q", order.ErrTypeIsInvalid, orderType)
|
||||
}
|
||||
}
|
||||
|
||||
// orderTypeString returns a string representation of order.Type instance
|
||||
func orderTypeString(orderType order.Type, tif order.TimeInForce) (string, error) {
|
||||
switch tif {
|
||||
case order.PostOnly:
|
||||
return orderPostOnly, nil
|
||||
case order.FillOrKill:
|
||||
return orderFOK, nil
|
||||
case order.ImmediateOrCancel:
|
||||
return orderIOC, nil
|
||||
}
|
||||
switch orderType {
|
||||
case order.Market,
|
||||
order.Limit,
|
||||
order.Trigger,
|
||||
order.OptimalLimitIOC,
|
||||
order.MarketMakerProtection,
|
||||
order.MarketMakerProtectionAndPostOnly,
|
||||
case order.MarketMakerProtection:
|
||||
if tif == order.PostOnly {
|
||||
return orderMarketMakerProtectionAndPostOnly, nil
|
||||
}
|
||||
return orderMarketMakerProtection, nil
|
||||
case order.OptimalLimit:
|
||||
return orderOptimalLimitIOC, nil
|
||||
case order.Limit:
|
||||
if tif == order.PostOnly {
|
||||
return orderPostOnly, nil
|
||||
}
|
||||
return orderLimit, nil
|
||||
case order.Market:
|
||||
switch tif {
|
||||
case order.FillOrKill:
|
||||
return orderFOK, nil
|
||||
case order.ImmediateOrCancel:
|
||||
return orderIOC, nil
|
||||
}
|
||||
return orderMarket, nil
|
||||
case order.Trigger,
|
||||
order.Chase,
|
||||
order.TWAP,
|
||||
order.OCO:
|
||||
return orderType.Lower(), nil
|
||||
case order.ConditionalStop:
|
||||
return "conditional", nil
|
||||
return orderConditional, nil
|
||||
case order.TrailingStop:
|
||||
return "move_order_stop", nil
|
||||
return orderMoveOrderStop, nil
|
||||
default:
|
||||
return "", fmt.Errorf("%w: `%v`", order.ErrUnsupportedOrderType, orderType)
|
||||
switch tif {
|
||||
case order.PostOnly:
|
||||
return orderPostOnly, nil
|
||||
case order.FillOrKill:
|
||||
return orderFOK, nil
|
||||
case order.ImmediateOrCancel:
|
||||
return orderIOC, nil
|
||||
}
|
||||
return "", fmt.Errorf("%w: %q", order.ErrUnsupportedOrderType, orderType)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -152,15 +167,15 @@ func assetTypeFromInstrumentType(instrumentType string) (asset.Item, error) {
|
||||
func assetTypeString(assetType asset.Item) (string, error) {
|
||||
switch assetType {
|
||||
case asset.Spot:
|
||||
return "SPOT", nil
|
||||
return instTypeSpot, nil
|
||||
case asset.Margin:
|
||||
return "MARGIN", nil
|
||||
return instTypeMargin, nil
|
||||
case asset.Futures:
|
||||
return "FUTURES", nil
|
||||
return instTypeFutures, nil
|
||||
case asset.Options:
|
||||
return "OPTION", nil
|
||||
return instTypeOption, nil
|
||||
case asset.PerpetualSwap:
|
||||
return "SWAP", nil
|
||||
return instTypeSwap, nil
|
||||
default:
|
||||
return "", asset.ErrNotSupported
|
||||
}
|
||||
|
||||
@@ -462,7 +462,7 @@ func (ok *Okx) PlaceTakeProfitStopLossOrder(ctx context.Context, arg *AlgoOrderP
|
||||
if *arg == (AlgoOrderParams{}) {
|
||||
return nil, common.ErrEmptyParams
|
||||
}
|
||||
if arg.OrderType != "conditional" {
|
||||
if arg.OrderType != orderConditional {
|
||||
return nil, fmt.Errorf("%w for TPSL: %q", order.ErrTypeIsInvalid, arg.OrderType)
|
||||
}
|
||||
if arg.StopLossTriggerPrice <= 0 {
|
||||
@@ -481,7 +481,7 @@ func (ok *Okx) PlaceChaseAlgoOrder(ctx context.Context, arg *AlgoOrderParams) (*
|
||||
if *arg == (AlgoOrderParams{}) {
|
||||
return nil, common.ErrEmptyParams
|
||||
}
|
||||
if arg.OrderType != "chase" {
|
||||
if arg.OrderType != orderChase {
|
||||
return nil, fmt.Errorf("%w: order type value 'chase' is only supported for chase orders", order.ErrTypeIsInvalid)
|
||||
}
|
||||
if (arg.MaxChaseType == "" || arg.MaxChaseValue == 0) &&
|
||||
@@ -496,7 +496,7 @@ func (ok *Okx) PlaceTriggerAlgoOrder(ctx context.Context, arg *AlgoOrderParams)
|
||||
if *arg == (AlgoOrderParams{}) {
|
||||
return nil, common.ErrEmptyParams
|
||||
}
|
||||
if arg.OrderType != "trigger" {
|
||||
if arg.OrderType != orderTrigger {
|
||||
return nil, fmt.Errorf("%w for Trigger: %q", order.ErrTypeIsInvalid, arg.OrderType)
|
||||
}
|
||||
if arg.TriggerPrice <= 0 {
|
||||
|
||||
@@ -1222,7 +1222,7 @@ func TestPlaceChaseAlgoOrder(t *testing.T) {
|
||||
_, err = ok.PlaceChaseAlgoOrder(contextGenerate(), arg)
|
||||
require.ErrorIs(t, err, order.ErrTypeIsInvalid)
|
||||
|
||||
arg.OrderType = "chase"
|
||||
arg.OrderType = orderChase
|
||||
arg.MaxChaseType = "percentage"
|
||||
_, err = ok.PlaceChaseAlgoOrder(contextGenerate(), arg)
|
||||
require.ErrorIs(t, err, errPriceTrackingNotSet)
|
||||
@@ -1250,7 +1250,7 @@ func TestPlaceChaseAlgoOrder(t *testing.T) {
|
||||
AlgoClientOrderID: "681096944655273984",
|
||||
InstrumentID: mainPair.String(),
|
||||
LimitPrice: 100.22,
|
||||
OrderType: "chase",
|
||||
OrderType: orderChase,
|
||||
TradeMode: "cross",
|
||||
Side: order.Sell.Lower(),
|
||||
MaxChaseType: "distance",
|
||||
@@ -1297,14 +1297,14 @@ func TestPlaceTrailingStopOrder(t *testing.T) {
|
||||
assert.ErrorIs(t, err, common.ErrEmptyParams)
|
||||
_, err = ok.PlaceTrailingStopOrder(contextGenerate(), &AlgoOrderParams{Size: 2})
|
||||
assert.ErrorIs(t, err, order.ErrTypeIsInvalid)
|
||||
_, err = ok.PlaceTrailingStopOrder(contextGenerate(), &AlgoOrderParams{Size: 2, OrderType: "move_order_stop"})
|
||||
_, err = ok.PlaceTrailingStopOrder(contextGenerate(), &AlgoOrderParams{Size: 2, OrderType: orderMoveOrderStop})
|
||||
assert.ErrorIs(t, err, errPriceTrackingNotSet)
|
||||
|
||||
// Offline error handling unit tests for the base function PlaceAlgoOrder are already covered within unit test TestPlaceAlgoOrder.
|
||||
sharedtestvalues.SkipTestIfCredentialsUnset(t, ok, canManipulateRealOrders)
|
||||
result, err := ok.PlaceTrailingStopOrder(contextGenerate(), &AlgoOrderParams{
|
||||
AlgoClientOrderID: "681096944655273984", CallbackRatio: 0.01,
|
||||
InstrumentID: mainPair.String(), OrderType: "move_order_stop",
|
||||
InstrumentID: mainPair.String(), OrderType: orderMoveOrderStop,
|
||||
Side: order.Buy.Lower(), TradeMode: "isolated",
|
||||
Size: 2, ActivePrice: 1234,
|
||||
})
|
||||
@@ -5843,26 +5843,35 @@ func TestOrderTypeString(t *testing.T) {
|
||||
Expected string
|
||||
Error error
|
||||
}{
|
||||
{OrderType: order.Market, TIF: order.UnknownTIF}: {Expected: orderMarket},
|
||||
{OrderType: order.Limit, TIF: order.UnknownTIF}: {Expected: orderLimit},
|
||||
{OrderType: order.Limit, TIF: order.PostOnly}: {Expected: orderPostOnly},
|
||||
{OrderType: order.Limit, TIF: order.FillOrKill}: {Expected: orderFOK},
|
||||
{OrderType: order.Limit, TIF: order.ImmediateOrCancel}: {Expected: orderIOC},
|
||||
{OrderType: order.OptimalLimitIOC, TIF: order.UnknownTIF}: {Expected: orderOptimalLimitIOC},
|
||||
{OrderType: order.MarketMakerProtection, TIF: order.UnknownTIF}: {Expected: "mmp"},
|
||||
{OrderType: order.MarketMakerProtectionAndPostOnly, TIF: order.UnknownTIF}: {Expected: "mmp_and_post_only"},
|
||||
{OrderType: order.Liquidation, TIF: order.UnknownTIF}: {Error: order.ErrUnsupportedOrderType},
|
||||
{OrderType: order.OCO, TIF: order.UnknownTIF}: {Expected: "oco"},
|
||||
{OrderType: order.TrailingStop, TIF: order.UnknownTIF}: {Expected: "move_order_stop"},
|
||||
{OrderType: order.Chase, TIF: order.UnknownTIF}: {Expected: "chase"},
|
||||
{OrderType: order.TWAP, TIF: order.UnknownTIF}: {Expected: "twap"},
|
||||
{OrderType: order.ConditionalStop, TIF: order.UnknownTIF}: {Expected: "conditional"},
|
||||
{OrderType: order.Trigger, TIF: order.UnknownTIF}: {Expected: "trigger"},
|
||||
{OrderType: order.Market, TIF: order.UnknownTIF}: {Expected: orderMarket},
|
||||
{OrderType: order.Limit, TIF: order.UnknownTIF}: {Expected: orderLimit},
|
||||
{OrderType: order.Limit, TIF: order.PostOnly}: {Expected: orderPostOnly},
|
||||
{OrderType: order.Market, TIF: order.FillOrKill}: {Expected: orderFOK},
|
||||
{OrderType: order.Market, TIF: order.ImmediateOrCancel}: {Expected: orderIOC},
|
||||
{OrderType: order.OptimalLimit, TIF: order.ImmediateOrCancel}: {Expected: orderOptimalLimitIOC},
|
||||
{OrderType: order.MarketMakerProtection, TIF: order.UnknownTIF}: {Expected: orderMarketMakerProtection},
|
||||
{OrderType: order.MarketMakerProtection, TIF: order.PostOnly}: {Expected: orderMarketMakerProtectionAndPostOnly},
|
||||
{OrderType: order.Liquidation, TIF: order.UnknownTIF}: {Error: order.ErrUnsupportedOrderType},
|
||||
{OrderType: order.OCO, TIF: order.UnknownTIF}: {Expected: orderOCO},
|
||||
{OrderType: order.TrailingStop, TIF: order.UnknownTIF}: {Expected: orderMoveOrderStop},
|
||||
{OrderType: order.Chase, TIF: order.UnknownTIF}: {Expected: orderChase},
|
||||
{OrderType: order.TWAP, TIF: order.UnknownTIF}: {Expected: orderTWAP},
|
||||
{OrderType: order.ConditionalStop, TIF: order.UnknownTIF}: {Expected: orderConditional},
|
||||
{OrderType: order.Chase, TIF: order.GoodTillCancel}: {Expected: orderChase},
|
||||
{OrderType: order.TWAP, TIF: order.ImmediateOrCancel}: {Expected: orderTWAP},
|
||||
{OrderType: order.ConditionalStop, TIF: order.GoodTillDay}: {Expected: orderConditional},
|
||||
{OrderType: order.Trigger, TIF: order.UnknownTIF}: {Expected: orderTrigger},
|
||||
{OrderType: order.UnknownType, TIF: order.PostOnly}: {Expected: orderPostOnly},
|
||||
{OrderType: order.UnknownType, TIF: order.FillOrKill}: {Expected: orderFOK},
|
||||
{OrderType: order.UnknownType, TIF: order.ImmediateOrCancel}: {Expected: orderIOC},
|
||||
}
|
||||
for tc, val := range orderTypesToStringMap {
|
||||
orderTypeString, err := orderTypeString(tc.OrderType, tc.TIF)
|
||||
require.ErrorIs(t, err, val.Error)
|
||||
assert.Equal(t, val.Expected, orderTypeString)
|
||||
t.Run(tc.OrderType.String()+"/"+tc.TIF.String(), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
orderTypeString, err := orderTypeString(tc.OrderType, tc.TIF)
|
||||
require.ErrorIs(t, err, val.Error)
|
||||
assert.Equal(t, val.Expected, orderTypeString)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6127,7 +6136,6 @@ func TestWsProcessSpreadTradesJSON(t *testing.T) {
|
||||
|
||||
func TestOrderTypeFromString(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
orderTypeStrings := map[string]struct {
|
||||
OType order.Type
|
||||
TIF order.TimeInForce
|
||||
@@ -6139,9 +6147,9 @@ func TestOrderTypeFromString(t *testing.T) {
|
||||
"post_only": {OType: order.Limit, TIF: order.PostOnly},
|
||||
"fok": {OType: order.Limit, TIF: order.FillOrKill},
|
||||
"ioc": {OType: order.Limit, TIF: order.ImmediateOrCancel},
|
||||
"optimal_limit_ioc": {OType: order.OptimalLimitIOC, TIF: order.ImmediateOrCancel},
|
||||
"optimal_limit_ioc": {OType: order.OptimalLimit, TIF: order.ImmediateOrCancel},
|
||||
"mmp": {OType: order.MarketMakerProtection},
|
||||
"mmp_and_post_only": {OType: order.MarketMakerProtectionAndPostOnly, TIF: order.PostOnly},
|
||||
"mmp_and_post_only": {OType: order.MarketMakerProtection, TIF: order.PostOnly},
|
||||
"trigger": {OType: order.UnknownType, Error: order.ErrTypeIsInvalid},
|
||||
"chase": {OType: order.Chase},
|
||||
"move_order_stop": {OType: order.TrailingStop},
|
||||
@@ -6149,10 +6157,13 @@ func TestOrderTypeFromString(t *testing.T) {
|
||||
"abcd": {OType: order.UnknownType, Error: order.ErrTypeIsInvalid},
|
||||
}
|
||||
for s, exp := range orderTypeStrings {
|
||||
oType, tif, err := orderTypeFromString(s)
|
||||
require.ErrorIs(t, err, exp.Error)
|
||||
assert.Equal(t, exp.OType, oType)
|
||||
assert.Equal(t, exp.TIF.String(), tif.String(), s)
|
||||
t.Run(s, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
oType, tif, err := orderTypeFromString(s)
|
||||
require.ErrorIs(t, err, exp.Error)
|
||||
assert.Equal(t, exp.OType, oType)
|
||||
assert.Equal(t, exp.TIF.String(), tif.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,19 +41,22 @@ const (
|
||||
positionSideNet = "net"
|
||||
)
|
||||
|
||||
// order types, margin balance types, and instrument types constants
|
||||
const (
|
||||
// orderLimit Limit order
|
||||
orderLimit = "limit"
|
||||
// orderMarket Market order
|
||||
orderMarket = "market"
|
||||
// orderPostOnly POST_ONLY order type
|
||||
orderPostOnly = "post_only"
|
||||
// orderFOK fill or kill order type
|
||||
orderFOK = "fok"
|
||||
// orderIOC IOC (immediate or cancel)
|
||||
orderIOC = "ioc"
|
||||
// orderOptimalLimitIOC OPTIMAL_LIMIT_IOC
|
||||
orderOptimalLimitIOC = "optimal_limit_ioc"
|
||||
orderLimit = "limit"
|
||||
orderMarket = "market"
|
||||
orderPostOnly = "post_only"
|
||||
orderFOK = "fok"
|
||||
orderIOC = "ioc"
|
||||
orderOptimalLimitIOC = "optimal_limit_ioc"
|
||||
orderConditional = "conditional"
|
||||
orderMoveOrderStop = "move_order_stop"
|
||||
orderChase = "chase"
|
||||
orderTWAP = "twap"
|
||||
orderTrigger = "trigger"
|
||||
orderMarketMakerProtectionAndPostOnly = "mmp_and_post_only"
|
||||
orderMarketMakerProtection = "mmp"
|
||||
orderOCO = "oco"
|
||||
|
||||
// represents a margin balance type
|
||||
marginBalanceReduce = "reduce"
|
||||
|
||||
@@ -958,7 +958,7 @@ func (ok *Okx) SubmitOrder(ctx context.Context, s *order.Submit) (*order.SubmitR
|
||||
return nil, err
|
||||
}
|
||||
return s.DeriveSubmitResponse(placeOrderResponse.OrderID)
|
||||
case "trigger":
|
||||
case orderTrigger:
|
||||
result, err = ok.PlaceTriggerAlgoOrder(ctx, &AlgoOrderParams{
|
||||
InstrumentID: pairString,
|
||||
TradeMode: tradeMode,
|
||||
@@ -970,7 +970,7 @@ func (ok *Okx) SubmitOrder(ctx context.Context, s *order.Submit) (*order.SubmitR
|
||||
TriggerPrice: s.TriggerPrice,
|
||||
TriggerPriceType: priceTypeString(s.TriggerPriceType),
|
||||
})
|
||||
case "conditional":
|
||||
case orderConditional:
|
||||
// Trigger Price and type are used as a stop losss trigger price and type.
|
||||
result, err = ok.PlaceTakeProfitStopLossOrder(ctx, &AlgoOrderParams{
|
||||
InstrumentID: pairString,
|
||||
@@ -984,7 +984,7 @@ func (ok *Okx) SubmitOrder(ctx context.Context, s *order.Submit) (*order.SubmitR
|
||||
StopLossOrderPrice: s.Price,
|
||||
StopLossTriggerPriceType: priceTypeString(s.TriggerPriceType),
|
||||
})
|
||||
case "chase":
|
||||
case orderChase:
|
||||
if s.TrackingMode == order.UnknownTrackingMode {
|
||||
return nil, fmt.Errorf("%w, tracking mode unset", order.ErrUnknownTrackingMode)
|
||||
}
|
||||
@@ -1002,7 +1002,7 @@ func (ok *Okx) SubmitOrder(ctx context.Context, s *order.Submit) (*order.SubmitR
|
||||
MaxChaseType: s.TrackingMode.String(),
|
||||
MaxChaseValue: s.TrackingValue,
|
||||
})
|
||||
case "move_order_stop":
|
||||
case orderMoveOrderStop:
|
||||
if s.TrackingMode == order.UnknownTrackingMode {
|
||||
return nil, fmt.Errorf("%w, tracking mode unset", order.ErrUnknownTrackingMode)
|
||||
}
|
||||
@@ -1025,7 +1025,7 @@ func (ok *Okx) SubmitOrder(ctx context.Context, s *order.Submit) (*order.SubmitR
|
||||
CallbackSpreadVariance: callbackSpread,
|
||||
ActivePrice: s.TriggerPrice,
|
||||
})
|
||||
case "twap":
|
||||
case orderTWAP:
|
||||
if s.TrackingMode == order.UnknownTrackingMode {
|
||||
return nil, fmt.Errorf("%w, tracking mode unset", order.ErrUnknownTrackingMode)
|
||||
}
|
||||
@@ -1050,7 +1050,7 @@ func (ok *Okx) SubmitOrder(ctx context.Context, s *order.Submit) (*order.SubmitR
|
||||
LimitPrice: s.Price,
|
||||
TimeInterval: kline.FifteenMin,
|
||||
})
|
||||
case "oco":
|
||||
case orderOCO:
|
||||
switch {
|
||||
case s.RiskManagementModes.TakeProfit.Price <= 0:
|
||||
return nil, fmt.Errorf("%w, take profit price is required", order.ErrPriceBelowMin)
|
||||
@@ -1144,7 +1144,7 @@ func (ok *Okx) ModifyOrder(ctx context.Context, action *order.Modify) (*order.Mo
|
||||
return nil, currency.ErrCurrencyPairEmpty
|
||||
}
|
||||
switch action.Type {
|
||||
case order.UnknownType, order.Market, order.Limit, order.OptimalLimitIOC, order.MarketMakerProtection, order.MarketMakerProtectionAndPostOnly:
|
||||
case order.UnknownType, order.Market, order.Limit, order.OptimalLimit, order.MarketMakerProtection:
|
||||
amendRequest := AmendOrderRequestParams{
|
||||
InstrumentID: pairFormat.Format(action.Pair),
|
||||
NewQuantity: action.Amount,
|
||||
@@ -1248,7 +1248,7 @@ func (ok *Okx) CancelOrder(ctx context.Context, ord *order.Cancel) error {
|
||||
}
|
||||
instrumentID := pairFormat.Format(ord.Pair)
|
||||
switch ord.Type {
|
||||
case order.UnknownType, order.Market, order.Limit, order.OptimalLimitIOC, order.MarketMakerProtection, order.MarketMakerProtectionAndPostOnly:
|
||||
case order.UnknownType, order.Market, order.Limit, order.OptimalLimit, order.MarketMakerProtection:
|
||||
req := CancelOrderRequestParam{
|
||||
InstrumentID: instrumentID,
|
||||
OrderID: ord.OrderID,
|
||||
@@ -1301,7 +1301,7 @@ func (ok *Okx) CancelBatchOrders(ctx context.Context, o []order.Cancel) (*order.
|
||||
return nil, currency.ErrCurrencyPairsEmpty
|
||||
}
|
||||
switch ord.Type {
|
||||
case order.UnknownType, order.Market, order.Limit, order.OptimalLimitIOC, order.MarketMakerProtection, order.MarketMakerProtectionAndPostOnly:
|
||||
case order.UnknownType, order.Market, order.Limit, order.OptimalLimit, order.MarketMakerProtection:
|
||||
if o[x].ClientID == "" && o[x].OrderID == "" {
|
||||
return nil, fmt.Errorf("%w, order ID required for order of type %v", order.ErrOrderIDNotSet, o[x].Type)
|
||||
}
|
||||
|
||||
@@ -297,6 +297,33 @@ func TestTitle(t *testing.T) {
|
||||
require.Equal(t, "Limit", orderType.Title())
|
||||
}
|
||||
|
||||
func TestOrderIs(t *testing.T) {
|
||||
t.Parallel()
|
||||
orderComparisonList := []struct {
|
||||
Type Type
|
||||
Targets []Type
|
||||
}{
|
||||
{Type: Limit | TakeProfit, Targets: []Type{TakeProfit, Limit}},
|
||||
{Type: IOS, Targets: []Type{IOS}},
|
||||
{Type: Stop, Targets: []Type{Stop}},
|
||||
{Type: AnyType, Targets: []Type{AnyType}},
|
||||
{Type: StopLimit, Targets: []Type{Stop, Limit}},
|
||||
{Type: TakeProfit, Targets: []Type{TakeProfit}},
|
||||
{Type: StopMarket, Targets: []Type{Stop, Market}},
|
||||
{Type: TrailingStop, Targets: []Type{TrailingStop}},
|
||||
{Type: UnknownType | Limit, Targets: []Type{Limit}},
|
||||
{Type: TakeProfitMarket, Targets: []Type{TakeProfit, Market}},
|
||||
}
|
||||
for _, oType := range orderComparisonList {
|
||||
t.Run(oType.Type.String(), func(t *testing.T) {
|
||||
t.Parallel()
|
||||
for _, target := range oType.Targets {
|
||||
assert.Truef(t, oType.Type.Is(target), "expected %v, got %q", target, oType.Type.String())
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrderTypes(t *testing.T) {
|
||||
t.Parallel()
|
||||
var orderType Type
|
||||
@@ -305,6 +332,41 @@ func TestOrderTypes(t *testing.T) {
|
||||
assert.Equal(t, "Unknown", orderType.Title())
|
||||
}
|
||||
|
||||
func TestOrderTypeToString(t *testing.T) {
|
||||
t.Parallel()
|
||||
orderToToStringsList := []struct {
|
||||
OrderType Type
|
||||
String string
|
||||
}{
|
||||
{StopMarket, "STOP MARKET"},
|
||||
{StopLimit, "STOP LIMIT"},
|
||||
{Limit, "LIMIT"},
|
||||
{Market, "MARKET"},
|
||||
{Stop, "STOP"},
|
||||
{ConditionalStop, "CONDITIONAL"},
|
||||
{TWAP, "TWAP"},
|
||||
{Chase, "CHASE"},
|
||||
{TakeProfit, "TAKE PROFIT"},
|
||||
{TakeProfitMarket, "TAKE PROFIT MARKET"},
|
||||
{TrailingStop, "TRAILING_STOP"},
|
||||
{IOS, "IOS"},
|
||||
{Liquidation, "LIQUIDATION"},
|
||||
{Trigger, "TRIGGER"},
|
||||
{OCO, "OCO"},
|
||||
{OptimalLimit, "OPTIMAL_LIMIT"},
|
||||
{MarketMakerProtection, "MMP"},
|
||||
{AnyType, "ANY"},
|
||||
{UnknownType | Limit, "LIMIT"},
|
||||
{StopMarket | ConditionalStop, "UNKNOWN"},
|
||||
}
|
||||
for _, tt := range orderToToStringsList {
|
||||
t.Run(tt.String, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
assert.Equal(t, tt.String, tt.OrderType.String())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestInferCostsAndTimes(t *testing.T) {
|
||||
t.Parallel()
|
||||
var detail Detail
|
||||
@@ -736,6 +798,7 @@ func BenchmarkStringToOrderSide(b *testing.B) {
|
||||
}
|
||||
|
||||
func TestStringToOrderType(t *testing.T) {
|
||||
t.Parallel()
|
||||
cases := []struct {
|
||||
in string
|
||||
out Type
|
||||
@@ -766,14 +829,12 @@ func TestStringToOrderType(t *testing.T) {
|
||||
{"conDitiOnal", ConditionalStop, nil},
|
||||
{"oCo", OCO, nil},
|
||||
{"mMp", MarketMakerProtection, nil},
|
||||
{"Mmp_And_Post_oNly", MarketMakerProtectionAndPostOnly, nil},
|
||||
{"tWaP", TWAP, nil},
|
||||
{"TWAP", TWAP, nil},
|
||||
{"woahMan", UnknownType, errUnrecognisedOrderType},
|
||||
{"chase", Chase, nil},
|
||||
{"MOVE_ORDER_STOP", TrailingStop, nil},
|
||||
{"mOVe_OrdeR_StoP", TrailingStop, nil},
|
||||
{"optimal_limit_IoC", OptimalLimitIOC, nil},
|
||||
{"Stop_market", StopMarket, nil},
|
||||
{"liquidation", Liquidation, nil},
|
||||
{"LiQuidation", Liquidation, nil},
|
||||
@@ -781,10 +842,13 @@ func TestStringToOrderType(t *testing.T) {
|
||||
{"Take ProfIt", TakeProfit, nil},
|
||||
{"TAKE PROFIT MARkEt", TakeProfitMarket, nil},
|
||||
{"TAKE_PROFIT_MARkEt", TakeProfitMarket, nil},
|
||||
{"optimal_limit", OptimalLimit, nil},
|
||||
{"OPTIMAL_LIMIT", OptimalLimit, nil},
|
||||
}
|
||||
for i := range cases {
|
||||
testData := &cases[i]
|
||||
t.Run(testData.in, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
out, err := StringToOrderType(testData.in)
|
||||
require.ErrorIs(t, err, testData.err)
|
||||
assert.Equal(t, testData.out, out)
|
||||
|
||||
@@ -348,7 +348,12 @@ const (
|
||||
)
|
||||
|
||||
// Type enforces a standard for order types across the code base
|
||||
type Type uint32
|
||||
type Type uint64
|
||||
|
||||
// Is checks to see if the Type contains the Type cmp
|
||||
func (t Type) Is(cmp Type) bool {
|
||||
return cmp != 0 && t&cmp == cmp
|
||||
}
|
||||
|
||||
// Defined package order types
|
||||
const (
|
||||
@@ -356,22 +361,45 @@ const (
|
||||
Limit Type = 1 << iota
|
||||
Market
|
||||
Stop
|
||||
StopLimit
|
||||
StopMarket
|
||||
TakeProfit
|
||||
TakeProfitMarket
|
||||
TrailingStop
|
||||
IOS
|
||||
AnyType
|
||||
Liquidation
|
||||
Trigger
|
||||
OptimalLimitIOC
|
||||
OCO // One-cancels-the-other order
|
||||
ConditionalStop // One-way stop order
|
||||
MarketMakerProtection // market-maker-protection used with portfolio margin mode. See https://www.okx.com/docs-v5/en/#order-book-trading-trade-post-place-order
|
||||
MarketMakerProtectionAndPostOnly // market-maker-protection and post-only mode. Used in Okx exchange orders.
|
||||
TWAP // time-weighted average price.
|
||||
Chase // chase order. See https://www.okx.com/docs-v5/en/#order-book-trading-algo-trading-post-place-algo-order
|
||||
OCO // One-cancels-the-other order
|
||||
ConditionalStop // One-way stop order
|
||||
TWAP // time-weighted average price
|
||||
Chase // chase limit order
|
||||
OptimalLimit
|
||||
MarketMakerProtection
|
||||
|
||||
// Hybrid order types
|
||||
StopLimit = Stop | Limit
|
||||
StopMarket = Stop | Market
|
||||
TakeProfitMarket = TakeProfit | Market
|
||||
)
|
||||
|
||||
// order-type string representations
|
||||
const (
|
||||
orderStopMarket = "STOP MARKET"
|
||||
orderStopLimit = "STOP LIMIT"
|
||||
orderLimit = "LIMIT"
|
||||
orderMarket = "MARKET"
|
||||
orderStop = "STOP"
|
||||
orderConditionalStop = "CONDITIONAL"
|
||||
orderTWAP = "TWAP"
|
||||
orderChase = "CHASE"
|
||||
orderTakeProfit = "TAKE PROFIT"
|
||||
orderTakeProfitMarket = "TAKE PROFIT MARKET"
|
||||
orderTrailingStop = "TRAILING_STOP"
|
||||
orderIOS = "IOS"
|
||||
orderLiquidation = "LIQUIDATION"
|
||||
orderTrigger = "TRIGGER"
|
||||
orderOCO = "OCO"
|
||||
orderOptimalLimit = "OPTIMAL_LIMIT"
|
||||
orderMarketMakerProtection = "MMP"
|
||||
orderAnyType = "ANY"
|
||||
)
|
||||
|
||||
// Side enforces a standard for order sides across the code base
|
||||
|
||||
@@ -667,44 +667,42 @@ func (d *Detail) DeriveCancel() (*Cancel, error) {
|
||||
// String implements the stringer interface
|
||||
func (t Type) String() string {
|
||||
switch t {
|
||||
case AnyType:
|
||||
return "ANY"
|
||||
case Limit:
|
||||
return "LIMIT"
|
||||
case Market:
|
||||
return "MARKET"
|
||||
case Stop:
|
||||
return "STOP"
|
||||
case ConditionalStop:
|
||||
return "CONDITIONAL"
|
||||
case MarketMakerProtection:
|
||||
return "MMP"
|
||||
case MarketMakerProtectionAndPostOnly:
|
||||
return "MMP_AND_POST_ONLY"
|
||||
case TWAP:
|
||||
return "TWAP"
|
||||
case Chase:
|
||||
return "CHASE"
|
||||
case StopLimit:
|
||||
return "STOP LIMIT"
|
||||
case StopMarket:
|
||||
return "STOP MARKET"
|
||||
return orderStopMarket
|
||||
case StopLimit:
|
||||
return orderStopLimit
|
||||
case Limit:
|
||||
return orderLimit
|
||||
case Market:
|
||||
return orderMarket
|
||||
case Stop:
|
||||
return orderStop
|
||||
case ConditionalStop:
|
||||
return orderConditionalStop
|
||||
case TWAP:
|
||||
return orderTWAP
|
||||
case Chase:
|
||||
return orderChase
|
||||
case TakeProfit:
|
||||
return "TAKE PROFIT"
|
||||
return orderTakeProfit
|
||||
case TakeProfitMarket:
|
||||
return "TAKE PROFIT MARKET"
|
||||
return orderTakeProfitMarket
|
||||
case TrailingStop:
|
||||
return "TRAILING_STOP"
|
||||
return orderTrailingStop
|
||||
case IOS:
|
||||
return "IOS"
|
||||
return orderIOS
|
||||
case Liquidation:
|
||||
return "LIQUIDATION"
|
||||
return orderLiquidation
|
||||
case Trigger:
|
||||
return "TRIGGER"
|
||||
case OptimalLimitIOC:
|
||||
return "OPTIMAL_LIMIT_IOC"
|
||||
return orderTrigger
|
||||
case OCO:
|
||||
return "OCO"
|
||||
return orderOCO
|
||||
case OptimalLimit:
|
||||
return orderOptimalLimit
|
||||
case MarketMakerProtection:
|
||||
return orderMarketMakerProtection
|
||||
case AnyType:
|
||||
return orderAnyType
|
||||
default:
|
||||
return "UNKNOWN"
|
||||
}
|
||||
@@ -1102,43 +1100,41 @@ func (s Side) MarshalJSON() ([]byte, error) {
|
||||
func StringToOrderType(oType string) (Type, error) {
|
||||
oType = strings.ToUpper(oType)
|
||||
switch oType {
|
||||
case Limit.String(), "EXCHANGE LIMIT":
|
||||
case orderLimit, "EXCHANGE LIMIT":
|
||||
return Limit, nil
|
||||
case Market.String(), "EXCHANGE MARKET":
|
||||
case orderMarket, "EXCHANGE MARKET":
|
||||
return Market, nil
|
||||
case Stop.String(), "STOP LOSS", "STOP_LOSS", "EXCHANGE STOP":
|
||||
case orderStop, "STOP LOSS", "STOP_LOSS", "EXCHANGE STOP":
|
||||
return Stop, nil
|
||||
case StopLimit.String(), "EXCHANGE STOP LIMIT", "STOP_LIMIT":
|
||||
case orderStopLimit, "EXCHANGE STOP LIMIT", "STOP_LIMIT":
|
||||
return StopLimit, nil
|
||||
case StopMarket.String(), "STOP_MARKET":
|
||||
case orderStopMarket, "STOP_MARKET":
|
||||
return StopMarket, nil
|
||||
case TrailingStop.String(), "TRAILING STOP", "EXCHANGE TRAILING STOP", "MOVE_ORDER_STOP":
|
||||
case orderTrailingStop, "TRAILING STOP", "EXCHANGE TRAILING STOP", "MOVE_ORDER_STOP":
|
||||
return TrailingStop, nil
|
||||
case IOS.String():
|
||||
case orderIOS:
|
||||
return IOS, nil
|
||||
case AnyType.String():
|
||||
case orderAnyType:
|
||||
return AnyType, nil
|
||||
case Trigger.String():
|
||||
case orderTrigger:
|
||||
return Trigger, nil
|
||||
case OptimalLimitIOC.String():
|
||||
return OptimalLimitIOC, nil
|
||||
case OCO.String():
|
||||
case orderOptimalLimit:
|
||||
return OptimalLimit, nil
|
||||
case orderOCO:
|
||||
return OCO, nil
|
||||
case ConditionalStop.String():
|
||||
case orderConditionalStop:
|
||||
return ConditionalStop, nil
|
||||
case MarketMakerProtection.String():
|
||||
case orderMarketMakerProtection:
|
||||
return MarketMakerProtection, nil
|
||||
case MarketMakerProtectionAndPostOnly.String():
|
||||
return MarketMakerProtectionAndPostOnly, nil
|
||||
case TWAP.String():
|
||||
case orderTWAP:
|
||||
return TWAP, nil
|
||||
case Chase.String():
|
||||
case orderChase:
|
||||
return Chase, nil
|
||||
case TakeProfitMarket.String(), "TAKE_PROFIT_MARKET":
|
||||
case orderTakeProfitMarket, "TAKE_PROFIT_MARKET":
|
||||
return TakeProfitMarket, nil
|
||||
case TakeProfit.String(), "TAKE_PROFIT":
|
||||
case orderTakeProfit, "TAKE_PROFIT":
|
||||
return TakeProfit, nil
|
||||
case Liquidation.String():
|
||||
case orderLiquidation:
|
||||
return Liquidation, nil
|
||||
default:
|
||||
return UnknownType, fmt.Errorf("'%v' %w", oType, errUnrecognisedOrderType)
|
||||
|
||||
Reference in New Issue
Block a user