#include "maths.h" #define DIFF_ALL_MIN_CYCLE_SIZE 0 namespace query { const std::string query_template_slope_ts_bot = "SELECT PRICE, TIMESTAMP FROM HISTORY "\ "WHERE COIN = '{}' AND TIMESTAMP <= {} AND TIMESTAMP > {} "\ "ORDER BY TIMESTAMP DESC "\ "LIMIT 1;"; const std::string query_template_last_n_spaced_prices = "select PRICE, TIMESTAMP FROM last_n_spaced_prices('{}', {}, {});"; } namespace norm { float norm(cycle_t c) { float rop = 0; for (auto const & element : c) { rop += pow(element.second, 2); } return sqrt(rop); } /* Should balance with weights. */ cycle_t history_to_cycle(ws_msg_parsed op) { cycle_t rop; for(auto const& element : op.transaction_list) { rop[element.coin] = element.quantity * pow((-1), element.type); } return rop; } cycle_t diff_vector(cycle_t op1, cycle_t op2) { cycle_t rop; rop = op1; for(auto const& element : op2) { if (op1.count(element.first)) { rop[element.first] -= element.second; } else { rop[element.first] = -element.second; } } return rop; } int cycle_size(cycle_t op) { int rop = 0; for (auto const & element : op) { rop += std::abs(element.second); } return rop; } std::map diff_all( pqxx::connection *C, cycle_t base_cycle, std::map cycles, long ts_high, long ts_low, float threshold){ std::map result; std::string tmp_uid; cycle_t tmp_c; float tmp_f; for(std::map::iterator iter = cycles.begin(); iter != cycles.end(); ++iter) { tmp_uid = iter->first; tmp_c = iter->second; tmp_f = norm(diff_vector(base_cycle, tmp_c)); if(tmp_f && tmp_f < threshold){ result.insert(std::pair(tmp_uid, tmp_f)); } } return result; } std::map> diff_map( pqxx::connection *C, std::vector userids, long ts_high, long ts_low, float threshold){ std::map> result; std::map cycles; std::map tmp; cycle_t tmp_c; int c_size; unsigned int pos; std::string userid; /* Prepare cycles from db. */ pos = 0; for(auto const& userid:userids) { tmp_c = history_to_cycle(db::pull_last_cycle_userid(C, userid)); c_size = cycle_size(tmp_c); /* Only keep players with large cycles */ if (c_size >= DIFF_ALL_MIN_CYCLE_SIZE) { cycles.insert(std::pair(userid, tmp_c)); } pos++; } /* Compute norms and diffs */ for(std::map::iterator iter = cycles.begin(); iter != cycles.end(); ++iter) { userid = iter->first; tmp = norm::diff_all(C, cycles[userid], cycles, ts_high, ts_low, threshold); result.insert( std::pair>( userid, tmp )); } return result; } void diff_save_json( pqxx::connection *C, std::map> op) { json j; std::string parent, child; for (auto& userid1_map:op) { parent = db::userid_to_username(C, userid1_map.first); for (auto& element:userid1_map.second) { child = db::userid_to_username(C, element.first); j[parent][child] = element.second; } } std::ofstream o("graph.json"); o << std::setw(4) << j << std::endl; } } namespace optimizer{ std::tuple get_last_nth_cycle_ts(int n) { long ts_now, ts_top, ts_bot; ts_now = time(NULL); ts_top = (ts_now - ts_now % 600) - n * 600; // floor (top) - n cycles ts_bot = ts_top - (n+1) * 600; return std::make_tuple(ts_top * 1000, ts_bot * 1000); } ///* Returns slope over last cycle. */ //float pull_last_cycle_slope(pqxx::connection* C, std::string coin) { // std::string query; // float price_top, price_bot, delta_p; // float ts_top, ts_bot, delta_t; // float slope; // pqxx::nontransaction N(*C); // pqxx::result::const_iterator c; // pqxx::result R; // auto [ts_high, ts_low] = optimizer::get_last_nth_cycle_ts(1); // //ts_high = time(NULL)*1000; // //ts_low = ts_high - 600*1000; // query = db::query::make_pull_query_top_price_cycle_ts(coin, ts_high, ts_low); // R = N.exec( query ); // c = R.begin(); // price_top = c[0].as(); // ts_top = c[1].as(); // query = db::query::make_pull_query_bot_price_cycle_ts(coin, ts_high, ts_low); // R = N.exec( query ); // c = R.begin(); // price_bot = c[0].as(); // ts_bot = c[1].as(); // slope = (price_top - price_bot) / ( (ts_top - ts_bot) ) * 1000 * 600; // std::cout << "pt: " << price_top << " pb: " << price_bot << std::endl; // std::cout << "tt: " << ts_top << " tb: " << ts_bot << std::endl; // return slope; //} float get_last_n_weighted_slope(pqxx::connection* C, std::string coin, int nb_cycles, int delta = 600) { std::string query; float wma, tmp_slope, price_top, price_bot; double ts_top, ts_bot; int weight, denum; query = db::query::make_pull_query_last_n_spaced_prices(coin, nb_cycles, delta); /* Create a non-transactional object. */ pqxx::nontransaction N(*C); /* Execute SQL query */ pqxx::result R( N.exec( query )); /* Parse result. */ price_top = R[0][0].as(); price_bot = R[1][0].as(); ts_top = R[0][1].as(); ts_bot = R[1][1].as(); tmp_slope = (price_top - price_bot) / (ts_top - ts_bot); weight = nb_cycles; wma = weight * tmp_slope; denum = weight; for (pqxx::result::const_iterator c = R.begin() + 1; c != R.end(); ++c) { price_bot = price_top; ts_bot = ts_top; price_top = c[0].as(); ts_top = c[1].as(); weight--; tmp_slope = (price_top - price_bot) / (ts_top - ts_bot); wma += weight * tmp_slope; denum += weight; } return wma / denum * 1000 * 600; } }