Knocks/BackEnd/WebSocket.Clients/Clients/HUOBIClient.cs

238 lines
7.7 KiB
C#

using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using WebSocket.Interfaces;
using System.Linq;
using System.IO;
using System.IO.Compression;
using System.Text;
namespace WebSocket.Clients
{
public class HUOBIClient : IWebClient
{
#region Members
internal class HUOBIResponse
{
[JsonProperty(PropertyName = "ts")]
public long Timestamp { get; set; }
public HUOBIMarket Tick { get; set; }
[JsonProperty(PropertyName = "ch")]
public string Name { get; set; }
public string Pair {
get {
var array = this.Name.Split('.');
return array.Length > 1 ? array[1].ToUpper() : string.Empty;
}
set { }
}
}
internal class HUOBIMarket
{
[JsonProperty(PropertyName = "open")]
public decimal Open { get; set; }
[JsonProperty(PropertyName = "close")]
public decimal Close { get; set; }
[JsonProperty(PropertyName = "low")]
public decimal Low { get; set; }
[JsonProperty(PropertyName = "high")]
public decimal High { get; set; }
[JsonProperty(PropertyName = "vol")]
public decimal Volume { get; set; }
//ts":1535719364915,
//"tick":{"id":1535719320,"open":0.000029570000000000,"close":0.000029630000000000,
// "low":0.000029570000000000,"high":0.000029630000000000,
// "amount":16.450000000000000000,"vol":0.000487268300000000000000000000000000,"count":2}}
}
private IWebSocketForClient server;
private Dictionary<string, Action<Command, string>> CommandAnswers = new Dictionary<string, Action<Command, string>>();
#endregion
/// <summary>
/// ctor
/// </summary>
/// <param name="server"></param>
public HUOBIClient(IWebSocketForClient server)
{
this.server = server;
Register();
}
public void Connected()
{
//SendAuth();
//wait connected message?
}
public void StartRequest(string[] pairs) {
Send(new { sub = $"market.{pairs[0].ToLower()}.kline.1min", id = $"id{1}" });
//Send(new {
// req = $"\"market.ethbtc.kline.1min\"",
// id = $"\"id10\""
//});
//server.Send($"{{\"sub\":\"market.{pairs[0].ToLower()}.kline.1min\", \"id\":\"id10\"}}");
//{
// "req": "market.ethbtc.kline.1min",
// "id": "id10"
//}
}
private void Register()
{
On("connected", (c, obj) => Connected());
On("ping", (c, obj) => SendPong());
//On("ohlcv1m", (c, obj) => Update(c.E, c, obj, typeof(Summary)));
}
public void Message(string message)
{
var parse = JsonConvert.DeserializeObject<Command>(message, GetSettings());
if (parse.Oid != null && CommandAnswers.ContainsKey(parse.E + parse.Oid))
{
CommandAnswers[parse.E + parse.Oid](parse, message);
}
if (CommandAnswers.ContainsKey(parse.E))
{
CommandAnswers[parse.E](parse, message);
}
/*
// response
{
"status": "ok",
"rep": "market.btccny.kline.1min",
"tick": [
{
"amount": 1.6206,
"count": 3,
"id": 1494465840,
"open": 9887.00,
"close": 9885.00,
"low": 9885.00,
"high": 9887.00,
"vol": 16021.632026
},
{
"amount": 2.2124,
"count": 6,
"id": 1494465900,
"open": 9885.00,
"close": 9880.00,
"low": 9880.00,
"high": 9885.00,
"vol": 21859.023500
}
]
}
*/
}
public void Tick()
{
//'ticker' or 'get-balance'
}
public void Data(byte[] data)
{
using (var compressedStream = new MemoryStream(data))
using (var zipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
using (var resultStream = new MemoryStream())
{
zipStream.CopyTo(resultStream);
var tickData = JsonConvert.DeserializeObject(Encoding.Default.GetString(resultStream.ToArray()), typeof(HUOBIResponse), GetSettings()) as HUOBIResponse;
if (tickData.Tick != null)
{
//this.server.updateData.Invoke(server.ExchangeId, "HUOBI", GetMarketOHLCVData(new Dictionary<string, object> { { tickData.Pair, tickData } }));
this.server.DataChanged("HUOBI", GetMarketOHLCVData(new Dictionary<string, object> { { tickData.Pair, tickData } }));
}
}
}
public void Data(Dictionary<string, object> data)
{
}
public void Closed(bool byUser, string reason)
{
//{"unsub": "market.btccny.trade.detail", "id": "id4"}
}
public void Error(Exception ex)
{
}
public void Error(string reason)
{
}
public void SendFailed(string data, Exception ex)
{
}
private void Send(object obj)
{
server.Send(JsonConvert.SerializeObject(obj, GetSettings()));
}
private void SendPong()
{
Send(new Command() { E = "pong" });
}
private void On(string name, Action<Command, string> command)
{
CommandAnswers[name] = command;
}
private void Off(string name)
{
if (CommandAnswers.ContainsKey(name))
{
CommandAnswers.Remove(name);
}
}
public Dictionary<string, IMarketOHLCVData> GetMarketOHLCVData(Dictionary<string, object> data)
{
return data.Select(x =>
{
var item = x.Value as HUOBIResponse;
return new MarketOHLCVData()
{
PairSymbol = item.Pair,
HighPrice = item.Tick.High,
LowPrice = item.Tick.Low,
OpenPrice = item.Tick.Open,
ClosePrice = item.Tick.Close,
Volume = item.Tick.Volume,
TimeStamp = ConvertFromLong(item.Timestamp),
} as IMarketOHLCVData;
}).ToDictionary(x => x.PairSymbol);
}
#region Helpers
private DateTime _1970Time = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private long ConvertToLong(DateTime time)
{
return (long)(time - _1970Time).TotalMilliseconds;
}
private DateTime ConvertFromLong(long ms)
{
return _1970Time.AddMilliseconds(ms);
}
private JsonSerializerSettings GetSettings()
{
var settings = new JsonSerializerSettings()
{
ContractResolver = new LowerCaseUnderscoreContractResolver()
//Formatting = Formatting.Indented
};
settings.Converters.Add(new Newtonsoft.Json.Converters.UnixDateTimeConverter());
return settings;
}
#endregion
}
}