aboutsummarylogtreecommitdiffstats
diff options
context:
space:
mode:
authorAntony Kellermann2018-06-01 10:32:01 -0400
committerAntony Kellermann2018-06-01 10:32:01 -0400
commitc9a14c7583047aeafe4c1dc839d69d4e5ccebc14 (patch)
treec6e41936d5bbbb81b9722cffe534e406ed8a0ca3
parent067278b8f578fef2b3da2d7924b2dc47626534cb (diff)
downloadaur-c9a14c7583047aeafe4c1dc839d69d4e5ccebc14.tar.gz
Added peer api function and portfolio data to info struct
-rw-r--r--api.c104
-rw-r--r--api.h46
2 files changed, 129 insertions, 21 deletions
diff --git a/api.c b/api.c
index 9ade469350d4..9066ae5b060d 100644
--- a/api.c
+++ b/api.c
@@ -18,8 +18,12 @@ Info* api_info_init(void) {
.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, .points = NULL, .articles = NULL, .num_articles = EMPTY
+ .fiscal_period[3][0] = '\0', .eps_year_ago = {EMPTY, EMPTY, EMPTY, EMPTY}, .price_last_close = EMPTY,
+ .price_7d = EMPTY, .price_30d = EMPTY, .points = NULL, .num_points = EMPTY, .articles = NULL,
+ .num_articles = EMPTY, .num_peers = 0, .amount = EMPTY, .total_spent = EMPTY, .current_value = 0,
+ .profit_total = EMPTY, .profit_total_percent = EMPTY, .profit_last_close = EMPTY,
+ .profit_last_close_percent = EMPTY, .profit_7d = EMPTY, .profit_7d_percent = EMPTY, .profit_30d = EMPTY,
+ .profit_30d_percent = EMPTY
};
return pInfo;
}
@@ -112,6 +116,11 @@ void* iex_store_quote(void* vpInfo) {
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_double(json_object_object_get(jobj, "peRatio"));
+ if (symbol_info->amount != EMPTY) {
+ symbol_info->current_value = symbol_info->amount * symbol_info->price;
+ symbol_info->profit_total = symbol_info->current_value - symbol_info->total_spent;
+ symbol_info->profit_total_percent = 100 * (symbol_info->current_value / symbol_info->total_spent - 1);
+ }
json_object_put(jobj);
string_destroy(&pString);
return NULL;
@@ -215,10 +224,20 @@ void* iex_store_chart(void* vpInfo) {
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]);
+ symbol_info->price_last_close = symbol_info->points[len - 2 + after_close];
+ symbol_info->price_7d = symbol_info->points[len - 6 + after_close];
+ symbol_info->price_30d = symbol_info->points[len - 22 + after_close];
+ if (symbol_info->amount != EMPTY) {
+ symbol_info->profit_last_close = symbol_info->amount * (symbol_info->price - symbol_info->price_last_close);
+ symbol_info->profit_last_close_percent = 100 * (symbol_info->current_value / (symbol_info->current_value -
+ symbol_info->profit_last_close) - 1);
+ symbol_info->profit_7d = symbol_info->amount * (symbol_info->price - symbol_info->price_7d);
+ symbol_info->profit_7d_percent = 100 * (symbol_info->current_value / (symbol_info->current_value -
+ symbol_info->profit_7d) - 1);
+ symbol_info->profit_30d = symbol_info->amount * (symbol_info->price - symbol_info->price_30d);
+ symbol_info->profit_30d_percent = 100 * (symbol_info->current_value / (symbol_info->current_value -
+ symbol_info->profit_30d) - 1);
+ }
json_object_put(jobj);
string_destroy(&pString);
return NULL;
@@ -284,6 +303,50 @@ void* iex_store_news(void* vpInfo) {
return NULL;
}
+void* iex_store_peers(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/peers", 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);
+ if (len > MAX_PEERS)
+ len = MAX_PEERS;
+
+ symbol_info->peers = malloc(sizeof(Info*) * len);
+ pthread_t threads[len];
+ char temp_symbol[SYMBOL_MAX_LENGTH];
+ for (size_t i = 0; i < len; i++) {
+ strcpy(temp_symbol, json_object_get_string(json_object_array_get_idx(jobj, i)));
+ // Cast function to enable it as a thread entrypoint
+ if (pthread_create(&threads[i], NULL, (void* (*)(void*)) api_get_check_info, (void*) temp_symbol))
+ EXIT_MSG("Error creating thread!");
+ }
+
+ for (size_t i = 0; i < len; i++) {
+ void* ret = NULL;
+ if (pthread_join(threads[i], &ret))
+ EXIT_MSG("Error joining thread!")
+
+ symbol_info->peers[i] = ret;
+ }
+
+ json_object_put(jobj);
+ string_destroy(&pString);
+ return NULL;
+}
+
void* morningstar_store_info(void* vpInfo) {
Info* symbol_info = vpInfo;
char today_str[DATE_MAX_LENGTH], five_year_str[DATE_MAX_LENGTH], morningstar_api_string[URL_MAX_LENGTH];
@@ -318,9 +381,9 @@ void* morningstar_store_info(void* vpInfo) {
json_object_array_get_idx(json_object_array_get_idx(datapoints, (size_t) i), 0));
symbol_info->points = api_data;
symbol_info->price = api_data[len - 1];
- symbol_info->change_1d = 100 / symbol_info->price * (symbol_info->price - api_data[len - 2]);
- symbol_info->change_7d = 100 / symbol_info->price * (symbol_info->price - api_data[len - 6]);
- symbol_info->change_30d = 100 / symbol_info->price * (symbol_info->price - api_data[len - 22]);
+ symbol_info->price_last_close = api_data[len - 2];
+ symbol_info->price_7d = api_data[len - 6];
+ symbol_info->price_30d = api_data[len - 22];
Json* vol = json_object_object_get(jobj, "VolumeList");
if (vol != NULL) // There is no volume for MUTF
symbol_info->volume_1d = (long) (1000000 * json_object_get_double( // Data listed in millions
@@ -348,10 +411,13 @@ void* coinmarketcap_store_info(void* vpInfo) {
strcpy(symbol_info->name, json_object_get_string(json_object_object_get(data, "name")));
strcpy(symbol_info->symbol, json_object_get_string(json_object_object_get(data, "symbol")));
symbol_info->price = strtod(json_object_get_string(json_object_object_get(data, "price_usd")), NULL);
- symbol_info->change_1d = strtod(json_object_get_string(json_object_object_get(data, "percent_change_24h")), NULL);
- symbol_info->change_7d = strtod(json_object_get_string(json_object_object_get(data, "percent_change_7d")), NULL);
+ symbol_info->price_last_close = symbol_info->price /
+ (strtod(json_object_get_string(json_object_object_get(data, "percent_change_24h")), NULL) / 100 + 1);
+ symbol_info->price_7d = symbol_info->price /
+ (strtod(json_object_get_string(json_object_object_get(data, "percent_change_7d")), NULL) / 100 + 1);
symbol_info->marketcap = strtol(json_object_get_string(json_object_object_get(data, "market_cap_usd")), NULL, 10);
symbol_info->volume_1d = strtol(json_object_get_string(json_object_object_get(data, "24h_volume_usd")), NULL, 10);
+ symbol_info->intraday_time = strtol(json_object_get_string(json_object_object_get(data, "last_updated")), NULL, 10);
json_object_put(jobj);
string_destroy(&pString);
return NULL;
@@ -360,15 +426,16 @@ void* coinmarketcap_store_info(void* vpInfo) {
Info* iex_get_info(const char* symbol) {
Info* symbol_info = api_info_init();
strcpy(symbol_info->symbol, symbol);
- pthread_t threads[6];
- void* (*funcs[6]) (void*) = {
- iex_store_company, iex_store_quote, iex_store_stats, iex_store_earnings, iex_store_chart, iex_store_news
+ pthread_t threads[7];
+ void* (*funcs[7]) (void*) = {
+ iex_store_company, iex_store_quote, iex_store_stats, iex_store_earnings, iex_store_chart, iex_store_news,
+ iex_store_peers
};
- for (int i = 0; i < 6; i++)
+ for (int i = 0; i < 7; i++)
if (pthread_create(&threads[i], NULL, funcs[i], symbol_info))
EXIT_MSG("Error creating thread!");
- for (int i = 0; i < 6; i++)
+ for (int i = 0; i < 7; i++)
if (pthread_join(threads[i], NULL))
EXIT_MSG("Error joining thread!");
@@ -455,6 +522,11 @@ void api_info_destroy(Info** phInfo) {
if (pInfo->articles != NULL)
for (int i = 0; i < pInfo->num_articles; i++)
api_news_destroy(&pInfo->articles[i]);
+
+ if (pInfo->peers != NULL)
+ for (int i = 0; i < pInfo->num_peers; i++)
+ api_info_destroy(&pInfo->peers[i]);
+
free(pInfo->articles);
free(*phInfo);
*phInfo = NULL;
diff --git a/api.h b/api.h
index 0c2fd2a6c9d3..dc30492ab53e 100644
--- a/api.h
+++ b/api.h
@@ -15,6 +15,7 @@
#define INFO_TEXT_MAX 2048
#define EMPTY (-999)
#define DEFAULT_NUM_ARTICLES 3
+#define MAX_PEERS 12
#include <stddef.h>
#include <curl/curl.h>
@@ -31,7 +32,11 @@ typedef struct news_article {
char related[INFO_TEXT_MAX];
} News;
-typedef struct info {
+typedef struct info Info;
+
+struct info {
+ /** API DATA **/
+
/* Company */
char symbol[SYMBOL_MAX_LENGTH]; // ex. AAPL
char name[INFO_TEXT_MAX]; // ex. Apple Inc.
@@ -71,15 +76,37 @@ typedef struct info {
double eps_year_ago[QUARTERS]; // Earnings per share per quarter for the previous year
/* Chart */
- double change_1d; // Percent change since last close
- double change_7d; // Percent change since 7 days ago
- double change_30d; // Percent change since 30 days ago
+ double price_last_close; // Last close price
+ double price_7d; // Price 7 days ago
+ double price_30d; // Price 30 days ago
double* points; // Array of one price per day, startings five years previously
+ int num_points; // Number of data points
/* News */
News** articles; // Array of News pointers
int num_articles; // Number of News pointers in array
-} Info;
+
+ /* Peers */
+ Info** peers; // Array of symbol strings
+ int num_peers; // Number of symbols in array
+
+ /** PORTFOLIO DATA **/
+
+ double amount; // Amount of security in porfolio
+ double total_spent; // Total USD spent
+ double current_value; // Total USD value
+
+ /** CALCULATED DATA **/
+
+ double profit_total; // Total profit
+ double profit_total_percent; // Total profit %
+ double profit_last_close; // Profit since last close
+ double profit_last_close_percent; // Profit since last close %
+ double profit_7d; // Profit since seven days ago
+ double profit_7d_percent; // Profit since seven days ago %
+ double profit_30d; // Profit since thirty days ago
+ double profit_30d_percent; // Profit since thirty days ago %
+};
/**
* Allocates a News struct and returns a pointer to it.
@@ -170,6 +197,15 @@ void* iex_store_news(void* vpInfo);
/**
* Designed for threading
*
+ * Queries IEX's peers endpoint and stores the data in the Info object pointed to by vpInfo.
+ * @param vpInfo Info*
+ * @return NULL
+ */
+void* iex_store_peers(void* vpInfo);
+
+/**
+ * Designed for threading
+ *
* Queries Morningstar's API and stores the data in the Info object pointed to by vpInfo. price, change_1d,
* change_7d, change_30d, points, and volume_1d are stored.
* @param vpInfo Info*