aboutsummarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntony Kellermann2018-05-27 23:15:55 -0400
committerAntony Kellermann2018-05-27 23:15:55 -0400
commitb776fc7eeba23d11198c9fa16c8a0797c1010e99 (patch)
tree5ab31f1a695de7b9a81e5af2c97a50bb5c851630
parentb84d32092615a3d0ec8f5fed98b035207f95807b (diff)
downloadaur-b776fc7eeba23d11198c9fa16c8a0797c1010e99.tar.gz
Added functions to store additional Info data
-rw-r--r--api.c257
-rw-r--r--api.h53
2 files changed, 237 insertions, 73 deletions
diff --git a/api.c b/api.c
index e3ebc7ecadee..c1620f2ad910 100644
--- a/api.c
+++ b/api.c
@@ -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
diff --git a/api.h b/api.h
index 4000c1ebbbf0..3e6bb5e54166 100644
--- a/api.h
+++ b/api.h
@@ -1,32 +1,59 @@
/**
- * API data is taken from IEX Trading, Morningstar, Coinmarketcap, and News API.
+ * API data is taken from IEX Trading, Morningstar, Coinmarketcap.
* https://iextrading.com/developer/docs/
* http://www.morningstar.com/
* https://coinmarketcap.com/api/
- * https://newsapi.org/docs
*/
#ifndef API_H
#define API_H
+#define QUARTERS 4
#define DATE_MAX_LENGTH 16
#define SYMBOL_MAX_LENGTH 32
#define URL_MAX_LENGTH 2048
+#define INFO_TEXT_MAX 2048
#define EMPTY (-999)
#include <stddef.h>
#include <curl/curl.h>
#include <json-c/json_tokener.h>
+#include <pthread.h>
#include "string-tick.h"
typedef struct info {
- char name[SYMBOL_MAX_LENGTH]; // Name of security (ex. Apple Inc.)
+ /* Company */
char symbol[SYMBOL_MAX_LENGTH]; // Symbol of security (ex. AAPL)
+ char name[INFO_TEXT_MAX]; // Name of security (ex. Apple Inc.)
+ char industry[INFO_TEXT_MAX];
+ char website[URL_MAX_LENGTH];
+ char description[INFO_TEXT_MAX]; // Description of company
+ char ceo[INFO_TEXT_MAX];
+ char issue_type[3];
+ char sector[INFO_TEXT_MAX];
+
+ /* Quote */
+ int64_t intraday_time; // unix time
double price; // Current price of security in USD (ex. 174.54)
- double change_1d, change_7d, change_30d; // Percent change in the past x days (ex. -7.49)
+ int64_t marketcap; // Market cap in USD (ex. 890489000000)
+ int64_t volume_1d; // Volume in shares of security (ex. 33812360)
+ double pe_ratio;
+
+ /* Stats */
double div_yield; // Percent dividend yield (ex. 1.46)
- long marketcap; // Market cap in USD (ex. 890489000000)
- long volume_1d; // Volume in shares of security (ex. 33812360)
+ int64_t revenue;
+ int64_t gross_profit;
+ int64_t cash;
+ int64_t debt;
+
+ /* Earnings */
+ double eps[QUARTERS];
+ char fiscal_period[QUARTERS][DATE_MAX_LENGTH];
+ double eps_year_ago[QUARTERS];
+
+ /* Chart */
+ double change_1d, change_7d, change_30d; // Percent change in the past x days (ex. -7.49)
+ double* points; // 5y
} Info;
/**
@@ -72,6 +99,16 @@ double* api_get_current_price(const char* symbol);
*/
double* iex_get_price(const char* symbol);
+void* iex_store_company(void* vpInfo);
+
+void* iex_store_quote(void* vpInfo);
+
+void* iex_store_stats(void* vpInfo);
+
+void* iex_store_earnings(void* vpInfo);
+
+void* iex_store_chart(void* vpInfo);
+
/**
* Returns current and yesterday's price of a mutual fund with data from Morningstar
* Tested for MUTF and OTCMKTS listed securities.
@@ -125,10 +162,10 @@ void api_print_info(const char* ticker_name_string);
/**
* Returns a pointer to an Info object containing info pertaining
* to the given symbol with data from IEX.
- * @param ticker_name_string stock/etf symbol
+ * @param symbol stock/etf symbol
* @return Info object
*/
-Info* iex_get_info(const char* ticker_name_string);
+Info* iex_get_info(const char* symbol);
/**
* Returns a pointer to an Info object containing info pertaining