<commit_before>#include "kraken.h"
#include "parameters.h"
#include "utils/restapi.h"
#include "utils/base64.h"

#include "openssl/sha.h"
#include "openssl/hmac.h"
#include "jansson.h"
#include <iomanip>
#include <vector>
#include <sys/time.h>

namespace Kraken {

// Initialise internal variables
static json_t *krakenTicker = nullptr;
static bool krakenGotTicker = false;
static json_t *krakenLimPrice = nullptr;
static bool krakenGotLimPrice = false;

static RestApi& queryHandle(Parameters &params)
{
  static RestApi query ("https://api.kraken.com",
                        params.cacert.c_str(), *params.logFile);
  return query;
}

quote_t getQuote(Parameters &params)
{
  json_t *root;
  if (krakenGotTicker) {
    root = krakenTicker;
    krakenGotTicker = false;
  } else {
    auto &exchange = queryHandle(params);
    root = exchange.getRequest("/0/public/Ticker?pair=XXBTZUSD");
    krakenGotTicker = true;
    krakenTicker = root;
  }
  const char *quote = json_string_value(json_array_get(json_object_get(json_object_get(json_object_get(root, "result"), "XXBTZUSD"), "b"), 0));
  auto bidValue = quote ? std::stod(quote) : 0.0;

  quote = json_string_value(json_array_get(json_object_get(json_object_get(json_object_get(root, "result"), "XXBTZUSD"), "a"), 0));
  auto askValue = quote ? std::stod(quote) : 0.0;

  if (!krakenGotTicker) {
    json_decref(root);
  }
  return std::make_pair(bidValue, askValue);
}

double getAvail(Parameters& params, std::string currency) {
  json_t* root = authRequest(params, "/0/private/Balance");
  json_t* result = json_object_get(root, "result");
  if (json_object_size(result) == 0) {
    return 0.0;
  }
  double available = 0.0;
  if (currency.compare("usd") == 0) {
    const char * avail_str = json_string_value(json_object_get(result, "ZUSD"));
    available = avail_str ? atof(avail_str) : 0.0;
  } else if (currency.compare("btc") == 0) {
    const char * avail_str = json_string_value(json_object_get(result, "XXBT"));
    available = avail_str ? atof(avail_str) : 0.0;
  } else {
    *params.logFile << "<Kraken> Currency not supported" << std::endl;
  }
  return available;
}

std::string sendLongOrder(Parameters& params, std::string direction, double quantity, double price) {
  if (direction.compare("buy") != 0 && direction.compare("sell") != 0) {
    *params.logFile  << "<Kraken> Error: Neither \"buy\" nor \"sell\" selected" << std::endl;
    return "0";
  }
  *params.logFile << "<Kraken> Trying to send a \"" << direction << "\" limit order: "
                  << std::setprecision(6) << quantity << " @ $"
                  << std::setprecision(2) << price << "...\n";
  std::string pair = "XXBTZUSD";
  std::string type = direction;
  std::string ordertype = "limit";
  std::string pricelimit = std::to_string(price);
  std::string volume = std::to_string(quantity);
  std::string options = "pair=" + pair + "&type=" + type + "&ordertype=" + ordertype + "&price=" + pricelimit + "&volume=" + volume;
  json_t* res = authRequest(params, "/0/private/AddOrder", options);
  json_t* root = json_object_get(res, "result");
  if (json_is_object(root) == 0) {
    *params.logFile << json_dumps(res, 0) << std::endl;
    exit(0);
  }
  std::string txid = json_string_value(json_array_get(json_object_get(root, "txid"), 0));
  *params.logFile << "<Kraken> Done (transaction ID: " << txid << ")\n" << std::endl;
  json_decref(root);
  return txid;
}

bool isOrderComplete(Parameters& params, std::string orderId) {
  json_t* root = authRequest(params, "/0/private/OpenOrders");
  // no open order: return true
  root = json_object_get(json_object_get(root, "result"), "open");
  if (json_object_size(root) == 0) {
    *params.logFile << "<Kraken> No order exists" << std::endl;
    return true;
  }
  *params.logFile << json_dumps(root, 0) << std::endl;
  root = json_object_get(root, orderId.c_str());
  // open orders exist but specific order not found: return true
  if (json_object_size(root) == 0) {
    *params.logFile << "<Kraken> Order " << orderId << " does not exist" << std::endl;
    return true;
  // open orders exist and specific order was found: return false
  } else {
    *params.logFile << "<Kraken> Order " << orderId << " still exists!" << std::endl;
    return false;
  }
}

double getActivePos(Parameters& params) {
  return getAvail(params, "btc");
}

double getLimitPrice(Parameters &params, double volume, bool isBid)
{
  if (!krakenGotLimPrice)
  {
    if (krakenLimPrice) json_decref(krakenLimPrice);
    auto &exchange = queryHandle(params);
    krakenLimPrice = exchange.getRequest("/0/public/Depth?pair=XXBTZUSD");
  }
  krakenGotLimPrice = !krakenGotLimPrice;
  auto root = krakenLimPrice;
  auto branch = json_object_get(json_object_get(root, "result"), "XXBTZUSD");
  branch = json_object_get(branch, isBid ? "bids" : "asks");

  // loop on volume
  double tmpVol = 0.0;
  int i = 0;
  // [[<price>, <volume>, <timestamp>], [<price>, <volume>, <timestamp>], ...]
  while (tmpVol < volume) {
    // volumes are added up until the requested volume is reached
    tmpVol += atof(json_string_value(json_array_get(json_array_get(branch, i), 1)));
    i++;<commit_msg>No more manual json_t management in kraken.<commit_after>#include "kraken.h"
#include "parameters.h"
#include "utils/restapi.h"
#include "utils/base64.h"
#include "unique_json.hpp"

#include "openssl/sha.h"
#include "openssl/hmac.h"
#include <iomanip>
#include <vector>
#include <sys/time.h>

namespace Kraken {

// Initialise internal variables
static unique_json krakenTicker = nullptr;
static bool krakenGotTicker = false;
static unique_json krakenLimPrice = nullptr;
static bool krakenGotLimPrice = false;

static RestApi& queryHandle(Parameters &params)
{
  static RestApi query ("https://api.kraken.com",
                        params.cacert.c_str(), *params.logFile);
  return query;
}

quote_t getQuote(Parameters &params)
{
  if (krakenGotTicker) {
    krakenGotTicker = false;
  } else {
    auto &exchange = queryHandle(params);
    krakenTicker.reset(exchange.getRequest("/0/public/Ticker?pair=XXBTZUSD"));
    krakenGotTicker = true;
  }
  json_t *root = krakenTicker.get();
  const char *quote = json_string_value(json_array_get(json_object_get(json_object_get(json_object_get(root, "result"), "XXBTZUSD"), "b"), 0));
  auto bidValue = quote ? std::stod(quote) : 0.0;

  quote = json_string_value(json_array_get(json_object_get(json_object_get(json_object_get(root, "result"), "XXBTZUSD"), "a"), 0));
  auto askValue = quote ? std::stod(quote) : 0.0;

  return std::make_pair(bidValue, askValue);
}

double getAvail(Parameters& params, std::string currency) {
  unique_json root { authRequest(params, "/0/private/Balance") };
  json_t *result = json_object_get(root.get(), "result");
  if (json_object_size(result) == 0) {
    return 0.0;
  }
  double available = 0.0;
  if (currency.compare("usd") == 0) {
    const char * avail_str = json_string_value(json_object_get(result, "ZUSD"));
    available = avail_str ? atof(avail_str) : 0.0;
  } else if (currency.compare("btc") == 0) {
    const char * avail_str = json_string_value(json_object_get(result, "XXBT"));
    available = avail_str ? atof(avail_str) : 0.0;
  } else {
    *params.logFile << "<Kraken> Currency not supported" << std::endl;
  }
  return available;
}

std::string sendLongOrder(Parameters& params, std::string direction, double quantity, double price) {
  if (direction.compare("buy") != 0 && direction.compare("sell") != 0) {
    *params.logFile  << "<Kraken> Error: Neither \"buy\" nor \"sell\" selected" << std::endl;
    return "0";
  }
  *params.logFile << "<Kraken> Trying to send a \"" << direction << "\" limit order: "
                  << std::setprecision(6) << quantity << " @ $"
                  << std::setprecision(2) << price << "...\n";
  std::string pair = "XXBTZUSD";
  std::string type = direction;
  std::string ordertype = "limit";
  std::string pricelimit = std::to_string(price);
  std::string volume = std::to_string(quantity);
  std::string options = "pair=" + pair + "&type=" + type + "&ordertype=" + ordertype + "&price=" + pricelimit + "&volume=" + volume;
  unique_json root { authRequest(params, "/0/private/AddOrder", options) };
  json_t *res = json_object_get(root.get(), "result");
  if (json_is_object(res) == 0) {
    *params.logFile << json_dumps(root.get(), 0) << std::endl;
    exit(0);
  }
  std::string txid = json_string_value(json_array_get(json_object_get(res, "txid"), 0));
  *params.logFile << "<Kraken> Done (transaction ID: " << txid << ")\n" << std::endl;
  return txid;
}

bool isOrderComplete(Parameters& params, std::string orderId) {
  unique_json root { authRequest(params, "/0/private/OpenOrders") };
  // no open order: return true
  auto res = json_object_get(json_object_get(root.get(), "result"), "open");
  if (json_object_size(res) == 0) {
    *params.logFile << "<Kraken> No order exists" << std::endl;
    return true;
  }
  *params.logFile << json_dumps(res, 0) << std::endl;
  res = json_object_get(res, orderId.c_str());
  // open orders exist but specific order not found: return true
  if (json_object_size(res) == 0) {
    *params.logFile << "<Kraken> Order " << orderId << " does not exist" << std::endl;
    return true;
  // open orders exist and specific order was found: return false
  } else {
    *params.logFile << "<Kraken> Order " << orderId << " still exists!" << std::endl;
    return false;
  }
}

double getActivePos(Parameters& params) {
  return getAvail(params, "btc");
}

double getLimitPrice(Parameters &params, double volume, bool isBid)
{
  if (!krakenGotLimPrice)
  {
    auto &exchange = queryHandle(params);
    krakenLimPrice.reset(exchange.getRequest("/0/public/Depth?pair=XXBTZUSD"));
  }
  krakenGotLimPrice = !krakenGotLimPrice;
  auto root = krakenLimPrice.get();
  auto branch = json_object_get(json_object_get(root, "result"), "XXBTZUSD");
  branch = json_object_get(branch, isBid ? "bids" : "asks");

  // loop on volume
  double tmpVol = 0.0;
  int i = 0;
  // [[<price>, <volume>, <timestamp>], [<price>, <volume>, <timestamp>], ...]
  while (tmpVol < volume) {
    // volumes are added up until the requested volume is reached
    tmpVol += atof(json_string_value(json_array_get(json_array_get(branch, i), 1)));
    i++;
{'fraction_non_alphanumeric': 0.16152573708280626, 'fraction_numerical': 0.007784372871460543, 'mean_word_length': 4.311627906976744, 'pattern_counts': {'":': 0, '<': 161, '<?xml version=': 0, '>': 35, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4404920', 'n_tokens_mistral': 3681, 'n_tokens_neox': 3579, 'n_words': 810}