* @method * @name coinbase#createOrder * @description create a trade order * @see https://docs.cdp.coinbase.com/api-reference/advanced-trade-api/rest-api/orders/create-order * @param {string} symbol unified symbol of the market to create an order in * @param {string} type 'm
(symbol, type, side, amount, price = undefined, params = {})
| 2983 | * @returns {object} an [order structure]{@link https://docs.ccxt.com/?id=order-structure} |
| 2984 | */ |
| 2985 | async createOrder(symbol, type, side, amount, price = undefined, params = {}) { |
| 2986 | await this.loadMarkets(); |
| 2987 | const market = this.market(symbol); |
| 2988 | const id = this.safeString(this.options, 'brokerId', 'ccxt'); |
| 2989 | let request = { |
| 2990 | 'client_order_id': id + '-' + this.uuid(), |
| 2991 | 'product_id': market['id'], |
| 2992 | 'side': side.toUpperCase(), |
| 2993 | }; |
| 2994 | const reduceOnly = this.safeBool(params, 'reduceOnly'); |
| 2995 | if (reduceOnly) { |
| 2996 | params = this.omit(params, 'reduceOnly'); |
| 2997 | params['amount'] = amount; |
| 2998 | return await this.closePosition(symbol, side, params); |
| 2999 | } |
| 3000 | const triggerPrice = this.safeNumberN(params, ['stopPrice', 'stop_price', 'triggerPrice']); |
| 3001 | const stopLossPrice = this.safeNumber(params, 'stopLossPrice'); |
| 3002 | const takeProfitPrice = this.safeNumber(params, 'takeProfitPrice'); |
| 3003 | const isStop = triggerPrice !== undefined; |
| 3004 | const isStopLoss = stopLossPrice !== undefined; |
| 3005 | const isTakeProfit = takeProfitPrice !== undefined; |
| 3006 | const timeInForce = this.safeString(params, 'timeInForce'); |
| 3007 | const postOnly = (timeInForce === 'PO') ? true : this.safeBool2(params, 'postOnly', 'post_only', false); |
| 3008 | const endTime = this.safeString(params, 'end_time'); |
| 3009 | let stopDirection = this.safeString(params, 'stop_direction'); |
| 3010 | if (type === 'limit') { |
| 3011 | if (isStop) { |
| 3012 | if (stopDirection === undefined) { |
| 3013 | stopDirection = (side === 'buy') ? 'STOP_DIRECTION_STOP_DOWN' : 'STOP_DIRECTION_STOP_UP'; |
| 3014 | } |
| 3015 | if ((timeInForce === 'GTD') || (endTime !== undefined)) { |
| 3016 | if (endTime === undefined) { |
| 3017 | throw new ExchangeError(this.id + ' createOrder() requires an end_time parameter for a GTD order'); |
| 3018 | } |
| 3019 | request['order_configuration'] = { |
| 3020 | 'stop_limit_stop_limit_gtd': { |
| 3021 | 'base_size': this.amountToPrecision(symbol, amount), |
| 3022 | 'limit_price': this.priceToPrecision(symbol, price), |
| 3023 | 'stop_price': this.priceToPrecision(symbol, triggerPrice), |
| 3024 | 'stop_direction': stopDirection, |
| 3025 | 'end_time': endTime, |
| 3026 | }, |
| 3027 | }; |
| 3028 | } |
| 3029 | else { |
| 3030 | request['order_configuration'] = { |
| 3031 | 'stop_limit_stop_limit_gtc': { |
| 3032 | 'base_size': this.amountToPrecision(symbol, amount), |
| 3033 | 'limit_price': this.priceToPrecision(symbol, price), |
| 3034 | 'stop_price': this.priceToPrecision(symbol, triggerPrice), |
| 3035 | 'stop_direction': stopDirection, |
| 3036 | }, |
| 3037 | }; |
| 3038 | } |
| 3039 | } |
| 3040 | else if (isStopLoss || isTakeProfit) { |
| 3041 | let tpslPrice = undefined; |
| 3042 | if (isStopLoss) { |
no test coverage detected