Эти ребята разработали C#-обёртки уже для API 11 криптобирж:
|
При работе с данными биржи некоторые задачи требуют получения информации в реальном времени. Если вы хотите показывать текущие котировки, то, конечно, можно с какой-то частотой дёргать соответствующий метод REST API и получать последнюю цену. Следить за статусами своих ордеров, например, тоже можно с периодичность раз в минуту. Но что, если вам надо моментально среагировать на событие исполнения заявки и нельзя опоздать ни на секунду? Дергать метод REST API чаще, чем раз в секунду, не получится – биржа не даст вам этого сделать, ясно же, что каналы связи не резиновые.
Для решения таких задач используем сокеты. Не хочу вдаваться в детали протокола WSS, наша цель в данный момент не отвлекаться на теорию, а реализовать код с использованием сокета на C#. Единственное только, не могу удержаться и не процитировать абзац из статьи на Хабре от 2009 года.
На мой взгляд, WebSocket — это самое кардинальное расширение протокола HTTP с его появления. Это не финтифлюшки, это сдвиг парадигмы HTTP.
Евгений Лисицкий
Таким образом, довольно-таки молодая, но к настоящему времени уже хорошо отработанная технология WebSocket расширяет возможности взаимодействия программных модулей по сети и облегчает автоматизацию, в том числе трейдинга на бирже.
function bbb(sym) {
var s = sym.toLowerCase();
var wsUrl = "wss://stream.binance.com:9443/ws/" + s + "@kline_1m";
if (binaSocket != null)
binaSocket.send(JSON.stringify({ method: "unsubscribe", topic: "kline_1m" }));
binaSocket = new WebSocket(wsUrl);
binaSocket.onmessage = function (event) {
var obj = JSON.parse(event.data);
if (obj.error) return;
var k = obj.k;
$("#opncls").html(k.o + " / " + k.c);
$("#higlow").html(k.h + " / " + k.l);
$("#volclt").html(k.v + " / " + (new Date(k.T + 1)).toLocaleTimeString().substr(0, 5));
Вот пример кода, как подключиться к сокету Binance API на C# и начать слушать события:
private bool SubscribeToOrdersUpdates(int minutesToReconnect = 20, bool spotMarg = true)
{
if (_apiKey != null && _apiKey.IsWorking)
{
if (CreateListenKey(spotMarg))
{
var lik = spotMarg ? _listenKeySpot : _listenKeyMarg;
var res = _socketClient!.SpotStreams.SubscribeToUserDataUpdatesAsync(
lik,
onOrderUpdateMessage => OnOrderUpdate(onOrderUpdateMessage.Data, spotMarg),
null,
onAccountPositionMessage => OnAccountUpdate(onAccountPositionMessage.Data),
null
).Result;
if (res.Success)
{
if (spotMarg)
_socketSubscrSpot = res.Data;
else
_socketSubscrMarg = res.Data;
Регистрация Windows Service:
sc create CaProducts binpath="D:\publish\caSvcProducts.exe" DisplayName="CryptoAlert Products" start=auto
Обязательно ставим двойные кавычки, одинарные не работают.
Свой Logger – как отдельная dll в виде синглтона, для удобства использования во всех модулях. В сервисе подключаем nLog и передаём всё, что приходит с нашего Logger’а ему.
public class Logger
{
static Action? _write;
public static void Write(Log msg) => _write?.Invoke(msg);
static object _lockFlag = new object();
static Logger? _instance;
public static Logger Instance
{
get
{
lock (_lockFlag)
{
if (_instance == null)
_instance = new Logger();
}
return _instance;
}
}
public void Init(Action write)
{
_write = write;
}
}