You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1208 lines
51 KiB

/******************************************************************************
* Copyright © 2014-2016 The SuperNET Developers. *
* *
* See the AUTHORS, DEVELOPER-AGREEMENT and LICENSE files at *
* the top-level directory of this distribution for the individual copyright *
* holder information and the developer policies on copyright and licensing. *
* *
* Unless otherwise agreed in a custom licensing agreement, no part of the *
* SuperNET software, including this file may be copied, modified, propagated *
* or distributed except according to the terms contained in the LICENSE file *
* *
* Removal or modification of this copyright notice is prohibited. *
* *
******************************************************************************/
#ifndef xcode_exchangeparse_h
#define xcode_exchangeparse_h
char *Supported_exchanges[] = { INSTANTDEX_NAME, INSTANTDEX_NXTAEUNCONF, INSTANTDEX_NXTAENAME, INSTANTDEX_BASKETNAME, "basketNXT", "basketUSD", "basketBTC", "basketCNY", INSTANTDEX_ACTIVENAME, "wallet", "jumblr", "pangea", "peggy", // peggy MUST be last of special exchanges
"bitfinex", "btc38", "bitstamp", "btce", "poloniex", "bittrex", "huobi", "coinbase", "okcoin", "lakebtc", "quadriga",
//"bityes", "kraken", "gatecoin", "quoine", "jubi", "hitbtc" // no trading for these exchanges yet
}; // "bter" <- orderbook is backwards and all entries are needed, later to support, "exmo" flakey apiservers
void init_exchanges()
{
int32_t i;
for (FIRST_EXTERNAL=0; FIRST_EXTERNAL<sizeof(Supported_exchanges)/sizeof(*Supported_exchanges); FIRST_EXTERNAL++)
{
find_exchange(0,Supported_exchanges[FIRST_EXTERNAL]);
if ( strcmp(Supported_exchanges[FIRST_EXTERNAL],"peggy") == 0 )
{
FIRST_EXTERNAL++;
break;
}
}
for (i=FIRST_EXTERNAL; i<sizeof(Supported_exchanges)/sizeof(*Supported_exchanges); i++)
find_exchange(0,Supported_exchanges[i]);
prices777_initpair(-1,0,0,0,0.,0,0,0,0);
void prices777_basketsloop(void *ptr);
iguana_launch(iguana_coinadd("BTCD"),"basketloop",(void *)prices777_basketsloop,0,IGUANA_EXCHANGETHREAD);
//prices777_makebasket("{\"name\":\"NXT/BTC\",\"base\":\"NXT\",\"rel\":\"BTC\",\"basket\":[{\"exchange\":\"bittrex\"},{\"exchange\":\"poloniex\"},{\"exchange\":\"btc38\"}]}",0);
}
void init_InstantDEX()
{
int32_t a,b;
//init_pingpong_queue(&Pending_offersQ,"pending_offers",0,0,0);
//Pending_offersQ.offset = 0;
init_exchanges();
find_exchange(&a,INSTANTDEX_NXTAENAME), find_exchange(&b,INSTANTDEX_NAME);
if ( a != INSTANTDEX_NXTAEID || b != INSTANTDEX_EXCHANGEID )
printf("invalid exchangeid %d, %d\n",a,b);
find_exchange(&a,INSTANTDEX_NXTAENAME), find_exchange(&b,INSTANTDEX_NAME);
if ( a != INSTANTDEX_NXTAEID || b != INSTANTDEX_EXCHANGEID )
printf("invalid exchangeid %d, %d\n",a,b);
printf("NXT-> %llu BTC -> %llu\n",(long long)stringbits("NXT"),(long long)stringbits("BTC"));
//INSTANTDEX.readyflag = 1;
}
int32_t supported_exchange(char *exchangestr)
{
int32_t i;
for (i=0; i<sizeof(Supported_exchanges)/sizeof(*Supported_exchanges); i++)
if ( strcmp(exchangestr,Supported_exchanges[i]) == 0 )
return(i);
return(-1);
}
cJSON *exchanges_json()
{
struct exchange_info *exchange; int32_t exchangeid,n = 0; char api[4]; cJSON *item,*array = cJSON_CreateArray();
for (exchangeid=0; exchangeid<MAX_EXCHANGES; exchangeid++)
{
item = cJSON_CreateObject();
exchange = &Exchanges[exchangeid];
if ( exchange->name[0] == 0 )
break;
cJSON_AddItemToObject(item,"name",cJSON_CreateString(exchange->name));
memset(api,0,sizeof(api));
n = 0;
if ( exchange->issue.trade != 0 )
{
//printf("%s.(%s/%s/%s).%p\n",exchange->name,exchange->apikey,exchange->apisecret,exchange->userid,exchange);
if ( exchange->apikey[0] != 0 )
api[n++] = 'K';
if ( exchange->apisecret[0] != 0 )
api[n++] = 'S';
if ( exchange->userid[0] != 0 )
api[n++] = 'U';
api[n] = 0;
cJSON_AddItemToObject(item,"trade",cJSON_CreateString(api));
}
cJSON_AddItemToArray(array,item);
}
return(array);
}
int32_t is_exchange_nxt64bits(uint64_t nxt64bits)
{
int32_t exchangeid;
struct exchange_info *exchange = 0;
for (exchangeid=0; exchangeid<MAX_EXCHANGES; exchangeid++)
{
exchange = &Exchanges[exchangeid];
// printf("(%s).(%llu vs %llu) ",exchange->name,(long long)exchange->nxt64bits,(long long)nxt64bits);
if ( exchange->name[0] == 0 )
return(0);
if ( exchange->nxt64bits == nxt64bits )
return(1);
}
printf("no exchangebits match\n");
return(0);
}
struct exchange_info *get_exchange(int32_t exchangeid) { return(&Exchanges[exchangeid]); }
char *exchange_str(int32_t exchangeid) { return(Exchanges[exchangeid].name); }
struct exchange_info *exchange_find(char *exchangestr)
{
int32_t exchangeid;
struct exchange_info *exchange = 0;
for (exchangeid=0; exchangeid<MAX_EXCHANGES; exchangeid++)
{
exchange = &Exchanges[exchangeid];
if ( strcmp(exchangestr,exchange->name) == 0 )
return(exchange);
}
return(0);
}
struct exchange_info *find_exchange(int32_t *exchangeidp,char *exchangestr)
{
int32_t exchangeid; struct exchange_info *exchange = 0;
if ( supported_exchange(exchangestr) < 0 )
{
if ( exchangeidp != 0 )
*exchangeidp = -1;
return(0);
}
for (exchangeid=0; exchangeid<MAX_EXCHANGES; exchangeid++)
{
exchange = &Exchanges[exchangeid];
//printf("(%s v %s) ",exchangestr,exchange->name);
if ( exchange->name[0] == 0 )
{
portable_mutex_init(&exchange->mutex);
strcpy(exchange->name,exchangestr);
exchange->exchangeid = exchangeid;
exchange->nxt64bits = stringbits(exchangestr);
printf("CREATE EXCHANGE.(%s) id.%d %llu\n",exchangestr,exchangeid,(long long)exchange->nxt64bits);
//if ( exchangestr[0] == 0 )
// getchar();
break;
}
if ( strcmp(exchangestr,exchange->name) == 0 )
break;
}
if ( exchange != 0 && exchangeidp != 0 )
*exchangeidp = exchange->exchangeid;
return(exchange);
}
int32_t baserel_polarity(char *pairs[][2],int32_t n,char *_base,char *_rel)
{
int32_t i; char base[16],rel[16];
strcpy(base,_base), tolowercase(base);
strcpy(rel,_rel), tolowercase(rel);
for (i=0; i<n; i++)
{
if ( strcmp(pairs[i][0],base) == 0 && strcmp(pairs[i][1],rel) == 0 )
return(1);
else if ( strcmp(pairs[i][0],rel) == 0 && strcmp(pairs[i][1],base) == 0 )
return(-1);
}
printf("cant find.(%s/%s) [%s/%s].%d\n",base,rel,pairs[0][0],pairs[0][1],n);
return(0);
}
double prices777_standard(char *exchangestr,char *url,struct prices777 *prices,char *price,char *volume,int32_t maxdepth,char *field)
{
char *jsonstr; cJSON *json; double hbla = 0.;
if ( (jsonstr= issue_curl(url)) != 0 )
{
//if ( strcmp(exchangestr,"btc38") == 0 )
printf("(%s) -> (%s)\n",url,jsonstr);
if ( (json= cJSON_Parse(jsonstr)) != 0 )
{
hbla = prices777_json_orderbook(exchangestr,prices,maxdepth,json,field,"bids","asks",price,volume);
free_json(json);
}
free(jsonstr);
}
return(hbla);
}
int32_t InstantDEX_supports(char *base,char *rel) { return(1); }
int32_t NXT_supports(char *base,char *rel)
{
if ( strcmp(rel,"NXT") == 0 )
return(1);
else if ( strcmp(base,"NXT") == 0 )
return(-1);
else return(0);
}
#ifdef notnow
char *bittrex_parsebalance(struct exchange_info *exchange,double *balancep,char *coinstr)
{
int32_t i,n; char *str,*itemstr = 0; cJSON *item,*array,*obj; double total,pending;
*balancep = 0.;
if ( exchange->balancejson != 0 && (array= jarray(&n,exchange->balancejson,"result")) != 0 )
{
for (i=0; i<n; i++)
{
if ( (item= jitem(array,i)) != 0 )
{
if ( (str= jstr(item,"Currency")) != 0 && strcmp(coinstr,str) == 0 )
{
itemstr = jprint(item,0);
*balancep = jdouble(item,"Available");
total = jdouble(item,"Balance");
pending = jdouble(item,"Pending");
if ( (obj= cJSON_Parse(itemstr)) != 0 )
{
jaddnum(obj,"balance",*balancep);
jaddnum(obj,"total",total);
jaddnum(obj,"pending",pending);
if ( (str= jstr(obj,"CryptoAddress")) != 0 )
jaddstr(obj,"deposit_address",str);
free(itemstr);
itemstr = jprint(obj,1);
}
break;
}
}
}
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
int32_t bittrex_supports(char *base,char *rel)
{
if ( strlen(base) > 5 || strlen(rel) > 5 || strcmp(rel,"CNY") == 0 || strcmp(base,"CNY") == 0 || strcmp(rel,"USD") == 0 || strcmp(base,"USD") == 0 )
return(0);
if ( strcmp(rel,"BTC") == 0 )
return(1);
else if ( strcmp(base,"BTC") == 0 )
return(-1);
else return(0);
}
double prices777_bittrex(struct prices777 *prices,int32_t maxdepth) // "BTC-BTCD"
{
cJSON *json,*obj; char *jsonstr,market[128]; double hbla = 0.;
if ( prices->url[0] == 0 )
{
sprintf(market,"%s-%s",prices->rel,prices->base);
sprintf(prices->url,"https://bittrex.com/api/v1.1/public/getorderbook?market=%s&type=both&depth=%d",market,maxdepth);
}
jsonstr = issue_curl(prices->url);
if ( jsonstr != 0 )
{
if ( (json = cJSON_Parse(jsonstr)) != 0 )
{
if ( (obj= cJSON_GetObjectItem(json,"success")) != 0 && is_cJSON_True(obj) != 0 )
hbla = prices777_json_orderbook("bittrex",prices,maxdepth,json,"result","buy","sell","Rate","Quantity");
free_json(json);
}
free(jsonstr);
}
return(hbla);
}
/*int32_t bter_supports(char *base,char *rel)
{
return(0);
if ( strcmp(rel,"BTC") == 0 || strcmp(rel,"CNY") == 0 )
return(1);
else if ( strcmp(base,"BTC") == 0 || strcmp(base,"CNY") == 0 )
return(-1);
else return(0);
char *bterassets[][8] = { { "UNITY", "12071612744977229797" }, { "ATOMIC", "11694807213441909013" }, { "DICE", "18184274154437352348" }, { "MRKT", "134138275353332190" }, { "MGW", "10524562908394749924" } };
uint64_t unityid = calc_nxt64bits("12071612744977229797");
n = add_exchange_assetids(assetids,n,BTC_ASSETID,baseid,relid,exchangeid,bterassets,(int32_t)(sizeof(bterassets)/sizeof(*bterassets)));
if ( baseid == unityid || relid == unityid )
{
n = add_exchange_assetid(assetids,n,unityid,BTC_ASSETID,exchangeid);
n = add_exchange_assetid(assetids,n,unityid,NXT_ASSETID,exchangeid);
n = add_exchange_assetid(assetids,n,unityid,CNY_ASSETID,exchangeid);
}
return(n);
}
double prices777_bter(struct prices777 *prices,int32_t maxdepth)
{
cJSON *json,*obj; char resultstr[MAX_JSON_FIELD],*jsonstr; double hbla = 0.;
if ( prices->url[0] == 0 )
sprintf(prices->url,"http://data.bter.com/api/1/depth/%s_%s",prices->base,prices->rel);
jsonstr = issue_curl(prices->url);
//printf("(%s) -> (%s)\n",ep->url,jsonstr);
//{"result":"true","asks":[["0.00008035",100],["0.00008030",2030],["0.00008024",100],["0.00008018",643.41783554],["0.00008012",100]
if ( jsonstr != 0 )
{
//printf("BTER.(%s)\n",jsonstr);
if ( (json = cJSON_Parse(jsonstr)) != 0 )
{
if ( (obj= cJSON_GetObjectItem(json,"result")) != 0 )
{
copy_cJSON(resultstr,obj);
if ( strcmp(resultstr,"true") == 0 )
{
maxdepth = MAX_DEPTH;//1000; // since bter ask is wrong order, need to scan entire list
hbla = prices777_json_orderbook("bter",prices,maxdepth,json,0,"bids","asks",0,0);
}
}
free_json(json);
}
free(jsonstr);
}
return(hbla);
}*/
char *poloniex_parsebalance(struct exchange_info *exchange,double *balancep,char *coinstr)
{
char *itemstr = 0; cJSON *item,*obj; double onorders,btcvalue;
*balancep = 0.;
if ( exchange->balancejson != 0 && (item= jobj(exchange->balancejson,coinstr)) != 0 )
{
itemstr = jprint(item,0);
*balancep = jdouble(item,"available");
onorders = jdouble(item,"onOrders");
btcvalue = jdouble(item,"btcValue");
if ( (obj= cJSON_Parse(itemstr)) != 0 )
{
free(itemstr);
jaddstr(obj,"base",coinstr);
jaddnum(obj,"balance",*balancep);
jaddnum(obj,"onOrders",onorders);
jaddnum(obj,"btcvalue",btcvalue);
itemstr = jprint(obj,1);
}
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
int32_t poloniex_supports(char *base,char *rel)
{
if ( strlen(base) > 5 || strlen(rel) > 5 || strcmp(rel,"CNY") == 0 || strcmp(base,"CNY") == 0 || strcmp(rel,"USD") == 0 || strcmp(base,"USD") == 0 )
return(0);
if ( strcmp(rel,"BTC") == 0 )
return(1);
else if ( strcmp(base,"BTC") == 0 )
return(-1);
else return(0);
//char *poloassets[][8] = { { "UNITY", "12071612744977229797" }, { "JLH", "6932037131189568014" }, { "XUSD", "12982485703607823902" }, { "LQD", "4630752101777892988" }, { "NXTI", "14273984620270850703" }, { "CNMT", "7474435909229872610", "6220108297598959542" } };
//return(add_exchange_assetids(assetids,n,BTC_ASSETID,baseid,relid,exchangeid,poloassets,(int32_t)(sizeof(poloassets)/sizeof(*poloassets))));
}
double prices777_poloniex(struct prices777 *prices,int32_t maxdepth)
{
char market[128];
if ( prices->url[0] == 0 )
{
sprintf(market,"%s_%s",prices->rel,prices->base);
sprintf(prices->url,"https://poloniex.com/public?command=returnOrderBook&currencyPair=%s&depth=%d",market,maxdepth);
}
return(prices777_standard("poloniex",prices->url,prices,0,0,maxdepth,0));
}
int32_t kraken_supports(char *_base,char *_rel)
{
char *supports[] = { "BTC", "ETH", "LTC", "NMC", "STR", "DOGE", "XVN", "XRP", "USD", "CAD", "JPY", "GBP", "KRW" };
int32_t i,j; char base[64],rel[64];
strcpy(base,_base), strcpy(rel,_rel);
touppercase(base), touppercase(rel);
if ( strlen(base) > 5 || strlen(rel) > 5 )
return(0);
for (i=0; i<sizeof(supports)/sizeof(*supports); i++)
if ( strcmp(base,supports[i]) == 0 )
{
for (j=0; j<sizeof(supports)/sizeof(*supports); j++)
if ( strcmp(rel,supports[j]) == 0 )
return(1);
break;
}
return(0);
}
double prices777_kraken(struct prices777 *prices,int32_t maxdepth)
{
char market[128],field[64],base[64],rel[64],*jsonstr; cJSON *json; double hbla = 0.;
strcpy(base,prices->base), strcpy(rel,prices->rel);
touppercase(base), touppercase(rel);
if ( strcmp(base,"BTC") == 0 )
strcpy(base,"XBT");
if ( strcmp(rel,"BTC") == 0 )
strcpy(rel,"XBT");
if ( strcmp(base,"DOGE") == 0 )
strcpy(base,"XDG");
if ( strcmp(rel,"DOGE") == 0 )
strcpy(rel,"XDG");
sprintf(field,"X%sZ%s",base,rel);
if ( prices->url[0] == 0 )
{
sprintf(market,"%s%s",base,rel);
sprintf(prices->url,"https://api.kraken.com/0/public/Depth?pair=%s&count=%d",market,maxdepth);
}
if ( (jsonstr= issue_curl(prices->url)) != 0 )
{
//{"error":[],"result":{"XXBTZUSD":{"asks":[["230.31677","1.438",1440886427],["230.31678","7.229",1440886068],["230.77732","0.012",1440876801],["230.77833","9.642",1440885707],["231.24081","9.719",1440884428]],"bids":[["228.04086","3.052",1440886443],["228.04085","0.590",1440886446],["228.04076","9.550",1440886434],["227.58559","10.214",1440800610],["227.56018","5.000",1440881811]]}}}
if ( (json= cJSON_Parse(jsonstr)) != 0 )
{
//printf("got.(%s)\n",jsonstr);
hbla = prices777_json_orderbook("kraken",prices,maxdepth,jobj(json,"result"),field,"bids","asks",0,0);
free_json(json);
}
free(jsonstr);
}
return(hbla);
}
char *bitfinex_parsebalance(struct exchange_info *exchange,double *balancep,char *coinstr)
{
//[[{"type":"deposit","currency":"btc","amount":"0.0","available":"0.0"},{"type":"deposit","currency":"usd","amount":"0.0","available":"0.0"},{"type":"exchange","currency":"btc","amount":"0.01065851","available":"0.01065851"},{"type":"exchange","currency":"usd","amount":"23386.37278962","available":"0.00378962"},{"type":"trading","currency":"btc","amount":"0.0","available":"0.0"},{"type":"trading","currency":"usd","amount":"0.0","available":"0.0"}]]
int32_t i,n,ind; char field[64],*str,*typestr,*itemstr = 0; cJSON *item,*obj,*array; double amounts[3],avail[3],val0,val1;
*balancep = 0.;
strcpy(field,coinstr), tolowercase(field);
memset(amounts,0,sizeof(amounts));
memset(avail,0,sizeof(avail));
if ( exchange->balancejson != 0 && is_cJSON_Array(exchange->balancejson) != 0 && (n= cJSON_GetArraySize(exchange->balancejson)) > 0 )
{
for (i=0; i<n; i++)
{
if ( (item= jitem(exchange->balancejson,i)) != 0 )
{
if ( (str= jstr(item,"currency")) != 0 && strcmp(field,str) == 0 )
{
val0 = jdouble(item,"amount");
val1 = jdouble(item,"available");
if ( (typestr= jstr(item,"type")) != 0 )
{
if ( strcmp(typestr,"deposit") == 0 )
ind = 0;
else if ( strcmp(typestr,"exchange") == 0 )
ind = 1;
else if ( strcmp(typestr,"trading") == 0 )
ind = 2;
else ind = -1;
if ( ind >= 0 )
{
amounts[ind] = val0;
avail[ind] = val1;
}
}
}
}
}
if ( (obj= cJSON_CreateObject()) != 0 )
{
touppercase(field);
*balancep = avail[0] + avail[1] + avail[2];
jaddstr(obj,"base",field);
jaddnum(obj,"balance",*balancep);
jaddnum(obj,"total",amounts[0]+amounts[1]+amounts[2]);
array = cJSON_CreateArray(), jaddinum(array,avail[0]), jaddinum(array,amounts[0]), jadd(obj,"deposit",array);
array = cJSON_CreateArray(), jaddinum(array,avail[1]), jaddinum(array,amounts[1]), jadd(obj,"exchange",array);
array = cJSON_CreateArray(), jaddinum(array,avail[2]), jaddinum(array,amounts[2]), jadd(obj,"trading",array);
itemstr = jprint(obj,1);
}
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
int32_t bitfinex_supports(char *base,char *rel)
{
char *baserels[][2] = { {"btc","usd"}, {"ltc","usd"}, {"ltc","btc"} };
return(baserel_polarity(baserels,(int32_t)(sizeof(baserels)/sizeof(*baserels)),base,rel));
}
double prices777_bitfinex(struct prices777 *prices,int32_t maxdepth)
{
if ( prices->url[0] == 0 )
sprintf(prices->url,"https://api.bitfinex.com/v1/book/%s%s",prices->base,prices->rel);
return(prices777_standard("bitfinex",prices->url,prices,"price","amount",maxdepth,0));
}
char *btce_parsebalance(struct exchange_info *exchange,double *balancep,char *coinstr)
{
//btce.({"success":1,"return":{"funds":{"usd":73.02571846,"btc":0,"ltc":0,"nmc":0,"rur":0,"eur":0,"nvc":0.0000322,"trc":0,"ppc":0.00000002,"ftc":0,"xpm":2.28605349,"cnh":0,"gbp":0},"rights":{"info":1,"trade":1,"withdraw":0},"transaction_count":0,"open_orders":3,"server_time":1441918649}})
char field[128],*itemstr = 0; cJSON *obj,*item;
*balancep = 0.;
strcpy(field,coinstr);
tolowercase(field);
if ( exchange->balancejson != 0 && (obj= jobj(exchange->balancejson,"return")) != 0 && (item= jobj(obj,"funds")) != 0 )
{
*balancep = jdouble(item,field);
obj = cJSON_CreateObject();
touppercase(field);
jaddstr(obj,"base",field);
jaddnum(obj,"balance",*balancep);
itemstr = jprint(obj,1);
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
int32_t btce_supports(char *base,char *rel)
{
char *baserels[][2] = { {"btc","usd"}, {"btc","rur"}, {"btc","eur"}, {"ltc","btc"}, {"ltc","usd"}, {"ltc","rur"}, {"ltc","eur"}, {"nmc","btc"}, {"nmc","usd"}, {"nvc","btc"}, {"nvc","usd"}, {"eur","usd"}, {"eur","rur"}, {"ppc","btc"}, {"ppc","usd"} };
return(baserel_polarity(baserels,(int32_t)(sizeof(baserels)/sizeof(*baserels)),base,rel));
}
double prices777_btce(struct prices777 *prices,int32_t maxdepth)
{
char field[64];
sprintf(field,"%s_%s",prices->lbase,prices->lrel);
if ( prices->url[0] == 0 )
sprintf(prices->url,"https://btc-e.com/api/3/depth/%s",field);
return(prices777_standard("btce",prices->url,prices,0,0,maxdepth,field));
}
char *bitstamp_parsebalance(struct exchange_info *exchange,double *balancep,char *coinstr)
{
char field[128],*itemstr = 0; cJSON *obj,*item;
*balancep = 0.;
strcpy(field,coinstr);
tolowercase(field);
if ( exchange->balancejson != 0 && (obj= jobj(exchange->balancejson,"return")) != 0 && (item= jobj(obj,"funds")) != 0 )
{
*balancep = jdouble(item,field);
obj = cJSON_CreateObject();
touppercase(field);
jaddstr(obj,"base",field);
jaddnum(obj,"balance",*balancep);
itemstr = jprint(obj,1);
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
int32_t bitstamp_supports(char *base,char *rel)
{
if ( strcmp(base,"BTC") == 0 && strcmp(rel,"USD") == 0 )
return(1);
else if ( strcmp(rel,"BTC") == 0 && strcmp(base,"USD") == 0 )
return(-1);
else return(0);
}
double prices777_bitstamp(struct prices777 *prices,int32_t maxdepth)
{
if ( prices->url[0] == 0 )
sprintf(prices->url,"https://www.bitstamp.net/api/order_book/");
return(prices777_standard("bitstamp",prices->url,prices,0,0,maxdepth,0));
}
char *okcoin_parsebalance(struct exchange_info *exchange,double *balancep,char *coinstr)
{
//okcoin.({"info":{"funds":{"asset":{"net":"0","total":"0"},"free":{"btc":"0","ltc":"0","usd":"0"},"freezed":{"btc":"0","ltc":"0","usd":"0"}}},"result":true})
char field[128],*itemstr = 0; cJSON *obj,*item,*avail,*locked; double lockval = 0;
*balancep = 0.;
strcpy(field,coinstr);
tolowercase(field);
if ( exchange->balancejson != 0 && (obj= jobj(exchange->balancejson,"info")) != 0 && (item= jobj(obj,"funds")) != 0 )
{
if ( (avail= jobj(item,"free")) != 0 )
*balancep = jdouble(avail,field);
if ( (locked= jobj(item,"freezed")) != 0 )
lockval = jdouble(locked,field);
obj = cJSON_CreateObject();
touppercase(field);
jaddstr(obj,"base",field);
jaddnum(obj,"balance",*balancep);
jaddnum(obj,"locked",lockval);
itemstr = jprint(obj,1);
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
int32_t okcoin_supports(char *base,char *rel)
{
char *baserels[][2] = { {"btc","usd"}, {"ltc","usd"} };
return(baserel_polarity(baserels,(int32_t)(sizeof(baserels)/sizeof(*baserels)),base,rel));
}
double prices777_okcoin(struct prices777 *prices,int32_t maxdepth)
{
if ( prices->url[0] == 0 )
sprintf(prices->url,"https://www.okcoin.com/api/v1/depth.do?symbol=%s_%s",prices->lbase,prices->lrel);
if ( strcmp(prices->rel,"USD") != 0 && strcmp(prices->rel,"BTC") != 0 )
{
fprintf(stderr,">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FATAL ERROR OKCOIN.(%s) only supports USD\n",prices->url);
printf(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> FATAL ERROR OKCOIN.(%s) only supports USD\n",prices->url);
exit(-1);
return(0);
}
return(prices777_standard("okcoin",prices->url,prices,0,0,maxdepth,0));
}
char *huobi_parsebalance(struct exchange_info *exchange,double *balancep,char *coinstr)
{
char field[128],*itemstr = 0; cJSON *obj,*item;
*balancep = 0.;
strcpy(field,coinstr);
tolowercase(field);
if ( exchange->balancejson != 0 && (obj= jobj(exchange->balancejson,"return")) != 0 && (item= jobj(obj,"funds")) != 0 )
{
*balancep = jdouble(item,field);
obj = cJSON_CreateObject();
touppercase(field);
jaddstr(obj,"base",field);
jaddnum(obj,"balance",*balancep);
itemstr = jprint(obj,1);
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
int32_t huobi_supports(char *base,char *rel)
{
char *baserels[][2] = { {"btc","cny"}, {"ltc","cny"} };
return(baserel_polarity(baserels,(int32_t)(sizeof(baserels)/sizeof(*baserels)),base,rel));
}
double prices777_huobi(struct prices777 *prices,int32_t maxdepth)
{
if ( prices->url[0] == 0 )
sprintf(prices->url,"http://api.huobi.com/staticmarket/depth_%s_json.js ",prices->lbase);
return(prices777_standard("huobi",prices->url,prices,0,0,maxdepth,0));
}
int32_t bityes_supports(char *base,char *rel)
{
char *baserels[][2] = { {"btc","usd"}, {"ltc","usd"} };
return(baserel_polarity(baserels,(int32_t)(sizeof(baserels)/sizeof(*baserels)),base,rel));
}
double prices777_bityes(struct prices777 *prices,int32_t maxdepth)
{
//if ( prices->url[0] == 0 )
sprintf(prices->url,"https://market.bityes.com/%s_%s/depth.js?time=%ld",prices->lrel,prices->lbase,(long)time(NULL));
return(prices777_standard("bityes",prices->url,prices,0,0,maxdepth,0));
}
char *coinbase_parsebalance(struct exchange_info *exchange,double *balancep,char *coinstr)
{
char field[128],*itemstr = 0; cJSON *obj,*item;
*balancep = 0.;
strcpy(field,coinstr);
tolowercase(field);
if ( exchange->balancejson != 0 && (obj= jobj(exchange->balancejson,"return")) != 0 && (item= jobj(obj,"funds")) != 0 )
{
*balancep = jdouble(item,field);
obj = cJSON_CreateObject();
touppercase(field);
jaddstr(obj,"base",field);
jaddnum(obj,"balance",*balancep);
itemstr = jprint(obj,1);
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
int32_t coinbase_supports(char *base,char *rel)
{
if ( strcmp(base,"BTC") == 0 && strcmp(rel,"USD") == 0 )
return(1);
else if ( strcmp(rel,"BTC") == 0 && strcmp(base,"USD") == 0 )
return(-1);
else return(0);
}
double prices777_coinbase(struct prices777 *prices,int32_t maxdepth)
{
if ( prices->url[0] == 0 )
sprintf(prices->url,"https://api.exchange.coinbase.com/products/%s-%s/book?level=2",prices->base,prices->rel);
return(prices777_standard("coinbase",prices->url,prices,0,0,maxdepth,0));
}
char *lakebtc_parsebalance(struct exchange_info *exchange,double *balancep,char *coinstr)
{
//lakebtc.({"balance":{"BTC":0.1},"locked":{"BTC":0.0},"profile":{"email":"jameslee777@yahoo.com","id":"U137561934","btc_deposit_addres":"1RyKrNJjezeFfvYaicnJEozHfhWfYzbuh"}})
char field[128],*str,*itemstr = 0; cJSON *obj=0,*item=0,*prof=0; double locked = 0;
*balancep = 0.;
strcpy(field,coinstr);
touppercase(field);
if ( exchange->balancejson != 0 && (obj= jobj(exchange->balancejson,"balance")) != 0 && (item= jobj(exchange->balancejson,"locked")) != 0 && (prof= jobj(exchange->balancejson,"profile")) != 0 )
{
*balancep = jdouble(obj,field);
locked = jdouble(item,field);
obj = cJSON_CreateObject();
jaddstr(obj,"base",field);
jaddnum(obj,"balance",*balancep);
jaddnum(obj,"locked",locked);
if ( (str= jstr(prof,"btc_deposit_addres")) != 0 )
jaddstr(obj,"deposit_address",str);
itemstr = jprint(obj,1);
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
int32_t lakebtc_supports(char *base,char *rel)
{
char *baserels[][2] = { {"btc","usd"}, {"btc","cny"} };
return(baserel_polarity(baserels,(int32_t)(sizeof(baserels)/sizeof(*baserels)),base,rel));
}
double prices777_lakebtc(struct prices777 *prices,int32_t maxdepth)
{
if ( prices->url[0] == 0 )
{
if ( strcmp(prices->rel,"USD") == 0 )
sprintf(prices->url,"https://www.LakeBTC.com/api_v1/bcorderbook");
else if ( strcmp(prices->rel,"CNY") == 0 )
sprintf(prices->url,"https://www.LakeBTC.com/api_v1/bcorderbook_cny");
else printf("illegal lakebtc pair.(%s/%s)\n",prices->base,prices->rel);
}
return(prices777_standard("lakebtc",prices->url,prices,0,0,maxdepth,0));
}
#ifdef exmo_supported
int32_t exmo_supports(char *base,char *rel)
{
if ( strcmp(base,"BTC") == 0 && (strcmp(rel,"USD") == 0 || strcmp(rel,"EUR") == 0 || strcmp(rel,"RUR") == 0) )
return(1);
else if ( strcmp(rel,"BTC") == 0 && (strcmp(base,"USD") == 0 || strcmp(base,"EUR") == 0 || strcmp(base,"RUR") == 0) )
return(-1);
else return(0);
}
double prices777_exmo(struct prices777 *prices,int32_t maxdepth)
{
if ( prices->url[0] == 0 )
sprintf(prices->url,"https://api.exmo.com/api_v2/orders_book?pair=%s_%s",prices->base,prices->rel);
return(prices777_standard("exmo",prices->url,prices,0,0,maxdepth,0));
}
#endif
// "gatecoin", "quoine", "jubi", "hitbtc"
char *btc38_parsebalance(struct exchange_info *exchange,double *balancep,char *coinstr)
{
char field[128],*str,*itemstr = 0; cJSON *obj; double lockbalance,imma;
*balancep = 0.;
strcpy(field,coinstr);
tolowercase(field);
strcat(field,"_balance");
if ( exchange->balancejson != 0 && (str= jstr(exchange->balancejson,field)) != 0 )
{
*balancep = jdouble(exchange->balancejson,field);
strcpy(field,coinstr), tolowercase(field), strcat(field,"_balance_lock");
lockbalance = jdouble(exchange->balancejson,field);
strcpy(field,coinstr), tolowercase(field), strcat(field,"_balance_imma");
imma = jdouble(exchange->balancejson,field);
obj = cJSON_CreateObject();
jaddnum(obj,"balance",*balancep);
jaddnum(obj,"locked_balance",lockbalance);
jaddnum(obj,"imma_balance",imma);
itemstr = jprint(obj,1);
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
int32_t btc38_supports(char *_base,char *_rel)
{
char *cnypairs[] = { "BTC", "LTC", "DOGE", "XRP", "BTS", "STR", "NXT", "BLK", "YBC", "BILS", "BOST", "PPC", "APC", "ZCC", "XPM", "DGC", "MEC", "WDC", "QRK", "BEC", "ANC", "UNC", "RIC", "SRC", "TAG" };
char *btcpairs[] = { "TMC", "LTC", "DOGE", "XRP", "BTS", "STR", "NXT", "BLK", "XEM", "VPN", "BILS", "BOST", "WDC", "ANC", "XCN", "VOOT", "SYS", "NRS", "NAS", "SYNC", "MED", "EAC" };
int32_t i; char base[64],rel[64];
strcpy(base,_base), strcpy(rel,_rel);
touppercase(base), touppercase(rel);
if ( strlen(base) > 5 || strlen(rel) > 5 )
return(0);
if ( strcmp(base,"BTC") == 0 && strcmp(rel,"CNY") == 0 )
return(1);
else if ( strcmp(base,"CNY") == 0 && strcmp(rel,"BTC") == 0 )
return(-1);
else if ( strcmp(base,"BTC") == 0 )
{
for (i=0; i<sizeof(btcpairs)/sizeof(*btcpairs); i++)
if ( strcmp(btcpairs[i],rel) == 0 )
return(-1);
}
else if ( strcmp(rel,"BTC") == 0 )
{
for (i=0; i<sizeof(btcpairs)/sizeof(*btcpairs); i++)
if ( strcmp(btcpairs[i],base) == 0 )
return(1);
}
else if ( strcmp(base,"CNY") == 0 )
{
for (i=0; i<sizeof(cnypairs)/sizeof(*cnypairs); i++)
if ( strcmp(cnypairs[i],rel) == 0 )
return(-1);
}
else if ( strcmp(rel,"CNY") == 0 )
{
for (i=0; i<sizeof(cnypairs)/sizeof(*cnypairs); i++)
if ( strcmp(cnypairs[i],base) == 0 )
return(1);
}
printf("BTC38 doesnt support (%s/%s)\n",base,rel);
return(0);
}
double prices777_btc38(struct prices777 *prices,int32_t maxdepth)
{
if ( prices->url[0] == 0 )
{
if ( strcmp(prices->lbase,"cny") == 0 && strcmp(prices->lrel,"btc") == 0 )
sprintf(prices->url,"http://api.btc38.com/v1/depth.php?c=%s&mk_type=%s","btc","cny");
else sprintf(prices->url,"http://api.btc38.com/v1/depth.php?c=%s&mk_type=%s",prices->lbase,prices->lrel);
}
return(prices777_standard("btc38",prices->url,prices,0,0,maxdepth,0));
}
char *quadriga_parsebalance(struct exchange_info *exchange,double *balancep,char *coinstr)
{
//[{"btc_available":"0.00000000","btc_reserved":"0.00000000","btc_balance":"0.00000000","cad_available":"0.00","cad_reserved":"0.00","cad_balance":"0.00","usd_available":"0.00","usd_reserved":"0.00","usd_balance":"0.00","xau_available":"0.000000","xau_reserved":"0.000000","xau_balance":"0.000000","fee":"0.5000"}]
char field[128],*str,*itemstr = 0; cJSON *obj; double reserv,total;
*balancep = 0.;
strcpy(field,coinstr);
tolowercase(field);
strcat(field,"_available");
if ( exchange->balancejson != 0 && (str= jstr(exchange->balancejson,field)) != 0 )
{
*balancep = jdouble(exchange->balancejson,field);
strcpy(field,coinstr), tolowercase(field), strcat(field,"_reserved");
reserv = jdouble(exchange->balancejson,field);
strcpy(field,coinstr), tolowercase(field), strcat(field,"_balance");
total = jdouble(exchange->balancejson,field);
obj = cJSON_CreateObject();
jaddnum(obj,"balance",*balancep);
jaddnum(obj,"locked_balance",reserv);
jaddnum(obj,"total",total);
itemstr = jprint(obj,1);
}
if ( itemstr == 0 )
return(clonestr("{\"error\":\"cant find coin balance\"}"));
return(itemstr);
}
int32_t quadriga_supports(char *base,char *rel)
{
char *baserels[][2] = { {"btc","usd"}, {"btc","cad"} };
return(baserel_polarity(baserels,(int32_t)(sizeof(baserels)/sizeof(*baserels)),base,rel));
}
double prices777_quadriga(struct prices777 *prices,int32_t maxdepth)
{
if ( prices->url[0] == 0 )
sprintf(prices->url,"https://api.quadrigacx.com/v2/order_book?book=%s_%s",prices->lbase,prices->lrel);
return(prices777_standard("quadriga",prices->url,prices,0,0,maxdepth,0));
}
/*void prices777_kraken(struct prices777 *prices,int32_t maxdepth)
{
if ( prices->url[0] == 0 )
sprintf(prices->url,"https://api.kraken.com/0/public/Depth"); // need POST
prices777_standard("kraken",prices->url,prices,0,0,maxdepth);
}*/
/*void prices777_itbit(struct prices777 *prices,int32_t maxdepth)
{
if ( prices->url[0] == 0 )
sprintf(prices->url,"https://www.itbit.com/%s%s",prices->base,prices->rel);
prices777_standard("itbit",prices->url,prices,0,0,maxdepth);
}*/
#endif
uint64_t prices777_truefx(uint64_t *millistamps,double *bids,double *asks,double *opens,double *highs,double *lows,char *username,char *password,uint64_t idnum)
{
char *truefxfmt = "http://webrates.truefx.com/rates/connect.html?f=csv&id=jl777:truefxtest:poll:1437671654417&c=EUR/USD,USD/JPY,GBP/USD,EUR/GBP,USD/CHF,AUD/NZD,CAD/CHF,CHF/JPY,EUR/AUD,EUR/CAD,EUR/JPY,EUR/CHF,USD/CAD,AUD/USD,GBP/JPY,AUD/CAD,AUD/CHF,AUD/JPY,EUR/NOK,EUR/NZD,GBP/CAD,GBP/CHF,NZD/JPY,NZD/USD,USD/NOK,USD/SEK";
// EUR/USD,1437569931314,1.09,034,1.09,038,1.08922,1.09673,1.09384 USD/JPY,1437569932078,123.,778,123.,781,123.569,123.903,123.860 GBP/USD,1437569929008,1.56,332,1.56,337,1.55458,1.56482,1.55538 EUR/GBP,1437569931291,0.69,742,0.69,750,0.69710,0.70383,0.70338 USD/CHF,1437569932237,0.96,142,0.96,153,0.95608,0.96234,0.95748 EUR/JPY,1437569932237,134.,960,134.,972,134.842,135.640,135.476 EUR/CHF,1437569930233,1.04,827,1.04,839,1.04698,1.04945,1.04843 USD/CAD,1437569929721,1.30,231,1.30,241,1.29367,1.30340,1.29466 AUD/USD,1437569931700,0.73,884,0.73,890,0.73721,0.74395,0.74200 GBP/JPY,1437569931924,193.,500,193.,520,192.298,193.670,192.649
char url[1024],userpass[1024],buf[128],base[64],rel[64],*str; cJSON *array; int32_t jpyflag,i,c,n = 0; double pre,pre2,bid,ask,open,high,low; long millistamp;
//printf("truefx.(%s)(%s).%llu\n",username,password,(long long)idnum);
url[0] = 0;
if ( username[0] != 0 && password[0] != 0 )
{
if ( idnum == 0 )
{
sprintf(userpass,"http://webrates.truefx.com/rates/connect.html?f=csv&s=y&u=%s&p=%s&q=poll",username,password);
if ( (str= issue_curl(userpass)) != 0 )
{
_stripwhite(str,0);
printf("(%s) -> (%s)\n",userpass,str);
sprintf(userpass,"%s:%s:poll:",username,password);
idnum = calc_nxt64bits(str + strlen(userpass));
free(str);
printf("idnum.%llu\n",(long long)idnum);
}
}
if ( idnum != 0 )
sprintf(url,truefxfmt,username,password,(long long)idnum);
}
if ( url[0] == 0 )
sprintf(url,"http://webrates.truefx.com/rates/connect.html?f=csv&s=y");
if ( (str= issue_curl(url)) != 0 )
{
//printf("(%s) -> (%s)\n",url,str);
while ( str[n + 0] != 0 && str[n] != '\n' && str[n] != '\r' )
{
for (i=jpyflag=0; str[n + i]!=' '&&str[n + i]!='\n'&&str[n + i]!='\r'&&str[n + i]!=0; i++)
{
if ( i > 0 && str[n+i] == ',' && str[n+i-1] == '.' )
str[n+i-1] = ' ', jpyflag = 1;
else if ( i > 0 && str[n+i-1] == ',' && str[n+i] == '0' && str[n+i+1+2] == ',' )
{
str[n+i] = ' ';
if ( str[n+i+1] == '0' )
str[n+i+1] = ' ', i++;
}
}
memcpy(base,str+n,3), base[3] = 0;
memcpy(rel,str+n+4,3), rel[3] = 0;
str[n + i] = 0;
//printf("str.(%s) (%s/%s) %d n.%d i.%d\n",str+n,base,rel,str[n],n,i);
sprintf(buf,"[%s]",str+n+7+1);
n += i + 1;
if ( (array= cJSON_Parse(buf)) != 0 )
{
if ( is_cJSON_Array(array) != 0 )
{
millistamp = (uint64_t)get_API_float(jitem(array,0));
pre = get_API_float(jitem(array,1));
bid = get_API_float(jitem(array,2));
pre2 = get_API_float(jitem(array,3));
ask = get_API_float(jitem(array,4));
open = get_API_float(jitem(array,5));
high = get_API_float(jitem(array,6));
low = get_API_float(jitem(array,7));
if ( jpyflag != 0 )
bid = pre + (bid / 1000.), ask = pre2 + (ask / 1000.);
else bid = pre + (bid / 100000.), ask = pre2 + (ask / 100000.);
if ( (c= prices777_contractnum(base,rel)) >= 0 )
{
char name[64];
strcpy(name,base), strcat(name,rel);
if ( BUNDLE.truefx[c] == 0 )
BUNDLE.truefx[c] = prices777_initpair(0,"truefx",base,rel,0,name,stringbits(base),stringbits(rel),0);
millistamps[c] = millistamp,opens[c] = open, highs[c] = high, lows[c] = low, bids[c] = bid, asks[c] = ask;
if ( Debuglevel > 2 )
{
if ( jpyflag != 0 )
printf("%s%s.%-2d %llu: %.3f %.3f %.3f | %.3f %.3f\n",base,rel,c,(long long)millistamp,open,high,low,bid,ask);
else printf("%s%s.%-2d %llu: %.5f %.5f %.5f | %.5f %.5f\n",base,rel,c,(long long)millistamp,open,high,low,bid,ask);
}
} else printf("unknown basepair.(%s) (%s)\n",base,rel);
}
free_json(array);
} else printf("cant parse.(%s)\n",buf);
}
free(str);
}
return(idnum);
}
double prices777_fxcm(double lhlogmatrix[8][8],double logmatrix[8][8],double bids[64],double asks[64],double highs[64],double lows[64])
{
char name[64],*xmlstr,*str; cJSON *json,*obj; int32_t i,j,c,flag,k,n = 0; double bid,ask,high,low; struct destbuf numstr;
memset(bids,0,sizeof(*bids) * NUM_CONTRACTS), memset(asks,0,sizeof(*asks) * NUM_CONTRACTS);
if ( (xmlstr= issue_curl("http://rates.fxcm.com/RatesXML")) != 0 )
{
_stripwhite(xmlstr,0);
//printf("(%s)\n",xmlstr);
i = 0;
if ( strncmp("<?xml",xmlstr,5) == 0 )
for (; xmlstr[i]!='>'&&xmlstr[i]!=0; i++)
;
if ( xmlstr[i] == '>' )
i++;
for (j=0; xmlstr[i]!=0; i++)
{
if ( strncmp("<Rates>",&xmlstr[i],strlen("<Rates>")) == 0 )
xmlstr[j++] = '[', i += strlen("<Rates>")-1;
else if ( strncmp("<RateSymbol=",&xmlstr[i],strlen("<RateSymbol=")) == 0 )
{
if ( j > 1 )
xmlstr[j++] = ',';
memcpy(&xmlstr[j],"{\"Symbol\":",strlen("{\"Symbol\":")), i += strlen("<RateSymbol=")-1, j += strlen("{\"Symbol\":");
}
else
{
char *strpairs[][2] = { { "<Bid>", "\"Bid\":" }, { "<Ask>", "\"Ask\":" }, { "<High>", "\"High\":" }, { "<Low>", "\"Low\":" }, { "<Direction>", "\"Direction\":" }, { "<Last>", "\"Last\":\"" } };
for (k=0; k<sizeof(strpairs)/sizeof(*strpairs); k++)
if ( strncmp(strpairs[k][0],&xmlstr[i],strlen(strpairs[k][0])) == 0 )
{
memcpy(&xmlstr[j],strpairs[k][1],strlen(strpairs[k][1]));
i += strlen(strpairs[k][0])-1;
j += strlen(strpairs[k][1]);
break;
}
if ( k == sizeof(strpairs)/sizeof(*strpairs) )
{
char *ends[] = { "</Bid>", "</Ask>", "</High>", "</Low>", "</Direction>", "</Last>", "</Rate>", "</Rates>", ">" };
for (k=0; k<sizeof(ends)/sizeof(*ends); k++)
if ( strncmp(ends[k],&xmlstr[i],strlen(ends[k])) == 0 )
{
i += strlen(ends[k])-1;
if ( strcmp("</Rate>",ends[k]) == 0 )
xmlstr[j++] = '}';
else if ( strcmp("</Rates>",ends[k]) == 0 )
xmlstr[j++] = ']';
else if ( strcmp("</Last>",ends[k]) == 0 )
xmlstr[j++] = '\"';
else xmlstr[j++] = ',';
break;
}
if ( k == sizeof(ends)/sizeof(*ends) )
xmlstr[j++] = xmlstr[i];
}
}
}
xmlstr[j] = 0;
if ( (json= cJSON_Parse(xmlstr)) != 0 )
{
/*<Rate Symbol="USDJPY">
<Bid>123.763</Bid>
<Ask>123.786</Ask>
<High>123.956</High>
<Low>123.562</Low>
<Direction>-1</Direction>
<Last>08:49:15</Last>*/
//printf("Parsed stupid XML! (%s)\n",xmlstr);
if ( is_cJSON_Array(json) != 0 && (n= cJSON_GetArraySize(json)) != 0 )
{
for (i=0; i<n; i++)
{
obj = jitem(json,i);
flag = 0;
c = -1;
if ( (str= jstr(obj,"Symbol")) != 0 && strlen(str) < 15 )
{
strcpy(name,str);
if ( strcmp(name,"USDCNH") == 0 )
strcpy(name,"USDCNY");
copy_cJSON(&numstr,jobj(obj,"Bid")), bid = atof(numstr.buf);
copy_cJSON(&numstr,jobj(obj,"Ask")), ask = atof(numstr.buf);
copy_cJSON(&numstr,jobj(obj,"High")), high = atof(numstr.buf);
copy_cJSON(&numstr,jobj(obj,"Low")), low = atof(numstr.buf);
if ( (c= prices777_contractnum(name,0)) >= 0 )
{
bids[c] = bid, asks[c] = ask, highs[c] = high, lows[c] = low;
//printf("c.%d (%s) %f %f\n",c,name,bid,ask);
flag = 1;
if ( BUNDLE.fxcm[c] == 0 )
{
//printf("max.%ld FXCM: not initialized.(%s) %d\n",sizeof(CONTRACTS)/sizeof(*CONTRACTS),name,c);
BUNDLE.fxcm[c] = prices777_initpair(0,"fxcm",name,0,0,name,peggy_basebits(name),peggy_relbits(name),0);
}
} else printf("cant find.%s\n",name);//, getchar();
}
if ( flag == 0 )
printf("FXCM: Error finding.(%s) c.%d (%s)\n",name,c,cJSON_Print(obj));
}
}
free_json(json);
} else printf("couldnt parse.(%s)\n",xmlstr);
free(xmlstr);
}
calc_primary_currencies(lhlogmatrix,lows,highs);
return(calc_primary_currencies(logmatrix,bids,asks));
}
double prices777_instaforex(double logmatrix[8][8],uint32_t timestamps[NUM_COMBINED+1],double bids[128],double asks[128])
{
//{"NZDUSD":{"symbol":"NZDUSD","lasttime":1437580206,"digits":4,"change":"-0.0001","bid":"0.6590","ask":"0.6593"},
char *jsonstr,*str; cJSON *json,*item; int32_t i,c; struct destbuf numstr;
memset(timestamps,0,sizeof(*timestamps) * (NUM_COMBINED + 1)), memset(bids,0,sizeof(*bids) * (NUM_COMBINED + 1)), memset(asks,0,sizeof(*asks) * (NUM_COMBINED + 1));
if ( (jsonstr= issue_curl("https://quotes.instaforex.com/get_quotes.php?q=NZDUSD,NZDCHF,NZDCAD,NZDJPY,GBPNZD,EURNZD,AUDNZD,CADJPY,CADCHF,USDCAD,EURCAD,GBPCAD,AUDCAD,USDCHF,CHFJPY,EURCHF,GBPCHF,AUDCHF,EURUSD,EURAUD,EURJPY,EURGBP,GBPUSD,GBPJPY,GBPAUD,USDJPY,AUDJPY,AUDUSD,XAUUSD&m=json")) != 0 )
{
// printf("(%s)\n",jsonstr);
if ( (json= cJSON_Parse(jsonstr)) != 0 )
{
for (i=0; i<=NUM_CONTRACTS; i++)
{
if ( i < NUM_CONTRACTS )
str = CONTRACTS[i], c = i;
else str = "XAUUSD", c = prices777_contractnum(str,0);
if ( (item= jobj(json,str)) != 0 )
{
timestamps[c] = juint(item,"lasttime");
copy_cJSON(&numstr,jobj(item,"bid")), bids[c] = atof(numstr.buf);
copy_cJSON(&numstr,jobj(item,"ask")), asks[c] = atof(numstr.buf);
//if ( c < NUM_CONTRACTS && Contract_rel[c] == JPY )
// bids[i] /= 100., asks[i] /= 100.;
if ( Debuglevel > 2 )
printf("%s.(%.6f %.6f) ",str,bids[c],asks[c]);
if ( BUNDLE.instaforex[c] == 0 )
BUNDLE.instaforex[c] = prices777_initpair(0,"instaforex",str,0,0,str,peggy_basebits(str),peggy_relbits(str),0);
}
}
free_json(json);
}
free(jsonstr);
}
return(calc_primary_currencies(logmatrix,bids,asks));
}
int32_t prices777_ecbparse(char *date,double *prices,char *url,int32_t basenum)
{
char *jsonstr,*relstr,*basestr; int32_t count=0,i,relnum; cJSON *json,*ratesobj,*item; struct destbuf tmp;
if ( (jsonstr= issue_curl(url)) != 0 )
{
if ( Debuglevel > 2 )
printf("(%s)\n",jsonstr);
if ( (json= cJSON_Parse(jsonstr)) != 0 )
{
copy_cJSON(&tmp,jobj(json,"date")), safecopy(date,tmp.buf,64);
if ( (basestr= jstr(json,"base")) != 0 && strcmp(basestr,CURRENCIES[basenum]) == 0 && (ratesobj= jobj(json,"rates")) != 0 && (item= ratesobj->child) != 0 )
{
while ( item != 0 )
{
if ( (relstr= get_cJSON_fieldname(item)) != 0 && (relnum= prices777_basenum(relstr)) >= 0 )
{
i = basenum*MAX_CURRENCIES + relnum;
prices[i] = item->valuedouble;
//if ( basenum == JPYNUM )
// prices[i] *= 100.;
// else if ( relnum == JPYNUM )
// prices[i] /= 100.;
count++;
if ( Debuglevel > 2 )
printf("(%02d:%02d %f) ",basenum,relnum,prices[i]);
} else printf("cant find.(%s)\n",relstr);//, getchar();
item = item->next;
}
}
free_json(json);
}
free(jsonstr);
}
return(count);
}
int32_t prices777_ecb(char *date,double *prices,int32_t year,int32_t month,int32_t day)
{
// http://api.fixer.io/latest?base=CNH
// http://api.fixer.io/2000-01-03?base=USD
// "USD", "EUR", "JPY", "GBP", "AUD", "CAD", "CHF", "NZD"
char baseurl[512],tmpdate[64],url[512],checkdate[16]; int32_t basenum,count,i,iter,nonz;
checkdate[0] = 0;
if ( year == 0 )
strcpy(baseurl,"http://api.fixer.io/latest?base=");
else
{
sprintf(checkdate,"%d-%02d-%02d",year,month,day);
sprintf(baseurl,"http://api.fixer.io/%s?base=",checkdate);
}
count = 0;
for (iter=0; iter<2; iter++)
{
for (basenum=0; basenum<sizeof(CURRENCIES)/sizeof(*CURRENCIES); basenum++)
{
if ( strcmp(CURRENCIES[basenum],"XAU") == 0 )
break;
if ( iter == 0 )
{
sprintf(url,"%s%s",baseurl,CURRENCIES[basenum]);
count += prices777_ecbparse(basenum == 0 ? date : tmpdate,prices,url,basenum);
if ( (basenum != 0 && strcmp(tmpdate,date) != 0) || (checkdate[0] != 0 && strcmp(checkdate,date) != 0) )
{
printf("date mismatch (%s) != (%s) or checkdate.(%s)\n",tmpdate,date,checkdate);
return(-1);
}
}
else
{
for (nonz=i=0; i<sizeof(CURRENCIES)/sizeof(*CURRENCIES); i++)
{
if ( strcmp(CURRENCIES[i],"XAU") == 0 )
break;
if ( prices[MAX_CURRENCIES*basenum + i] != 0. )
nonz++;
if ( Debuglevel > 2 )
printf("%8.5f ",prices[MAX_CURRENCIES*basenum + i]);
}
if ( Debuglevel > 2 )
printf("%s.%d %d\n",CURRENCIES[basenum],basenum,nonz);
}
}
}
return(count);
}
#endif