diff options
Diffstat (limited to 'api.c')
-rw-r--r-- | api.c | 257 |
1 files changed, 192 insertions, 65 deletions
@@ -3,15 +3,15 @@ Info* api_info_init(void) { Info* pInfo = malloc(sizeof(Info)); pointer_alloc_check(pInfo); - pInfo->name[0] = '\0'; - pInfo->symbol[0] = '\0'; - pInfo->price = EMPTY; - pInfo->change_1d = EMPTY; - pInfo->change_7d = EMPTY; - pInfo->change_30d = EMPTY; - pInfo->div_yield = EMPTY; - pInfo->marketcap = EMPTY; - pInfo->volume_1d = EMPTY; + *pInfo = (Info) { + .symbol[0] = '\0', .name[0] = '\0', .industry[0] = '\0', .website[0] = '\0', .description[0] = '\0', + .ceo[0] = '\0', .issue_type[0] = '\0', .sector[0] = '\0', .intraday_time = EMPTY, .price = EMPTY, + .marketcap = EMPTY, .volume_1d = EMPTY, .pe_ratio = EMPTY, .div_yield = EMPTY, .revenue = EMPTY, + .gross_profit = EMPTY, .cash = EMPTY, .debt = EMPTY, .eps = {EMPTY, EMPTY, EMPTY, EMPTY}, + .fiscal_period[0][0] = '\0', .fiscal_period[1][0] = '\0', .fiscal_period[2][0] = '\0', + .fiscal_period[3][0] = '\0', .eps_year_ago = {EMPTY, EMPTY, EMPTY, EMPTY}, .change_1d = EMPTY, + .change_7d = EMPTY, .change_30d = EMPTY + }; return pInfo; } @@ -69,7 +69,7 @@ double* api_get_current_price(const char* symbol) { } double* iex_get_price(const char* symbol) { - char iex_api_string[80]; + char iex_api_string[URL_MAX_LENGTH]; sprintf(iex_api_string, "https://api.iextrading.com/1.0/stock/%s/quote", symbol); String* pString = api_curl_data(iex_api_string); if (pString == NULL) @@ -111,14 +111,164 @@ double* iex_get_price(const char* symbol) { return api_data; } +void* iex_store_company(void* vpInfo) { + Info* symbol_info = vpInfo; + symbol_info->symbol[0] = '\0'; + char iex_api_string[URL_MAX_LENGTH]; + sprintf(iex_api_string, "https://api.iextrading.com/1.0/stock/%s/company", symbol_info->symbol); + String* pString = api_curl_data(iex_api_string); // API CALL 1 -- Company + if (pString == NULL) + return NULL; + + Json* jobj = json_tokener_parse(pString->data); + if (jobj == NULL) { // Invalid symbol + string_destroy(&pString); + return NULL; + } + + strcpy(symbol_info->symbol, json_object_get_string(json_object_object_get(jobj, "symbol"))); + strcpy(symbol_info->name, json_object_get_string(json_object_object_get(jobj, "companyName"))); + strcpy(symbol_info->industry, json_object_get_string(json_object_object_get(jobj, "industry"))); + strcpy(symbol_info->website, json_object_get_string(json_object_object_get(jobj, "website"))); + strcpy(symbol_info->description, json_object_get_string(json_object_object_get(jobj, "description"))); + strcpy(symbol_info->ceo, json_object_get_string(json_object_object_get(jobj, "CEO"))); + strcpy(symbol_info->issue_type, json_object_get_string(json_object_object_get(jobj, "issueType"))); + strcpy(symbol_info->sector, json_object_get_string(json_object_object_get(jobj, "sector"))); + json_object_put(jobj); + string_destroy(&pString); + return NULL; +} + +void* iex_store_quote(void* vpInfo) { + Info* symbol_info = vpInfo; + if (symbol_info->symbol[0] == '\0') + return NULL; + + char iex_api_string[URL_MAX_LENGTH]; + sprintf(iex_api_string, "https://api.iextrading.com/1.0/stock/%s/quote", symbol_info->symbol); + String* pString = api_curl_data(iex_api_string); // API CALL 2 -- Quote + if (pString == NULL) + return NULL; + + Json* jobj = json_tokener_parse(pString->data); + if (jobj == NULL) { // Invalid symbol + string_destroy(&pString); + return NULL; + } + + symbol_info->price = json_object_get_double(json_object_object_get(jobj, "latestPrice")); + symbol_info->intraday_time = json_object_get_int64(json_object_object_get(jobj, "latestUpdate")); + symbol_info->marketcap = json_object_get_int64(json_object_object_get(jobj, "marketCap")); + symbol_info->volume_1d = json_object_get_int64(json_object_object_get(jobj, "latestVolume")); + symbol_info->pe_ratio = json_object_get_int64(json_object_object_get(jobj, "peRatio")); + json_object_put(jobj); + string_destroy(&pString); + return NULL; +} + +void* iex_store_stats(void* vpInfo) { + Info* symbol_info = vpInfo; + if (symbol_info->symbol[0] == '\0') + return NULL; + + char iex_api_string[URL_MAX_LENGTH]; + sprintf(iex_api_string, "https://api.iextrading.com/1.0/stock/%s/stats", symbol_info->symbol); + String* pString = api_curl_data(iex_api_string); // API CALL 3 -- Stats + if (pString == NULL) + return NULL; + + Json* jobj = json_tokener_parse(pString->data); + if (jobj == NULL) { // Invalid symbol + string_destroy(&pString); + return NULL; + } + + symbol_info->div_yield = json_object_get_double(json_object_object_get(jobj, "dividentYield")); + symbol_info->revenue = json_object_get_int64(json_object_object_get(jobj, "revenue")); + symbol_info->gross_profit = json_object_get_int64(json_object_object_get(jobj, "grossProfit")); + symbol_info->cash = json_object_get_int64(json_object_object_get(jobj, "cash")); + symbol_info->debt = json_object_get_int64(json_object_object_get(jobj, "debt")); + json_object_put(jobj); + string_destroy(&pString); + return NULL; +} + +void* iex_store_earnings(void* vpInfo) { + Info* symbol_info = vpInfo; + if (symbol_info->symbol[0] == '\0') + return NULL; + + char iex_api_string[URL_MAX_LENGTH]; + sprintf(iex_api_string, "https://api.iextrading.com/1.0/stock/%s/earnings", symbol_info->symbol); + String* pString = api_curl_data(iex_api_string); // API CALL 4 -- Earnings + if (pString == NULL) + return NULL; + + Json* jobj = json_tokener_parse(pString->data); + if (jobj == NULL) { // Invalid symbol + string_destroy(&pString); + return NULL; + } + + Json* idx; + size_t len = json_object_array_length(json_object_object_get(jobj, "earnings")); + for (size_t i = 0; i < len; i++) { + idx = json_object_array_get_idx(json_object_object_get(jobj, "earnings"), i); + symbol_info->eps[i] = json_object_get_double(json_object_object_get(idx, "actualEPS")); + symbol_info->eps_year_ago[i] = json_object_get_double(json_object_object_get(idx, "yearAgo")); + strcpy(symbol_info->fiscal_period[i], json_object_get_string(json_object_object_get(idx, "fiscalPeriod"))); + } + json_object_put(jobj); + string_destroy(&pString); + return NULL; +} + +void* iex_store_chart(void* vpInfo) { + Info* symbol_info = vpInfo; + if (symbol_info->symbol[0] == '\0') + return NULL; + + char iex_api_string[URL_MAX_LENGTH]; + sprintf(iex_api_string, "https://api.iextrading.com/1.0/stock/%s/chart/5y", symbol_info->symbol); + String* pString = api_curl_data(iex_api_string); + if (pString == NULL) + return NULL; + + Json* jobj = json_tokener_parse(pString->data); + if (jobj == NULL) { // Invalid symbol + string_destroy(&pString); + return NULL; + } + + size_t len = json_object_array_length(jobj); + symbol_info->points = calloc(len + 1, sizeof(double)); + pointer_alloc_check(symbol_info->points); + for (size_t i = 0; i < len; i++) + symbol_info->points[i] = json_object_get_double( + json_object_object_get(json_object_array_get_idx(jobj, i), "close")); + + len = 0; + while (symbol_info->points[len] != '\0') + len++; + time_t now = time(NULL); + struct tm* ts = localtime(&now); + mktime(ts); + int after_close = ts->tm_hour > 16 && ts->tm_wday != 0 && ts->tm_wday != 6; + double coef = 100 / symbol_info->price; + symbol_info->change_1d = coef * (symbol_info->price - symbol_info->points[len - 2 + after_close]); + symbol_info->change_7d = coef * (symbol_info->price - symbol_info->points[len - 6 + after_close]); + symbol_info->change_30d = coef * (symbol_info->price - symbol_info->points[len - 22 + after_close]); + return NULL; +} + double* morningstar_get_price(const char* symbol) { - char today_str[16], yesterday_str[16], morningstar_api_string[256]; + char today_str[DATE_MAX_LENGTH], yesterday_str[DATE_MAX_LENGTH], morningstar_api_string[URL_MAX_LENGTH]; time_t now = time(NULL); struct tm* ts = localtime(&now); - strftime(today_str, 16, "%Y-%m-%d", ts); + strftime(today_str, DATE_MAX_LENGTH, "%Y-%m-%d", ts); ts->tm_mday -= 12; // Get info from past 12 days mktime(ts); - strftime(yesterday_str, 16, "%Y-%m-%d", ts); + strftime(yesterday_str, DATE_MAX_LENGTH, "%Y-%m-%d", ts); sprintf(morningstar_api_string, "http://globalquote.morningstar.com/globalcomponent/RealtimeHistoricalStockData.ashx?showVol=true&dtype=his" "&f=d&curry=USD&isD=true&isS=true&hasF=true&ProdCode=DIRECT&ticker=%s&range=%s|%s", @@ -147,7 +297,7 @@ double* morningstar_get_price(const char* symbol) { } double* coinmarketcap_get_price(const char* symbol) { - char coinmarketcap_api_string[64]; + char coinmarketcap_api_string[URL_MAX_LENGTH]; sprintf(coinmarketcap_api_string, "https://api.coinmarketcap.com/v1/ticker/%s", symbol); String* pString = api_curl_data(coinmarketcap_api_string); if (pString == NULL) @@ -182,7 +332,7 @@ double* api_get_hist_5y(const char* symbol) { } double* iex_get_hist_5y(const char* symbol) { - char iex_api_string[64]; + char iex_api_string[URL_MAX_LENGTH]; sprintf(iex_api_string, "https://api.iextrading.com/1.0/stock/%s/chart/5y", symbol); String* pString = api_curl_data(iex_api_string); if (pString == NULL) @@ -205,14 +355,14 @@ double* iex_get_hist_5y(const char* symbol) { } double* morningstar_get_hist_5y(const char* symbol) { - char today_str[16], yesterday_str[16], morningstar_api_string[256]; + char today_str[DATE_MAX_LENGTH], yesterday_str[DATE_MAX_LENGTH], morningstar_api_string[URL_MAX_LENGTH]; time_t now = time(NULL); struct tm* ts = localtime(&now); mktime(ts); - strftime(today_str, 16, "%Y-%m-%d", ts); + strftime(today_str, DATE_MAX_LENGTH, "%Y-%m-%d", ts); ts->tm_year -= 5; //get info from past 5 years mktime(ts); - strftime(yesterday_str, 16, "%Y-%m-%d", ts); + strftime(yesterday_str, DATE_MAX_LENGTH, "%Y-%m-%d", ts); sprintf(morningstar_api_string, "http://globalquote.morningstar.com/globalcomponent/RealtimeHistoricalStockData.ashx?showVol=true&dtype=his" "&f=d&curry=USD&isD=true&isS=true&hasF=true&ProdCode=DIRECT&ticker=%s&range=%s|%s", @@ -329,60 +479,36 @@ void api_print_info(const char* ticker_name_string) { api_info_destroy(&ticker_info); } -Info* iex_get_info(const char* ticker_name_string) { - char iex_api_string[128]; - sprintf(iex_api_string, "https://api.iextrading.com/1.0/stock/%s/quote", ticker_name_string); - String* pString = api_curl_data(iex_api_string); // API CALL 1 -- name, symbol, price, mcap, volume - if (strcmp(pString->data, "Unknown symbol") == 0) { //Invalid symbol - string_destroy(&pString); - return NULL; - } - Info* ticker_info = api_info_init(); - Json* jobj = json_tokener_parse(pString->data); - strcpy(ticker_info->name, json_object_get_string(json_object_object_get(jobj, "companyName"))); - strcpy(ticker_info->symbol, json_object_get_string(json_object_object_get(jobj, "symbol"))); - ticker_info->price = json_object_get_double(json_object_object_get(jobj, "latestPrice")); - ticker_info->marketcap = json_object_get_int64(json_object_object_get(jobj, "marketCap")); - ticker_info->volume_1d = json_object_get_int64(json_object_object_get(jobj, "latestVolume")); - json_object_put(jobj); - string_destroy(&pString); - - sprintf(iex_api_string, "https://api.iextrading.com/1.0/stock/%s/stats/dividendYield", ticker_name_string); - pString = api_curl_data(iex_api_string); // API CALL 2 -- dividend - if (strcmp("0", pString->data) != 0) - ticker_info->div_yield = strtod(pString->data, NULL); - string_destroy(&pString); - - sprintf(iex_api_string, "https://api.iextrading.com/1.0/stock/%s/chart", ticker_name_string); - pString = api_curl_data(iex_api_string); // API CALL 3 -- historical - jobj = json_tokener_parse(pString->data); - time_t now = time(NULL); - struct tm* ts = localtime(&now); - mktime(ts); - int after_close = ts->tm_hour > 16 && ts->tm_wday != 0 && ts->tm_wday != 6; - Json* d_30 = json_object_array_get_idx(jobj, (size_t) after_close); - Json* d_7 = json_object_array_get_idx(jobj, json_object_array_length(jobj) - 6 + after_close); - Json* d_1 = json_object_array_get_idx(jobj, json_object_array_length(jobj) - 2 + after_close); - ticker_info->change_30d = 100 / ticker_info->price * - (ticker_info->price - json_object_get_double(json_object_object_get(d_30, "close"))); - ticker_info->change_7d = 100 / ticker_info->price * - (ticker_info->price - json_object_get_double(json_object_object_get(d_7, "close"))); - ticker_info->change_1d = 100 / ticker_info->price * - (ticker_info->price - json_object_get_double(json_object_object_get(d_1, "close"))); - json_object_put(jobj); - string_destroy(&pString); - return ticker_info; +Info* iex_get_info(const char* symbol) { + Info* symbol_info = api_info_init(); + strcpy(symbol_info->symbol, symbol); + pthread_t threads[5]; + void* (*funcs[5]) (void*) = { + iex_store_company, iex_store_quote, iex_store_stats, iex_store_earnings, iex_store_chart + }; + for (int i = 0; i < 5; i++) + if (pthread_create(&threads[i], NULL, funcs[i], symbol_info)) + EXIT_MSG("Error creating thread!"); + + for (int i = 0; i < 5; i++) + if (pthread_join(threads[i], NULL)) + EXIT_MSG("Error joining thread!"); + + if (symbol_info->symbol[0] == '\0') + api_info_destroy(&symbol_info); + + return symbol_info; } Info* morningstar_get_info(const char* ticker_name_string) { - char today_char[16], yesterday_char[16], morningstar_api_string[512]; + char today_char[DATE_MAX_LENGTH], yesterday_char[DATE_MAX_LENGTH], morningstar_api_string[URL_MAX_LENGTH]; time_t now = time(NULL); struct tm* ts = localtime(&now); mktime(ts); - strftime(today_char, 16, "%Y-%m-%d", ts); + strftime(today_char, DATE_MAX_LENGTH, "%Y-%m-%d", ts); ts->tm_mday -= 30; // Get info from past 30 days mktime(ts); - strftime(yesterday_char, 16, "%Y-%m-%d", ts); + strftime(yesterday_char, DATE_MAX_LENGTH, "%Y-%m-%d", ts); sprintf(morningstar_api_string, "http://globalquote.morningstar.com/globalcomponent/RealtimeHistoricalStockData.ashx?showVol=true&dtype=his" "&f=d&curry=USD&isD=true&isS=true&hasF=true&ProdCode=DIRECT&ticker=%s&range=%s|%s", @@ -417,7 +543,7 @@ Info* morningstar_get_info(const char* ticker_name_string) { } Info* coinmarketcap_get_info(const char* ticker_name_string) { - char coinmarketcap_api_string[64]; + char coinmarketcap_api_string[URL_MAX_LENGTH]; sprintf(coinmarketcap_api_string, "https://api.coinmarketcap.com/v1/ticker/%s", ticker_name_string); String* pString = api_curl_data(coinmarketcap_api_string); if (pString->data[0] == '{') { // Invalid symbol @@ -440,6 +566,7 @@ Info* coinmarketcap_get_info(const char* ticker_name_string) { } void api_info_destroy(Info** phInfo) { + free((*phInfo)->points); free(*phInfo); *phInfo = NULL; }
\ No newline at end of file |