Code Monkey home page Code Monkey logo

huobi_csharp's Introduction

Huobi C# SDK

This is Huobi C# SDK, This is a lightweight .NET library, you can use import to your C# project and use this SDK to query all market data, trading and manage your account.

The SDK supports both synchronous and asynchronous RESTful API invoking, and subscribe the market, account and order update from the websocket connection.

Table of Contents

Quick Start

The SDK is compiled by .NET Standard 2.1, you can import the source code in C# IDE. If you use Visual Studio, you can open the solution file directly.

The project Huobi.SDK.Example is a console application that you can start directly.

If you want to create your own application, you can follow below steps:

  • Create a client (under namespace Huobi.SDK.Core.Client) instance.
  • Call the method provided by client.
// Get the timestamp from Huobi server and print on console
var client = new CommonClient();

var timestampResponse = client.GetTimestampAsync().Result;
Console.WriteLine($"timestamp (ms): {timestampResponse.data}");


// Get the list of accounts owned by this API user and print the detail on console
var accountClient = new AccountClient(APIKey.AccessKey, APIKey.SecretKey);

var getAIResult = accountClient.GetAccountInfoAsync().Result;
if (getAIResult != null && getAIResult.data != null)
{
  foreach (var a in getAIResult.data)
  {
    Console.WriteLine($"account id: {a.id}, type: {a.type}, state: {a.state}");
  }
}

Usage

Configuration

If you need to access private data, you need to add key.json into your solution. The purpose of this file is to prevent submitting SecretKey into repository by accident, so this file is added in the .gitignore file.

Just create a key.json file and include it into your solution with below definition

{
    "SecretKey": "xxxx-xxxx-xxxx-xxxx"
}

After that you should set the property of key.json in your IDE to allow it is copied to output directory.

If you don't need to access private data, you can ignore this.

Folder Structure

This is the folder and namespace structure of SDK source code and the description

  • Huobi.SDK.Core: The core of the SDK
    • Client: The client classes that are responsible to access data
    • Log: The internal logger interface and implementations
    • Model: The internal data model used in core
    • RequestBuilder: Responsible to build the request with the signature
  • Huobi.SDK.Model: The data model that user need to care about
    • Request: The request data model
    • Response: The response data model
  • Huobi.SDK.Core.Test: The unit test of core
  • Huobi.SDK.Example: The examples how to use Core and Model to access API and read response.

As the example indicates, there are two important namespaces: Huobi.SDK.Core.Client and Huobi.SDK.Model.Response, this section will introduce both of them below.

Client

In this SDK, the client is the object to access the Huobi API. In order to isolate the private data with public data, and isolated different kind of data, the client category is designated to match the API category.

All the client is listed in below table. Each client is very small and simple, it is only responsible to operate its related data, you can pick up multiple clients to create your own application based on your business.

Data Category Client Privacy Access Type
Common CommonClient Public Rest
Market MarketClient Public Rest
CandlestickWebSocketClient Public WebSocket v1
DepthWebSocketClient Public WebSocket v1
MarketByPriceWebSocketClient Public WebSocket v1
BestBidOfferWebSocketClient Public WebSocket v1
TradeWebSocketClient Public WebSocket v1
Last24hCandlestickWebSocketClient Public WebSocket v1
Account AccountClient Private Rest
RequestAccountWebSocketClient Private WebSocket v1
SubscribeAccountWebSocketV1Client Private WebSocket v1
SubscribeAccountWebSocketV2Client Private WebSocket v2
Wallet WalletClient Private Rest
Order OrderClient Private Rest
RequestOrdersWebSocketV1Client Private WebSocket v1
RequestOrderWebSocketV1Client Private WebSocket v1
SubscribeOrderWebSocketV1Client Private WebSocket v1
SubscribeTradeClearWebSocketV2Client Private WebSocket v2
Isolated Margin IsolatedMarginClient Private Rest
Cross Margin CrossMarginClient Private Rest
Stable Coin StableCoinClient Private Rest
ETF ETFClient Private Rest

Public vs. Private

There are two types of privacy that is correspondent with privacy of API:

Public client: It invokes public API to get public data (Common data and Market data), therefore you can create a new instance without applying an API Key.

// Create a CommonClient instance
var client = new CommonClient();

// Create a CandlestickWebSocketClient instance
var client = new CandlestickWebSocketClient();

Private client: It invokes private API to access private data, you need to follow the API document to apply an API Key first, and pass the API Key to the constructor.

// Create an AccountClient instance with APIKey
var accountClient = new AccountClient("AccessKey", "SecretKey");

// Create a RequestOrdersWebSocketV1Client instance with API Key
var client = new RequestOrdersWebSocketV1Client("AccessKey", "SecretKey");

The API key is used for authentication. If the authentication cannot pass, the invoking of private interface will fail.

Rest vs. WebSocket

Rest Client: It invokes Rest API and get once-off response.

The method for all Rest Client is asynchronism, it invoke Huobi API asynchronous and returns a Task immediately without blocking further statements. If you would like to get the result synchronous, just simply access its Result property, it will be blocked until the data is returned.

// You can call the method asynchronously
var task = client.GetTimestampAsync();
// do something else
// ...
// wait for the task return
var result = await task;
  

// Or you can call the method synchronously
var result = client.GetTimestampAsync().Result;

You can refer to C# programming guide Asynchronous programming with async and await to know more details.

WebSocket Client: It establishes WebSocket connection with server and data will be pushed from server actively. There are two types of method for WebSocket client:

  • Request method: The method name starts with "Request-", it will receive the once-off data after sending the request.
  • Subscription: The method name starts with "Subscribe-", it will receive update after sending the subscription.

Custom host

Each client constructor support an optional host parameter, by default it is "api.huobi.pro". If you need to use different host, you can specify the custom host.

// Use "xxx.yyy.zzz" as custom host to create a public client
var client = new CommonClient("xxx.yyy.zzz");

// Use "xxx.yyy.zzz" as custom host to create a private client
var accountClient = new AccountClient("AccessKey", "SecretKey", "xxx.yyy.zzz");

Response

In this SDK, the response is the object that define the data returned from API, which is deserialized from JSON string. It is the return type from each client method, you can declare the object use keyword var and don't need to specify the concrete type.

// Use 'var' to declare a variable to hold the response
var symbolsResponse = client.GetSymbolsAsync().Result;

After that you can check the value of the response and define your own business logic. The example in this SDK assume the JSON data from API is valid and do a basic validation. To make your application robust, you'd better consider all the possibilities of the data returned from API.

// Check the status of response and print some properties
if (symbolsResponse != null && symbolsResponse.status != null && symbolsResponse.status.Equals("ok"))
{
  foreach (var d in symbolsResponse.data)
  {
    Console.WriteLine($"{d.symbol}: {d.baseCurrency} {d.quoteCurrency}");
  }
  Console.WriteLine($"there are total {symbolsResponse.data.Length} symbols");
}

Request Examples

Common data

Exchange timestamp

var client = new CommonClient();
var timestampResponse = client.GetTimestampAsync().Result;

Symbol and currencies

var client = new CommonClient();
var symbolsResponse = client.GetSymbolsAsync().Result;

var currencysResponse = client.GetCurrencysAsync().Result;

Market data

Candlestick/KLine

var marketClient = new MarketClient();
var reqParams = new RequestParammeters()
                .AddParam("symbol", "btcusdt")
                .AddParam("period", "1min")
                .AddParam("size", "10");
var getCResponse = marketClient.GetCandlestickAsync(reqParams).Result;

Depth

var marketClient = new MarketClient();
var depthReqParams = new RequestParammeters()
  .AddParam("symbol", "btcusdt")
  .AddParam("depth", "5")
  .AddParam("type", "step0");
var getDepthResponse = marketClient.GetDepthAsync(depthReqParams).Result;

Latest trade

var marketClient = new MarketClient();
var getLastTradeResponse = marketClient.GetLastTradeAsync("btcusdt").Result;

Best bid/ask

var marketClient = new MarketClient();
var getl24CABResponse = marketClient.GetLast24hCandlestickAskBidAsync("btcusdt").Result;

Historical trade

var marketClient = new MarketClient();
var getLastTradesResponse = marketClient.GetLastTradesAsync("btcusdt", 3).Result;

24H statistics

var marketClient = new MarketClient();
var getl24CsResponse = marketClient.GetLast24hCandlesticksAsync().Result;

Account

Authentication is required.

var accountClient = new AccountClient(APIKey.AccessKey, APIKey.SecretKey);
var getAIResult = accountClient.GetAccountInfoAsync().Result;

Wallet

Authentication is required.

Withdraw

var walletClient = new WalletClient(APIKey.AccessKey, APIKey.SecretKey);
var request = new WithdrawRequest
{
  address = ""
};
var withdrawCResult = walletClient.WithdrawCurrencyAsync(request).Result;

Cancel withdraw

var walletClient = new WalletClient(APIKey.AccessKey, APIKey.SecretKey);
var cancelWCResult = walletClient.CancelWithdrawCurrencyAsync(1).Result;

Withdraw and deposit history

var walletClient = new WalletClient(APIKey.AccessKey, APIKey.SecretKey);
var depReqParams = new RequestParammeters()
  .AddParam("type", "deposit");
var getDWHResult = walletClient.GetDepositWithdrawHistoryAsync(depReqParams).Result;

Trading

Authentication is required.

Create order

var tradeClient = new OrderClient(APIKey.AccessKey, APIKey.SecretKey);
var request = new PlaceOrderRequest
{
  AccountId = APIKey.AccountId,
  type = "buy-limit",
  symbol = "btcusdt",
  amount = "1",
  price = "1.1"
};

var response = tradeClient.PlaceOrderAsync(request).Result;

Cancel order

var tradeClient = new OrderClient(APIKey.AccessKey, APIKey.SecretKey);
var response = tradeClient.CancelOrderByIdAsync("1").Result;

Cancel open orders

var tradeClient = new OrderClient(APIKey.AccessKey, APIKey.SecretKey);
var bclbaRequest = new BatchCancelOrdersByAccountIdRequest
{
  AccountId = APIKey.AccountId
};
var response = tradeClient.CancelOrdersByCriteriaAsync(bclbaRequest).Result;

Get order info

var tradeClient = new OrderClient(APIKey.AccessKey, APIKey.SecretKey);
var response = tradeClient.GetOrderByIdAsync("1").Result;

Historical orders

var tradeClient = new OrderClient(APIKey.AccessKey, APIKey.SecretKey);
var reqParams = new RequestParammeters()
  .AddParam("symbol", "btcusdt")
  .AddParam("states", "canceled");
var response = tradeClient.GetHistoryOrdersAsync(reqParams).Result;

Margin Loan

Authentication is required.

Apply loan

var marginClient = new IsolatedMarginClient(APIKey.AccessKey, APIKey.SecretKey);
var response = marginClient.ApplyLoanAsync("eosht", "eos", "0.001").Result;

Repay loan

var marginClient = new IsolatedMarginClient(APIKey.AccessKey, APIKey.SecretKey);
var response = marginClient.RepayAsync("123", "0.001").Result;

Loan history

var marginClient = new IsolatedMarginClient(APIKey.AccessKey, APIKey.SecretKey);
var reqParams = new RequestParammeters()
  .AddParam("symbols", "btcusdt");

var response = marginClient.GetLoanOrdersAsync(reqParams).Result;

Subscription Examples

Subscribe trade update

Authentication is required.

// Initialize a new instance
var client = new SubscribeTradeClearWebSocketV2Client(APIKey.AccessKey, APIKey.SecretKey);

// Add the auth receive handler
client.OnAuthenticationReceived += Client_OnAuthReceived;
void Client_OnAuthReceived(WebSocketAuthenticationV2Response response)
{
  if (response.code == 200)
  {
    // Subscribe if authentication passed
    client.Subscribe("btcusdt");
  }
}

// Add the data receive handler
client.OnDataReceived += Client_OnDataReceived;
void Client_OnDataReceived(SubscribeTradeClearResponse response)
{
  if (response != null && response.data != null)
  {
    var t = response.data;
    Console.WriteLine($"trade clear update, symbol: {t.symbol}, id: {t.orderId}, price: {t.tradePrice}, volume: {t.tradeVolume}");
  }
}

// Then connect to server and wait for the handler to handle the response
client.Connect();

Subscribe candlestick update

// Initialize a new instance
var client = new Last24hCandlestickWebSocketClient();

// Add the response receive handler
client.OnResponseReceived += Client_OnResponseReceived;
void Client_OnResponseReceived(SubscribeLast24hCandlestickResponse response)
{
  if (response != null)
  {
    if (response.tick != null)
    {
      Console.WriteLine($"id: {response.tick.id}, count: {response.tick.count}, vol: {response.tick.vol}");
    }
  }
}

// Then connect to server and wait for the handler to handle the response
client.Connect();

// Subscribe the specific topic
client.Subscribe("btcusdt");

Subscribe order update

Authentication is required.

// Initialize a new instance
var client = new SubscribeOrderWebSocketV1Client(APIKey.AccessKey, APIKey.SecretKey);

// Add the auth receive handler
client.OnAuthenticationReceived += Client_OnAuthReceived;
void Client_OnAuthReceived(WebSocketAuthenticationV1Response response)
{
  if (response.errCode == 0)
  {
    // Subscribe if authentication passed
    client.Subscribe("btcusdt");
  }
}

// Add the data receive handler
client.OnDataReceived += Client_OnDataReceived;
void Client_OnDataReceived(SubscribeOrderResponse response)
{
  if (response != null && response.data != null)
  {
    var o = response.data;
    Console.WriteLine($"order update, symbol: {o.symbol}, id: {o.orderId}, role: {o.role}, filled amount: {o.filledAmount}");
  }
}

// Then connect to server and wait for the handler to handle the response
client.Connect();

Subscribe account change

Authentication is required.

// Initialize a new instance
var client = new SubscribeAccountWebSocketV1Client(APIKey.AccessKey, APIKey.SecretKey);

// Add the auth receive handler
client.OnAuthenticationReceived += Client_OnAuthReceived;
void Client_OnAuthReceived(WebSocketAuthenticationV1Response response)
{
  if (response.errCode == 0)
  {
    // Subscribe the specific topic
    client.Subscribe("1");
  }
}

// Add the data receive handler
client.OnDataReceived += Client_OnDataReceived;
void Client_OnDataReceived(SubscribeAccountV1Response response)
{
  if (response != null && response.data != null)
  {
    Console.WriteLine($"Account update: {response.data.@event}");
    if (response.data.list != null)
    {
      foreach (var b in response.data.list)
      {
        Console.WriteLine($"account id: {b.accountId}, currency: {b.currency}, type: {b.type}, balance: {b.balance}");
      }
    }
  }
}

// Then connect to server and wait for the handler to handle the response
client.Connect();

Unsubscribe

Since each websocket client manage the subscription separately, therefore you can cancel each individual subscription.

huobi_csharp's People

Contributors

eynzhang avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

huobi_csharp's Issues

合约Api

请问有永续合约相关的实现吗

币币交易行情问题

在东京阿里云上单独执行MarketWebSocketClientExample下的SubscribeFullMBP方法, `并获取火币的推送时间戳ts,用当前服务器时间戳(localTimestamp)减去ts得到一个延迟值delay,发现delay经常大于100毫秒,即使用增量订阅方式(ReqAndSubScribeMBPTick),也是频繁出现延迟delay>100毫秒,这里是不是websocket写法上有bug?示例代码如下:

var ts = response.ts;
long localTimestamp = (long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalMilliseconds;
var delay = localTimestamp - ts;
if(delay >= 100)
{
Console.WriteLine($"{DateTime.Now},delay={delay}");
}

显示一段时间的延迟截图如下:
delay

Place Order Error (account-get-accounts-inexistent-error)

My first thought is to thank you for the great work you've done.

I receive the following error message when placing an order:

"Place order fail, error code: account-get-accounts-inexistent-error, error message: account for type 257744360and user id25774436 does not exist"

The message shows the two numbers, but the numbers are different, why?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.