diff options
author | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2021-05-31 06:11:22 -0700 |
---|---|---|
committer | David Vazgenovich Shakaryan <dvshakaryan@gmail.com> | 2021-05-31 06:11:22 -0700 |
commit | 18bde7391efb9c6bd6ea7846891ab5d16276a809 (patch) | |
tree | 237cc152edbdf934ed32e4c8c54c5ce97535e57f /stonks.c | |
download | stonks-master.tar.gz stonks-master.tar.xz |
A bit messy and missing error handling in some places.
Diffstat (limited to 'stonks.c')
-rw-r--r-- | stonks.c | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/stonks.c b/stonks.c new file mode 100644 index 0000000..77b7296 --- /dev/null +++ b/stonks.c @@ -0,0 +1,172 @@ +#include "assets.h" +#include "json_curl.h" +#include "output.h" +#include "quotes.h" +#include "tda.h" +#include "yahoo.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <lauxlib.h> +#include <lua.h> +#include <lualib.h> + +#define ASSETS_MAX 100 + +int load_assets_stock(struct asset **assets, lua_State *L) +{ + lua_getglobal(L, "stock"); + lua_pushnil(L); + + int n = 0; + while (lua_next(L, -2)) { + struct asset *asset = calloc(1, sizeof(*asset)); + asset->symbol = strdup(lua_tostring(L, -2)); + asset->amt = lua_tonumber(L, -1); + asset->type = STOCK; + assets[n++] = asset; + + lua_pop(L, 1); + } + + lua_pop(L, 1); + return n; +} + +int load_assets_crypto(struct asset **assets, lua_State *L) +{ + lua_getglobal(L, "crypto"); + lua_pushnil(L); + + int n = 0; + while (lua_next(L, -2)) { + struct asset *asset = calloc(1, sizeof(*asset)); + asset->symbol = strdup(lua_tostring(L, -2)); + asset->amt = lua_tonumber(L, -1); + asset->type = CRYPTO; + assets[n++] = asset; + + lua_pop(L, 1); + } + + lua_pop(L, 1); + return n; +} + +static int read_token(const char *path, char *buf, size_t bufsize) +{ + FILE *f = fopen(path, "r"); + if (!f) return 0; + + int ret = 0; + if (fgets(buf, bufsize, f)) { + ret = 1; + char *nl = strchr(buf, '\n'); + if (nl) *nl = '\0'; + } + + fclose(f); + return ret; +} + +static int write_token(const char *path, char *buf) +{ + FILE *f = fopen(path, "w"); + if (!f) return 0; + + int ret = 0; + if (fputs(buf, f) != EOF && fputc('\n', f) != EOF) + ret = 1; + + fclose(f); + return ret; +} + +int load_tda(struct asset **assets, lua_State *L, struct tda_session **sessptr) +{ + int ret = -1; + struct tda_session *sess = NULL; + + size_t token_size = 2048; + char *token = malloc(token_size); + if (!token) goto out; + + lua_getglobal(L, "tda"); + lua_getfield(L, -1, "account_id"); + const char *account_id = lua_tostring(L, -1); + lua_getfield(L, -2, "client_id"); + const char *client_id = lua_tostring(L, -1); + lua_getfield(L, -3, "token_path"); + const char *token_path = lua_tostring(L, -1); + + if (read_token(token_path, token, token_size) && + (sess = tda_init(client_id, account_id, token))) { + if (write_token(token_path, sess->refresh_token)) { + ret = tda_load_assets(sess, assets); + } else { + tda_cleanup(sess); + sess = NULL; + } + } + + lua_pop(L, 4); + free(token); +out: + *sessptr = sess; + return ret; +} + +int main() +{ + lua_State *L = luaL_newstate(); + luaL_openlibs(L); + luaL_dofile(L, "config.lua"); + lua_pushcfunction(L, push_field_lua); + lua_setglobal(L, "get_asset_field"); + + if (curl_global_init(CURL_GLOBAL_DEFAULT) != 0) + return 1; + + struct tda_session *tda; + struct asset **assets = calloc(ASSETS_MAX, sizeof(*assets)); + int n_assets = load_tda(assets, L, &tda); + n_assets += load_assets_stock(assets + n_assets, L); + n_assets += load_assets_crypto(assets + n_assets, L); + + struct quote **quotes; + char *symbols; + int n_quotes; + + yahoo_get_quote_symbols(assets, n_assets, &symbols); + n_quotes = yahoo_get_quotes(symbols, "es); + free(symbols); + add_quotes_to_assets(assets, n_assets, quotes, n_quotes); + + for (int i = 0; i < n_quotes; ++i) + quote_free(quotes[i]); + free(quotes); + + tda_get_quote_symbols(assets, n_assets, &symbols); + n_quotes = tda_get_quotes(tda, symbols, "es); + free(symbols); + add_quotes_to_assets(assets, n_assets, quotes, n_quotes); + + for (int i = 0; i < n_quotes; ++i) + quote_free(quotes[i]); + free(quotes); + + qsort(assets, n_assets, sizeof(*assets), asset_cmp); + n_assets += add_totals(assets, n_assets); + output(assets, n_assets, L); + + for (int i = 0; i < n_assets; ++i) + asset_free(assets[i]); + free(assets); + + tda_cleanup(tda); + curl_global_cleanup(); + lua_close(L); + return 0; +} |