From b38e6fe3022694f176269b209793dc59f2ac0324 Mon Sep 17 00:00:00 2001 From: JKorf Date: Wed, 28 Aug 2024 18:32:09 +0200 Subject: [PATCH] Added FuturesApi.Trading.PlaceTpSlOrderAsync endpoint, added ClientOrderId property to futures order placement response --- .../Futures/Trading/PlaceTpSlOrder.txt | 10 ++++ Kucoin.Net.UnitTests/RestRequestTests.cs | 1 + .../KucoinRestClientFuturesApiTrading.cs | 52 +++++++++++++++++++ .../IKucoinRestClientFuturesApiTrading.cs | 52 +++++++++++++++++++ Kucoin.Net/Kucoin.Net.xml | 36 +++++++++++++ .../Objects/Models/Spot/KucoinOrderId.cs | 5 ++ 6 files changed, 156 insertions(+) create mode 100644 Kucoin.Net.UnitTests/Endpoints/Futures/Trading/PlaceTpSlOrder.txt diff --git a/Kucoin.Net.UnitTests/Endpoints/Futures/Trading/PlaceTpSlOrder.txt b/Kucoin.Net.UnitTests/Endpoints/Futures/Trading/PlaceTpSlOrder.txt new file mode 100644 index 00000000..e2a7ead5 --- /dev/null +++ b/Kucoin.Net.UnitTests/Endpoints/Futures/Trading/PlaceTpSlOrder.txt @@ -0,0 +1,10 @@ +POST +/api/v1/st-orders +true +{ + "code": "200000", + "data": { + "orderId": "5bd6e9286d99522a52e458de", + "clientOid": "5c52e11203aa677f33e493fb" + } + } \ No newline at end of file diff --git a/Kucoin.Net.UnitTests/RestRequestTests.cs b/Kucoin.Net.UnitTests/RestRequestTests.cs index ba13b183..3aa20f4f 100644 --- a/Kucoin.Net.UnitTests/RestRequestTests.cs +++ b/Kucoin.Net.UnitTests/RestRequestTests.cs @@ -225,6 +225,7 @@ public async Task ValidateFuturesTradingCalls() var tester = new RestRequestValidator(client, "Endpoints/Futures/Trading", "https://api-futures.kucoin.com", IsAuthenticated, "data", stjCompare: false); await tester.ValidateAsync(client => client.FuturesApi.Trading.PlaceOrderAsync("ETHUSDT", Enums.OrderSide.Buy, Enums.NewOrderType.Market, 1, 1), "PlaceOrder"); await tester.ValidateAsync(client => client.FuturesApi.Trading.PlaceTestOrderAsync("ETHUSDT", Enums.OrderSide.Buy, Enums.NewOrderType.Market, 1, 1), "PlaceTestOrder"); + await tester.ValidateAsync(client => client.FuturesApi.Trading.PlaceTpSlOrderAsync("ETHUSDT", Enums.OrderSide.Buy, Enums.NewOrderType.Market, 1, 1), "PlaceTpSlOrder"); await tester.ValidateAsync(client => client.FuturesApi.Trading.PlaceMultipleOrdersAsync(new[] { new KucoinFuturesOrderRequestEntry() }), "PlaceMultipleOrders"); await tester.ValidateAsync(client => client.FuturesApi.Trading.CancelOrderAsync("123"), "CancelOrder"); await tester.ValidateAsync(client => client.FuturesApi.Trading.CancelOrderByClientOrderIdAsync("ETHUSDT", "123"), "CancelOrderByClientOrderId"); diff --git a/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApiTrading.cs b/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApiTrading.cs index c3842422..9b00a729 100644 --- a/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApiTrading.cs +++ b/Kucoin.Net/Clients/FuturesApi/KucoinRestClientFuturesApiTrading.cs @@ -135,6 +135,58 @@ public async Task> PlaceTestOrderAsync( return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); } + /// + public async Task> PlaceTpSlOrderAsync( + string symbol, + OrderSide side, + NewOrderType type, + decimal leverage, + int quantity, + + decimal? price = null, + TimeInForce? timeInForce = null, + bool? postOnly = null, + bool? hidden = null, + bool? iceberg = null, + decimal? visibleSize = null, + + string? remark = null, + decimal? takeProfitPrice = null, + decimal? stopLossPrice = null, + StopPriceType? stopPriceType = null, + bool? reduceOnly = null, + bool? closeOrder = null, + bool? forceHold = null, + string? clientOrderId = null, + SelfTradePrevention? selfTradePrevention = null, + CancellationToken ct = default) + { + var parameters = new ParameterCollection(); + parameters.AddParameter("symbol", symbol); + parameters.AddParameter("side", JsonConvert.SerializeObject(side, new OrderSideConverter(false))); + parameters.AddParameter("type", JsonConvert.SerializeObject(type, new NewOrderTypeConverter(false))); + parameters.AddParameter("leverage", leverage.ToString(CultureInfo.InvariantCulture)); + parameters.AddParameter("size", quantity.ToString(CultureInfo.InvariantCulture)); + parameters.AddParameter("clientOid", clientOrderId ?? Guid.NewGuid().ToString()); + parameters.AddOptionalParameter("remark", remark); + parameters.AddOptionalString("triggerStopUpPrice", takeProfitPrice); + parameters.AddOptionalParameter("stopPriceType", stopPriceType != null ? JsonConvert.SerializeObject(stopPriceType, new StopPriceTypeConverter(false)) : null); + parameters.AddOptionalString("triggerStopDownPrice", stopLossPrice); + parameters.AddOptionalParameter("reduceOnly", reduceOnly?.ToString()); + parameters.AddOptionalParameter("closeOrder", closeOrder?.ToString()); + parameters.AddOptionalParameter("forceHold", forceHold?.ToString()); + parameters.AddOptionalParameter("price", price?.ToString(CultureInfo.InvariantCulture)); + parameters.AddOptionalParameter("timeInForce", timeInForce != null ? JsonConvert.SerializeObject(timeInForce, new TimeInForceConverter(false)) : null); + parameters.AddOptionalParameter("postOnly", postOnly?.ToString()); + parameters.AddOptionalParameter("hidden", hidden?.ToString()); + parameters.AddOptionalParameter("iceberg", iceberg); + parameters.AddOptionalParameter("visibleSize", visibleSize?.ToString()); + parameters.AddOptionalEnum("stp", selfTradePrevention); + + var request = _definitions.GetOrCreate(HttpMethod.Post, $"api/v1/st-orders", KucoinExchange.RateLimiter.FuturesRest, 2, true); + return await _baseClient.SendAsync(request, parameters, ct).ConfigureAwait(false); + } + /// public async Task>> PlaceMultipleOrdersAsync(IEnumerable orders, CancellationToken ct = default) { diff --git a/Kucoin.Net/Interfaces/Clients/FuturesApi/IKucoinRestClientFuturesApiTrading.cs b/Kucoin.Net/Interfaces/Clients/FuturesApi/IKucoinRestClientFuturesApiTrading.cs index 5fdee566..5a049521 100644 --- a/Kucoin.Net/Interfaces/Clients/FuturesApi/IKucoinRestClientFuturesApiTrading.cs +++ b/Kucoin.Net/Interfaces/Clients/FuturesApi/IKucoinRestClientFuturesApiTrading.cs @@ -115,6 +115,58 @@ Task> PlaceTestOrderAsync( SelfTradePrevention? selfTradePrevention = null, CancellationToken ct = default); + + /// + /// Place a new take profit / stop loss order + /// + /// + /// The contract for the order, for example `XBTUSDM` + /// Side of the order + /// Type of order + /// Leverage of the order + /// Limit price, only for limit orders + /// Time in force, only for limit orders + /// Post only flag, invalid when timeInForce is IOC + /// Orders not displaying in order book. When hidden chose + /// Only visible portion of the order is displayed in the order book + /// The maximum visible size of an iceberg order + /// Quantity of contract to buy or sell + /// Remark for the order + /// Price type + /// Take profit price + /// Stop loss price + /// A mark to reduce the position size only. Set to false by default + /// A mark to close the position. Set to false by default. All the positions will be closed if true + /// A mark to forcely hold the funds for an order, even though it's an order to reduce the position size. This helps the order stay on the order book and not get canceled when the position size changes. Set to false by default + /// Self Trade Prevention mode + /// Client order id + /// Cancellation token + /// Order details + Task> PlaceTpSlOrderAsync( + string symbol, + OrderSide side, + NewOrderType type, + decimal leverage, + int quantity, + + decimal? price = null, + TimeInForce? timeInForce = null, + bool? postOnly = null, + bool? hidden = null, + bool? iceberg = null, + decimal? visibleSize = null, + + string? remark = null, + decimal? takeProfitPrice = null, + decimal? stopLossPrice = null, + StopPriceType? stopPriceType = null, + bool? reduceOnly = null, + bool? closeOrder = null, + bool? forceHold = null, + string? clientOrderId = null, + SelfTradePrevention? selfTradePrevention = null, + CancellationToken ct = default); + /// /// Place multiple orders /// diff --git a/Kucoin.Net/Kucoin.Net.xml b/Kucoin.Net/Kucoin.Net.xml index e9f75987..7055819e 100644 --- a/Kucoin.Net/Kucoin.Net.xml +++ b/Kucoin.Net/Kucoin.Net.xml @@ -175,6 +175,9 @@ + + + @@ -2769,6 +2772,34 @@ Cancellation token Order details + + + Place a new take profit / stop loss order + + + The contract for the order, for example `XBTUSDM` + Side of the order + Type of order + Leverage of the order + Limit price, only for limit orders + Time in force, only for limit orders + Post only flag, invalid when timeInForce is IOC + Orders not displaying in order book. When hidden chose + Only visible portion of the order is displayed in the order book + The maximum visible size of an iceberg order + Quantity of contract to buy or sell + Remark for the order + Price type + Take profit price + Stop loss price + A mark to reduce the position size only. Set to false by default + A mark to close the position. Set to false by default. All the positions will be closed if true + A mark to forcely hold the funds for an order, even though it's an order to reduce the position size. This helps the order stay on the order book and not get canceled when the position size changes. Set to false by default + Self Trade Prevention mode + Client order id + Cancellation token + Order details + Place multiple orders @@ -10000,6 +10031,11 @@ The id of the order + + + The client order id + + Redemption record diff --git a/Kucoin.Net/Objects/Models/Spot/KucoinOrderId.cs b/Kucoin.Net/Objects/Models/Spot/KucoinOrderId.cs index 2e0f1eb1..7abf6a78 100644 --- a/Kucoin.Net/Objects/Models/Spot/KucoinOrderId.cs +++ b/Kucoin.Net/Objects/Models/Spot/KucoinOrderId.cs @@ -12,5 +12,10 @@ public record KucoinOrderId /// [JsonProperty("orderId")] public string Id { get; set; } = string.Empty; + /// + /// The client order id + /// + [JsonProperty("clientOid")] + public string? ClientOrderId { get; set; } } }