-
Notifications
You must be signed in to change notification settings - Fork 1
现货 WebSocket 市场数据API
Socket.io API是公开使用的, 即时市场行情和即时市场交易无需进行身份验证,但私人订单即时更新需要使用私人秘钥进行验证。 为确保正常使用Socket.io API,请提前在您的计算机中安装socket.io。Socket.io的相关知识可参考以下网站:
在代码中包含socket.io资源, 文中均为Javascript版本示例:
<script src="<YOUR PATH>/socket.io.js"></script>
使用如下方式与BTCC的websocket服务器建立连接:
var socket = io ('https://websocket.btcc.com/');
使用 “subscribe” 方法订阅我们的websocket服务器推送的不同交易市场的即时交易信息;
## 订阅三个不同的市场 ##
socket.emit('subscribe', 'marketdata_cnybtc');
socket.emit('subscribe', 'marketdata_cnyltc');
socket.emit('subscribe', 'marketdata_btcltc');
socket.emit('subscribe', 'grouporder_cnybtc');
socket.emit('subscribe', 'grouporder_cnyltc');
socket.emit('subscribe', 'grouporder_btcltc');
Name | Value | Description |
---|---|---|
market_data | string | 订阅的市场数据可以是 'marketdata_cnybtc', 'marketdata_cnyltc' 或者 'marketdata_btcltc'中的一个或多个,以”,”作为分隔符 |
grouporder | string | 订阅市场深度数据,可以是 'grouporder_cnybtc', 'grouporder_cnyltc' 或者 'grouporder_btcltc'中的一个或多个,以”,”作为分隔符 |
使用 “ticker” 方法监听即时市场行情并处理接收到的实时数据,示例:
socket.on('ticker', function (data) { console.log(data); });
接收到的数据样本
{
buy: 2940.03
date: 1410399073
high: 2970
last: 2940.04
low: 2901
market: "btccny"
open: 2930.15
prev_close: 2931.03
sell: 2940.06
vol: 15187.3352
vwap: 2936.02
}
使用 “trade” 方法监听即时市场交易数据并处理接收到的实时数据,示例:
socket.on('trade', function (data) { console.log(data); });
## 接收到的数据样本 ##
{
amount: 0.056
date: 1402970632
market: "btccny"
price: 3735.83
trade_id: 6069941
type: "sell"
}
即时市场深度方法会实时返回市场上的5对未成交的买卖订单。 使用 “grouporder” 方法监听即时市场深度数据并处理接收到的实时数据,示例:
socket.on('grouporder', function (data) { console.log(data); });
## 接收到的数据样本 ##
{
"grouporder":
{
"market":"btccny",
"ask":[
{"price":2405.04,"type":"ask","totalamount":0.1},
{"price":2404.24,"type":"ask","totalamount":2.9544},
{"price":2404.21,"type":"ask","totalamount":0.011},
{"price":2404.02,"type":"ask","totalamount":0.011},
{"price":2403.71,"type":"ask","totalamount":0.01}
],
"bid":[
{"price":2402.74,"type":"bid","totalamount":0.099},
{"price":2401.11,"type":"bid","totalamount":6},
{"price":2401.1,"type":"bid","totalamount":1.0014},
{"price":2400.66,"type":"bid","totalamount":0.1},
{"price":2400.65,"type":"bid","totalamount":0.1066}
]
}
}
使用'private'方法订阅私人订单即时更新来接收处理私人订单数据。每当您的私人订单状态发生改变时,服务器就会主动推送此订单的最新状态给客户端。 此方法需要使用访问秘钥和秘密秘钥进行个人身份认证,和交易API的加密方法一致。请参照Java示例代码的以下部分进行加密和订阅处理:
//Use 'private' method to subscribe the order feed
List arg = new ArrayList();
arg.add(sm.get_payload());
arg.add(sm.get_sign());
socket.emit("private",arg);
## 接收到的数据样本 ##
{
"amount": 0
"id": 3804213
"price": 33.51
"market": "ltccny"
"status": "closed"
"date":1410400468
"type":"ask"
"amount_original":1
}
使用'private'方法订阅即时余额更新来接收处理账户余额数据。每当您的余额发生改变时,服务器就会主动推送账户的相应最新余额给客户端。 此方法需要使用访问秘钥和秘密秘钥进行个人身份认证,和交易API的加密方法一致。请参照Java示例代码的以下部分进行加密和订阅处理:
//Use 'private' method to subscribe the order and account_info feed
List arg = new ArrayList();
arg.add(sm.get_payload());
arg.add(sm.get_sign());
socket.emit("private",arg);
## 接收到的数据样本 ##
{
"balance":
{
"amount":0.0349086,
"symbol":"฿",
"currency":"BTC"
}
}
{
"balance":
{
"amount":10.191074,
"symbol":"¥",
"currency":"CNY"
}
}
点击以下链接,获取更多Socket.io客户端示例源代码: Python: https://github.com/BTCChina/btcchina-websocket-api-python Java: https://github.com/BTCChina/btcchina-websocket-api-java Ruby: https://github.com/BTCChina/btcchina-websocket-api-ruby JavaScript: https://github.com/BTCChina/btcchina-websocket-api-js C++: https://github.com/BTCChina/btcchina-api-cpp C#: https://github.com/BTCChina/btcchina-api-csharp
<script src="./js/socket.io.js"></script>
<script>
var socket = io('https://websocket.btcc.com/');
socket.emit('subscribe', 'marketdata_cnybtc');
socket.emit('subscribe', 'marketdata_cnyltc');
socket.emit('subscribe', 'marketdata_btcltc');
socket.emit('subscribe', 'grouporder_cnybtc');
socket.emit('subscribe', 'grouporder_cnyltc');
socket.emit('subscribe', 'grouporder_btcltc');
socket.on('connect', function(){
socket.on('trade', function (data) {
console.log(data);
});
socket.on('ticker', function (data) {
console.log(data);
});
socket.on('grouporder', function (data) {
console.log(data);
});
});
</script>
// an example
import com.github.nkzawa.emitter.Emitter;
import com.github.nkzawa.socketio.client.IO;
import com.github.nkzawa.socketio.client.Socket;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;
import org.json.JSONObject;
public class SocketMain {
private String ACCESS_KEY="YOUR_ACCESS_KEY";
private String SECRET_KEY="YOUR_SECRET_KEY";
private static String HMAC_SHA1_ALGORITHM = "HmacSHA1";
private String postdata="";
private String tonce = ""+(System.currentTimeMillis() * 1000);
public static void main(String[] args) throws Exception {
try {
IO.Options opt = new IO.Options();
opt.reconnection = true;
Logger.getLogger(SocketMain.class.getName()).setLevel(Level.FINE);
final Socket socket = IO.socket("https://websocket.btcc.com", opt);
socket.on(Socket.EVENT_CONNECT, new Emitter.Listener() {
SocketMain sm= new SocketMain();
@Override
public void call(Object... args) {
System.out.println("connected");
socket.emit("subscribe", "marketdata_cnybtc"); // subscribe
socket.emit("subscribe", "marketdata_cnyltc"); // subscribe another market
socket.emit("subscribe", "marketdata_btcltc"); // subscribe another market
socket.emit("subscribe", "grouporder_cnybtc"); // subscribe grouporder
socket.emit("subscribe", "grouporder_cnyltc"); // subscribe another market
socket.emit("subscribe", "grouporder_btcltc"); // subscribe another market
//Use 'private' method to subscribe the order and account_info feed
try {
List arg = new ArrayList();
arg.add(sm.get_payload());
arg.add(sm.get_sign());
socket.emit("private",arg);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}).on("trade", new Emitter.Listener() {
@Override
public void call(Object... args) {
JSONObject json = (JSONObject) args[0]; //receive the trade message
System.out.println(json);
}
}).on("ticker", new Emitter.Listener() {
@Override
public void call(Object... args) {
JSONObject json = (JSONObject) args[0];//receive the ticker message
System.out.println(json);
}
}).on("grouporder", new Emitter.Listener() {
@Override
public void call(Object... args) {
JSONObject json = (JSONObject) args[0];//receive the grouporder message
System.out.println(json);
}
}).on("order", new Emitter.Listener() {
@Override
public void call(Object... args) {
JSONObject json = (JSONObject) args[0];//receive your order feed
System.out.println(json);
}
}).on("account_info", new Emitter.Listener() {
@Override
public void call(Object... args) {
JSONObject json = (JSONObject) args[0];//receive your account_info feed
System.out.println(json);
}
}).on(Socket.EVENT_DISCONNECT, new Emitter.Listener() {
@Override
public void call(Object... args) {
System.out.println("disconnected");
}
});
socket.connect();
} catch (URISyntaxException ex) {
Logger.getLogger(SocketMain.class.getName()).log(Level.SEVERE, null, ex);
}
}
public String get_payload() throws Exception{
postdata = "{\"tonce\":\""+tonce.toString()+"\",\"accesskey\":\""+ACCESS_KEY+"\",\"requestmethod\": \"post\",\"id\":\""+tonce.toString()+"\", \"method\": \"subscribe\", \"params\": [\"order_cnyltc\",\"account_info\"]}";//subscribe order feed for cnyltc market and balance feed
System.out.println("postdata is: " + postdata);
return postdata;
}
public String get_sign() throws Exception{
String params = "tonce="+tonce.toString()+"&accesskey="+ACCESS_KEY+"&requestmethod=post&id="+tonce.toString()+"&method=subscribe¶ms=order_cnyltc,account_info"; //subscribe the order of cnyltc market and the account_info
String hash = getSignature(params, SECRET_KEY);
String userpass = ACCESS_KEY + ":" + hash;
String basicAuth = DatatypeConverter.printBase64Binary(userpass.getBytes());
return basicAuth;
}
public String getSignature(String data,String key) throws Exception {
// get an hmac_sha1 key from the raw key bytes
SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), HMAC_SHA1_ALGORITHM);
// get an hmac_sha1 Mac instance and initialize with the signing key
Mac mac = Mac.getInstance(HMAC_SHA1_ALGORITHM);
mac.init(signingKey);
// compute the hmac on input data bytes
byte[] rawHmac = mac.doFinal(data.getBytes());
return bytArrayToHex(rawHmac);
}
private String bytArrayToHex(byte[] a) {
StringBuilder sb = new StringBuilder();
for(byte b: a)
sb.append(String.format("%02x", b&0xff));
return sb.toString();
}
}
# Require installing socket.io-client-simple
require 'socket.io-client-simple'
require 'base64'
require 'json'
$access_key = "<YOUR ACCESS KEY>"
$secret_key = "<YOUR SECRET KEY>"
def initial_post_data
post_data = {}
post_data['tonce'] = (Time.now.to_f * 1000000).to_i.to_s
post_data
end
def params_string(post_data)
post_data['params'] = post_data['params'].join(',')
params_parse(post_data).collect{|k, v| "#{k}=#{v}"} * '&'
end
def params_parse(post_data)
post_data['accesskey'] = $access_key #access key
post_data['requestmethod'] = 'post'
post_data['id'] = post_data['tonce'] unless post_data.keys.include?('id')
fields=['tonce','accesskey','requestmethod','id','method','params']
ordered_data = {}
fields.each do |field|
ordered_data[field] = post_data[field]
end
ordered_data
end
def sign(params_string)
signature = OpenSSL::HMAC.hexdigest(OpenSSL::Digest::Digest.new('sha1'), $secret_key, params_string) #secret key
Base64.strict_encode64($access_key+ ':' + signature)
end
socket = SocketIO::Client::Simple.connect 'https://websocket.btcc.com'
socket.on:connect do
puts "connected!"
socket.emit :subscribe, "marketdata_cnybtc"
socket.emit :subscribe, "marketdata_cnyltc"
socket.emit :subscribe, "marketdata_btcltc"
socket.emit :subscribe, "grouporder_cnybtc"
socket.emit :subscribe, "grouporder_cnyltc"
socket.emit :subscribe, "grouporder_btcltc"
post_data = initial_post_data
post_data['method'] = 'subscribe'
post_data['params'] = ["order_cnybtc", "order_cnyltc", "order_btcltc", "account_info"]
payload = params_parse(post_data)
pstr = params_string(payload.clone)
signature_string = sign(pstr)
socket.emit :private, [payload.to_json, signature_string]
end
socket.on :disconnect do
puts "disconnected!"
end
socket.on :message do |data|
puts "message: "+data
end
socket.on :trade do |data|
puts 'trade:'
p data
end
socket.on :ticker do |data|
puts 'ticker:'
p data
end
socket.on :grouporder do |data|
puts 'grouporder:'
p data
end
socket.on :order do |data|
puts 'order:'
p data
end
socket.on :account_info do |data|
puts 'account_info:'
p data
end
loop do
sleep 3
end
2014-10-27 将文档标题由Websocket API改为Socket.io API .
2014-10-15 Socket.io API v1.2.2 增加了即时市场深度方法.
2014-09-30 Socket.io API v1.2.1 增加了即时余额更新方法;增加了Java的即时余额更新('account_info')方法示例代码 和 Ruby的私人订单即时更新('order')和即时余额更新('account_info')方法示例代码.
2014-09-11 Socket.io API v1.2 增加了C#和C++的示例代码; 增加了即时市场行情和私人订单即时更新方法;增加了java的私人订单即时更新('order')方法示例代码.
2014-07-30 Socket.io API v1.1加入了更多的Github上的示例代码链接,包括Java,Python,Ruby和JavaScript.
Socket.io API v1.0 包含trade方法和JavaScript的客户端代码示例.