Created
September 15, 2024 00:38
-
-
Save denisdemaisbr/d095b8640259b7db0300075a1a447a12 to your computer and use it in GitHub Desktop.
binance kline kline/tick fetch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
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