Skip to content

Instantly share code, notes, and snippets.

@denisdemaisbr
Created September 15, 2024 00:38
Show Gist options
  • Save denisdemaisbr/d095b8640259b7db0300075a1a447a12 to your computer and use it in GitHub Desktop.
Save denisdemaisbr/d095b8640259b7db0300075a1a447a12 to your computer and use it in GitHub Desktop.
binance kline kline/tick fetch
/*
fetch data from binance, using kline
using libcurl and cjson
gcc -I. -Icjson -o /cygdrive/x/test test.fetch.c cjson/libcjson.a -lcurl -lrt && /cygdrive/x/test
=================================
it's a poc of a ubot binance bot!
=================================
fell to free to test.
*/
#include <stdio.h>
#include <math.h>
#include <time.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <curl/curl.h>
#include "cjson/cJSON.h"
#define BINANCE_API_URL "https://api.binance.com/api/v3/klines?symbol=BTCUSDT&interval=30m&limit=15"
#define BINANCE_API_LIVE "https://api.binance.com/api/v3/ticker/price?symbol=BTCUSDT"
static size_t write_callback(char *data, size_t size, size_t nmemb, void *clientp);
struct memory {
char *response;
size_t size;
};
struct memorylive {
char *response;
size_t size;
};
extern char **environ;
cJSON *json = NULL;
cJSON *kline_data;
CURL *curl = NULL;
CURL *curlive = NULL;
struct memory chunk = {NULL, 0};
struct memorylive chunklive = {NULL, 0};
CURLcode res;
//
//
//
int main(int argc, char* argv[], char* envp[]) {
int rc;
int array_size;
int index;
char time[24];
char *endptr; // strtod() / otherwise... check errno
setbuf(stdout, NULL);
puts("** start **");
// setup //
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
curlive = curl_easy_init();
if (!curl || !curlive)
goto cleanup;
// live data from binance //
{
curl_easy_setopt(curlive, CURLOPT_URL, BINANCE_API_LIVE);
curl_easy_setopt(curlive, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(curlive, CURLOPT_WRITEDATA, (void*) &chunklive);
curl_easy_setopt(curlive, CURLOPT_TIMEOUT, 5L);
curl_easy_setopt(curlive, CURLOPT_CONNECTTIMEOUT, 5L);
curl_easy_setopt(curlive, CURLOPT_TCP_KEEPALIVE, 1L);
curl_easy_setopt(curlive, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curlive, CURLOPT_HEADER, 0);
curl_easy_setopt(curlive, CURLOPT_NOPROGRESS, 1);
curl_easy_setopt(curlive, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curlive, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curlive, CURLOPT_NOSIGNAL, 1);
}
// fetch data from binance //
{
printf("fetching data from binance");
curl_easy_setopt(curl, CURLOPT_URL, BINANCE_API_URL);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*) &chunk);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 5L);
curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, 5L);
curl_easy_setopt(curl, CURLOPT_TCP_KEEPALIVE, 1L);
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(curl, CURLOPT_HEADER, 0);
curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 1);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
res = curl_easy_perform(curl);
if (res != CURLE_OK) {
puts("fail");
goto cleanup;
}
puts("ok");
}
if (!chunk.response)
goto cleanup;
// proccess cjson
json = cJSON_Parse(chunk.response);
if (!json)
goto cleanup;
array_size = cJSON_GetArraySize(json);
for (int i=0; i<array_size; i++) {
kline_data = cJSON_GetArrayItem(json, i);
if (!kline_data)
break;
/* binance kline format
[[
1499040000000, // Open time
"0.01634790", // Open
"0.80000000", // High
"0.01575800", // Low
"0.01577100", // Close
"148976.11427815", // Volume
1499644799999, // Close time
"2434.19055334", // Quote asset volume
308, // Number of trades
"1756.87402397", // Taker buy base asset volume
"28.46694368", // Taker buy quote asset volume
"17928899.62484339" // Ignore (not used)
]]
*/
{
double _time = cJSON_GetArrayItem(kline_data, 0)->valuedouble;
time_t raw_time = _time/1000;
struct tm *timeinfo = localtime(&raw_time);
strftime(time, sizeof(time)-1, "%Y-%m-%d %H:%M:%S", timeinfo);
time[19] = 0x0;
}
double open = strtod(cJSON_GetArrayItem(kline_data, 1)->valuestring, &endptr);
double high = strtod(cJSON_GetArrayItem(kline_data, 2)->valuestring, &endptr);
double low = strtod(cJSON_GetArrayItem(kline_data, 3)->valuestring, &endptr);
double close = strtod(cJSON_GetArrayItem(kline_data, 4)->valuestring, &endptr);
double volume = strtod(cJSON_GetArrayItem(kline_data, 5)->valuestring, &endptr);
int trades = atoi(cJSON_GetArrayItem(kline_data, 7)->valuestring);
printf("%s o:%.2f h:%.2f l:%.2f c:%.2f v:%9.2f t:%d\n",
time, open, high, low, close, volume, trades
);
}
printf("\n");
for(int i=0; i<100; i++) {
res = curl_easy_perform(curlive);
if (res != CURLE_OK) {
break;
}
printf("%05d ", i);
printf("%s\n", chunklive.response );
fflush(stdout);
if (chunklive.response != NULL) {
free(chunklive.response);
chunklive.response = NULL;
chunklive.size = 0;
}
sleep(5);
}
// cleanup //
cleanup:
if (chunk.response != NULL) free(chunk.response);
if (curl != NULL) curl_easy_cleanup(curl);
if (curlive != NULL) curl_easy_cleanup(curlive);
if (json != NULL) cJSON_Delete(json);
curl_global_cleanup();
puts("** done **");
return 0;
}
//
//
//
static size_t write_callback(char *data, size_t size, size_t nmemb, void *clientp) {
char *ptr;
size_t realsize;
struct memory *mem;
mem = (struct memory*) clientp;
if (!mem)
return 0;
realsize = size * nmemb;
ptr = realloc(mem->response, mem->size + realsize + 1);
if (!ptr)
return 0;
mem->response = ptr;
memcpy(&(mem->response[mem->size]), data, realsize);
mem->size += realsize;
mem->response[mem->size] = 0;
return realsize;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment