#include "maths.h" 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, std::vector userid_list, std::string userid, long ts_high, long ts_low, float threshold) { std::map result; cycle_t tmp1, tmp2; float tmp_res; for(auto const& id : userid_list) { tmp2 = cycles.find(id)->second; if (cycle_size(tmp2) >= 10) { tmp_res = norm(diff_vector(tmp1, tmp2)); if (tmp_res < threshold) { result[id] = tmp_res; std::cout << "Difference between " << userid << " and " << id << " : " << result[id] << std::endl; } } } 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; /* Prepare cycles from db. */ for(auto const& id : userids) { cycles.insert( std::pair(id, history_to_cycle(db::pull_last_cycle_userid(C, id))) ); } for (auto& userid:userids) { tmp = norm::diff_all(C, cycles[userid], cycles, userids, userid, 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; } }