Skip to content

Commit

Permalink
Version 1.4.0
Browse files Browse the repository at this point in the history
  • Loading branch information
burakoner committed Sep 18, 2023
1 parent 63dac4b commit a233227
Show file tree
Hide file tree
Showing 28 changed files with 796 additions and 525 deletions.
759 changes: 374 additions & 385 deletions OKX.Api.Examples/Program.cs

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions OKX.Api.Examples/Usings.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
global using ApiSharp.WebSocket;
global using OKX.Api.Enums;
global using OKX.Api.Models.AlgoTrading;
global using OKX.Api.Models.GridTrading;
global using OKX.Api.Models.Trade;
global using System;
global using System.Collections.Generic;
global using System.Linq;
global using System.Threading.Tasks;
4 changes: 1 addition & 3 deletions OKX.Api/Clients/RestApi/OKXRestApiBaseClient.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using OKX.Api.Models;

namespace OKX.Api.Clients.RestApi;
namespace OKX.Api.Clients.RestApi;

/// <summary>
/// OKX Rest Api Base Client
Expand Down
108 changes: 69 additions & 39 deletions OKX.Api/Clients/RestApi/OKXRestApiMarketDataClient.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using OKX.Api.Models;
using OKX.Api.Models.MarketData;
using OKX.Api.Models.MarketData;

namespace OKX.Api.Clients.RestApi;

Expand All @@ -12,13 +11,13 @@ public class OKXRestApiMarketDataClient : OKXRestApiBaseClient
private const string v5MarketTickers = "api/v5/market/tickers";
private const string v5MarketTicker = "api/v5/market/ticker";
private const string v5MarketBooks = "api/v5/market/books";
// TODO: api/v5/market/books-lite
private const string v5MarketBooksLite = "api/v5/market/books-lite";
private const string v5MarketCandles = "api/v5/market/candles";
private const string v5MarketHistoryCandles = "api/v5/market/history-candles";
private const string v5MarketTrades = "api/v5/market/trades";
private const string v5MarketTradesHistory = "api/v5/market/history-trades";
// TODO: api/v5/market/option/instrument-family-trades
// TODO: api/v5/public/option-trades
private const string v5MarketOptionInstrumentFamilyTrades = "api/v5/market/option/instrument-family-trades";
private const string v5PublicOptionTrades = "api/v5/public/option-trades";
private const string v5MarketPlatform24Volume = "api/v5/market/platform-24-volume";

internal OKXRestApiMarketDataClient(OKXRestApiClient root) : base(root)
Expand Down Expand Up @@ -91,6 +90,29 @@ public async Task<RestCallResult<OkxOrderBook>> GetOrderBookAsync(string instrum
return result.As(orderbook);
}

// BURAK
/// <summary>
/// Retrieve order top 25 book of the instrument more quickly
/// </summary>
/// <param name="instrumentId">Instrument ID</param>
/// <param name="ct">Cancellation Token</param>
/// <returns></returns>
public async Task<RestCallResult<OkxOrderBook>> GetOrderBookLiteAsync(string instrumentId, CancellationToken ct = default)
{
var parameters = new Dictionary<string, object>
{
{ "instId", instrumentId},
};

var result = await SendOKXRequest<IEnumerable<OkxOrderBook>>(GetUri(v5MarketBooksLite), HttpMethod.Get, ct, signed: false, queryParameters: parameters).ConfigureAwait(false);
if (!result.Success || result.Data.Count() == 0) return result.AsError<OkxOrderBook>(new OkxRestApiError(result.Error.Code, result.Error.Message, result.Error.Data));
if (result.Error != null && result.Error.Code > 0) return result.AsError<OkxOrderBook>(new OkxRestApiError(result.Error.Code, result.Error.Message, null));

var orderbook = result.Data.FirstOrDefault();
orderbook.Instrument = instrumentId;
return result.As(orderbook);
}

/// <summary>
/// Retrieve the candlestick charts. This endpoint can retrieve the latest 1,440 data entries. Charts are returned in groups based on the requested bar.
/// </summary>
Expand Down Expand Up @@ -208,49 +230,57 @@ public async Task<RestCallResult<IEnumerable<OkxTrade>>> GetTradesHistoryAsync(
return await SendOKXRequest<IEnumerable<OkxTrade>>(GetUri(v5MarketTradesHistory), HttpMethod.Get, ct, signed: false, queryParameters: parameters).ConfigureAwait(false);
}

// BURAK
/// <summary>
/// The 24-hour trading volume is calculated on a rolling basis, using USD as the pricing unit.
/// Retrieve the recent transactions of an instrument under same instFamily. The maximum is 100.
/// </summary>
/// <param name="instrumentFamily">Instrument family, e.g. BTC-USD. Applicable to OPTION</param>
/// <param name="ct">Cancellation Token</param>
/// <returns></returns>
public async Task<RestCallResult<Okx24HourVolume>> Get24HourVolumeAsync(CancellationToken ct = default)
public async Task<RestCallResult<IEnumerable<OkxOptionTradeByInstrumentFamily>>> GetOptionTradesByInstrumentFamilyAsync(
string instrumentFamily,
CancellationToken ct = default)
{
return await SendOKXSingleRequest<Okx24HourVolume>(GetUri(v5MarketPlatform24Volume), HttpMethod.Get, ct).ConfigureAwait(false);
}






























var parameters = new Dictionary<string, object>
{
{ "instFamily", instrumentFamily },
};

return await SendOKXRequest<IEnumerable<OkxOptionTradeByInstrumentFamily>>(GetUri(v5MarketOptionInstrumentFamilyTrades), HttpMethod.Get, ct, signed: false, queryParameters: parameters).ConfigureAwait(false);
}

// BURAK
/// <summary>
/// The maximum is 100.
/// </summary>
/// <param name="instrumentId">Instrument ID, e.g. BTC-USD-221230-4000-C, Either instId or instFamily is required. If both are passed, instId will be used.</param>
/// <param name="instrumentFamily">Instrument family, e.g. BTC-USD</param>
/// <param name="optionType">Option type, C: Call P: put</param>
/// <param name="ct">Cancellation Token</param>
/// <returns></returns>
public async Task<RestCallResult<IEnumerable<OkxOptionTrade>>> GetOptionTradesByInstrumentFamilyAsync(
string instrumentId = null,
string instrumentFamily = null,
OkxOptionType? optionType = null,
CancellationToken ct = default)
{
var parameters = new Dictionary<string, object>();
parameters.AddOptionalParameter("instId", instrumentId);
parameters.AddOptionalParameter("instFamily", instrumentFamily);
parameters.AddOptionalParameter("optType", JsonConvert.SerializeObject(optionType, new OptionTypeConverter(false)));

return await SendOKXRequest<IEnumerable<OkxOptionTrade>>(GetUri(v5PublicOptionTrades), HttpMethod.Get, ct, signed: false, queryParameters: parameters).ConfigureAwait(false);
}

/// <summary>
/// The 24-hour trading volume is calculated on a rolling basis, using USD as the pricing unit.
/// </summary>
/// <param name="ct">Cancellation Token</param>
/// <returns></returns>
public async Task<RestCallResult<Okx24HourVolume>> Get24HourVolumeAsync(CancellationToken ct = default)
{
return await SendOKXSingleRequest<Okx24HourVolume>(GetUri(v5MarketPlatform24Volume), HttpMethod.Get, ct).ConfigureAwait(false);
}
#endregion

}
24 changes: 22 additions & 2 deletions OKX.Api/Clients/RestApi/OKXRestApiTradingAccountClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public class OKXRestApiTradingAccountClient : OKXRestApiBaseClient
private const string v5AccountInterestAccrued = "api/v5/account/interest-accrued";
private const string v5AccountInterestRate = "api/v5/account/interest-rate";
private const string v5AccountSetGreeks = "api/v5/account/set-greeks";
// TODO: api/v5/account/set-isolated-mode
private const string v5AccountSetIsolatedMode = "api/v5/account/set-isolated-mode";
private const string v5AccountMaxWithdrawal = "api/v5/account/max-withdrawal";
// TODO: api/v5/account/risk-state
// TODO: api/v5/account/quick-margin-borrow-repay
Expand Down Expand Up @@ -526,7 +526,7 @@ public async Task<RestCallResult<IEnumerable<OkxInterestRate>>> GetInterestRateA
/// <param name="greeksType">Display type of Greeks.</param>
/// <param name="ct">Cancellation Token</param>
/// <returns></returns>
public async Task<RestCallResult<OkxAccountGreeksType>> SetGreeksAsync(Enums.OkxGreeksType greeksType, CancellationToken ct = default)
public async Task<RestCallResult<OkxAccountGreeksType>> SetGreeksAsync(OkxGreeksType greeksType, CancellationToken ct = default)
{
var parameters = new Dictionary<string, object> {
{"greeksType", JsonConvert.SerializeObject(greeksType, new GreeksTypeConverter(false)) },
Expand All @@ -535,6 +535,26 @@ public async Task<RestCallResult<OkxAccountGreeksType>> SetGreeksAsync(Enums.Okx
return await SendOKXSingleRequest<OkxAccountGreeksType>(GetUri(v5AccountSetGreeks), HttpMethod.Post, ct, signed: true, bodyParameters: parameters).ConfigureAwait(false);
}

// BURAK
/// <summary>
/// You can set the currency margin and futures/perpetual Isolated margin trading mode
/// </summary>
/// <param name="instrumentType">Instrument type</param>
/// <param name="marginMode">Isolated margin trading settings</param>
/// <param name="ct">Cancellation Token</param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public async Task<RestCallResult<OkxIsolatedMarginModeSettings>> SetIsolatedMarginModeAsync(OkxInstrumentType instrumentType, Enums.OkxIsolatedMarginMode marginMode, CancellationToken ct = default)
{
if (!instrumentType.IsIn(OkxInstrumentType.Margin, OkxInstrumentType.Contracts)) throw new ArgumentException("Only Margin and Contracts allowed", nameof(instrumentType));
var parameters = new Dictionary<string, object> {
{"isoMode", JsonConvert.SerializeObject(marginMode, new IsolatedMarginModeConverter(false)) },
{"type", JsonConvert.SerializeObject(instrumentType, new InstrumentTypeConverter(false)) },
};

return await SendOKXSingleRequest<OkxIsolatedMarginModeSettings>(GetUri(v5AccountSetIsolatedMode), HttpMethod.Post, ct, signed: true, bodyParameters: parameters).ConfigureAwait(false);
}

/// <summary>
/// Retrieve the maximum transferable amount.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using OKX.Api.Models;
using OKX.Api.Models.AlgoTrading;
using OKX.Api.Models.AlgoTrading;

namespace OKX.Api.Clients.WebSocketApi;

Expand Down Expand Up @@ -61,7 +60,7 @@ public async Task<CallResult<WebSocketUpdateSubscription>> SubscribeToAlgoOrderU
InstrumentFamily = symbol.InstrumentFamily,
});
var request = new OkxSocketRequest(OkxSocketOperation.Subscribe, arguments);
return await this.RootClient.RootSubscribeAsync(request, null, true, internalHandler, ct).ConfigureAwait(false);
return await this.RootClient.RootSubscribeAsync( OkxSocketEndpoint.Business, request, null, true, internalHandler, ct).ConfigureAwait(false);
}


Expand Down Expand Up @@ -109,7 +108,7 @@ public async Task<CallResult<WebSocketUpdateSubscription>> SubscribeToAdvanceAlg
InstrumentFamily = symbol.InstrumentFamily,
});
var request = new OkxSocketRequest(OkxSocketOperation.Subscribe, arguments);
return await this.RootClient.RootSubscribeAsync(request, null, true, internalHandler, ct).ConfigureAwait(false);
return await this.RootClient.RootSubscribeAsync(OkxSocketEndpoint.Business, request, null, true, internalHandler, ct).ConfigureAwait(false);
}

}
33 changes: 8 additions & 25 deletions OKX.Api/Clients/WebSocketApi/OKXWebSocketApiBaseClient.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
using OKX.Api.Models;

namespace OKX.Api;
namespace OKX.Api;

/// <summary>
/// OKX WebSocket Api Base Client
Expand Down Expand Up @@ -30,7 +28,6 @@ internal OKXWebSocketApiBaseClient(OKXWebSocketApiClientOptions options) : base(

SetDataInterpreter(DecompressData, null);
SendPeriodic("Ping", TimeSpan.FromSeconds(5), con => "ping");

}

#region Overrided Methods
Expand Down Expand Up @@ -152,10 +149,11 @@ protected override bool HandleSubscriptionResponse(WebSocketConnection connectio

// Check for Error
// 30040: {0} Channel : {1} doesn't exist
if (data.HasValues && data["event"] != null && (string)data["event"]! == "error" && data["errorCode"] != null && (string)data["errorCode"]! == "30040")
if (data.HasValues && data["event"] != null && (string)data["event"] == "error" &&
data["msg"] != null && data["code"] != null)
{
log.Write(LogLevel.Warning, "Subscription failed: " + (string)data["message"]!);
callResult = new CallResult<object>(new ServerError($"{(string)data["errorCode"]!}, {(string)data["message"]!}"));
log.Write(LogLevel.Warning, "Subscription failed: " + (string)data["msg"]!);
callResult = new CallResult<object>(new ServerError(data["code"].ToInt(), (string)data["msg"]));
return true;
}

Expand Down Expand Up @@ -246,23 +244,6 @@ await connection.SendAndWaitAsync(request, TimeSpan.FromSeconds(10), data =>
});
return false;
}

/// <inheritdoc />
protected override async Task<CallResult<WebSocketConnection>> GetWebSocketConnection(string address, bool authenticated)
{
address = authenticated
? "wss://ws.okx.com:8443/ws/v5/private"
: "wss://ws.okx.com:8443/ws/v5/public";

if (((OKXWebSocketApiClientOptions)ClientOptions).DemoTradingService)
{
address = authenticated
? "wss://wspap.okx.com:8443/ws/v5/private?brokerId=9999"
: "wss://wspap.okx.com:8443/ws/v5/public?brokerId=9999";
}

return await base.GetWebSocketConnection(address, authenticated);
}
#endregion

#region Private Methods
Expand All @@ -287,7 +268,9 @@ private string DecompressData(byte[] byteData)
/// <param name="passPhrase">The passphrase you specified when creating the API key</param>
public void SetApiCredentials(string apiKey, string apiSecret, string passPhrase)
{
SetApiCredentials(new OkxApiCredentials(apiKey, apiSecret, passPhrase));
var credentials = new OkxApiCredentials(apiKey, apiSecret, passPhrase);
ClientOptions.ApiCredentials = credentials;
SetApiCredentials(credentials);
}

#region Ping
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,5 @@ internal OKXWebSocketApiFundingAccountClient(OKXWebSocketApiClient root)
}

// TODO: Deposit info channel

// TODO: Withdrawal info channel
}
13 changes: 7 additions & 6 deletions OKX.Api/Clients/WebSocketApi/OKXWebSocketApiMarketDataClient.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using OKX.Api.Models;
using OKX.Api.Models.MarketData;
using OKX.Api.Models.MarketData;

namespace OKX.Api.Clients.WebSocketApi;

Expand Down Expand Up @@ -48,7 +47,7 @@ public async Task<CallResult<WebSocketUpdateSubscription>> SubscribeToTickersAsy
InstrumentId = instrumentId,
});
var request = new OkxSocketRequest(OkxSocketOperation.Subscribe, arguments);
return await this.RootClient.RootSubscribeAsync(request, null, false, internalHandler, ct).ConfigureAwait(false);
return await this.RootClient.RootSubscribeAsync(OkxSocketEndpoint.Public, request, null, false, internalHandler, ct).ConfigureAwait(false);
}

/// <summary>
Expand Down Expand Up @@ -88,7 +87,7 @@ public async Task<CallResult<WebSocketUpdateSubscription>> SubscribeToCandlestic
InstrumentId = instrumentId,
});
var request = new OkxSocketRequest(OkxSocketOperation.Subscribe, arguments);
return await this.RootClient.RootSubscribeAsync(request, null, false, internalHandler, ct).ConfigureAwait(false);
return await this.RootClient.RootSubscribeAsync(OkxSocketEndpoint.Business, request, null, false, internalHandler, ct).ConfigureAwait(false);
}

/// <summary>
Expand Down Expand Up @@ -123,9 +122,11 @@ public async Task<CallResult<WebSocketUpdateSubscription>> SubscribeToTradesAsyn
InstrumentId = instrumentId,
});
var request = new OkxSocketRequest(OkxSocketOperation.Subscribe, arguments);
return await this.RootClient.RootSubscribeAsync(request, null, false, internalHandler, ct).ConfigureAwait(false);
return await this.RootClient.RootSubscribeAsync(OkxSocketEndpoint.Public, request, null, false, internalHandler, ct).ConfigureAwait(false);
}

// TODO: WS / All trades channel

/// <summary>
/// Retrieve order book data.
/// Use books for 400 depth levels, book5 for 5 depth levels, books50-l2-tbt tick-by-tick 50 depth levels, and books-l2-tbt for tick-by-tick 400 depth levels.
Expand Down Expand Up @@ -174,7 +175,7 @@ public async Task<CallResult<WebSocketUpdateSubscription>> SubscribeToOrderBookA
InstrumentId = instrumentId,
});
var request = new OkxSocketRequest(OkxSocketOperation.Subscribe, arguments);
return await this.RootClient.RootSubscribeAsync(request, null, false, internalHandler, ct).ConfigureAwait(false);
return await this.RootClient.RootSubscribeAsync(OkxSocketEndpoint.Public, request, null, false, internalHandler, ct).ConfigureAwait(false);
}

// TODO: WS / Option trades channel
Expand Down
Loading

0 comments on commit a233227

Please sign in to comment.