/******************************************************************************
* 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_orderbooks_h
# define xcode_orderbooks_h
char * peggy_contracts [ 64 ] =
{
" BTCD " , " USD " , " EUR " , " JPY " , " GBP " , " AUD " , " CAD " , " CHF " , " NZD " , // major currencies
" CNY " , " RUB " , " MXN " , " BRL " , " INR " , " HKD " , " TRY " , " ZAR " , " PLN " , " NOK " , " SEK " , " DKK " , " CZK " , " HUF " , " ILS " , " KRW " , " MYR " , " PHP " , " RON " , " SGD " , " THB " , " BGN " , " IDR " , " HRK " ,
" BTCUSD " , " NXTBTC " , " SuperNET " , " ETHBTC " , " LTCBTC " , " XMRBTC " , " BTSBTC " , " XCPBTC " , // BTC priced
" XAUUSD " , " XAGUSD " , " XPTUSD " , " XPDUSD " , " Copper " , " NGAS " , " UKOil " , " USOil " , // USD priced
" Bund " , " NAS100 " , " SPX500 " , " US30 " , " EUSTX50 " , " UK100 " , " JPN225 " , " GER30 " , " SUI30 " , " AUS200 " , " HKG33 " , " XAUUSD " , " BTCRUB " , " BTCCNY " , " BTCUSD " // abstract
} ;
char * MGWassets [ ] [ 3 ] =
{
{ " 12659653638116877017 " , " BTC " , " 8 " } ,
{ " 17554243582654188572 " , " BTC " , " 8 " } , // assetid, name, decimals
{ " 4551058913252105307 " , " BTC " , " 8 " } ,
{ " 6918149200730574743 " , " BTCD " , " 4 " } ,
{ " 11060861818140490423 " , " BTCD " , " 4 " } ,
{ " 13120372057981370228 " , " BITS " , " 6 " } ,
{ " 16344939950195952527 " , " DOGE " , " 4 " } ,
{ " 2303962892272487643 " , " DOGE " , " 4 " } ,
{ " 6775076774325697454 " , " OPAL " , " 8 " } ,
{ " 7734432159113182240 " , " VPN " , " 4 " } ,
{ " 9037144112883608562 " , " VRC " , " 8 " } ,
{ " 1369181773544917037 " , " BBR " , " 8 " } ,
{ " 17353118525598940144 " , " DRK " , " 8 " } ,
{ " 2881764795164526882 " , " LTC " , " 4 " } ,
{ " 7117580438310874759 " , " BC " , " 4 " } ,
{ " 275548135983837356 " , " VIA " , " 4 " } ,
{ " 6220108297598959542 " , " CNMT " , " 0 " } ,
{ " 7474435909229872610 " , " CNMT " , " 0 " } ,
} ;
char * Tradedassets [ ] [ 4 ] =
{
{ " 6220108297598959542 " , " CNMT " , " 0 " , " poloniex " } ,
{ " 7474435909229872610 " , " CNMT " , " 0 " , " poloniex " } ,
{ " 979292558519844732 " , " MMNXT " , " 0 " , " poloniex " } ,
{ " 12982485703607823902 " , " XUSD " , " 0 " , " poloniex " } ,
{ " 13634675574519917918 " , " INDEX " , " 0 " , " poloniex " } ,
{ " 6932037131189568014 " , " JLH " , " 0 " , " poloniex " } ,
{ " 14273984620270850703 " , " NXTI " , " 0 " , " poloniex " } ,
{ " 12071612744977229797 " , " UNITY " , " 4 " , " poloniex " } ,
} ;
char * is_tradedasset ( char * exchange , char * assetidstr )
{
int32_t i ;
for ( i = 0 ; i < ( int32_t ) ( sizeof ( Tradedassets ) / sizeof ( * Tradedassets ) ) ; i + + )
if ( strcmp ( Tradedassets [ i ] [ 0 ] , assetidstr ) = = 0 )
{
strcpy ( exchange , Tradedassets [ i ] [ 3 ] ) ;
return ( Tradedassets [ i ] [ 1 ] ) ;
}
return ( 0 ) ;
}
uint64_t is_MGWcoin ( char * name )
{
int32_t i ;
for ( i = 0 ; i < ( int32_t ) ( sizeof ( MGWassets ) / sizeof ( * MGWassets ) ) ; i + + )
if ( strcmp ( MGWassets [ i ] [ 1 ] , name ) = = 0 )
return ( calc_nxt64bits ( MGWassets [ i ] [ 0 ] ) ) ;
return ( 0 ) ;
}
char * is_MGWasset ( uint64_t assetid )
{
int32_t i ; char assetidstr [ 64 ] ;
expand_nxt64bits ( assetidstr , assetid ) ;
for ( i = 0 ; i < ( int32_t ) ( sizeof ( MGWassets ) / sizeof ( * MGWassets ) ) ; i + + )
if ( strcmp ( MGWassets [ i ] [ 0 ] , assetidstr ) = = 0 )
return ( MGWassets [ i ] [ 1 ] ) ;
return ( 0 ) ;
}
uint64_t prices777_equiv ( uint64_t assetid )
{
char * str ;
if ( ( str = is_MGWasset ( assetid ) ) ! = 0 )
return ( stringbits ( str ) ) ;
return ( assetid ) ;
}
struct prices777 * prices777_find ( int32_t * invertedp , uint64_t baseid , uint64_t relid , char * exchange )
{
int32_t i ; struct prices777 * prices ;
* invertedp = 0 ;
for ( i = 0 ; i < BUNDLE . num ; i + + )
{
if ( ( prices = BUNDLE . ptrs [ i ] ) ! = 0 & & strcmp ( prices - > exchange , exchange ) = = 0 )
{
//printf("FOUND.(%s)\n",exchange);
if ( prices777_equiv ( prices - > baseid ) = = prices777_equiv ( baseid ) & & prices777_equiv ( prices - > relid ) = = prices777_equiv ( relid ) )
return ( prices ) ;
else if ( prices777_equiv ( prices - > relid ) = = prices777_equiv ( baseid ) & & prices777_equiv ( prices - > baseid ) = = prices777_equiv ( relid ) )
{
* invertedp = 1 ;
return ( prices ) ;
}
//else printf("(%llu/%llu) != (%llu/%llu)\n",(long long)baseid,(long long)relid,(long long)prices->baseid,(long long)prices->relid);
} //else fprintf(stderr,"(%s).%d ",prices->exchange,i);
}
//printf("CANTFIND.(%s) %llu/%llu\n",exchange,(long long)baseid,(long long)relid);
return ( 0 ) ;
}
struct prices777 * prices777_createbasket ( int32_t addbasket , char * name , char * base , char * rel , uint64_t baseid , uint64_t relid , struct prices777_basket * basket , int32_t n , char * typestr )
{
int32_t i , j , m , iter , max = 0 ; double firstwt , wtsum ; struct prices777 * prices , * feature ;
printf ( " createbasket.%s n.%d (%s/%s) \n " , typestr , n , base , rel ) ;
prices = prices777_initpair ( 1 , typestr , base , rel , 0. , name , baseid , relid , n ) ;
for ( iter = 0 ; iter < 2 ; iter + + )
{
for ( i = 0 ; i < n ; i + + )
{
feature = basket [ i ] . prices ;
if ( addbasket * iter ! = 0 )
{
feature - > dependents = realloc ( feature - > dependents , sizeof ( * feature - > dependents ) * ( feature - > numdependents + 1 ) ) ;
feature - > dependents [ feature - > numdependents + + ] = & prices - > changed ;
printf ( " %p i.%d/%d addlink.%s groupid.%d wt.%f (%s.%llu/%llu -> %s.%llu/%llu).%s \n " , feature , i , n , feature - > exchange , basket [ i ] . groupid , basket [ i ] . wt , feature - > contract , ( long long ) feature - > baseid , ( long long ) feature - > relid , prices - > contract , ( long long ) prices - > baseid , ( long long ) prices - > relid , prices - > exchange ) ;
}
if ( basket [ i ] . groupid > max )
max = basket [ i ] . groupid ;
if ( fabs ( basket [ i ] . wt ) < SMALLVAL )
{
printf ( " all basket features.%s i.%d must have nonzero wt \n " , feature - > contract , i ) ;
free ( prices ) ;
return ( 0 ) ;
}
if ( strcmp ( feature - > base , feature - > rel ) = = 0 | | feature - > baseid = = feature - > relid )
{
printf ( " base rel cant be the same (%s %s) %llu %llu \n " , feature - > base , feature - > rel , ( long long ) feature - > baseid , ( long long ) feature - > relid ) ;
free ( prices ) ;
return ( 0 ) ;
}
}
if ( ( max + 1 ) > MAX_GROUPS )
{
printf ( " baskets limited to %d, %d is too many for %s.(%s/%s) \n " , MAX_GROUPS , n , name , base , rel ) ;
return ( 0 ) ;
}
}
prices - > numgroups = ( max + 1 ) ;
for ( j = 0 ; j < prices - > numgroups ; j + + )
{
for ( firstwt = i = m = 0 ; i < n ; i + + )
{
//printf("i.%d groupid.%d wt %f m.%d\n",i,basket[i].groupid,basket[i].wt,m);
if ( basket [ i ] . groupid = = j )
{
if ( firstwt = = 0. )
prices - > groupwts [ j ] = firstwt = basket [ i ] . wt ;
else if ( basket [ i ] . wt ! = firstwt )
{
printf ( " warning features of same group.%d different wt: %d %f != %f \n " , j , i , firstwt , basket [ i ] . wt ) ;
// free(prices);
// return(0);
}
m + + ;
}
}
//printf("m.%d\n",m);
for ( i = 0 ; i < n ; i + + )
if ( basket [ i ] . groupid = = j )
basket [ i ] . groupsize = m , printf ( " basketsize.%d n.%d j.%d groupsize[%d] <- m.%d \n " , prices - > basketsize , n , j , i , m ) ;
}
for ( j = 0 ; j < prices - > numgroups ; j + + )
for ( i = 0 ; i < n ; i + + )
if ( basket [ i ] . groupid = = j )
prices - > basket [ prices - > basketsize + + ] = basket [ i ] ;
for ( i = - 1 ; i < = 1 ; i + = 2 )
{
for ( wtsum = j = m = 0 ; j < prices - > numgroups ; j + + )
{
if ( prices - > groupwts [ j ] * i > 0 )
wtsum + = prices - > groupwts [ j ] , m + + ;
}
if ( 0 & & wtsum ! = 0. )
{
if ( wtsum < 0. )
wtsum = - wtsum ;
for ( j = 0 ; j < prices - > numgroups ; j + + )
prices - > groupwts [ j ] / = wtsum ;
}
}
if ( prices - > numgroups = = 1 )
prices - > groupwts [ 0 ] = 1. ;
for ( j = 0 ; j < prices - > numgroups ; j + + )
printf ( " %9.6f " , prices - > groupwts [ j ] ) ;
printf ( " groupwts %s \n " , typestr ) ;
return ( prices ) ;
}
double prices777_price_volume ( double * volumep , uint64_t baseamount , uint64_t relamount )
{
* volumep = ( ( ( double ) baseamount + 0.000000009999999 ) / SATOSHIDEN ) ;
if ( baseamount > 0. )
return ( ( double ) relamount / ( double ) baseamount ) ;
else return ( 0. ) ;
}
void prices777_best_amounts ( uint64_t * baseamountp , uint64_t * relamountp , double price , double volume )
{
double checkprice , checkvol , distA , distB , metric , bestmetric = ( 1. / SMALLVAL ) ;
uint64_t baseamount , relamount , bestbaseamount = 0 , bestrelamount = 0 ;
int32_t i , j ;
baseamount = volume * SATOSHIDEN ;
relamount = ( ( price * volume ) * SATOSHIDEN ) ;
//*baseamountp = baseamount, *relamountp = relamount;
//return;
for ( i = - 1 ; i < = 1 ; i + + )
for ( j = - 1 ; j < = 1 ; j + + )
{
checkprice = prices777_price_volume ( & checkvol , baseamount + i , relamount + j ) ;
distA = ( checkprice - price ) ;
distA * = distA ;
distB = ( checkvol - volume ) ;
distB * = distB ;
metric = sqrt ( distA + distB ) ;
if ( metric < bestmetric )
{
bestmetric = metric ;
bestbaseamount = baseamount + i ;
bestrelamount = relamount + j ;
//printf("i.%d j.%d metric. %f\n",i,j,metric);
}
}
* baseamountp = bestbaseamount ;
* relamountp = bestrelamount ;
}
void prices777_additem ( cJSON * * highbidp , cJSON * * lowaskp , cJSON * bids , cJSON * asks , int32_t ind , cJSON * item , int32_t bidask )
{
if ( bidask = = 0 )
{
cJSON_AddItemToArray ( bids , item ) ;
if ( ind = = 0 )
* highbidp = item ;
}
else
{
cJSON_AddItemToArray ( asks , item ) ;
if ( ind = = 0 )
* lowaskp = item ;
}
}
uint64_t calc_qty ( uint64_t mult , uint64_t assetid , uint64_t amount )
{
if ( assetid ! = NXT_ASSETID )
return ( amount / mult ) ;
else return ( amount ) ;
}
int32_t verify_NXTtx ( cJSON * json , uint64_t refasset , uint64_t qty , uint64_t destNXTbits )
{
int32_t typeval , subtypeval , n = 0 ;
uint64_t quantity , price , assetidbits ;
cJSON * attachmentobj ;
char sender [ MAX_JSON_FIELD ] , recipient [ MAX_JSON_FIELD ] , deadline [ MAX_JSON_FIELD ] , feeNQT [ MAX_JSON_FIELD ] , amountNQT [ MAX_JSON_FIELD ] , type [ MAX_JSON_FIELD ] , subtype [ MAX_JSON_FIELD ] , verify [ MAX_JSON_FIELD ] , referencedTransaction [ MAX_JSON_FIELD ] , quantityQNT [ MAX_JSON_FIELD ] , priceNQT [ MAX_JSON_FIELD ] , assetidstr [ MAX_JSON_FIELD ] , sighash [ MAX_JSON_FIELD ] , fullhash [ MAX_JSON_FIELD ] , timestamp [ MAX_JSON_FIELD ] , transaction [ MAX_JSON_FIELD ] ;
if ( json = = 0 )
{
printf ( " verify_NXTtx cant parse json \n " ) ;
return ( - 1 ) ;
}
if ( extract_cJSON_str ( sender , sizeof ( sender ) , json , " sender " ) > 0 ) n + + ;
if ( extract_cJSON_str ( recipient , sizeof ( recipient ) , json , " recipient " ) > 0 ) n + + ;
if ( extract_cJSON_str ( referencedTransaction , sizeof ( referencedTransaction ) , json , " referencedTransactionFullHash " ) > 0 ) n + + ;
if ( extract_cJSON_str ( amountNQT , sizeof ( amountNQT ) , json , " amountNQT " ) > 0 ) n + + ;
if ( extract_cJSON_str ( feeNQT , sizeof ( feeNQT ) , json , " feeNQT " ) > 0 ) n + + ;
if ( extract_cJSON_str ( deadline , sizeof ( deadline ) , json , " deadline " ) > 0 ) n + + ;
if ( extract_cJSON_str ( type , sizeof ( type ) , json , " type " ) > 0 ) n + + ;
if ( extract_cJSON_str ( subtype , sizeof ( subtype ) , json , " subtype " ) > 0 ) n + + ;
if ( extract_cJSON_str ( verify , sizeof ( verify ) , json , " verify " ) > 0 ) n + + ;
if ( extract_cJSON_str ( sighash , sizeof ( sighash ) , json , " signatureHash " ) > 0 ) n + + ;
if ( extract_cJSON_str ( fullhash , sizeof ( fullhash ) , json , " fullHash " ) > 0 ) n + + ;
if ( extract_cJSON_str ( timestamp , sizeof ( timestamp ) , json , " timestamp " ) > 0 ) n + + ;
if ( extract_cJSON_str ( transaction , sizeof ( transaction ) , json , " transaction " ) > 0 ) n + + ;
if ( calc_nxt64bits ( recipient ) ! = destNXTbits )
{
if ( Debuglevel > 2 )
fprintf ( stderr , " recipient.%s != %llu \n " , recipient , ( long long ) destNXTbits ) ;
return ( - 2 ) ;
}
typeval = myatoi ( type , 256 ) , subtypeval = myatoi ( subtype , 256 ) ;
if ( refasset = = NXT_ASSETID )
{
if ( typeval ! = 0 | | subtypeval ! = 0 )
{
fprintf ( stderr , " unexpected typeval.%d subtypeval.%d \n " , typeval , subtypeval ) ;
return ( - 3 ) ;
}
if ( qty ! = calc_nxt64bits ( amountNQT ) )
{
fprintf ( stderr , " unexpected qty.%llu vs.%s \n " , ( long long ) qty , amountNQT ) ;
return ( - 4 ) ;
}
return ( 0 ) ;
}
else
{
if ( typeval ! = 2 | | subtypeval ! = 1 )
{
if ( Debuglevel > 2 )
fprintf ( stderr , " refasset.%llu qty %lld \n " , ( long long ) refasset , ( long long ) qty ) ;
return ( - 11 ) ;
}
price = quantity = assetidbits = 0 ;
attachmentobj = cJSON_GetObjectItem ( json , " attachment " ) ;
if ( attachmentobj ! = 0 )
{
if ( extract_cJSON_str ( assetidstr , sizeof ( assetidstr ) , attachmentobj , " asset " ) > 0 )
assetidbits = calc_nxt64bits ( assetidstr ) ;
//else if ( extract_cJSON_str(assetidstr,sizeof(assetidstr),attachmentobj,"currency") > 0 )
// assetidbits = calc_nxt64bits(assetidstr);
if ( extract_cJSON_str ( quantityQNT , sizeof ( quantityQNT ) , attachmentobj , " quantityQNT " ) > 0 )
quantity = calc_nxt64bits ( quantityQNT ) ;
//else if ( extract_cJSON_str(quantityQNT,sizeof(quantityQNT),attachmentobj,"units") > 0 )
// quantity = calc_nxt64bits(quantityQNT);
if ( extract_cJSON_str ( priceNQT , sizeof ( priceNQT ) , attachmentobj , " priceNQT " ) > 0 )
price = calc_nxt64bits ( priceNQT ) ;
}
if ( assetidbits ! = refasset )
{
fprintf ( stderr , " assetidbits %llu != %llu refasset \n " , ( long long ) assetidbits , ( long long ) refasset ) ;
return ( - 12 ) ;
}
if ( qty ! = quantity )
{
fprintf ( stderr , " qty.%llu != %llu \n " , ( long long ) qty , ( long long ) quantity ) ;
return ( - 13 ) ;
}
return ( 0 ) ;
}
return ( - 1 ) ;
}
int32_t InstantDEX_verify ( uint64_t destNXTaddr , uint64_t sendasset , uint64_t sendqty , cJSON * txobj , uint64_t recvasset , uint64_t recvqty )
{
int32_t err ;
// verify recipient, amounts in txobj
if ( ( err = verify_NXTtx ( txobj , recvasset , recvqty , destNXTaddr ) ) ! = 0 )
{
if ( Debuglevel > 2 )
printf ( " InstantDEX_verify dest.(%llu) tx mismatch %d (%llu %lld) -> (%llu %lld) \n " , ( long long ) destNXTaddr , err , ( long long ) sendasset , ( long long ) sendqty , ( long long ) recvasset , ( long long ) recvqty ) ;
return ( - 1 ) ;
}
return ( 0 ) ;
}
cJSON * wallet_swapjson ( char * recv , uint64_t recvasset , char * send , uint64_t sendasset , uint64_t orderid , uint64_t quoteid )
{
return ( cJSON_Parse ( clonestr ( " { \" error \" : \" notyet \" } " ) ) ) ;
# ifdef notyet
int32_t iter ; uint64_t assetid ; struct coin777 * coin ; struct InstantDEX_quote * iQ ;
char account [ 128 ] , walletstr [ 512 ] , * addr , * str ; cJSON * walletitem = 0 ;
printf ( " wallet_swapjson is not yet \n " ) ;
if ( ( iQ = find_iQ ( quoteid ) ) ! = 0 & & iQ - > s . wallet ! = 0 )
{
walletitem = cJSON_Parse ( iQ - > walletstr ) ;
//printf("start with (%s)\n",iQ->walletstr);
}
for ( iter = 0 ; iter < 2 ; iter + + )
{
addr = 0 ;
str = ( iter = = 0 ) ? recv : send ;
assetid = ( iter = = 0 ) ? recvasset : sendasset ;
if ( ( coin = coin777_find ( str , 1 ) ) ! = 0 )
{
if ( is_NXT_native ( assetid ) = = 0 )
{
if ( ( walletitem = set_walletstr ( walletitem , walletstr , iQ ) ) ! = 0 )
{
}
} // else printf("%s is NXT\n",coin->name);
if ( is_NXT_native ( assetid ) ! = 0 )
addr = SUPERNET . NXTADDR ;
else
{
addr = ( iter = = 0 ) ? coin - > atomicrecv : coin - > atomicsend ;
if ( addr [ 0 ] = = 0 )
addr = get_acct_coinaddr ( addr , str , coin - > serverport , coin - > userpass , account ) ;
}
if ( addr ! = 0 )
{
} else printf ( " %s no addr \n " , coin - > name ) ;
} else printf ( " cant find coin.(%s) \n " , iter = = 0 ? recv : send ) ;
}
if ( walletitem = = 0 )
walletitem = cJSON_CreateObject ( ) , jaddstr ( walletitem , " error " , " cant find local coin daemons " ) ;
return ( walletitem ) ;
# endif
}
void _prices777_item ( cJSON * item , int32_t group , struct prices777 * prices , int32_t bidask , double price , double volume , uint64_t orderid , uint64_t quoteid )
{
uint64_t baseqty , relqty ; int32_t iswallet = 0 ; char basec , relc ; struct InstantDEX_quote * iQ ;
jaddnum ( item , " group " , group ) ;
jaddstr ( item , " exchange " , prices - > exchange ) ;
jaddstr ( item , " base " , prices - > base ) , jaddstr ( item , " rel " , prices - > rel ) ;
if ( ( iQ = find_iQ ( quoteid ) ) ! = 0 )
jadd64bits ( item , " offerNXT " , iQ - > s . offerNXT ) ;
if ( strcmp ( prices - > exchange , " nxtae " ) = = 0 | | strcmp ( prices - > exchange , " unconf " ) = = 0 | | strcmp ( prices - > exchange , " InstantDEX " ) = = 0 | | strcmp ( prices - > exchange , " wallet " ) = = 0 )
{
jadd64bits ( item , prices - > type = = 5 ? " currency " : " asset " , prices - > baseid ) ;
//else if ( quoteid != 0 ) printf("cant find offerNXT.%llu\n",(long long)quoteid);
jadd64bits ( item , " baseid " , prices - > baseid ) , jadd64bits ( item , " relid " , prices - > relid ) ;
iswallet = ( strcmp ( prices - > exchange , " wallet " ) = = 0 ) ;
if ( strcmp ( prices - > exchange , " InstantDEX " ) = = 0 | | iswallet ! = 0 )
{
jaddstr ( item , " trade " , " swap " ) ;
baseqty = calc_qty ( prices - > basemult , prices - > baseid , SATOSHIDEN * volume + 0.5 / SATOSHIDEN ) ;
//printf("baseid.%llu basemult.%llu -> %llu\n",(long long)prices->baseid,(long long)prices->basemult,(long long)baseqty);
relqty = calc_qty ( prices - > relmult , prices - > relid , SATOSHIDEN * volume * price + 0.5 / SATOSHIDEN ) ;
if ( bidask ! = 0 )
{
basec = ' + ' , relc = ' - ' ;
jadd64bits ( item , " recvbase " , baseqty ) ;
jadd64bits ( item , " sendrel " , relqty ) ;
if ( iswallet ! = 0 )
jadd ( item , " wallet " , wallet_swapjson ( prices - > base , prices - > baseid , prices - > rel , prices - > relid , orderid , quoteid ) ) ;
}
else
{
basec = ' - ' , relc = ' + ' ;
jadd64bits ( item , " sendbase " , baseqty ) ;
jadd64bits ( item , " recvrel " , relqty ) ;
if ( iswallet ! = 0 )
jadd ( item , " wallet " , wallet_swapjson ( prices - > rel , prices - > relid , prices - > base , prices - > baseid , orderid , quoteid ) ) ;
}
//printf("(%s %cbaseqty.%llu <-> %s %crelqty.%llu) basemult.%llu baseid.%llu vol %f amount %llu\n",prices->base,basec,(long long)baseqty,prices->rel,relc,(long long)relqty,(long long)prices->basemult,(long long)prices->baseid,volume,(long long)volume*SATOSHIDEN);
}
else
{
//printf("alternate path\n");
jaddstr ( item , " trade " , bidask = = 0 ? " sell " : " buy " ) ;
}
}
else
{
//printf("alternate path\n");
jaddstr ( item , " trade " , bidask = = 0 ? " sell " : " buy " ) ;
jaddstr ( item , " name " , prices - > contract ) ;
}
jaddnum ( item , " orderprice " , price ) ;
jaddnum ( item , " ordervolume " , volume ) ;
if ( orderid ! = 0 )
jadd64bits ( item , " orderid " , orderid ) ;
if ( quoteid ! = 0 )
jadd64bits ( item , " quoteid " , quoteid ) ;
}
cJSON * prices777_item ( int32_t rootbidask , struct prices777 * prices , int32_t group , int32_t bidask , double origprice , double origvolume , double rootwt , double groupwt , double wt , uint64_t orderid , uint64_t quoteid )
{
cJSON * item ; double price , volume , oppo = 1. ;
item = cJSON_CreateObject ( ) ;
jaddstr ( item , " basket " , rootbidask = = 0 ? " bid " : " ask " ) ;
//jaddnum(item,"rootwt",rootwt);
//jaddnum(item,"groupwt",groupwt);
//jaddnum(item,"wt",wt);
if ( wt * groupwt < 0. )
oppo = - 1. ;
if ( wt * groupwt < 0 )
{
volume = origprice * origvolume ;
price = 1. / origprice ;
} else price = origprice , volume = origvolume ;
jaddnum ( item , " price " , price ) ;
jaddnum ( item , " volume " , volume ) ;
if ( groupwt * wt < 0 )
{
volume = origprice * origvolume ;
price = 1. / origprice ;
} else price = origprice , volume = origvolume ;
_prices777_item ( item , group , prices , bidask , price , volume , orderid , quoteid ) ;
return ( item ) ;
}
cJSON * prices777_tradeitem ( int32_t rootbidask , struct prices777 * prices , int32_t group , int32_t bidask , int32_t slot , uint32_t timestamp , double price , double volume , double rootwt , double groupwt , double wt , uint64_t orderid , uint64_t quoteid )
{
static uint32_t match , error ;
if ( prices - > O . timestamp = = timestamp )
{
//printf("tradeitem.(%s %f %f)\n",prices->exchange,price,volume);
if ( bidask = = 0 & & prices - > O . book [ MAX_GROUPS ] [ slot ] . bid . s . price = = price & & prices - > O . book [ MAX_GROUPS ] [ slot ] . bid . s . vol = = volume )
match + + ;
else if ( bidask ! = 0 & & prices - > O . book [ MAX_GROUPS ] [ slot ] . ask . s . price = = price & & prices - > O . book [ MAX_GROUPS ] [ slot ] . ask . s . vol = = volume )
match + + ;
}
else if ( prices - > O2 . timestamp = = timestamp )
{
//printf("2tradeitem.(%s %f %f)\n",prices->exchange,price,volume);
if ( bidask = = 0 & & prices - > O2 . book [ MAX_GROUPS ] [ slot ] . bid . s . price = = price & & prices - > O2 . book [ MAX_GROUPS ] [ slot ] . bid . s . vol = = volume )
match + + ;
else if ( bidask ! = 0 & & prices - > O2 . book [ MAX_GROUPS ] [ slot ] . ask . s . price = = price & & prices - > O2 . book [ MAX_GROUPS ] [ slot ] . ask . s . vol = = volume )
match + + ;
} else error + + , printf ( " mismatched tradeitem error.%d match.%d \n " , error , match ) ;
return ( prices777_item ( rootbidask , prices , group , bidask , price , volume , rootwt , groupwt , wt , orderid , quoteid ) ) ;
}
cJSON * prices777_tradesequence ( struct prices777 * prices , int32_t bidask , struct prices777_order * orders [ ] , double rootwt , double groupwt , double wt , int32_t refgroup )
{
int32_t i , j , srcslot , srcbidask , err = 0 ; cJSON * array ; struct prices777_order * suborders [ MAX_GROUPS ] ;
struct prices777_order * order ; struct prices777 * src ;
array = cJSON_CreateArray ( ) ;
for ( i = 0 ; i < prices - > numgroups ; i + + )
{
order = orders [ i ] ;
groupwt = prices - > groupwts [ i ] ;
memset ( suborders , 0 , sizeof ( suborders ) ) ;
srcbidask = ( order - > slot_ba & 1 ) ; srcslot = order - > slot_ba > > 1 ;
if ( ( src = order - > source ) ! = 0 )
{
if ( src - > basketsize = = 0 )
jaddi ( array , prices777_tradeitem ( bidask , src , refgroup * 10 + i , srcbidask , srcslot , order - > s . timestamp , order - > s . price , order - > ratio * order - > s . vol , rootwt , groupwt / groupwt , order - > wt , order - > id , order - > s . quoteid ) ) ;
else if ( src - > O . timestamp = = order - > s . timestamp )
{
for ( j = 0 ; j < src - > numgroups ; j + + )
suborders [ j ] = ( srcbidask = = 0 ) ? & src - > O . book [ j ] [ srcslot ] . bid : & src - > O . book [ j ] [ srcslot ] . ask ;
jaddi ( array , prices777_tradesequence ( src , bidask , suborders , rootwt , groupwt / groupwt , order - > wt , refgroup * 10 + i ) ) ;
}
else if ( src - > O2 . timestamp = = order - > s . timestamp )
{
for ( j = 0 ; j < src - > numgroups ; j + + )
suborders [ j ] = ( srcbidask = = 0 ) ? & src - > O2 . book [ j ] [ srcslot ] . bid : & src - > O2 . book [ j ] [ srcslot ] . ask ;
jaddi ( array , prices777_tradesequence ( src , bidask , suborders , rootwt , groupwt / groupwt , order - > wt , refgroup * 10 + i ) ) ;
}
else err = 1 ;
}
if ( src = = 0 | | err ! = 0 )
{
//jaddi(array,prices777_item(prices,bidask,price,volume,wt,orderid));
//printf("prices777_tradesequence warning cant match timestamp %u (%s %s/%s)\n",order->timestamp,prices->contract,prices->base,prices->rel);
}
}
return ( array ) ;
}
void prices777_orderbook_item ( struct prices777 * prices , int32_t bidask , struct prices777_order * suborders [ ] , cJSON * array , int32_t invert , int32_t allflag , double origprice , double origvolume , uint64_t orderid , uint64_t quoteid )
{
cJSON * item , * obj , * tarray , * walletitem ; double price , volume ; struct InstantDEX_quote * iQ ;
item = cJSON_CreateObject ( ) ;
if ( invert ! = 0 )
volume = ( origvolume * origprice ) , price = 1. / origprice ;
else price = origprice , volume = origvolume ;
if ( strcmp ( prices - > exchange , " jumblr " ) = = 0 | | strcmp ( prices - > exchange , " pangea " ) = = 0 )
{
jaddstr ( item , " plugin " , prices - > exchange ) , jaddstr ( item , " method " , " start " ) ;
jaddnum ( item , " dotrade " , 1 ) , jaddnum ( item , " volume " , volume ) ;
jaddnum ( item , " timeout " , 20000 ) ;
jaddstr ( item , " base " , prices - > base ) ;
if ( ( iQ = find_iQ ( quoteid ) ) ! = 0 )
jadd64bits ( item , " offerNXT " , iQ - > s . offerNXT ) ;
jadd64bits ( item , " quoteid " , iQ - > s . quoteid ) ;
if ( strcmp ( prices - > exchange , " pangea " ) = = 0 & & iQ - > s . wallet ! = 0 & & ( walletitem = cJSON_Parse ( iQ - > walletstr ) ) ! = 0 )
jadd ( item , " wallet " , walletitem ) ;
jaddi ( array , item ) ;
return ;
}
jaddstr ( item , " plugin " , " InstantDEX " ) , jaddstr ( item , " method " , " tradesequence " ) ;
jaddnum ( item , " dotrade " , 1 ) , jaddnum ( item , " price " , price ) , jaddnum ( item , " volume " , volume ) ;
//jaddnum(item,"invert",invert), jaddnum(item,"origprice",origprice), jaddnum(item,"origvolume",origvolume);
//jaddstr(item,"base",prices->base), jaddstr(item,"rel",prices->rel);
if ( allflag ! = 0 )
{
if ( prices - > basketsize = = 0 )
{
tarray = cJSON_CreateArray ( ) ;
obj = cJSON_CreateObject ( ) ;
_prices777_item ( obj , 0 , prices , bidask , origprice , origvolume , orderid , quoteid ) ;
jaddi ( tarray , obj ) ;
} else tarray = prices777_tradesequence ( prices , bidask , suborders , invert ! = 0 ? - 1 : 1. , 1. , 1. , 0 ) ;
jadd ( item , " trades " , tarray ) ;
}
jaddi ( array , item ) ;
}
char * prices777_orderbook_jsonstr ( int32_t invert , uint64_t nxt64bits , struct prices777 * prices , struct prices777_basketinfo * OB , int32_t maxdepth , int32_t allflag )
{
struct prices777_orderentry * gp ; struct prices777_order * suborders [ MAX_GROUPS ] ; cJSON * json , * bids , * asks ;
int32_t i , slot ; char baserel [ 64 ] , base [ 64 ] , rel [ 64 ] , assetA [ 64 ] , assetB [ 64 ] , NXTaddr [ 64 ] ;
if ( invert = = 0 )
sprintf ( baserel , " %s/%s " , prices - > base , prices - > rel ) ;
else sprintf ( baserel , " %s/%s " , prices - > rel , prices - > base ) ;
if ( Debuglevel > 2 )
printf ( " ORDERBOOK %s/%s iQsize.%ld numbids.%d numasks.%d maxdepth.%d (%llu %llu) \n " , prices - > base , prices - > rel , ( long ) sizeof ( struct InstantDEX_quote ) , OB - > numbids , OB - > numasks , maxdepth , ( long long ) prices - > baseid , ( long long ) prices - > relid ) ;
json = cJSON_CreateObject ( ) , bids = cJSON_CreateArray ( ) , asks = cJSON_CreateArray ( ) ;
gp = & OB - > book [ MAX_GROUPS ] [ 0 ] ;
memset ( suborders , 0 , sizeof ( suborders ) ) ;
for ( slot = 0 ; ( slot < OB - > numbids | | slot < OB - > numasks ) & & slot < maxdepth ; slot + + , gp + + )
{
//printf("slot.%d\n",slot);
if ( slot < OB - > numbids )
{
for ( i = 0 ; i < prices - > numgroups ; i + + )
suborders [ i ] = & OB - > book [ i ] [ slot ] . bid ;
prices777_orderbook_item ( prices , 0 , suborders , ( invert = = 0 ) ? bids : asks , invert , allflag , gp - > bid . s . price , gp - > bid . s . vol , gp - > bid . id , gp - > bid . s . quoteid ) ;
}
if ( slot < OB - > numasks )
{
for ( i = 0 ; i < prices - > numgroups ; i + + )
suborders [ i ] = & OB - > book [ i ] [ slot ] . ask ;
prices777_orderbook_item ( prices , 1 , suborders , ( invert = = 0 ) ? asks : bids , invert , allflag , gp - > ask . s . price , gp - > ask . s . vol , gp - > ask . id , gp - > ask . s . quoteid ) ;
}
}
expand_nxt64bits ( NXTaddr , nxt64bits ) ;
if ( invert ! = 0 )
strcpy ( base , prices - > rel ) , strcpy ( rel , prices - > base ) ;
else strcpy ( base , prices - > base ) , strcpy ( rel , prices - > rel ) ;
expand_nxt64bits ( assetA , invert = = 0 ? prices - > baseid : prices - > relid ) ;
expand_nxt64bits ( assetB , invert ! = 0 ? prices - > baseid : prices - > relid ) ;
cJSON_AddItemToObject ( json , " exchange " , cJSON_CreateString ( prices - > exchange ) ) ;
cJSON_AddItemToObject ( json , " inverted " , cJSON_CreateNumber ( invert ) ) ;
cJSON_AddItemToObject ( json , " contract " , cJSON_CreateString ( prices - > contract ) ) ;
cJSON_AddItemToObject ( json , " baseid " , cJSON_CreateString ( assetA ) ) ;
if ( assetB [ 0 ] ! = 0 )
cJSON_AddItemToObject ( json , " relid " , cJSON_CreateString ( assetB ) ) ;
cJSON_AddItemToObject ( json , " base " , cJSON_CreateString ( base ) ) ;
if ( rel [ 0 ] ! = 0 )
cJSON_AddItemToObject ( json , " rel " , cJSON_CreateString ( rel ) ) ;
cJSON_AddItemToObject ( json , " bids " , bids ) ;
cJSON_AddItemToObject ( json , " asks " , asks ) ;
if ( invert = = 0 )
{
cJSON_AddItemToObject ( json , " numbids " , cJSON_CreateNumber ( OB - > numbids ) ) ;
cJSON_AddItemToObject ( json , " numasks " , cJSON_CreateNumber ( OB - > numasks ) ) ;
cJSON_AddItemToObject ( json , " lastbid " , cJSON_CreateNumber ( prices - > lastbid ) ) ;
cJSON_AddItemToObject ( json , " lastask " , cJSON_CreateNumber ( prices - > lastask ) ) ;
}
else
{
cJSON_AddItemToObject ( json , " numbids " , cJSON_CreateNumber ( OB - > numasks ) ) ;
cJSON_AddItemToObject ( json , " numasks " , cJSON_CreateNumber ( OB - > numbids ) ) ;
if ( prices - > lastask ! = 0 )
cJSON_AddItemToObject ( json , " lastbid " , cJSON_CreateNumber ( 1. / prices - > lastask ) ) ;
if ( prices - > lastbid ! = 0 )
cJSON_AddItemToObject ( json , " lastask " , cJSON_CreateNumber ( 1. / prices - > lastbid ) ) ;
}
cJSON_AddItemToObject ( json , " NXT " , cJSON_CreateString ( NXTaddr ) ) ;
cJSON_AddItemToObject ( json , " timestamp " , cJSON_CreateNumber ( time ( NULL ) ) ) ;
cJSON_AddItemToObject ( json , " maxdepth " , cJSON_CreateNumber ( maxdepth ) ) ;
return ( jprint ( json , 1 ) ) ;
}
void prices777_jsonstrs ( struct prices777 * prices , struct prices777_basketinfo * OB )
{
int32_t allflag ; char * strs [ 4 ] ;
if ( OB - > numbids = = 0 & & OB - > numasks = = 0 )
{
printf ( " warning: updating null orderbook ignored for %s (%s/%s) \n " , prices - > contract , prices - > base , prices - > rel ) ;
return ;
}
for ( allflag = 0 ; allflag < 4 ; allflag + + )
{
strs [ allflag ] = prices777_orderbook_jsonstr ( allflag / 2 , IGUANA_MY64BITS , prices , OB , MAX_DEPTH , allflag % 2 ) ;
if ( Debuglevel > 2 )
printf ( " strs[%d].(%s) prices.%p \n " , allflag , strs [ allflag ] , prices ) ;
}
portable_mutex_lock ( & prices - > mutex ) ;
for ( allflag = 0 ; allflag < 4 ; allflag + + )
{
if ( prices - > orderbook_jsonstrs [ allflag / 2 ] [ allflag % 2 ] ! = 0 )
free ( prices - > orderbook_jsonstrs [ allflag / 2 ] [ allflag % 2 ] ) ;
prices - > orderbook_jsonstrs [ allflag / 2 ] [ allflag % 2 ] = strs [ allflag ] ;
}
portable_mutex_unlock ( & prices - > mutex ) ;
}
char * orderbook_clonestr ( struct prices777 * prices , int32_t invert , int32_t allflag )
{
char * str , * clone = 0 ;
portable_mutex_lock ( & prices - > mutex ) ;
if ( ( str = prices - > orderbook_jsonstrs [ invert ] [ allflag ] ) ! = 0 )
clone = clonestr ( str ) ;
portable_mutex_unlock ( & prices - > mutex ) ;
return ( clone ) ;
}
void prices777_json_quotes ( double * hblap , struct prices777 * prices , cJSON * bids , cJSON * asks , int32_t maxdepth , char * pricefield , char * volfield , uint32_t reftimestamp )
{
cJSON * item ; int32_t i , slot , n = 0 , m = 0 , dir , bidask , numitems ; uint64_t orderid , quoteid ; uint32_t timestamp ; double price , volume , hbla = 0. ;
struct prices777_basketinfo OB ; struct prices777_orderentry * gp ; struct prices777_order * order ;
memset ( & OB , 0 , sizeof ( OB ) ) ;
if ( reftimestamp = = 0 )
reftimestamp = ( uint32_t ) time ( NULL ) ;
OB . timestamp = reftimestamp ;
if ( bids ! = 0 )
{
n = cJSON_GetArraySize ( bids ) ;
if ( maxdepth ! = 0 & & n > maxdepth )
n = maxdepth ;
}
if ( asks ! = 0 )
{
m = cJSON_GetArraySize ( asks ) ;
if ( maxdepth ! = 0 & & m > maxdepth )
m = maxdepth ;
}
for ( i = 0 ; i < n | | i < m ; i + + )
{
gp = & OB . book [ MAX_GROUPS ] [ i ] ;
gp - > bid . source = gp - > ask . source = prices ;
for ( bidask = 0 ; bidask < 2 ; bidask + + )
{
price = volume = 0. ;
orderid = quoteid = 0 ;
dir = ( bidask = = 0 ) ? 1 : - 1 ;
if ( bidask = = 0 & & i > = n )
continue ;
else if ( bidask = = 1 & & i > = m )
continue ;
if ( strcmp ( prices - > exchange , " bter " ) = = 0 & & dir < 0 )
slot = ( ( bidask = = 0 ? n : m ) - 1 ) - i ;
else slot = i ;
timestamp = 0 ;
item = jitem ( bidask = = 0 ? bids : asks , slot ) ;
if ( pricefield ! = 0 & & volfield ! = 0 )
price = jdouble ( item , pricefield ) , volume = jdouble ( item , volfield ) ;
else if ( is_cJSON_Array ( item ) ! = 0 & & ( numitems = cJSON_GetArraySize ( item ) ) ! = 0 ) // big assumptions about order within nested array!
{
price = jdouble ( jitem ( item , 0 ) , 0 ) , volume = jdouble ( jitem ( item , 1 ) , 0 ) ;
if ( strcmp ( prices - > exchange , " kraken " ) = = 0 )
timestamp = juint ( jitem ( item , 2 ) , 0 ) ;
else orderid = j64bits ( jitem ( item , 2 ) , 0 ) ;
}
else continue ;
if ( quoteid = = 0 )
quoteid = orderid ;
if ( price > SMALLVAL & & volume > SMALLVAL )
{
if ( prices - > commission ! = 0. )
{
//printf("price %f fee %f -> ",price,prices->commission * price);
if ( bidask = = 0 )
price - = prices - > commission * price ;
else price + = prices - > commission * price ;
//printf("%f\n",price);
}
order = ( bidask = = 0 ) ? & gp - > bid : & gp - > ask ;
order - > s . price = price , order - > s . vol = volume , order - > source = prices , order - > s . timestamp = OB . timestamp , order - > wt = 1 , order - > id = orderid , order - > s . quoteid = quoteid ;
if ( bidask = = 0 )
order - > slot_ba = ( OB . numbids + + < < 1 ) ;
else order - > slot_ba = ( OB . numasks + + < < 1 ) | 1 ;
if ( i = = 0 )
{
if ( bidask = = 0 )
prices - > lastbid = price ;
else prices - > lastask = price ;
if ( hbla = = 0. )
hbla = price ;
else hbla = 0.5 * ( hbla + price ) ;
}
if ( Debuglevel > 2 ) //|| prices->basketsize > 0 || strcmp("unconf",prices->exchange) == 0 )
printf ( " %d,%d: %-8s %s %5s/%-5s %13.8f vol %13.8f | invert %13.8f vol %13.8f | timestamp.%u \n " , OB . numbids , OB . numasks , prices - > exchange , dir > 0 ? " bid " : " ask " , prices - > base , prices - > rel , price , volume , 1. / price , volume * price , timestamp ) ;
}
}
}
if ( hbla ! = 0. )
* hblap = hbla ;
prices - > O2 = prices - > O ;
//prices->O = OB;
for ( i = 0 ; i < MAX_GROUPS ; i + + )
memcpy ( prices - > O . book [ i ] , prices - > O . book [ i + 1 ] , sizeof ( prices - > O . book [ i ] ) ) ;
memcpy ( prices - > O . book [ MAX_GROUPS ] , OB . book [ MAX_GROUPS ] , sizeof ( OB . book [ MAX_GROUPS ] ) ) ;
prices - > O . numbids = OB . numbids , prices - > O . numasks = OB . numasks , prices - > O . timestamp = OB . timestamp ;
}
double prices777_json_orderbook ( char * exchangestr , struct prices777 * prices , int32_t maxdepth , cJSON * json , char * resultfield , char * bidfield , char * askfield , char * pricefield , char * volfield )
{
cJSON * obj = 0 , * bidobj = 0 , * askobj = 0 ; double hbla = 0. ; int32_t numasks = 0 , numbids = 0 ;
if ( resultfield = = 0 )
obj = json ;
if ( maxdepth = = 0 )
maxdepth = MAX_DEPTH ;
if ( resultfield = = 0 | | ( obj = jobj ( json , resultfield ) ) ! = 0 )
{
bidobj = jarray ( & numbids , obj , bidfield ) ;
askobj = jarray ( & numasks , obj , askfield ) ;
if ( bidobj ! = 0 | | askobj ! = 0 )
{
prices777_json_quotes ( & hbla , prices , bidobj , askobj , maxdepth , pricefield , volfield , 0 ) ;
prices777_jsonstrs ( prices , & prices - > O ) ;
}
}
return ( hbla ) ;
}
void prices777_hbla ( uint64_t * bidorderid , uint64_t * askorderid , int32_t * lowaski , int32_t * highbidi , double * highbid , double * bidvol , double * lowask , double * askvol , double groupwt , int32_t i , int32_t bidask , double price , double vol , uint64_t orderid )
{
if ( groupwt > SMALLVAL & & ( * lowask = = 0. | | price < * lowask ) )
* askorderid = orderid , * lowask = price , * askvol = vol , * lowaski = ( i < < 1 ) | bidask ;
else if ( groupwt < - SMALLVAL & & ( * highbid = = 0. | | price > * highbid ) )
* bidorderid = orderid , * highbid = price , * bidvol = vol , * highbidi = ( i < < 1 ) | bidask ;
//printf("hbla.(%f %f)\n",price,vol);
}
void prices777_setorder ( struct prices777_order * order , struct prices777_basket * group , int32_t coordinate , uint64_t orderid , double refprice , double refvol )
{
int32_t bidask ; struct prices777 * prices ; double price = 0 , vol = 0 ;
bidask = ( coordinate & 1 ) , coordinate > > = 1 ;
prices = group [ coordinate ] . prices ;
if ( bidask ! = 0 & & group [ coordinate ] . aski < prices - > O . numasks )
price = prices - > O . book [ MAX_GROUPS ] [ group [ coordinate ] . aski ] . ask . s . price , vol = prices - > O . book [ MAX_GROUPS ] [ group [ coordinate ] . aski ] . ask . s . vol , order - > slot_ba = ( group [ coordinate ] . aski + + < < 1 ) | 1 ;
else if ( group [ coordinate ] . bidi < prices - > O . numbids )
price = prices - > O . book [ MAX_GROUPS ] [ group [ coordinate ] . bidi ] . bid . s . price , vol = prices - > O . book [ MAX_GROUPS ] [ group [ coordinate ] . bidi ] . bid . s . vol , order - > slot_ba = ( group [ coordinate ] . bidi + + < < 1 ) ;
else printf ( " illegal coordinate.%d bidask.%d when bidi.%d aski.%d numbids.%d numasks.%d \n " , coordinate , bidask , group [ coordinate ] . bidi , group [ coordinate ] . aski , prices - > O . numbids , prices - > O . numasks ) ;
order - > source = prices ;
order - > wt = group [ coordinate ] . wt ;
order - > s . timestamp = prices - > O . timestamp ;
order - > id = orderid ;
if ( order - > wt < 0. )
vol * = price , price = ( 1. / price ) ;
if ( fabs ( price - refprice ) > SMALLVAL | | fabs ( vol - refvol ) > SMALLVAL )
{
printf ( " [ERROR] " ) ;
printf ( " %s group.%d (%s/%s) bidask.%d coordinate.%d wt %.8f (%.8f %.8f) vs (%.8f %.8f) \n " , prices - > exchange , group [ coordinate ] . groupid , prices - > base , prices - > rel , bidask , coordinate , order - > wt , price , vol , refprice , refvol ) ;
}
}
int32_t prices777_groupbidasks ( struct prices777_orderentry * gp , double groupwt , double minvol , struct prices777_basket * group , int32_t groupsize )
{
int32_t i , highbidi , lowaski ; double highbid , lowask , bidvol , askvol , vol , price , polarity ; uint64_t bidorderid , askorderid ;
struct prices777 * feature ; struct prices777_order * order ;
memset ( gp , 0 , sizeof ( * gp ) ) ;
highbidi = lowaski = - 1 ;
for ( bidvol = askvol = highbid = lowask = bidorderid = askorderid = i = 0 ; i < groupsize ; i + + )
{
if ( ( feature = group [ i ] . prices ) ! = 0 )
{
//if ( strcmp(feature->base,group[0].rel) == 0 && strcmp(feature->rel,group[0].base) == 0 )
// polarity = -1.;
//else polarity = 1.;
//if ( group[i].wt * groupwt < 0 ) fixes supernet/BTC
// polarity *= -1;
polarity = group [ i ] . wt ; // * groupwt;
order = & feature - > O . book [ MAX_GROUPS ] [ group [ i ] . bidi ] . bid ;
if ( group [ i ] . bidi < feature - > O . numbids & & ( vol = order - > s . vol ) > minvol & & ( price = order - > s . price ) > SMALLVAL )
{
//printf("%d/%d: (%s/%s) %s bidi.%d price.%f polarity.%f groupwt.%f -> ",i,groupsize,feature->base,feature->rel,feature->exchange,group[i].bidi,price,polarity,groupwt);
if ( polarity < 0. )
vol * = price , price = ( 1. / price ) ;
prices777_hbla ( & bidorderid , & askorderid , & lowaski , & highbidi , & highbid , & bidvol , & lowask , & askvol , - polarity , i , 0 , price , vol , order - > id ) ;
}
order = & feature - > O . book [ MAX_GROUPS ] [ group [ i ] . aski ] . ask ;
if ( group [ i ] . aski < feature - > O . numasks & & ( vol = order - > s . vol ) > minvol & & ( price = order - > s . price ) > SMALLVAL )
{
//printf("%d/%d: (%s/%s) %s aski.%d price.%f polarity.%f groupwt.%f -> ",i,groupsize,feature->base,feature->rel,feature->exchange,group[i].aski,price,polarity,groupwt);
if ( polarity < 0. )
vol * = price , price = ( 1. / price ) ;
prices777_hbla ( & bidorderid , & askorderid , & lowaski , & highbidi , & highbid , & bidvol , & lowask , & askvol , polarity , i , 1 , price , vol , order - > id ) ;
}
} else printf ( " null feature.%p \n " , feature ) ;
}
gp - > bid . s . price = highbid , gp - > bid . s . vol = bidvol , gp - > ask . s . price = lowask , gp - > ask . s . vol = askvol ;
if ( highbidi > = 0 )
prices777_setorder ( & gp - > bid , group , highbidi , bidorderid , highbid , bidvol ) ;
if ( lowaski > = 0 )
prices777_setorder ( & gp - > ask , group , lowaski , askorderid , lowask , askvol ) ;
// if ( lowaski >= 0 && highbidi >= 0 )
//printf("groupwt %f groupsize.%d %s highbidi.%d %f %f %s lowaski.%d wts.(%f %f)\n",groupwt,groupsize,gp->bid.source->exchange,highbidi,gp->bid.s.price,gp->ask.s.price,gp->ask.source->exchange,lowaski,gp->bid.wt,gp->ask.wt);
if ( gp - > bid . s . price > SMALLVAL & & gp - > ask . s . price > SMALLVAL )
return ( 0 ) ;
return ( - 1 ) ;
}
double prices777_volcalc ( double * basevols , uint64_t * baseids , uint64_t baseid , double basevol )
{
int32_t i ;
//printf("(add %llu %f) ",(long long)baseid,basevol);
for ( i = 0 ; i < MAX_GROUPS * 2 ; i + + )
{
if ( baseids [ i ] = = baseid )
{
if ( basevols [ i ] = = 0. | | basevol < basevols [ i ] )
basevols [ i ] = basevol ; //, printf("set %llu <= %f ",(long long)baseid,basevol);
// else printf("missed basevols[%d] %f, ",i,basevols[i]);
break ;
}
}
return ( 1 ) ;
}
double prices777_volratio ( double * basevols , uint64_t * baseids , uint64_t baseid , double vol )
{
int32_t i ;
for ( i = 0 ; i < MAX_GROUPS * 2 ; i + + )
{
if ( baseids [ i ] = = baseid )
{
if ( basevols [ i ] > 0. )
{
//printf("(vol %f vs %f) ",vol,basevols[i]);
if ( vol > basevols [ i ] )
return ( basevols [ i ] / vol ) ;
else return ( 1. ) ;
}
printf ( " unexpected zero vol basevols.%d \n " , i ) ;
return ( 1. ) ;
break ;
}
}
printf ( " unexpected cant find baseid.%llu \n " , ( long long ) baseid ) ;
return ( 1. ) ;
}
double prices777_basket ( struct prices777 * prices , int32_t maxdepth )
{
int32_t i , j , groupsize , slot ; uint64_t baseids [ MAX_GROUPS * 2 ] ;
double basevols [ MAX_GROUPS * 2 ] , relvols [ MAX_GROUPS * 2 ] , baseratio , relratio , a , av , b , bv , gap , bid , ask , minvol , bidvol , askvol , hbla = 0. ;
struct prices777_basketinfo OB ; uint32_t timestamp ; struct prices777 * feature ; struct prices777_orderentry * gp ;
a = av = b = bv = 0 ;
timestamp = ( uint32_t ) time ( NULL ) ;
memset ( & OB , 0 , sizeof ( OB ) ) ;
memset ( baseids , 0 , sizeof ( baseids ) ) ;
OB . timestamp = timestamp ;
//printf("prices777_basket.(%s) %s (%s/%s) %llu/%llu basketsize.%d\n",prices->exchange,prices->contract,prices->base,prices->rel,(long long)prices->baseid,(long long)prices->relid,prices->basketsize);
for ( i = 0 ; i < prices - > basketsize ; i + + )
{
if ( 0 & & strcmp ( prices - > exchange , " active " ) = = 0 & & prices - > basket [ i ] . prices ! = 0 )
printf ( " %s.group.%d %10s %10s/%10s wt %3.0f %.8f %.8f \n " , prices - > exchange , i , prices - > basket [ i ] . prices - > exchange , prices - > basket [ i ] . prices - > base , prices - > basket [ i ] . rel , prices - > basket [ i ] . wt , prices - > basket [ i ] . prices - > O . book [ MAX_GROUPS ] [ 0 ] . bid . s . price , prices - > basket [ i ] . prices - > O . book [ MAX_GROUPS ] [ 0 ] . ask . s . price ) ;
if ( ( feature = prices - > basket [ i ] . prices ) ! = 0 )
{
if ( 0 & & ( gap = ( prices - > lastupdate - feature - > lastupdate ) ) < 0 )
{
if ( prices - > lastupdate ! = 0 )
printf ( " you can ignore this harmless warning about unexpected time traveling feature %f vs %f or laggy feature \n " , prices - > lastupdate , feature - > lastupdate ) ;
return ( 0. ) ;
}
}
else
{
printf ( " unexpected null basket item %s[%d] \n " , prices - > contract , i ) ;
return ( 0. ) ;
}
prices - > basket [ i ] . aski = prices - > basket [ i ] . bidi = 0 ;
for ( j = 0 ; j < MAX_GROUPS * 2 ; j + + )
{
if ( prices - > basket [ i ] . prices = = 0 | | prices - > basket [ i ] . prices - > baseid = = baseids [ j ] )
break ;
if ( baseids [ j ] = = 0 )
{
baseids [ j ] = prices - > basket [ i ] . prices - > baseid ;
break ;
}
}
for ( j = 0 ; j < MAX_GROUPS * 2 ; j + + )
{
if ( prices - > basket [ i ] . prices = = 0 | | prices - > basket [ i ] . prices - > relid = = baseids [ j ] )
break ;
if ( baseids [ j ] = = 0 )
{
baseids [ j ] = prices - > basket [ i ] . prices - > relid ;
break ;
}
}
}
//printf("%s basketsize.%d numgroups.%d maxdepth.%d group0size.%d\n",prices->contract,prices->basketsize,prices->numgroups,maxdepth,prices->basket[0].groupsize);
for ( slot = 0 ; slot < maxdepth ; slot + + )
{
memset ( basevols , 0 , sizeof ( basevols ) ) ;
memset ( relvols , 0 , sizeof ( relvols ) ) ;
groupsize = prices - > basket [ 0 ] . groupsize ;
minvol = ( 1. / SATOSHIDEN ) ;
bid = ask = 1. ; bidvol = askvol = 0. ;
for ( j = i = 0 ; j < prices - > numgroups ; j + + , i + = groupsize )
{
groupsize = prices - > basket [ i ] . groupsize ;
gp = & OB . book [ j ] [ slot ] ;
if ( prices777_groupbidasks ( gp , prices - > groupwts [ j ] , minvol , & prices - > basket [ i ] , groupsize ) ! = 0 )
{
//printf("prices777_groupbidasks i.%d j.%d error\n",i,j);
break ;
}
//printf("%s j%d slot.%d %s numgroups.%d groupsize.%d\n",prices->exchange,j,slot,prices->contract,prices->numgroups,groupsize);
if ( bid > SMALLVAL & & ( b = gp - > bid . s . price ) > SMALLVAL & & ( bv = gp - > bid . s . vol ) > SMALLVAL )
{
//if ( gp->bid.wt*prices->groupwts[j] < 0 )
// bid /= b;
//else
bid * = b ;
prices777_volcalc ( basevols , baseids , gp - > bid . source - > baseid , bv ) ;
prices777_volcalc ( basevols , baseids , gp - > bid . source - > relid , b * bv ) ;
//printf("bid %f b %f bv %f %s %s %f\n",bid,b,bv,gp->bid.source->base,gp->bid.source->rel,bv*b);
} else bid = 0. ;
if ( ask > SMALLVAL & & ( a = gp - > ask . s . price ) > SMALLVAL & & ( av = gp - > ask . s . vol ) > SMALLVAL )
{
//if ( gp->ask.wt*prices->groupwts[j] < 0 )
// ask /= a;
//else
ask * = a ;
prices777_volcalc ( relvols , baseids , gp - > ask . source - > baseid , av ) ;
prices777_volcalc ( relvols , baseids , gp - > ask . source - > relid , a * av ) ;
//printf("ask %f b %f bv %f %s %s %f\n",ask,a,av,gp->ask.source->base,gp->ask.source->rel,av*a);
} else ask = 0. ;
if ( Debuglevel > 2 )
printf ( " %10s %10s/%10s %s (%s %s) wt:%f %2.0f/%2.0f j.%d: b %.8f %12.6f a %.8f %12.6f, bid %.8f ask %.8f inv %f %f \n " , prices - > exchange , gp - > bid . source - > exchange , gp - > ask . source - > exchange , prices - > contract , gp - > bid . source - > contract , gp - > ask . source - > contract , prices - > groupwts [ j ] , gp - > bid . wt , gp - > ask . wt , j , b , bv , a , av , bid , ask , 1 / bid , 1 / ask ) ;
}
for ( j = 0 ; j < prices - > numgroups ; j + + )
{
gp = & OB . book [ j ] [ slot ] ;
if ( gp - > bid . source = = 0 | | gp - > ask . source = = 0 )
{
printf ( " %s: (%s/%s) null source slot.%d j.%d \n " , prices - > exchange , prices - > base , prices - > rel , slot , j ) ;
break ;
}
baseratio = prices777_volratio ( basevols , baseids , gp - > bid . source - > baseid , gp - > bid . s . vol ) ;
relratio = prices777_volratio ( basevols , baseids , gp - > bid . source - > relid , gp - > bid . s . vol * gp - > bid . s . price ) ;
gp - > bid . ratio = ( baseratio < relratio ) ? baseratio : relratio ;
if ( j = = 0 )
bidvol = ( gp - > bid . ratio * gp - > bid . s . vol ) ;
//printf("(%f %f) (%f %f) bid%d bidratio %f bidvol %f ",gp->bid.s.vol,baseratio,gp->bid.s.vol * gp->bid.s.price,relratio,j,gp->bid.ratio,bidvol);
baseratio = prices777_volratio ( relvols , baseids , gp - > ask . source - > baseid , gp - > ask . s . vol ) ;
relratio = prices777_volratio ( relvols , baseids , gp - > ask . source - > relid , gp - > ask . s . vol * gp - > ask . s . price ) ;
gp - > ask . ratio = ( baseratio < relratio ) ? baseratio : relratio ;
if ( j = = 0 )
askvol = ( gp - > ask . ratio * gp - > ask . s . vol ) ;
}
if ( j ! = prices - > numgroups )
{
//printf("%s: j.%d != numgroups.%d\n",prices->exchange,j,prices->numgroups);
break ;
}
for ( j = 0 ; j < MAX_GROUPS * 2 ; j + + )
{
if ( baseids [ j ] = = 0 )
break ;
//printf("{%llu %f %f} ",(long long)baseids[j],basevols[j],relvols[j]);
}
//printf("basevols bidvol %f, askvol %f\n",bidvol,askvol);
gp = & OB . book [ MAX_GROUPS ] [ slot ] ;
if ( bid > SMALLVAL & & bidvol > SMALLVAL )
{
if ( slot = = 0 )
prices - > lastbid = bid ;
gp - > bid . s . timestamp = OB . timestamp , gp - > bid . s . price = bid , gp - > bid . s . vol = bidvol , gp - > bid . slot_ba = ( OB . numbids + + < < 1 ) ;
gp - > bid . source = prices , gp - > bid . wt = prices - > groupwts [ j ] ;
}
if ( ask > SMALLVAL & & askvol > SMALLVAL )
{
if ( slot = = 0 )
prices - > lastask = ask ;
gp - > ask . s . timestamp = OB . timestamp , gp - > ask . s . price = ask , gp - > ask . s . vol = askvol , gp - > ask . slot_ba = ( OB . numasks + + < < 1 ) | 1 ;
gp - > ask . source = prices , gp - > ask . wt = prices - > groupwts [ j ] ;
}
//printf("%s %s slot.%d (%.8f %.6f %.8f %.6f) (%d %d)\n",prices->exchange,prices->contract,slot,gp->bid.s.price,gp->bid.s.vol,gp->ask.s.price,gp->ask.s.vol,OB.numbids,OB.numasks);
}
//fprintf(stderr,"%s basket.%s slot.%d numbids.%d numasks.%d %f %f\n",prices->exchange,prices->contract,slot,prices->O.numbids,prices->O.numasks,prices->O.book[MAX_GROUPS][0].bid.s.price,prices->O.book[MAX_GROUPS][0].ask.s.price);
if ( slot > 0 )
{
prices - > O2 = prices - > O ;
prices - > O = OB ;
if ( prices - > lastbid > SMALLVAL & & prices - > lastask > SMALLVAL )
hbla = 0.5 * ( prices - > lastbid + prices - > lastask ) ;
}
return ( hbla ) ;
}
struct prices777 * prices777_addbundle ( int32_t * validp , int32_t loadprices , struct prices777 * prices , char * exchangestr , uint64_t baseid , uint64_t relid )
{
int32_t j ; struct prices777 * ptr ; struct exchange_info * exchange ;
* validp = - 1 ;
if ( prices ! = 0 )
{
exchangestr = prices - > exchange ;
baseid = prices - > baseid , relid = prices - > relid ;
}
for ( j = 0 ; j < BUNDLE . num ; j + + )
{
if ( ( ptr = BUNDLE . ptrs [ j ] ) ! = 0 & & ( ( ptr - > baseid = = baseid & & ptr - > relid = = relid ) | | ( ptr - > relid = = baseid & & ptr - > baseid = = relid ) ) & & strcmp ( ptr - > exchange , exchangestr ) = = 0 )
return ( ptr ) ;
}
if ( j = = BUNDLE . num )
{
if ( prices ! = 0 )
{
exchange = & Exchanges [ prices - > exchangeid ] ;
if ( loadprices ! = 0 & & exchange - > issue . update ! = 0 )
{
portable_mutex_lock ( & exchange - > mutex ) ;
( exchange - > issue . update ) ( prices , MAX_DEPTH ) ;
portable_mutex_unlock ( & exchange - > mutex ) ;
}
printf ( " total polling.%d added.(%s) \n " , BUNDLE . num , prices - > contract ) ;
if ( exchange - > polling = = 0 )
{
printf ( " First pair for (%s), start polling] \n " , exchange_str ( prices - > exchangeid ) ) ;
exchange - > polling = 1 ;
if ( strcmp ( exchange - > name , " wallet " ) ! = 0 ) //&& strcmp(exchange->name,"jumblr") != 0 && strcmp(exchange->name,"pangea") != 0 )
iguana_launch ( iguana_coinadd ( " BTCD " ) , " exchangeloop " , ( void * ) prices777_exchangeloop , & Exchanges [ prices - > exchangeid ] , IGUANA_EXCHANGETHREAD ) ;
}
BUNDLE . ptrs [ BUNDLE . num ] = prices ;
printf ( " prices777_addbundle.(%s) (%s/%s).%s %llu %llu \n " , prices - > contract , prices - > base , prices - > rel , prices - > exchange , ( long long ) prices - > baseid , ( long long ) prices - > relid ) ;
BUNDLE . num + + ;
} else printf ( " no prices \n " ) ;
* validp = BUNDLE . num ;
return ( prices ) ;
}
return ( 0 ) ;
}
int32_t is_native_crypto ( char * name , uint64_t bits )
{
int32_t i , n ;
if ( ( n = ( int32_t ) strlen ( name ) ) > 0 | | ( n = unstringbits ( name , bits ) ) < = 5 )
{
for ( i = 0 ; i < n ; i + + )
{
if ( ( name [ i ] > = ' 0 ' & & name [ i ] < = ' 9 ' ) | | ( name [ i ] > = ' A ' & & name [ i ] < = ' Z ' ) ) // || (name[i] >= '0' && name[i] <= '9') )
continue ;
printf ( " (%s) is not native crypto \n " , name ) ;
return ( 0 ) ;
}
printf ( " (%s) is native crypto \n " , name ) ;
return ( 1 ) ;
}
return ( 0 ) ;
}
char * _issue_getAsset ( char * assetidstr )
{
char cmd [ 4096 ] , * jsonstr ;
//sprintf(cmd,"requestType=getAsset&asset=%s",assetidstr);
sprintf ( cmd , " requestType=getAsset&asset=%s " , assetidstr ) ;
//printf("_cmd.(%s)\n",cmd);
jsonstr = issue_NXTPOST ( cmd ) ;
//printf("(%s) -> (%s)\n",cmd,jsonstr);
return ( jsonstr ) ;
}
char * _issue_getCurrency ( char * assetidstr )
{
char cmd [ 4096 ] ;
//sprintf(cmd,"requestType=getAsset&asset=%s",assetidstr);
sprintf ( cmd , " requestType=getCurrency¤cy=%s " , assetidstr ) ;
//printf("_cmd.(%s)\n",cmd);
return ( issue_NXTPOST ( cmd ) ) ;
}
int32_t is_mscoin ( char * assetidstr )
{
char * jsonstr ; cJSON * json ; int32_t retcode = 0 ;
if ( ( jsonstr = _issue_getCurrency ( assetidstr ) ) ! = 0 )
{
if ( ( json = cJSON_Parse ( jsonstr ) ) ! = 0 )
{
if ( get_cJSON_int ( json , " errorCode " ) = = 0 )
retcode = 1 ;
free_json ( json ) ;
}
free ( jsonstr ) ;
}
return ( retcode ) ;
}
int32_t get_assetname ( char * name , uint64_t assetid )
{
char assetidstr [ 64 ] , * jsonstr ; cJSON * json ;
name [ 0 ] = 0 ;
if ( is_native_crypto ( name , assetid ) ! = 0 )
return ( ( int32_t ) strlen ( name ) ) ;
expand_nxt64bits ( assetidstr , assetid ) ;
name [ 0 ] = 0 ;
if ( ( jsonstr = _issue_getAsset ( assetidstr ) ) ! = 0 )
{
if ( ( json = cJSON_Parse ( jsonstr ) ) ! = 0 )
{
extract_cJSON_str ( name , 15 , json , " name " ) ;
free_json ( json ) ;
}
free ( jsonstr ) ;
}
return ( ( int32_t ) strlen ( assetidstr ) ) ;
}
uint32_t get_blockutime ( uint32_t blocknum )
{
cJSON * json ;
uint32_t timestamp = 0 ;
char cmd [ 4096 ] , * jsonstr ;
sprintf ( cmd , " requestType=getBlock&height=%u " , blocknum ) ;
if ( ( jsonstr = issue_NXTPOST ( cmd ) ) ! = 0 )
{
//printf("(%s) -> (%s)\n",cmd,jsonstr);
if ( ( json = cJSON_Parse ( jsonstr ) ) ! = 0 )
{
if ( ( timestamp = juint ( json , " timestamp " ) ) ! = 0 )
timestamp + = NXT_GENESISTIME ;
free_json ( json ) ;
}
free ( jsonstr ) ;
}
return ( timestamp ) ;
}
uint64_t calc_decimals_mult ( int32_t decimals )
{
int32_t i ; uint64_t mult = 1 ;
for ( i = 7 - decimals ; i > = 0 ; i - - )
mult * = 10 ;
return ( mult ) ;
}
int32_t _set_assetname ( uint64_t * multp , char * buf , char * jsonstr , uint64_t assetid )
{
int32_t type = 0 , decimals = - 1 ; cJSON * json = 0 ; char assetidstr [ 64 ] , * str ;
* multp = 1 ;
buf [ 0 ] = 0 ;
if ( assetid ! = 0 )
{
//fprintf(stderr,"assetid.%llu\n",(long long)assetid);
if ( ( str = is_MGWasset ( assetid ) ) ! = 0 )
{
strcpy ( buf , str ) ;
return ( 0 ) ;
}
if ( is_native_crypto ( buf , assetid ) ! = 0 )
{
unstringbits ( buf , assetid ) ;
return ( 0 ) ;
}
}
if ( jsonstr = = 0 )
{
if ( assetid = = 0 )
printf ( " _set_assetname null assetid \n " ) , getchar ( ) ;
expand_nxt64bits ( assetidstr , assetid ) ;
type = 2 ;
if ( ( jsonstr = _issue_getAsset ( assetidstr ) ) ! = 0 )
{
//printf("%llu (%s) -> (%s)\n",(long long)assetid,assetidstr,jsonstr);
if ( ( json = cJSON_Parse ( jsonstr ) ) ! = 0 )
{
if ( get_cJSON_int ( json , " errorCode " ) ! = 0 )
{
free_json ( json ) , free ( jsonstr ) ;
if ( ( jsonstr = _issue_getCurrency ( assetidstr ) ) ! = 0 )
{
//printf("(%s) -> (%s)\n",assetidstr,jsonstr);
if ( ( json = cJSON_Parse ( jsonstr ) ) ! = 0 )
{
if ( get_cJSON_int ( json , " errorCode " ) ! = 0 )
{
printf ( " (%s) not asset and not currency (%s) \n " , assetidstr , jsonstr ) ; //, getchar();
free_json ( json ) , free ( jsonstr ) ;
return ( - 1 ) ;
}
type = 5 ;
}
}
}
}
free ( jsonstr ) , jsonstr = 0 ;
} else return ( - 1 ) ;
}
if ( multp ! = 0 )
* multp = 0 ;
if ( json = = 0 )
json = cJSON_Parse ( jsonstr ) ;
if ( json ! = 0 )
{
if ( get_cJSON_int ( json , " errorCode " ) = = 0 )
{
decimals = ( int32_t ) get_cJSON_int ( json , " decimals " ) ;
if ( multp ! = 0 & & decimals > = 0 & & decimals < = 8 )
* multp = calc_decimals_mult ( decimals ) ;
if ( extract_cJSON_str ( buf , 16 , json , " name " ) < = 0 )
decimals = - 1 ;
//printf("%s decimals.%d (%s)\n",assetidstr,decimals,buf);
}
free_json ( json ) ;
}
return ( type ) ;
}
char * peggy_mapname ( char * basebuf , char * relbuf , int32_t i ) // sorry it is messy thing
{
char * base , * rel , buf [ 16 ] ;
base = rel = 0 ;
strcpy ( buf , peggy_contracts [ i ] ) ;
base = buf , rel = " BTCD " ;
if ( strlen ( buf ) > 3 & & strcmp ( buf + strlen ( buf ) - 3 , " USD " ) = = 0 )
{
if ( strcmp ( buf , " BTCUSD " ) = = 0 )
base = " BTC " ;
buf [ strlen ( buf ) - 3 ] = 0 ;
}
else if ( strcmp ( buf , " Copper " ) = = 0 | | strcmp ( buf , " NGAS " ) = = 0 | | strcmp ( buf , " UKOil " ) = = 0 | | strcmp ( buf , " USOil " ) = = 0 | | strcmp ( buf , " US30 " ) = = 0 | | strcmp ( buf , " SPX500 " ) = = 0 | | strcmp ( buf , " NAS100 " ) = = 0 )
rel = " USD " ;
else if ( strcmp ( buf , " Bund " ) = = 0 )
rel = " yield " ;
else if ( strcmp ( buf , " EUSTX50 " ) = = 0 )
rel = " EUR " ;
else if ( strcmp ( buf , " JPN225 " ) = = 0 )
rel = " JPY " ;
else if ( strcmp ( buf , " UK100 " ) = = 0 )
rel = " GBP " ;
else if ( strcmp ( buf , " GER30 " ) = = 0 )
rel = " EUR " ;
else if ( strcmp ( buf , " SUI30 " ) = = 0 )
rel = " CHF " ;
else if ( strcmp ( buf , " AUS200 " ) = = 0 )
rel = " AUD " ;
else if ( strcmp ( buf , " HKG33 " ) = = 0 )
rel = " HKD " ;
else if ( strlen ( buf ) > 3 & & strcmp ( buf + strlen ( buf ) - 3 , " BTC " ) = = 0 )
base = buf , buf [ strlen ( buf ) - 3 ] = 0 ;
if ( i = = sizeof ( peggy_contracts ) / sizeof ( * peggy_contracts ) - 1 & & strcmp ( peggy_contracts [ i ] , " BTCUSD " ) = = 0 )
base = " BTC " , rel = " USD " ;
else if ( i = = sizeof ( peggy_contracts ) / sizeof ( * peggy_contracts ) - 2 & & strcmp ( peggy_contracts [ i ] , " BTCCNY " ) = = 0 )
base = " BTC " , rel = " CNY " ;
else if ( i = = sizeof ( peggy_contracts ) / sizeof ( * peggy_contracts ) - 3 & & strcmp ( peggy_contracts [ i ] , " BTCRUB " ) = = 0 )
base = " BTC " , rel = " RUB " ;
else if ( i = = sizeof ( peggy_contracts ) / sizeof ( * peggy_contracts ) - 4 & & strcmp ( peggy_contracts [ i ] , " XAUUSD " ) = = 0 )
base = " XAU " , rel = " USD " ;
else if ( i = = 0 )
base = " BTCD " , rel = " maincurrency peggy, price is BTCD/BTC for info only " ;
basebuf [ 0 ] = relbuf [ 0 ] = 0 ;
if ( rel ! = 0 )
strcpy ( relbuf , rel ) ; //, printf("rel.(%s) ",rel);
if ( base ! = 0 )
strcpy ( basebuf , base ) ; //, printf("base.(%s) ",base);
return ( basebuf ) ;
}
uint64_t peggy_basebits ( char * name )
{
int32_t i ; char basebuf [ 64 ] , relbuf [ 64 ] ;
for ( i = 0 ; i < 64 ; i + + )
{
if ( strcmp ( name , peggy_contracts [ i ] ) = = 0 )
{
peggy_mapname ( basebuf , relbuf , i ) ;
return ( stringbits ( basebuf ) ) ;
}
}
return ( 0 ) ;
}
uint64_t peggy_relbits ( char * name )
{
int32_t i ; char basebuf [ 64 ] , relbuf [ 64 ] ;
for ( i = 0 ; i < 64 ; i + + )
{
if ( strcmp ( name , peggy_contracts [ i ] ) = = 0 )
{
peggy_mapname ( basebuf , relbuf , i ) ;
return ( stringbits ( relbuf ) ) ;
}
}
return ( 0 ) ;
}
int32_t prices777_key ( char * key , char * exchange , char * name , char * base , uint64_t baseid , char * rel , uint64_t relid )
{
int32_t len , keysize = 0 ;
memcpy ( & key [ keysize ] , & baseid , sizeof ( baseid ) ) , keysize + = sizeof ( baseid ) ;
memcpy ( & key [ keysize ] , & relid , sizeof ( relid ) ) , keysize + = sizeof ( relid ) ;
strcpy ( & key [ keysize ] , exchange ) , keysize + = strlen ( exchange ) + 1 ;
strcpy ( & key [ keysize ] , name ) , keysize + = strlen ( name ) + 1 ;
memcpy ( & key [ keysize ] , base , strlen ( base ) + 1 ) , keysize + = strlen ( base ) + 1 ;
if ( rel ! = 0 & & ( len = ( int32_t ) strlen ( rel ) ) > 0 )
memcpy ( & key [ keysize ] , rel , len + 1 ) , keysize + = len + 1 ;
return ( keysize ) ;
}
uint64_t InstantDEX_name ( char * key , int32_t * keysizep , char * exchange , char * name , char * base , uint64_t * baseidp , char * rel , uint64_t * relidp )
{
uint64_t baseid , relid , assetbits = 0 ; char * s , * str ;
baseid = * baseidp , relid = * relidp ;
//printf(">>>>>> name.(%s) (%s/%s) %llu/%llu\n",name,base,rel,(long long)baseid,(long long)relid);
if ( strcmp ( base , " 5527630 " ) = = 0 | | baseid = = 5527630 )
strcpy ( base , " NXT " ) ;
if ( strcmp ( rel , " 5527630 " ) = = 0 | | relid = = 5527630 )
strcpy ( rel , " NXT " ) ;
if ( relid = = 0 & & rel [ 0 ] ! = 0 )
{
if ( is_decimalstr ( rel ) ! = 0 )
relid = calc_nxt64bits ( rel ) ;
else relid = is_MGWcoin ( rel ) ;
}
else if ( ( str = is_MGWasset ( relid ) ) ! = 0 )
strcpy ( rel , str ) ;
if ( baseid = = 0 & & base [ 0 ] ! = 0 )
{
if ( is_decimalstr ( base ) ! = 0 )
baseid = calc_nxt64bits ( base ) ;
else baseid = is_MGWcoin ( base ) ;
}
else if ( ( str = is_MGWasset ( baseid ) ) ! = 0 )
strcpy ( base , str ) ;
if ( strcmp ( " InstantDEX " , exchange ) = = 0 | | strcmp ( " nxtae " , exchange ) = = 0 | | strcmp ( " unconf " , exchange ) = = 0 | | ( baseid ! = 0 & & relid ! = 0 ) )
{
if ( strcmp ( rel , " NXT " ) = = 0 )
s = " + " , relid = stringbits ( " NXT " ) , strcpy ( rel , " NXT " ) ;
else if ( strcmp ( base , " NXT " ) = = 0 )
s = " - " , baseid = stringbits ( " NXT " ) , strcpy ( base , " NXT " ) ;
else s = " " ;
if ( base [ 0 ] = = 0 )
{
get_assetname ( base , baseid ) ;
//printf("mapped %llu -> (%s)\n",(long long)baseid,base);
}
if ( rel [ 0 ] = = 0 )
{
get_assetname ( rel , relid ) ;
//printf("mapped %llu -> (%s)\n",(long long)relid,rel);
}
if ( name [ 0 ] = = 0 )
{
if ( relid = = NXT_ASSETID )
sprintf ( name , " %llu " , ( long long ) baseid ) ;
else if ( baseid = = NXT_ASSETID )
sprintf ( name , " -%llu " , ( long long ) relid ) ;
else sprintf ( name , " %llu/%llu " , ( long long ) baseid , ( long long ) relid ) ;
}
}
else
{
if ( base [ 0 ] ! = 0 & & rel [ 0 ] ! = 0 & & baseid = = 0 & & relid = = 0 )
{
baseid = peggy_basebits ( base ) , relid = peggy_basebits ( rel ) ;
if ( name [ 0 ] = = 0 & & baseid ! = 0 & & relid ! = 0 )
{
strcpy ( name , base ) ; // need to be smarter
strcat ( name , " / " ) ;
strcat ( name , rel ) ;
}
}
if ( name [ 0 ] = = 0 | | baseid = = 0 | | relid = = 0 | | base [ 0 ] = = 0 | | rel [ 0 ] = = 0 )
{
if ( baseid = = 0 & & base [ 0 ] ! = 0 )
baseid = stringbits ( base ) ;
else if ( baseid ! = 0 & & base [ 0 ] = = 0 )
sprintf ( base , " %llu " , ( long long ) baseid ) ;
if ( relid = = 0 & & rel [ 0 ] ! = 0 )
{
relid = stringbits ( rel ) ;
printf ( " set relid.%llu <- (%s) \n " , ( long long ) relid , rel ) ;
}
else if ( relid ! = 0 & & rel [ 0 ] = = 0 )
sprintf ( rel , " %llu " , ( long long ) relid ) ;
if ( name [ 0 ] = = 0 )
strcpy ( name , base ) , strcat ( name , " / " ) , strcat ( name , rel ) ;
}
}
* baseidp = baseid , * relidp = relid ;
* keysizep = prices777_key ( key , exchange , name , base , baseid , rel , relid ) ;
//printf("<<<<<<< name.(%s) (%s/%s) %llu/%llu\n",name,base,rel,(long long)baseid,(long long)relid);
return ( assetbits ) ;
}
int32_t create_basketitem ( struct prices777_basket * basketitem , cJSON * item , char * refbase , char * refrel , int32_t basketsize )
{
struct destbuf exchangestr , name , base , rel ; char key [ 512 ] ; uint64_t tmp , baseid , relid ; int32_t groupid , keysize , valid ; double wt ; struct prices777 * prices ;
copy_cJSON ( & exchangestr , jobj ( item , " exchange " ) ) ;
if ( strcmp ( " jumblr " , exchangestr . buf ) = = 0 | | strcmp ( " pangea " , exchangestr . buf ) = = 0 | | strcmp ( " wallet " , exchangestr . buf ) = = 0 | | exchange_find ( exchangestr . buf ) = = 0 )
{
printf ( " create_basketitem: illegal exchange.%s \n " , exchangestr . buf ) ;
return ( - 1 ) ;
}
copy_cJSON ( & name , jobj ( item , " name " ) ) ;
copy_cJSON ( & base , jobj ( item , " base " ) ) ;
copy_cJSON ( & rel , jobj ( item , " rel " ) ) ;
if ( ( baseid = j64bits ( item , " baseid " ) ) ! = 0 & & base . buf [ 0 ] = = 0 )
{
_set_assetname ( & tmp , base . buf , 0 , baseid ) ;
//printf("GOT.(%s) <- %llu\n",base.buf,(long long)baseid);
}
else if ( baseid = = 0 )
baseid = stringbits ( base . buf ) ;
if ( ( relid = j64bits ( item , " relid " ) ) ! = 0 & & rel . buf [ 0 ] = = 0 )
{
_set_assetname ( & tmp , rel . buf , 0 , relid ) ;
//printf("GOT.(%s) <- %llu\n",rel.buf,(long long)relid);
}
else if ( relid = = 0 )
relid = stringbits ( rel . buf ) ;
groupid = juint ( item , " group " ) ;
wt = jdouble ( item , " wt " ) ;
if ( wt = = 0. )
wt = 1. ;
if ( strcmp ( refbase , rel . buf ) = = 0 | | strcmp ( refrel , base . buf ) = = 0 )
{
if ( wt ! = - 1 )
{
printf ( " need to flip wt %f for (%s/%s) ref.(%s/%s) \n " , wt , base . buf , rel . buf , refbase , refrel ) ;
wt = - 1. ;
}
}
else if ( wt ! = 1. )
{
printf ( " need to flip wt %f for (%s/%s) ref.(%s/%s) \n " , wt , base . buf , rel . buf , refbase , refrel ) ;
wt = 1. ;
}
if ( name . buf [ 0 ] = = 0 )
sprintf ( name . buf , " %s/%s " , base . buf , rel . buf ) ;
if ( base . buf [ 0 ] = = 0 )
strcpy ( base . buf , refbase ) ;
if ( rel . buf [ 0 ] = = 0 )
strcpy ( rel . buf , refrel ) ;
InstantDEX_name ( key , & keysize , exchangestr . buf , name . buf , base . buf , & baseid , rel . buf , & relid ) ;
printf ( " >>>>>>>>>> create basketitem.(%s) name.(%s) %s (%s/%s) %llu/%llu wt %f \n " , jprint ( item , 0 ) , name . buf , exchangestr . buf , base . buf , rel . buf , ( long long ) baseid , ( long long ) relid , wt ) ;
if ( ( prices = prices777_initpair ( 1 , exchangestr . buf , base . buf , rel . buf , 0. , name . buf , baseid , relid , basketsize ) ) ! = 0 )
{
prices777_addbundle ( & valid , 0 , prices , 0 , 0 , 0 ) ;
basketitem - > prices = prices ;
basketitem - > wt = wt ;
basketitem - > groupid = groupid ;
strcpy ( basketitem - > base , base . buf ) ;
strcpy ( basketitem - > rel , rel . buf ) ;
return ( 0 ) ;
} else printf ( " couldnt create basketitem \n " ) ;
return ( - 1 ) ;
}
struct prices777 * prices777_makebasket ( char * basketstr , cJSON * _basketjson , int32_t addbasket , char * typestr , struct prices777 * ptrs [ ] , int32_t num )
{
//{"name":"NXT/BTC","base":"NXT","rel":"BTC","basket":[{"exchange":"poloniex"},{"exchange":"btc38"}]}
int32_t i , j , n , keysize , valid , basketsize , total = 0 ; struct destbuf refname , refbase , refrel ; char key [ 8192 ] ; uint64_t refbaseid = 0 , refrelid = 0 ;
struct prices777_basket * basketitem , * basket = 0 ; cJSON * basketjson , * array , * item ; struct prices777 * prices = 0 ;
if ( ( basketjson = _basketjson ) = = 0 & & ( basketjson = cJSON_Parse ( basketstr ) ) = = 0 )
{
printf ( " cant parse basketstr.(%s) \n " , basketstr ) ;
return ( 0 ) ;
}
copy_cJSON ( & refname , jobj ( basketjson , " name " ) ) ;
copy_cJSON ( & refbase , jobj ( basketjson , " base " ) ) ;
copy_cJSON ( & refrel , jobj ( basketjson , " rel " ) ) ;
refbaseid = j64bits ( basketjson , " baseid " ) ;
refrelid = j64bits ( basketjson , " relid " ) ;
if ( ( array = jarray ( & n , basketjson , " basket " ) ) ! = 0 )
{
printf ( " MAKE/(%s) n.%d num.%d \n " , jprint ( basketjson , 0 ) , n , num ) ;
basketsize = ( n + num ) ;
basket = calloc ( 1 , sizeof ( * basket ) * basketsize ) ;
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( array , i ) ;
if ( create_basketitem ( & basket [ total ] , item , refbase . buf , refrel . buf , basketsize ) < 0 )
printf ( " warning: >>>>>>>>>>>> skipped create_basketitem %d of %d of %d \n " , i , n , basketsize ) ;
else
{
printf ( " MAKE.%d: (%s) %p.%s \n " , total , jprint ( item , 0 ) , basket [ total ] . prices , basket [ total ] . prices - > exchange ) ;
total + + ;
}
}
if ( ptrs ! = 0 & & num > 0 )
{
for ( i = 0 ; i < num ; i + + )
{
basketitem = & basket [ total ] ;
j = 0 ;
if ( total > 0 )
{
for ( j = 0 ; j < n + i ; j + + )
{
if ( basket [ j ] . prices = = ptrs [ i ] )
{
printf ( " skip duplicate basket[%d] == ptrs[%d] \n " , j , i ) ;
break ;
}
}
}
if ( j = = n + i )
{
basketitem - > prices = ptrs [ i ] ;
if ( strcmp ( refbase . buf , ptrs [ i ] - > rel ) = = 0 | | strcmp ( refrel . buf , ptrs [ i ] - > base ) = = 0 )
basketitem - > wt = - 1 ;
else basketitem - > wt = 1 ;
basketitem - > groupid = 0 ;
strcpy ( basketitem - > base , ptrs [ i ] - > base ) ;
strcpy ( basketitem - > rel , ptrs [ i ] - > rel ) ;
total + + ;
printf ( " extrai.%d/%d total.%d wt.%f (%s/%s).%s \n " , i , num , total , basketitem - > wt , ptrs [ i ] - > base , ptrs [ i ] - > rel , ptrs [ i ] - > exchange ) ;
}
}
}
printf ( " >>>>> addbasket.%d (%s/%s).%s %llu %llu \n " , addbasket , refbase . buf , refrel . buf , typestr , ( long long ) refbaseid , ( long long ) refrelid ) ;
InstantDEX_name ( key , & keysize , typestr , refname . buf , refbase . buf , & refbaseid , refrel . buf , & refrelid ) ;
printf ( " >>>>> addbasket.%d (%s/%s).%s %llu %llu \n " , addbasket , refbase . buf , refrel . buf , typestr , ( long long ) refbaseid , ( long long ) refrelid ) ;
if ( addbasket ! = 0 )
{
prices777_addbundle ( & valid , 0 , 0 , typestr , refbaseid , refrelid ) ;
printf ( " <<<<< created.%s valid.%d refname.(%s) (%s/%s).%s %llu %llu \n " , typestr , valid , refname . buf , refbase . buf , refrel . buf , typestr , ( long long ) refbaseid , ( long long ) refrelid ) ;
} else valid = 0 ;
if ( valid > = 0 )
{
if ( ( prices = prices777_createbasket ( addbasket , refname . buf , refbase . buf , refrel . buf , refbaseid , refrelid , basket , total , typestr ) ) ! = 0 )
{
if ( addbasket ! = 0 )
BUNDLE . ptrs [ BUNDLE . num ] = prices ;
prices - > lastprice = prices777_basket ( prices , MAX_DEPTH ) ;
//printf("C.bsize.%d total polling.%d added.(%s/%s).%s updating basket lastprice %f changed.%p %d groupsize.%d numgroups.%d %p\n",total,BUNDLE.num,prices->base,prices->rel,prices->exchange,prices->lastprice,&prices->changed,prices->changed,prices->basket[0].groupsize,prices->numgroups,&prices->basket[0].groupsize);
BUNDLE . num + + ;
}
} else prices = 0 ;
if ( basketjson ! = _basketjson )
free_json ( basketjson ) ;
free ( basket ) ;
}
return ( prices ) ;
}
cJSON * inner_json ( double price , double vol , uint32_t timestamp , uint64_t quoteid , uint64_t nxt64bits , uint64_t qty , uint64_t pqt , uint64_t baseamount , uint64_t relamount )
{
cJSON * inner = cJSON_CreateArray ( ) ;
char numstr [ 64 ] ;
sprintf ( numstr , " %.8f " , price ) , cJSON_AddItemToArray ( inner , cJSON_CreateString ( numstr ) ) ;
sprintf ( numstr , " %.8f " , vol ) , cJSON_AddItemToArray ( inner , cJSON_CreateString ( numstr ) ) ;
sprintf ( numstr , " %llu " , ( long long ) quoteid ) , cJSON_AddItemToArray ( inner , cJSON_CreateString ( numstr ) ) ;
cJSON_AddItemToArray ( inner , cJSON_CreateNumber ( timestamp ) ) ;
sprintf ( numstr , " %llu " , ( long long ) nxt64bits ) , cJSON_AddItemToArray ( inner , cJSON_CreateString ( numstr ) ) ;
sprintf ( numstr , " %llu " , ( long long ) qty ) , cJSON_AddItemToArray ( inner , cJSON_CreateString ( numstr ) ) ;
sprintf ( numstr , " %llu " , ( long long ) pqt ) , cJSON_AddItemToArray ( inner , cJSON_CreateString ( numstr ) ) ;
sprintf ( numstr , " %llu " , ( long long ) baseamount ) , cJSON_AddItemToArray ( inner , cJSON_CreateString ( numstr ) ) ;
sprintf ( numstr , " %llu " , ( long long ) relamount ) , cJSON_AddItemToArray ( inner , cJSON_CreateString ( numstr ) ) ;
// printf("(%s) ",jprint(inner,0));
return ( inner ) ;
}
double prices777_NXT ( struct prices777 * prices , int32_t maxdepth )
{
uint32_t timestamp ; int32_t flip , i , n ; uint64_t baseamount , relamount , qty , pqt ; char url [ 1024 ] , * str , * cmd , * field ;
cJSON * json , * bids , * asks , * srcobj , * item , * array ; double price , vol , hbla = 0. ;
if ( NXT_ASSETID ! = stringbits ( " NXT " ) | | ( strcmp ( prices - > rel , " NXT " ) ! = 0 & & strcmp ( prices - > rel , " 5527630 " ) ! = 0 ) )
{
printf ( " NXT_ASSETID.%llu != %llu stringbits rel.%s \n " , ( long long ) NXT_ASSETID , ( long long ) stringbits ( " NXT " ) , prices - > rel ) ; //, getchar();
return ( 0 ) ;
}
bids = cJSON_CreateArray ( ) , asks = cJSON_CreateArray ( ) ;
for ( flip = 0 ; flip < 2 ; flip + + )
{
/*{
" offer " : " 16959774565785265980 " ,
" expirationHeight " : 1000000 ,
" accountRS " : " NXT-QFAF-GR4F-RBSR-AXW2G " ,
" limit " : " 9000000 " ,
" currency " : " 5775213290661997199 " ,
" supply " : " 0 " ,
" account " : " 9728792749189838093 " ,
" height " : 348856 ,
" rateNQT " : " 650 "
} */
if ( prices - > type ! = 5 )
{
if ( flip = = 0 )
cmd = " getBidOrders " , field = " bidOrders " , array = bids ;
else cmd = " getAskOrders " , field = " askOrders " , array = asks ;
sprintf ( url , " requestType=%s&asset=%llu&limit=%d " , cmd , ( long long ) prices - > baseid , maxdepth ) ;
}
else
{
if ( flip = = 0 )
cmd = " getBuyOffers " , field = " offers " , array = bids ;
else cmd = " getSellOffers " , field = " offers " , array = asks ;
sprintf ( url , " requestType=%s¤cy=%llu&limit=%d " , cmd , ( long long ) prices - > baseid , maxdepth ) ;
}
if ( ( str = issue_NXTPOST ( url ) ) ! = 0 )
{
//printf("{%s}\n",str);
if ( ( json = cJSON_Parse ( str ) ) ! = 0 )
{
if ( ( srcobj = jarray ( & n , json , field ) ) ! = 0 )
{
for ( i = 0 ; i < n & & i < maxdepth ; i + + )
{
/*
" quantityQNT " : " 79 " ,
" priceNQT " : " 13499000000 " ,
" transactionHeight " : 480173 ,
" accountRS " : " NXT-FJQN-8QL2-BMY3-64VLK " ,
" transactionIndex " : 1 ,
" asset " : " 15344649963748848799 " ,
" type " : " ask " ,
" account " : " 5245394173527769812 " ,
" order " : " 17926122097022414596 " ,
" height " : 480173
*/
item = cJSON_GetArrayItem ( srcobj , i ) ;
if ( prices - > type ! = 5 )
qty = j64bits ( item , " quantityQNT " ) , pqt = j64bits ( item , " priceNQT " ) ;
else qty = j64bits ( item , " limit " ) , pqt = j64bits ( item , " rateNQT " ) ;
baseamount = ( qty * prices - > ap_mult ) , relamount = ( qty * pqt ) ;
price = prices777_price_volume ( & vol , baseamount , relamount ) ;
if ( i = = 0 )
{
hbla = ( hbla = = 0. ) ? price : 0.5 * ( price + hbla ) ;
if ( flip = = 0 )
prices - > lastbid = price ;
else prices - > lastask = price ;
}
//printf("(%llu %llu) %f %f mult.%llu qty.%llu pqt.%llu baseamount.%lld relamount.%lld\n",(long long)prices->baseid,(long long)prices->relid,price,vol,(long long)prices->ap_mult,(long long)qty,(long long)pqt,(long long)baseamount,(long long)relamount);
timestamp = get_blockutime ( juint ( item , " height " ) ) ;
item = inner_json ( price , vol , timestamp , j64bits ( item , prices - > type ! = 5 ? " order " : " offer " ) , j64bits ( item , " account " ) , qty , pqt , baseamount , relamount ) ;
cJSON_AddItemToArray ( array , item ) ;
}
}
free_json ( json ) ;
}
free ( str ) ;
} else printf ( " cant get.(%s) \n " , url ) ;
}
json = cJSON_CreateObject ( ) ;
cJSON_AddItemToObject ( json , " bids " , bids ) ;
cJSON_AddItemToObject ( json , " asks " , asks ) ;
if ( Debuglevel > 2 )
printf ( " NXTAE.(%s) \n " , jprint ( json , 0 ) ) ;
prices777_json_orderbook ( " nxtae " , prices , maxdepth , json , 0 , " bids " , " asks " , 0 , 0 ) ;
free_json ( json ) ;
return ( hbla ) ;
}
double prices777_unconfNXT ( struct prices777 * prices , int32_t maxdepth )
{
struct destbuf account , txidstr , comment , recipient ; char url [ 1024 ] , * str ; uint32_t timestamp ; int32_t type , i , subtype , n ;
cJSON * json , * bids , * asks , * array , * txobj , * attachment ;
double price , vol ; uint64_t assetid , accountid , quoteid , baseamount , relamount , qty , priceNQT , amount ;
bids = cJSON_CreateArray ( ) , asks = cJSON_CreateArray ( ) ;
prices - > lastbid = prices - > lastask = 0. ;
prices - > O . numbids = prices - > O . numasks = 0 ;
sprintf ( url , " requestType=getUnconfirmedTransactions " ) ;
if ( IGUANA_disableNXT = = 0 & & ( str = issue_NXTPOST ( url ) ) ! = 0 )
{
//printf("{%s}\n",str);
if ( ( json = cJSON_Parse ( str ) ) ! = 0 )
{
if ( ( array = jarray ( & n , json , " unconfirmedTransactions " ) ) ! = 0 )
{
for ( i = 0 ; i < n ; i + + )
{
//{"senderPublicKey":"45c9266036e705a9559ccbd2b2c92b28ea6363d2723e8d42433b1dfaa421066c","signature":"9d6cefff4c67f8cf4e9487122e5e6b1b65725815127063df52e9061036e78c0b49ba38dbfc12f03c158697f0af5811ce9398702c4acb008323df37dc55c1b43d","feeNQT":"100000000","type":2,"fullHash":"6a2cd914b9d4a5d8ebfaecaba94ef4e7d2b681c236a4bee56023aafcecd9b704","version":1,"phased":false,"ecBlockId":"887016880740444200","signatureHash":"ba8eee4beba8edbb6973df4243a94813239bf57b91cac744cb8d6a5d032d5257","attachment":{"quantityQNT":"50","priceNQT":"18503000003","asset":"13634675574519917918","version.BidOrderPlacement":1},"senderRS":"NXT-FJQN-8QL2-BMY3-64VLK","subtype":3,"amountNQT":"0","sender":"5245394173527769812","ecBlockHeight":495983,"deadline":1440,"transaction":"15611117574733507690","timestamp":54136768,"height":2147483647},{"senderPublicKey":"c42956d0a9abc5a2e455e69c7e65ff9a53de2b697e913b25fcb06791f127af06","signature":"ca2c3f8e32d3aa003692fef423193053c751235a25eb5b67c21aefdeb7a41d0d37bc084bd2e33461606e25f09ced02d1e061420da7e688306e76de4d4cf90ae0","feeNQT":"100000000","type":2,"fullHash":"51c04de7106a5d5a2895db05305b53dd33fa8b9935d549f765aa829a23c68a6b","version":1,"phased":false,"ecBlockId":"887016880740444200","signatureHash":"d76fce4c081adc29f7e60eba2a930ab5050dd79b6a1355fae04863dddf63730c","attachment":{"version.AskOrderPlacement":1,"quantityQNT":"11570","priceNQT":"110399999","asset":"979292558519844732"},"senderRS":"NXT-ANWW-C5BZ-SGSB-8LGZY","subtype":2,"amountNQT":"0","sender":"8033808554894054300","ecBlockHeight":495983,"deadline":1440,"transaction":"6511477257080258641","timestamp":54136767,"height":2147483647}],"requestProcessingTime":0}
/* "senderRS": "NXT-M6QF-Q5WK-2UXK-5D3HR",
" subtype " : 0 ,
" amountNQT " : " 137700000000 " ,
" sender " : " 4304363382952792781 " ,
" recipientRS " : " NXT-6AC7-V9BD-NL5W-5BUWF " ,
" recipient " : " 3959589697280418117 " ,
" ecBlockHeight " : 506207 ,
" deadline " : 1440 ,
" transaction " : " 5605109208989354417 " ,
" timestamp " : 55276659 ,
" height " : 2147483647 */
if ( ( txobj = jitem ( array , i ) ) = = 0 )
continue ;
copy_cJSON ( & txidstr , cJSON_GetObjectItem ( txobj , " transaction " ) ) ;
copy_cJSON ( & recipient , cJSON_GetObjectItem ( txobj , " recipient " ) ) ;
copy_cJSON ( & account , cJSON_GetObjectItem ( txobj , " account " ) ) ;
if ( account . buf [ 0 ] = = 0 )
copy_cJSON ( & account , cJSON_GetObjectItem ( txobj , " sender " ) ) ;
accountid = calc_nxt64bits ( account . buf ) ;
type = ( int32_t ) get_API_int ( cJSON_GetObjectItem ( txobj , " type " ) , - 1 ) ;
subtype = ( int32_t ) get_API_int ( cJSON_GetObjectItem ( txobj , " subtype " ) , - 1 ) ;
timestamp = juint ( txobj , " timestamp " ) ;
amount = get_API_nxt64bits ( cJSON_GetObjectItem ( txobj , " amountNQT " ) ) ;
qty = amount = assetid = 0 ;
if ( ( attachment = cJSON_GetObjectItem ( txobj , " attachment " ) ) ! = 0 )
{
assetid = get_API_nxt64bits ( cJSON_GetObjectItem ( attachment , " asset " ) ) ;
comment . buf [ 0 ] = 0 ;
qty = get_API_nxt64bits ( cJSON_GetObjectItem ( attachment , " quantityQNT " ) ) ;
priceNQT = get_API_nxt64bits ( cJSON_GetObjectItem ( attachment , " priceNQT " ) ) ;
baseamount = ( qty * prices - > ap_mult ) , relamount = ( qty * priceNQT ) ;
copy_cJSON ( & comment , jobj ( attachment , " message " ) ) ;
if ( comment . buf [ 0 ] ! = 0 )
{
int32_t match_unconfirmed ( char * sender , char * hexstr , cJSON * txobj , char * txidstr , char * account , uint64_t amount , uint64_t qty , uint64_t assetid , char * recipient ) ;
//printf("sender.%s -> recv.(%s)\n",account,recipient);
match_unconfirmed ( account . buf , comment . buf , txobj , txidstr . buf , account . buf , amount , qty , assetid , recipient . buf ) ;
}
quoteid = calc_nxt64bits ( txidstr . buf ) ;
price = prices777_price_volume ( & vol , baseamount , relamount ) ;
if ( prices - > baseid = = assetid )
{
if ( Debuglevel > 2 )
printf ( " unconf.%d subtype.%d %s %llu (%llu %llu) %f %f mult.%llu qty.%llu pqt.%llu baseamount.%lld relamount.%lld \n " , i , subtype , txidstr . buf , ( long long ) prices - > baseid , ( long long ) assetid , ( long long ) NXT_ASSETID , price , vol , ( long long ) prices - > ap_mult , ( long long ) qty , ( long long ) priceNQT , ( long long ) baseamount , ( long long ) relamount ) ;
if ( subtype = = 2 )
{
array = bids ;
prices - > lastbid = price ;
}
else if ( subtype = = 3 )
{
array = asks ;
prices - > lastask = price ;
}
cJSON_AddItemToArray ( array , inner_json ( price , vol , timestamp , quoteid , accountid , qty , priceNQT , baseamount , relamount ) ) ;
}
}
}
free_json ( json ) ;
}
free ( str ) ;
} else printf ( " cant get.(%s) \n " , url ) ;
}
json = cJSON_CreateObject ( ) ;
cJSON_AddItemToObject ( json , " bids " , bids ) ;
cJSON_AddItemToObject ( json , " asks " , asks ) ;
prices777_json_orderbook ( " unconf " , prices , maxdepth , json , 0 , " bids " , " asks " , 0 , 0 ) ;
if ( Debuglevel > 2 ) //|| prices->O.numbids != 0 || prices->O.numasks != 0 )
printf ( " %s %s/%s unconf.(%s) %f %f (%d %d) \n " , prices - > contract , prices - > base , prices - > rel , jprint ( json , 0 ) , prices - > lastbid , prices - > lastask , prices - > O . numbids , prices - > O . numasks ) ;
free_json ( json ) ;
return ( _pairaved ( prices - > lastbid , prices - > lastask ) ) ;
}
double prices777_InstantDEX ( struct prices777 * prices , int32_t maxdepth )
{
cJSON * json ; double hbla = 0. ;
if ( ( json = InstantDEX_orderbook ( prices ) ) ! = 0 ) // strcmp(prices->exchange,INSTANTDEX_NAME) == 0 &&
{
if ( Debuglevel > 2 )
printf ( " InstantDEX.(%s) \n " , jprint ( json , 0 ) ) ;
prices777_json_orderbook ( " InstantDEX " , prices , maxdepth , json , 0 , " bids " , " asks " , 0 , 0 ) ;
free_json ( json ) ;
}
return ( hbla ) ;
}
# define BASE_ISNXT 1
# define BASE_ISASSET 2
# define BASE_ISNAME 4
# define BASE_ISMGW 8
# define BASE_EXCHANGEASSET 16
int32_t calc_baseflags ( char * exchange , char * base , uint64_t * baseidp )
{
char assetidstr [ 64 ] , tmpstr [ 64 ] , * str ; uint64_t tmp ; int32_t flags = 0 ;
exchange [ 0 ] = 0 ;
printf ( " calc_baseflags.(%s/%llu) " , base , ( long long ) * baseidp ) ;
if ( strcmp ( base , " NXT " ) = = 0 | | * baseidp = = NXT_ASSETID )
strcpy ( base , " NXT " ) , * baseidp = NXT_ASSETID , flags | = BASE_ISNXT ;
else
{
if ( * baseidp = = 0 )
{
if ( is_decimalstr ( base ) ! = 0 )
{
* baseidp = calc_nxt64bits ( base ) , flags | = BASE_ISASSET ;
unstringbits ( tmpstr , * baseidp ) ;
if ( ( tmp = is_MGWcoin ( tmpstr ) ) ! = 0 )
* baseidp = tmp , flags | = ( BASE_EXCHANGEASSET | BASE_ISMGW ) ;
else
{
printf ( " set base.(%s) -> %llu \n " , base , ( long long ) * baseidp ) ;
if ( ( str = is_MGWasset ( * baseidp ) ) ! = 0 )
strcpy ( base , str ) , flags | = ( BASE_EXCHANGEASSET | BASE_ISMGW ) ;
}
}
else
{
* baseidp = stringbits ( base ) , flags | = BASE_ISNAME ;
printf ( " stringbits.(%s) -> %llu \n " , base , ( long long ) * baseidp ) ;
}
}
else
{
if ( ( str = is_MGWasset ( * baseidp ) ) ! = 0 )
{
printf ( " is MGWasset.(%s) \n " , str ) ;
strcpy ( base , str ) , flags | = ( BASE_EXCHANGEASSET | BASE_ISMGW | BASE_ISASSET ) ;
}
else
{
expand_nxt64bits ( assetidstr , * baseidp ) ;
if ( ( str = is_tradedasset ( exchange , assetidstr ) ) ! = 0 )
{
strcpy ( base , str ) , flags | = ( BASE_EXCHANGEASSET | BASE_ISASSET ) ;
printf ( " %s is tradedasset at (%s) %llu \n " , assetidstr , str , ( long long ) * baseidp ) ;
}
else
{
unstringbits ( tmpstr , * baseidp ) ;
if ( ( tmp = is_MGWcoin ( tmpstr ) ) ! = 0 )
strcpy ( base , tmpstr ) , * baseidp = tmp , flags | = ( BASE_EXCHANGEASSET | BASE_ISMGW | BASE_ISASSET ) ;
else
{
_set_assetname ( & tmp , base , 0 , * baseidp ) , flags | = BASE_ISASSET ;
printf ( " _set_assetname.(%s) from %llu \n " , base , ( long long ) * baseidp ) ;
}
}
}
}
if ( ( flags & ( BASE_ISASSET | BASE_EXCHANGEASSET | BASE_ISMGW ) ) = = 0 )
* baseidp = stringbits ( base ) ;
}
printf ( " -> flags.%d (%s %llu) %s \n " , flags , base , ( long long ) * baseidp , exchange ) ;
return ( flags ) ;
}
void setitemjson ( cJSON * item , char * name , char * base , uint64_t baseid , char * rel , uint64_t relid )
{
char numstr [ 64 ] ;
jaddstr ( item , " name " , name ) , jaddstr ( item , " base " , base ) , jaddstr ( item , " rel " , rel ) ;
sprintf ( numstr , " %llu " , ( long long ) baseid ) , jaddstr ( item , " baseid " , numstr ) ;
sprintf ( numstr , " %llu " , ( long long ) relid ) , jaddstr ( item , " relid " , numstr ) ;
}
int32_t nxt_basketjson ( cJSON * array , int32_t groupid , int32_t polarity , char * base , uint64_t baseid , char * rel , uint64_t relid , char * refbase , char * refrel )
{
cJSON * item , * item2 , * item3 ; char name [ 64 ] ; int32_t dir = 0 ;
item = cJSON_CreateObject ( ) , jaddstr ( item , " exchange " , INSTANTDEX_NXTAENAME ) ;
item2 = cJSON_CreateObject ( ) , jaddstr ( item2 , " exchange " , INSTANTDEX_NXTAEUNCONF ) ;
item3 = cJSON_CreateObject ( ) , jaddstr ( item3 , " exchange " , INSTANTDEX_NAME ) ;
if ( strcmp ( base , " NXT " ) = = 0 )
{
sprintf ( name , " %s/%s " , rel , " NXT " ) ;
setitemjson ( item , name , rel , relid , " NXT " , NXT_ASSETID ) ;
setitemjson ( item2 , name , rel , relid , " NXT " , NXT_ASSETID ) ;
setitemjson ( item3 , name , rel , relid , " NXT " , NXT_ASSETID ) ;
}
else if ( strcmp ( rel , " NXT " ) = = 0 )
{
sprintf ( name , " %s/%s " , base , " NXT " ) ;
setitemjson ( item , name , base , baseid , " NXT " , NXT_ASSETID ) ;
setitemjson ( item2 , name , base , baseid , " NXT " , NXT_ASSETID ) ;
setitemjson ( item3 , name , base , baseid , " NXT " , NXT_ASSETID ) ;
}
else
{
free_json ( item ) ;
free_json ( item2 ) ;
free_json ( item3 ) ;
return ( 0 ) ;
}
if ( strcmp ( refbase , rel ) = = 0 | | strcmp ( refrel , base ) = = 0 )
dir = - 1 ;
else dir = 1 ;
jaddnum ( item , " wt " , dir ) , jaddnum ( item2 , " wt " , dir ) , jaddnum ( item3 , " wt " , dir ) ;
jaddnum ( item , " group " , groupid ) , jaddnum ( item2 , " group " , groupid ) , jaddnum ( item3 , " group " , groupid ) ;
printf ( " nxt_basketjson (%s/%s) %llu/%llu ref.(%s/%s) dir.%d polarity.%d \n " , base , rel , ( long long ) baseid , ( long long ) relid , refbase , refrel , dir , polarity ) ;
jaddi ( array , item ) , jaddi ( array , item2 ) , jaddi ( array , item3 ) ;
return ( dir * polarity ) ;
}
void add_nxtbtc ( cJSON * array , int32_t groupid , double wt )
{
char * btcnxt_xchgs [ ] = { " poloniex " , " bittrex " , " btc38 " } ;
int32_t i ; cJSON * item ;
if ( wt ! = 0 )
{
printf ( " add NXT/BTC \n " ) ;
for ( i = 0 ; i < sizeof ( btcnxt_xchgs ) / sizeof ( * btcnxt_xchgs ) ; i + + )
{
item = cJSON_CreateObject ( ) , jaddstr ( item , " exchange " , btcnxt_xchgs [ i ] ) ;
setitemjson ( item , " NXT/BTC " , " NXT " , NXT_ASSETID , " BTC " , BTC_ASSETID ) ;
jaddnum ( item , " wt " , wt ) ;
jaddnum ( item , " group " , groupid ) ;
jaddi ( array , item ) ;
}
}
}
int32_t get_duplicates ( uint64_t * duplicates , uint64_t baseid )
{
int32_t i , j , n = 0 ; char assetidstr [ 64 ] , name [ 64 ] ; uint64_t tmp ;
unstringbits ( name , baseid ) ;
if ( ( tmp = is_MGWcoin ( name ) ) ! = 0 )
baseid = tmp ;
else
{
for ( i = 0 ; i < ( int32_t ) ( sizeof ( Tradedassets ) / sizeof ( * Tradedassets ) ) ; i + + )
if ( strcmp ( Tradedassets [ i ] [ 1 ] , name ) = = 0 )
{
baseid = calc_nxt64bits ( Tradedassets [ i ] [ 0 ] ) ;
printf ( " baseid.%llu <- (%s) \n " , ( long long ) baseid , name ) ;
}
}
expand_nxt64bits ( assetidstr , baseid ) ;
duplicates [ n + + ] = baseid ;
for ( i = 0 ; i < ( int32_t ) ( sizeof ( Tradedassets ) / sizeof ( * Tradedassets ) ) ; i + + )
if ( strcmp ( Tradedassets [ i ] [ 0 ] , assetidstr ) = = 0 )
{
for ( j = 0 ; j < ( int32_t ) ( sizeof ( Tradedassets ) / sizeof ( * Tradedassets ) ) ; j + + )
{
if ( i ! = j & & strcmp ( Tradedassets [ i ] [ 1 ] , Tradedassets [ j ] [ 1 ] ) = = 0 )
{
duplicates [ n + + ] = calc_nxt64bits ( Tradedassets [ j ] [ 0 ] ) ;
printf ( " found duplicate.%s \n " , Tradedassets [ j ] [ 0 ] ) ;
}
}
break ;
}
for ( i = 0 ; i < ( int32_t ) ( sizeof ( MGWassets ) / sizeof ( * MGWassets ) ) ; i + + )
if ( strcmp ( MGWassets [ i ] [ 0 ] , assetidstr ) = = 0 )
{
for ( j = 0 ; j < ( int32_t ) ( sizeof ( MGWassets ) / sizeof ( * MGWassets ) ) ; j + + )
{
if ( i ! = j & & strcmp ( MGWassets [ i ] [ 1 ] , MGWassets [ j ] [ 1 ] ) = = 0 )
duplicates [ n + + ] = calc_nxt64bits ( MGWassets [ j ] [ 0 ] ) ;
}
break ;
}
return ( n ) ;
}
cJSON * make_arrayNXT ( cJSON * directarray , cJSON * * arrayBTCp , char * base , char * rel , uint64_t baseid , uint64_t relid )
{
cJSON * item , * arrayNXT = 0 ; char tmpstr [ 64 ] , baseexchange [ 64 ] , relexchange [ 64 ] , * str ;
int32_t wt , baseflags , relflags , i , j , n , m ; uint64_t duplicatebases [ 16 ] , duplicaterels [ 16 ] ;
baseflags = calc_baseflags ( baseexchange , base , & baseid ) ;
relflags = calc_baseflags ( relexchange , rel , & relid ) ;
sprintf ( tmpstr , " %s/%s " , base , rel ) ;
printf ( " make_arrayNXT base.(%s) %llu rel.(%s) %llu baseflags.%d relflags.%d \n " , base , ( long long ) baseid , rel , ( long long ) relid , baseflags , relflags ) ;
item = cJSON_CreateObject ( ) , setitemjson ( item , tmpstr , base , baseid , rel , relid ) ;
jaddstr ( item , " exchange " , INSTANTDEX_NAME ) ;
jaddnum ( item , " wt " , 1 ) , jaddnum ( item , " group " , 0 ) , jaddi ( directarray , item ) ;
if ( ( ( baseflags | relflags ) & BASE_ISNXT ) ! = 0 )
{
printf ( " one is NXT \n " ) ;
if ( strcmp ( base , " NXT " ) = = 0 )
n = get_duplicates ( duplicatebases , relid ) , wt = - 1 , str = rel ;
else n = get_duplicates ( duplicatebases , baseid ) , wt = 1 , str = base ;
sprintf ( tmpstr , " %s/%s " , str , " NXT " ) ;
for ( i = 0 ; i < n ; i + + )
nxt_basketjson ( directarray , 0 , wt , str , duplicatebases [ i ] , " NXT " , NXT_ASSETID , base , rel ) ;
}
else if ( ( baseflags & BASE_ISASSET ) ! = 0 & & ( relflags & BASE_ISASSET ) ! = 0 )
{
printf ( " both are assets (%s/%s) \n " , base , rel ) ;
arrayNXT = cJSON_CreateArray ( ) ;
n = get_duplicates ( duplicatebases , baseid ) ;
for ( i = 0 ; i < n ; i + + )
nxt_basketjson ( arrayNXT , 0 , 1 , base , duplicatebases [ i ] , " NXT " , NXT_ASSETID , base , rel ) ;
if ( strcmp ( base , " BTC " ) = = 0 )
add_nxtbtc ( arrayNXT , 0 , - 1 ) ;
sprintf ( tmpstr , " %s/%s " , rel , " NXT " ) ;
m = get_duplicates ( duplicaterels , relid ) ;
for ( j = 0 ; j < m ; j + + )
nxt_basketjson ( arrayNXT , 1 , - 1 , rel , duplicaterels [ j ] , " NXT " , NXT_ASSETID , base , rel ) ;
if ( strcmp ( rel , " BTC " ) = = 0 )
add_nxtbtc ( arrayNXT , 1 , 1 ) ;
}
if ( ( baseflags & BASE_EXCHANGEASSET ) ! = 0 | | ( relflags & BASE_EXCHANGEASSET ) ! = 0 )
{
printf ( " have exchange asset %d %d \n " , baseflags , relflags ) ;
if ( ( baseflags & BASE_EXCHANGEASSET ) ! = 0 & & ( relflags & BASE_EXCHANGEASSET ) ! = 0 )
{
printf ( " both are exchange asset \n " ) ;
if ( * arrayBTCp = = 0 )
* arrayBTCp = cJSON_CreateArray ( ) ;
if ( strcmp ( base , " BTC " ) ! = 0 & & strcmp ( rel , " BTC " ) ! = 0 )
{
printf ( " a both are exchange asset \n " ) ;
item = cJSON_CreateObject ( ) , jaddstr ( item , " exchange " , baseexchange ) ;
sprintf ( tmpstr , " %s/%s " , base , " BTC " ) ;
setitemjson ( item , tmpstr , base , baseid , " BTC " , stringbits ( " BTC " ) ) ;
jaddi ( * arrayBTCp , item ) ;
item = cJSON_CreateObject ( ) , jaddstr ( item , " exchange " , relexchange ) ;
sprintf ( tmpstr , " %s/%s " , rel , " BTC " ) ;
setitemjson ( item , tmpstr , rel , relid , " BTC " , stringbits ( " BTC " ) ) ;
jaddnum ( item , " wt " , - 1 ) ;
jaddnum ( item , " group " , 1 ) ;
jaddi ( * arrayBTCp , item ) ;
}
}
else if ( ( baseflags & BASE_EXCHANGEASSET ) ! = 0 )
{
if ( strcmp ( base , " BTC " ) ! = 0 & & strcmp ( rel , " BTC " ) = = 0 )
{
printf ( " base.(%s/%s) is exchangeasset \n " , base , rel ) ;
item = cJSON_CreateObject ( ) , jaddstr ( item , " exchange " , baseexchange ) ;
sprintf ( tmpstr , " %s/%s " , base , " BTC " ) ;
setitemjson ( item , tmpstr , base , baseid , " BTC " , stringbits ( " BTC " ) ) ;
jaddi ( directarray , item ) ;
}
}
else
{
if ( strcmp ( rel , " BTC " ) ! = 0 & & strcmp ( base , " BTC " ) = = 0 )
{
printf ( " rel.(%s/%s) is exchangeasset \n " , base , rel ) ;
item = cJSON_CreateObject ( ) , jaddstr ( item , " exchange " , relexchange ) ;
sprintf ( tmpstr , " %s/%s " , rel , " BTC " ) ;
setitemjson ( item , tmpstr , rel , relid , " BTC " , stringbits ( " BTC " ) ) ;
jaddnum ( item , " wt " , - 1 ) ;
jaddi ( directarray , item ) ;
}
}
}
return ( arrayNXT ) ;
}
int32_t centralexchange_items ( int32_t group , double wt , cJSON * array , char * _base , char * _rel , int32_t tradeable , char * refbase , char * refrel )
{
int32_t exchangeid , inverted , n = 0 ; char base [ 64 ] , rel [ 64 ] , name [ 64 ] ; cJSON * item ;
for ( exchangeid = FIRST_EXTERNAL ; exchangeid < MAX_EXCHANGES ; exchangeid + + )
{
strcpy ( base , _base ) , strcpy ( rel , _rel ) ;
if ( Exchanges [ exchangeid ] . name [ 0 ] = = 0 )
break ;
//printf("check %s for (%s/%s) group.%d wt.%f\n",Exchanges[exchangeid].name,base,rel,group,wt);
if ( Exchanges [ exchangeid ] . issue . supports ! = 0 & & ( inverted = ( * Exchanges [ exchangeid ] . issue . supports ) ( base , rel ) ) ! = 0 & & ( tradeable = = 0 | | Exchanges [ exchangeid ] . apikey [ 0 ] ! = 0 | | Exchanges [ exchangeid ] . apisecret [ 0 ] ! = 0 ) )
{
if ( array ! = 0 )
{
item = cJSON_CreateObject ( ) , jaddstr ( item , " exchange " , Exchanges [ exchangeid ] . name ) ;
//printf("ref.(%s/%s) vs (%s/%s) inverted.%d flipped.%d\n",refbase,refrel,base,rel,inverted,strcmp(refbase,rel) == 0 || strcmp(refrel,base) == 0);
if ( inverted < 0 )
jaddstr ( item , " base " , rel ) , jaddstr ( item , " rel " , base ) , sprintf ( name , " %s/%s " , rel , base ) ;
else jaddstr ( item , " base " , base ) , jaddstr ( item , " rel " , rel ) , sprintf ( name , " %s/%s " , base , rel ) ;
if ( strcmp ( refbase , rel ) = = 0 | | strcmp ( refrel , base ) = = 0 )
jaddnum ( item , " wt " , - inverted ) ;
else jaddnum ( item , " wt " , inverted ) ;
jaddstr ( item , " name " , name ) , jaddnum ( item , " group " , group ) ;
printf ( " ADDED.%s inverted.%d (%s) ref.(%s/%s) \n " , Exchanges [ exchangeid ] . name , inverted , name , refbase , refrel ) ;
jaddi ( array , item ) ;
}
n + + ;
} //else printf("%s doesnt support.(%s/%s)\n",Exchanges[exchangeid].name,base,rel);
}
return ( n ) ;
}
cJSON * external_combo ( char * base , char * rel , char * coinstr , int32_t tradeable )
{
cJSON * array = 0 ;
printf ( " check central jumper.(%s) for (%s/%s) \n " , coinstr , base , rel ) ;
//if ( (baseflags & (BASE_ISNAME|BASE_ISMGW)) != 0 && (relflags & (BASE_ISNAME|BASE_ISMGW)) != 0 )
{
if ( strcmp ( base , coinstr ) ! = 0 & & strcmp ( rel , coinstr ) ! = 0 & & centralexchange_items ( 0 , 1 , 0 , base , coinstr , tradeable , base , rel ) > 0 & & centralexchange_items ( 0 , 1 , 0 , rel , coinstr , tradeable , base , rel ) > 0 )
{
array = cJSON_CreateArray ( ) ;
printf ( " add central jumper.(%s) for (%s/%s) \n " , coinstr , base , rel ) ;
centralexchange_items ( 0 , 1 , array , base , coinstr , tradeable , base , rel ) ;
centralexchange_items ( 1 , - 1 , array , rel , coinstr , tradeable , base , rel ) ;
}
}
return ( array ) ;
}
int32_t make_subactive ( struct prices777 * baskets [ ] , int32_t n , cJSON * array , char * prefix , char * base , char * rel , uint64_t baseid , uint64_t relid , int32_t maxdepth )
{
char tmpstr [ 64 ] , typestr [ 64 ] ; struct prices777 * basket ; cJSON * basketjson ;
basketjson = cJSON_CreateObject ( ) ;
sprintf ( tmpstr , " %s/%s " , base , rel ) ;
setitemjson ( basketjson , tmpstr , base , baseid , rel , relid ) ;
jadd ( basketjson , " basket " , array ) ;
printf ( " %s BASKETMAKE.(%s) \n " , prefix , jprint ( basketjson , 0 ) ) ;
sprintf ( typestr , " basket%s " , prefix ) ;
if ( ( basket = prices777_makebasket ( 0 , basketjson , 1 , typestr , 0 , 0 ) ) ! = 0 )
{
prices777_basket ( basket , maxdepth ) ;
prices777_jsonstrs ( basket , & basket - > O ) ;
printf ( " add to baskets[%d].%s (%s/%s) (%s) \n " , n , basket - > exchange , basket - > base , basket - > rel , basket - > contract ) ;
baskets [ n + + ] = basket ;
}
free_json ( basketjson ) ;
return ( n ) ;
}
char * prices777_activebooks ( char * name , char * _base , char * _rel , uint64_t baseid , uint64_t relid , int32_t maxdepth , int32_t allflag , int32_t tradeable )
{
cJSON * array , * arrayNXT , * arrayBTC , * arrayUSD , * arrayCNY , * basketjson ; struct prices777 * active , * basket , * baskets [ 64 ] ;
int32_t inverted , keysize , baseflags , relflags , n = 0 ; char tmpstr [ 64 ] , base [ 64 ] , rel [ 64 ] , bexchange [ 64 ] , rexchange [ 64 ] , key [ 512 ] , * retstr = 0 ;
memset ( baskets , 0 , sizeof ( baskets ) ) ;
strcpy ( base , _base ) , strcpy ( rel , _rel ) ;
baseflags = calc_baseflags ( bexchange , base , & baseid ) ;
relflags = calc_baseflags ( rexchange , rel , & relid ) ;
InstantDEX_name ( key , & keysize , " active " , name , base , & baseid , rel , & relid ) ;
printf ( " activebooks (%s/%s) (%llu/%llu) \n " , base , rel , ( long long ) baseid , ( long long ) relid ) ;
if ( ( active = prices777_find ( & inverted , baseid , relid , " active " ) ) = = 0 )
{
if ( ( ( baseflags & BASE_ISMGW ) ! = 0 | | ( baseflags & BASE_ISASSET ) = = 0 ) & & ( ( relflags & BASE_ISMGW ) ! = 0 | | ( relflags & BASE_ISASSET ) = = 0 ) )
{
if ( ( arrayUSD = external_combo ( base , rel , " USD " , tradeable ) ) ! = 0 )
n = make_subactive ( baskets , n , arrayUSD , " USD " , base , rel , baseid , relid , maxdepth ) ;
if ( ( arrayCNY = external_combo ( base , rel , " CNY " , tradeable ) ) ! = 0 )
n = make_subactive ( baskets , n , arrayCNY , " CNY " , base , rel , baseid , relid , maxdepth ) ;
}
arrayBTC = external_combo ( base , rel , " BTC " , tradeable ) ;
basketjson = cJSON_CreateObject ( ) , array = cJSON_CreateArray ( ) ;
sprintf ( tmpstr , " %s/%s " , base , rel ) ;
setitemjson ( basketjson , tmpstr , base , baseid , rel , relid ) ;
//if ( baseflags != BASE_ISASSET && relflags != BASE_ISASSET )
centralexchange_items ( 0 , 1 , array , base , rel , tradeable , base , rel ) ;
if ( ( arrayNXT = make_arrayNXT ( array , & arrayBTC , base , rel , baseid , relid ) ) ! = 0 )
n = make_subactive ( baskets , n , arrayNXT , " NXT " , base , rel , baseid , relid , maxdepth ) ;
if ( arrayBTC ! = 0 )
n = make_subactive ( baskets , n , arrayBTC , " BTC " , base , rel , baseid , relid , maxdepth ) ;
if ( ( basket = prices777_find ( & inverted , baseid , relid , " basket " ) ) ! = 0 )
baskets [ n + + ] = basket ;
jadd ( basketjson , " basket " , array ) ;
printf ( " ACTIVE MAKE.(%s) \n " , jprint ( basketjson , 0 ) ) ;
if ( ( active = prices777_makebasket ( 0 , basketjson , 1 , " active " , baskets , n ) ) ! = 0 )
{
prices777_basket ( active , maxdepth ) ;
prices777_jsonstrs ( active , & active - > O ) ;
}
free_json ( array ) ;
}
if ( active ! = 0 & & retstr = = 0 )
{
prices777_basket ( active , maxdepth ) ;
prices777_jsonstrs ( active , & active - > O ) ;
if ( ( retstr = active - > orderbook_jsonstrs [ inverted ] [ allflag ] ) ! = 0 )
retstr = clonestr ( retstr ) ;
}
if ( retstr = = 0 )
retstr = clonestr ( " { \" error \" : \" null active orderbook \" } " ) ;
return ( retstr ) ;
}
cJSON * basketitem_json ( struct prices777 * prices )
{
int32_t i ; char numstr [ 64 ] ; cJSON * json , * array , * item ;
json = cJSON_CreateObject ( ) ;
if ( prices ! = 0 )
{
jaddstr ( json , " exchange " , prices - > exchange ) ;
jaddstr ( json , " name " , prices - > contract ) ;
jaddstr ( json , " base " , prices - > base ) ;
sprintf ( numstr , " %llu " , ( long long ) prices - > baseid ) , jaddstr ( json , " baseid " , numstr ) ;
jaddstr ( json , " rel " , prices - > rel ) ;
sprintf ( numstr , " %llu " , ( long long ) prices - > relid ) , jaddstr ( json , " relid " , numstr ) ;
jaddnum ( json , " commission " , prices - > commission ) ;
if ( prices - > basketsize ! = 0 )
{
array = cJSON_CreateArray ( ) ;
for ( i = 0 ; i < prices - > basketsize ; i + + )
{
item = basketitem_json ( prices - > basket [ i ] . prices ) ;
if ( prices - > basket [ i ] . groupsize ! = 0 )
jaddnum ( item , " groupsize " , prices - > basket [ i ] . groupsize ) ;
jaddnum ( item , " group " , prices - > basket [ i ] . groupid ) ;
jaddnum ( item , " wt " , prices - > basket [ i ] . wt ) ;
jaddi ( array , item ) ;
}
jadd ( json , " basket " , array ) ;
}
}
return ( json ) ;
}
char * prices777_allorderbooks ( )
{
int32_t i ; cJSON * json , * array = cJSON_CreateArray ( ) ;
for ( i = 0 ; i < BUNDLE . num ; i + + )
jaddi ( array , basketitem_json ( BUNDLE . ptrs [ i ] ) ) ;
json = cJSON_CreateObject ( ) ;
cJSON_AddItemToObject ( json , " orderbooks " , array ) ;
return ( jprint ( json , 1 ) ) ;
}
struct prices777 * prices777_initpair ( int32_t needfunc , char * exchange , char * _base , char * _rel , double decay , char * _name , uint64_t baseid , uint64_t relid , int32_t basketsize )
{
static long allocated ;
struct exchange_funcs funcs [ ] =
{
{ " nxtae " , prices777_NXT , NXT_supports , NXT_tradestub } ,
{ " unconf " , prices777_unconfNXT , NXT_supports , NXT_tradestub } ,
{ " InstantDEX " , prices777_InstantDEX , InstantDEX_supports , InstantDEX_tradestub } ,
{ " wallet " , prices777_InstantDEX , InstantDEX_supports , InstantDEX_tradestub } ,
{ " basket " , prices777_basket , InstantDEX_supports , InstantDEX_tradestub } ,
{ " basketNXT " , prices777_basket , InstantDEX_supports , InstantDEX_tradestub } ,
{ " basketBTC " , prices777_basket , InstantDEX_supports , InstantDEX_tradestub } ,
{ " basketUSD " , prices777_basket , InstantDEX_supports , InstantDEX_tradestub } ,
{ " basketCNY " , prices777_basket , InstantDEX_supports , InstantDEX_tradestub } ,
{ " active " , prices777_basket , InstantDEX_supports , InstantDEX_tradestub } ,
{ " peggy " , prices777_InstantDEX , InstantDEX_supports , InstantDEX_tradestub } ,
{ " jumblr " , prices777_InstantDEX , InstantDEX_supports } ,
{ " pangea " , prices777_InstantDEX , InstantDEX_supports } ,
{ " truefx " , 0 } , { " ecb " , 0 } , { " instaforex " , 0 } , { " fxcm " , 0 } , { " yahoo " , 0 } ,
poloniex_funcs , bittrex_funcs , btce_funcs , bitfinex_funcs , btc38_funcs , huobi_funcs ,
lakebtc_funcs , quadriga_funcs , okcoin_funcs , coinbase_funcs , bitstamp_funcs
} ;
int32_t i , rellen ; char basebuf [ 64 ] , relbuf [ 64 ] , base [ 64 ] , rel [ 64 ] , name [ 64 ] ; struct exchange_info * exchangeptr ;
struct prices777 * prices ;
safecopy ( base , _base , sizeof ( base ) ) ;
safecopy ( rel , _rel , sizeof ( rel ) ) ;
safecopy ( name , _name , sizeof ( name ) ) ;
if ( needfunc < 0 )
{
for ( i = 0 ; i < sizeof ( funcs ) / sizeof ( * funcs ) ; i + + )
{
if ( ( exchangeptr = find_exchange ( 0 , funcs [ i ] . exchange ) ) ! = 0 )
{
printf ( " %p %s set supports.%p %p coinbalance.%p \n " , exchangeptr , funcs [ i ] . exchange , funcs [ i ] . supports , funcs [ i ] . trade , funcs [ i ] . parsebalance ) ;
exchangeptr - > issue = funcs [ i ] ;
}
}
return ( 0 ) ;
}
//printf("init.(%s/%s) name.(%s) %llu %llu\n",base,rel,name,(long long)baseid,(long long)relid);
if ( strcmp ( exchange , " nxtae " ) = = 0 | | strcmp ( exchange , " unconf " ) = = 0 ) //|| strcmp(exchange,"InstantDEX") == 0 )
{
if ( strcmp ( base , " NXT " ) = = 0 | | baseid = = NXT_ASSETID )
{
strcpy ( base , rel ) , baseid = relid ;
strcpy ( rel , " NXT " ) , relid = NXT_ASSETID ;
printf ( " flip.(%s/%s) %llu %llu \n " , base , rel , ( long long ) baseid , ( long long ) relid ) ;
}
}
for ( i = 0 ; i < BUNDLE . num ; i + + )
{
if ( strcmp ( BUNDLE . ptrs [ i ] - > exchange , exchange ) = = 0 )
{
if ( baseid ! = 0 & & relid ! = 0 & & BUNDLE . ptrs [ i ] - > baseid = = baseid & & BUNDLE . ptrs [ i ] - > relid = = relid )
return ( BUNDLE . ptrs [ i ] ) ;
if ( strcmp ( BUNDLE . ptrs [ i ] - > origbase , base ) = = 0 & & strcmp ( BUNDLE . ptrs [ i ] - > origrel , rel ) = = 0 )
return ( BUNDLE . ptrs [ i ] ) ;
}
}
printf ( " cant find (%s) (%llu) (%llu) (%s) (%s) \n " , exchange , ( long long ) baseid , ( long long ) relid , base , rel ) ;
prices = calloc ( 1 , sizeof ( * prices ) + basketsize * sizeof ( * prices - > basket ) ) ;
// printf("new prices %ld\n",sizeof(*prices));
strcpy ( prices - > exchange , exchange ) , strcpy ( prices - > contract , name ) , strcpy ( prices - > base , base ) , strcpy ( prices - > rel , rel ) ;
prices - > baseid = baseid , prices - > relid = relid ;
prices - > contractnum = InstantDEX_name ( prices - > key , & prices - > keysize , exchange , prices - > contract , prices - > base , & prices - > baseid , prices - > rel , & prices - > relid ) ;
portable_mutex_init ( & prices - > mutex ) ;
strcpy ( prices - > origbase , base ) ;
if ( rel [ 0 ] ! = 0 )
strcpy ( prices - > origrel , rel ) ;
allocated + = sizeof ( * prices ) ;
safecopy ( prices - > exchange , exchange , sizeof ( prices - > exchange ) ) ;
if ( strcmp ( exchange , " nxtae " ) = = 0 | | strcmp ( exchange , " unconf " ) = = 0 | | strcmp ( exchange , INSTANTDEX_NAME ) = = 0 )
{
char tmp [ 16 ] ;
_set_assetname ( & prices - > basemult , tmp , 0 , prices - > baseid ) ;
_set_assetname ( & prices - > relmult , tmp , 0 , prices - > relid ) ;
if ( ( prices - > relid ! = NXT_ASSETID & & prices - > relid < ( 1LL < < ( 5 * 8 ) ) ) | | ( prices - > baseid ! = NXT_ASSETID & & prices - > baseid = = ( 1LL < < ( 5 * 8 ) ) ) )
{
printf ( " illegal baseid.%llu or relid.%llu \n " , ( long long ) prices - > baseid , ( long long ) prices - > relid ) ;
free ( prices ) ;
return ( 0 ) ;
}
//prices->nxtbooks = calloc(1,sizeof(*prices->nxtbooks));
safecopy ( prices - > lbase , base , sizeof ( prices - > lbase ) ) , tolowercase ( prices - > lbase ) ;
safecopy ( prices - > lrel , rel , sizeof ( prices - > lrel ) ) , tolowercase ( prices - > lrel ) ;
rellen = ( int32_t ) ( strlen ( prices - > rel ) + 1 ) ;
tmp [ 0 ] = 0 ;
prices - > type = _set_assetname ( & prices - > ap_mult , tmp , 0 , prices - > baseid ) ;
printf ( " nxtbook.(%s) -> NXT %s %llu/%llu vs (%s) mult.%llu (%llu/%llu) \n " , base , prices - > contract , ( long long ) prices - > baseid , ( long long ) prices - > relid , tmp , ( long long ) prices - > ap_mult , ( long long ) prices - > basemult , ( long long ) prices - > relmult ) ;
}
else
{
prices - > basemult = prices - > relmult = 1 ;
safecopy ( prices - > base , base , sizeof ( prices - > base ) ) , touppercase ( prices - > base ) ;
safecopy ( prices - > lbase , base , sizeof ( prices - > lbase ) ) , tolowercase ( prices - > lbase ) ;
if ( rel [ 0 ] = = 0 & & prices777_ispair ( basebuf , relbuf , base ) > = 0 )
{
strcpy ( base , basebuf ) , strcpy ( rel , relbuf ) ;
//printf("(%s) is a pair (%s)+(%s)\n",base,basebuf,relbuf);
}
if ( rel [ 0 ] ! = 0 )
{
rellen = ( int32_t ) ( strlen ( rel ) + 1 ) ;
safecopy ( prices - > rel , rel , sizeof ( prices - > rel ) ) , touppercase ( prices - > rel ) ;
safecopy ( prices - > lrel , rel , sizeof ( prices - > lrel ) ) , tolowercase ( prices - > lrel ) ;
if ( prices - > contract [ 0 ] = = 0 )
{
strcpy ( prices - > contract , prices - > base ) ;
if ( strcmp ( prices - > rel , & prices - > contract [ strlen ( prices - > contract ) - 3 ] ) ! = 0 )
strcat ( prices - > contract , " / " ) , strcat ( prices - > contract , prices - > rel ) ;
}
//printf("create base.(%s) rel.(%s)\n",prices->base,prices->rel);
}
else
{
if ( prices - > contract [ 0 ] = = 0 )
strcpy ( prices - > contract , base ) ;
}
}
char str [ 65 ] ; printf ( " %s init_pair.(%s) (%s)(%s).%llu -> (%s) keysize.%d crc.%u (baseid.%llu relid.%llu) \n " , mbstr ( str , allocated ) , exchange , base , rel , ( long long ) prices - > contractnum , prices - > contract , prices - > keysize , calc_crc32 ( 0 , ( void * ) prices - > key , prices - > keysize ) , ( long long ) prices - > baseid , ( long long ) prices - > relid ) ;
prices - > decay = decay , prices - > oppodecay = ( 1. - decay ) ;
prices - > RTflag = 1 ;
if ( ( exchangeptr = find_exchange ( 0 , exchange ) ) ! = 0 )
{
if ( prices - > commission = = 0. )
prices - > commission = exchangeptr - > commission ;
prices - > exchangeid = exchangeptr - > exchangeid ;
if ( exchangeptr - > issue . update = = 0 )
{
for ( i = 0 ; i < sizeof ( funcs ) / sizeof ( * funcs ) ; i + + )
{
if ( strcmp ( exchange , funcs [ i ] . exchange ) = = 0 )
{
exchangeptr - > issue = funcs [ i ] ;
//printf("return prices.%p\n",prices);
}
}
}
if ( exchangeptr - > refcount = = 0 )
{
printf ( " incr refcount.%s from %d \n " , exchangeptr - > name , exchangeptr - > refcount ) ;
exchangeptr - > refcount + + ;
}
return ( prices ) ;
}
//printf("initialized.(%s).%lld\n",prices->contract,(long long)prices->contractnum);
return ( prices ) ;
}
int32_t is_pair ( char * base , char * rel , char * refbase , char * refrel )
{
if ( strcmp ( base , refbase ) = = 0 & & strcmp ( rel , refrel ) = = 0 )
return ( 1 ) ;
else if ( strcmp ( rel , refbase ) = = 0 & & strcmp ( base , refrel ) = = 0 )
return ( - 1 ) ;
return ( 0 ) ;
}
struct prices777 * prices777_poll ( char * _exchangestr , char * _name , char * _base , uint64_t refbaseid , char * _rel , uint64_t refrelid )
{
char exchangestr [ 64 ] , base [ 64 ] , rel [ 64 ] , name [ 64 ] , key [ 1024 ] ; uint64_t baseid , relid ;
int32_t keysize , exchangeid , valid ; struct exchange_info * exchange ; struct prices777 * prices ;
baseid = refbaseid , relid = refrelid ;
strcpy ( exchangestr , _exchangestr ) , strcpy ( base , _base ) , strcpy ( rel , _rel ) , strcpy ( name , _name ) ;
if ( ( strcmp ( exchangestr , " huobi " ) = = 0 & & is_pair ( base , rel , " BTC " , " CNY " ) = = 0 & & is_pair ( base , rel , " LTC " , " CNY " ) = = 0 ) | |
( ( strcmp ( exchangestr , " bityes " ) = = 0 | | strcmp ( exchangestr , " okcoin " ) = = 0 ) & & is_pair ( base , rel , " BTC " , " USD " ) = = 0 & & is_pair ( base , rel , " LTC " , " USD " ) = = 0 ) | |
( ( strcmp ( exchangestr , " bitstamp " ) = = 0 | | strcmp ( exchangestr , " coinbase " ) = = 0 ) & & is_pair ( base , rel , " BTC " , " USD " ) = = 0 ) | |
( strcmp ( exchangestr , " lakebtc " ) = = 0 & & is_pair ( base , rel , " BTC " , " CNY " ) = = 0 & & is_pair ( base , rel , " BTC " , " USD " ) = = 0 ) | |
( strcmp ( exchangestr , " quadriga " ) = = 0 & & is_pair ( base , rel , " BTC " , " CAD " ) = = 0 & & is_pair ( base , rel , " BTC " , " USD " ) = = 0 ) | |
0 )
{
printf ( " %s (%s/%s) is not a supported trading pair \n " , exchangestr , base , rel ) ;
return ( 0 ) ;
}
InstantDEX_name ( key , & keysize , exchangestr , name , base , & baseid , rel , & relid ) ;
//printf("call addbundle\n");
if ( ( prices = prices777_addbundle ( & valid , 0 , 0 , exchangestr , baseid , relid ) ) ! = 0 )
{
printf ( " found (%s/%s).%s %llu %llu in slot-> %p \n " , base , rel , exchangestr , ( long long ) baseid , ( long long ) relid , prices ) ;
return ( prices ) ;
}
//printf("call find_exchange\n");
if ( ( exchange = find_exchange ( & exchangeid , exchangestr ) ) = = 0 )
{
printf ( " cant add exchange.(%s) \n " , exchangestr ) ;
return ( 0 ) ;
}
if ( strcmp ( exchangestr , " nxtae " ) = = 0 | | strcmp ( exchangestr , " unconf " ) = = 0 )
{
if ( strcmp ( base , " NXT " ) ! = 0 & & strcmp ( rel , " NXT " ) ! = 0 )
{
printf ( " nxtae/unconf needs to be relative to NXT (%s/%s) %llu/%llu \n " , base , rel , ( long long ) baseid , ( long long ) relid ) ;
return ( 0 ) ;
}
}
if ( ( prices = prices777_initpair ( 1 , exchangestr , base , rel , 0. , name , baseid , relid , 0 ) ) ! = 0 )
{
//printf("call addbundle after initpair\n");
prices777_addbundle ( & valid , 1 , prices , 0 , 0 , 0 ) ;
}
return ( prices ) ;
}
int32_t prices777_propagate ( struct prices777 * prices )
{
int32_t i , n = 0 ;
for ( i = 0 ; i < prices - > numdependents ; i + + )
{
n + + ;
if ( ( * prices - > dependents [ i ] ) < 0xff )
( * prices - > dependents [ i ] ) + + ;
if ( Debuglevel > 2 )
printf ( " numdependents.%d of %d %p %d \n " , i , prices - > numdependents , prices - > dependents [ i ] , * prices - > dependents [ i ] ) ;
}
return ( n ) ;
}
int32_t prices777_updated ;
void prices777_basketsloop ( void * ptr )
{
extern int32_t prices777_NXTBLOCK ;
int32_t i , n ; uint32_t updated ; struct prices777 * prices ;
while ( 1 )
{
for ( i = n = 0 ; i < BUNDLE . num ; i + + )
{
updated = ( uint32_t ) time ( NULL ) ;
if ( ( prices = BUNDLE . ptrs [ i ] ) ! = 0 & & prices - > disabled = = 0 & & prices - > basketsize ! = 0 )
{
if ( prices - > changed ! = 0 )
{
if ( Debuglevel > 2 )
printf ( " %s updating basket(%s) lastprice %.8f changed.%p %d \n " , prices - > exchange , prices - > contract , prices - > lastprice , & prices - > changed , prices - > changed ) ;
prices - > pollnxtblock = prices777_NXTBLOCK ;
n + + ;
prices - > lastupdate = updated ;
if ( ( prices - > lastprice = prices777_basket ( prices , MAX_DEPTH ) ) ! = 0. )
{
if ( prices - > O . numbids > 0 | | prices - > O . numasks > 0 )
{
prices777_jsonstrs ( prices , & prices - > O ) ;
prices777_updated + = prices777_propagate ( prices ) ;
}
}
prices - > changed = 0 ;
}
}
}
if ( n = = 0 )
usleep ( 250000 ) ;
else usleep ( 10000 ) ;
}
}
void prices777_exchangeloop ( void * ptr )
{
extern int32_t prices777_NXTBLOCK ;
struct prices777 * prices ; int32_t i , n , pollflag , isnxtae = 0 ; double updated = 0. ; struct exchange_info * exchange = ptr ;
if ( strcmp ( exchange - > name , " nxtae " ) = = 0 | | strcmp ( exchange - > name , " unconf " ) = = 0 )
isnxtae = 1 ;
printf ( " POLL.(%s) \n " , exchange - > name ) ;
while ( 1 )
{
for ( i = n = 0 ; i < BUNDLE . num ; i + + )
{
if ( ( prices = BUNDLE . ptrs [ i ] ) ! = 0 & & prices - > disabled = = 0 & & prices - > basketsize = = 0 & & prices - > exchangeid = = exchange - > exchangeid )
{
if ( prices - > exchangeid = = INSTANTDEX_EXCHANGEID & & prices - > dirty ! = 0 )
pollflag = 1 ;
else if ( isnxtae = = 0 )
pollflag = milliseconds ( ) > ( exchange - > lastupdate + exchange - > pollgap * 1000 ) & & milliseconds ( ) > ( prices - > lastupdate + 1000 * IGUANA_EXCHANGEIDLE ) ;
else if ( ( strcmp ( exchange - > name , " unconf " ) = = 0 & & milliseconds ( ) > prices - > lastupdate + 5000 ) | | prices - > pollnxtblock < prices777_NXTBLOCK | | milliseconds ( ) > prices - > lastupdate + 1000 * IGUANA_EXCHANGEIDLE )
pollflag = 1 ;
else continue ;
//printf("(%s) pollflag.%d %p\n",exchange->name,pollflag,exchange->issue.update);
if ( pollflag ! = 0 & & exchange - > issue . update ! = 0 )
{
portable_mutex_lock ( & exchange - > mutex ) ;
prices - > lastprice = ( * exchange - > issue . update ) ( prices , MAX_DEPTH ) ;
portable_mutex_unlock ( & exchange - > mutex ) ;
updated = exchange - > lastupdate = milliseconds ( ) , prices - > lastupdate = milliseconds ( ) ;
if ( prices - > lastprice ! = 0. )
{
if ( Debuglevel > 2 & & strcmp ( exchange - > name , " unconf " ) ! = 0 )
printf ( " %-8s %8s (%8s %8s) %llu %llu isnxtae.%d poll %u -> %u %.8f hbla %.8f %.8f \n " , prices - > exchange , prices - > contract , prices - > base , prices - > rel , ( long long ) prices - > baseid , ( long long ) prices - > relid , isnxtae , prices - > pollnxtblock , prices777_NXTBLOCK , prices - > lastprice , prices - > lastbid , prices - > lastask ) ;
prices777_propagate ( prices ) ;
}
prices - > pollnxtblock = prices777_NXTBLOCK ;
prices - > dirty = 0 ;
n + + ;
}
/*if ( 0 && exchange->issue.trade != 0 && exchange->apikey[0] != 0 && exchange->exchangeid >= FIRST_EXTERNAL && time(NULL) > exchange->lastbalancetime+300 )
{
if ( ( json = ( * exchange - > issue . balances ) ( exchange ) ) ! = 0 )
{
if ( exchange - > balancejson ! = 0 )
free_json ( exchange - > balancejson ) ;
exchange - > balancejson = json ;
}
exchange - > lastbalancetime = ( uint32_t ) time ( NULL ) ;
} */
}
}
if ( n = = 0 )
sleep ( 3 ) ;
else sleep ( 1 ) ;
}
}
int32_t prices777_init ( char * jsonstr , int32_t peggyflag )
{
static int32_t didinit ;
char * btcdexchanges [ ] = { " poloniex " , " bittrex " } ; //, "bter" };
char * btcusdexchanges [ ] = { " bityes " , " bitfinex " , " bitstamp " , " okcoin " , " coinbase " , " btce " , " lakebtc " , " kraken " } ;
cJSON * json = 0 , * item , * exchanges ; int32_t i , n ; char * exchange , * base , * rel , * contract ; struct exchange_info * exchangeptr = 0 ; struct destbuf tmp ;
if ( didinit ! = 0 )
return ( 0 ) ;
didinit = 1 ;
if ( ( BUNDLE . ptrs [ BUNDLE . num ] = prices777_initpair ( 1 , " unconf " , " BTC " , " NXT " , 0 , " BTC/NXT " , calc_nxt64bits ( " 12659653638116877017 " ) , NXT_ASSETID , 0 ) ) ! = 0 )
BUNDLE . num + + ;
if ( peggyflag ! = 0 )
{
if ( ( BUNDLE . ptrs [ BUNDLE . num ] = prices777_initpair ( 1 , " huobi " , " BTC " , " USD " , 0. , 0 , 0 , 0 , 0 ) ) ! = 0 )
BUNDLE . num + + ;
if ( ( BUNDLE . ptrs [ BUNDLE . num ] = prices777_initpair ( 1 , " btc38 " , " CNY " , " NXT " , 0. , 0 , 0 , 0 , 0 ) ) ! = 0 )
BUNDLE . num + + ;
if ( ( BUNDLE . ptrs [ BUNDLE . num ] = prices777_initpair ( 1 , " okcoin " , " LTC " , " BTC " , 0. , 0 , 0 , 0 , 0 ) ) ! = 0 )
BUNDLE . num + + ;
if ( ( BUNDLE . ptrs [ BUNDLE . num ] = prices777_initpair ( 1 , " poloniex " , " LTC " , " BTC " , 0. , 0 , 0 , 0 , 0 ) ) ! = 0 )
BUNDLE . num + + ;
if ( ( BUNDLE . ptrs [ BUNDLE . num ] = prices777_initpair ( 1 , " poloniex " , " XMR " , " BTC " , 0. , 0 , 0 , 0 , 0 ) ) ! = 0 )
BUNDLE . num + + ;
if ( ( BUNDLE . ptrs [ BUNDLE . num ] = prices777_initpair ( 1 , " poloniex " , " BTS " , " BTC " , 0. , 0 , 0 , 0 , 0 ) ) ! = 0 )
BUNDLE . num + + ;
if ( ( BUNDLE . ptrs [ BUNDLE . num ] = prices777_initpair ( 1 , " poloniex " , " XCP " , " BTC " , 0. , 0 , 0 , 0 , 0 ) ) ! = 0 )
BUNDLE . num + + ;
for ( i = 0 ; i < sizeof ( btcdexchanges ) / sizeof ( * btcdexchanges ) ; i + + )
if ( ( BUNDLE . ptrs [ BUNDLE . num ] = prices777_initpair ( 1 , btcusdexchanges [ i ] , " BTC " , " USD " , 0. , 0 , 0 , 0 , 0 ) ) ! = 0 )
BUNDLE . num + + ;
for ( i = 0 ; i < sizeof ( btcdexchanges ) / sizeof ( * btcdexchanges ) ; i + + )
if ( ( BUNDLE . ptrs [ BUNDLE . num ] = prices777_initpair ( 1 , btcdexchanges [ i ] , " BTCD " , " BTC " , 0. , 0 , 0 , 0 , 0 ) ) ! = 0 )
BUNDLE . num + + ;
}
if ( ( json = cJSON_Parse ( jsonstr ) ) ! = 0 & & ( exchanges = jarray ( & n , json , " prices " ) ) ! = 0 )
{
printf ( " prices has %d items \n " , n ) ;
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( exchanges , i ) ;
exchange = jstr ( item , " exchange " ) , base = jstr ( item , " base " ) , rel = jstr ( item , " rel " ) ;
if ( ( base = = 0 | | rel = = 0 ) & & ( contract = jstr ( item , " contract " ) ) ! = 0 )
rel = 0 , base = contract ;
else contract = 0 ;
//printf("PRICES[%d] %p %p %p\n",i,exchange,base,rel);
if ( exchange ! = 0 & & ( strcmp ( exchange , " bter " ) = = 0 | | strcmp ( exchange , " exmo " ) = = 0 ) )
continue ;
if ( exchange ! = 0 & & ( exchangeptr = find_exchange ( 0 , exchange ) ) ! = 0 )
{
exchangeptr - > pollgap = get_API_int ( cJSON_GetObjectItem ( item , " pollgap " ) , IGUANA_EXCHANGEIDLE ) ;
extract_cJSON_str ( exchangeptr - > apikey , sizeof ( exchangeptr - > apikey ) , item , " key " ) ;
if ( exchangeptr - > apikey [ 0 ] = = 0 )
extract_cJSON_str ( exchangeptr - > apikey , sizeof ( exchangeptr - > apikey ) , item , " apikey " ) ;
extract_cJSON_str ( exchangeptr - > userid , sizeof ( exchangeptr - > userid ) , item , " userid " ) ;
extract_cJSON_str ( exchangeptr - > apisecret , sizeof ( exchangeptr - > apisecret ) , item , " secret " ) ;
if ( exchangeptr - > apisecret [ 0 ] = = 0 )
extract_cJSON_str ( exchangeptr - > apisecret , sizeof ( exchangeptr - > apisecret ) , item , " apisecret " ) ;
if ( exchangeptr - > commission = = 0. )
exchangeptr - > commission = jdouble ( item , " commission " ) ;
printf ( " %p ADDEXCHANGE.(%s) [%s, %s, %s] commission %.3f%% \n " , exchangeptr , exchange , exchangeptr - > apikey , exchangeptr - > userid , exchangeptr - > apisecret , exchangeptr - > commission * 100 ) ;
} else printf ( " exchangeptr.%p for (%p) \n " , exchangeptr , exchange ) ;
if ( exchange ! = 0 & & strcmp ( exchange , " truefx " ) = = 0 )
{
copy_cJSON ( & tmp , jobj ( item , " truefxuser " ) ) , safecopy ( BUNDLE . truefxuser , tmp . buf , sizeof ( BUNDLE . truefxuser ) ) ;
copy_cJSON ( & tmp , jobj ( item , " truefxpass " ) ) , safecopy ( BUNDLE . truefxpass , tmp . buf , sizeof ( BUNDLE . truefxpass ) ) ; ;
printf ( " truefx.(%s %s) \n " , BUNDLE . truefxuser , BUNDLE . truefxpass ) ;
}
else if ( base ! = 0 & & rel ! = 0 & & base [ 0 ] ! = 0 & & rel [ 0 ] ! = 0 & & ( BUNDLE . ptrs [ BUNDLE . num ] = prices777_initpair ( 1 , exchange , base , rel , jdouble ( item , " decay " ) , contract , stringbits ( base ) , stringbits ( rel ) , 0 ) ) ! = 0 )
{
if ( exchangeptr ! = 0 & & ( BUNDLE . ptrs [ BUNDLE . num ] - > commission = jdouble ( item , " commission " ) ) = = 0. )
BUNDLE . ptrs [ BUNDLE . num ] - > commission = exchangeptr - > commission ;
printf ( " SET COMMISSION.%s %f for %s/%s \n " , exchange , exchangeptr ! = 0 ? exchangeptr - > commission : 0 , base , rel ) ;
BUNDLE . num + + ;
}
}
} else printf ( " (%s) has no prices[] \n " , jsonstr ) ;
if ( json ! = 0 )
free_json ( json ) ;
for ( i = 0 ; i < MAX_EXCHANGES ; i + + )
{
exchangeptr = & Exchanges [ i ] ;
if ( ( exchangeptr - > refcount > 0 | | strcmp ( exchangeptr - > name , " unconf " ) = = 0 ) ) //&& strcmp(exchangeptr->name,"pangea") != 0 && strcmp(exchangeptr->name,"jumblr") != 0 )
iguana_launch ( iguana_coinadd ( " BTCD " ) , " exchangeloop " , ( void * ) prices777_exchangeloop , exchangeptr , IGUANA_EXCHANGETHREAD ) ;
}
return ( 0 ) ;
}
double prices777_yahoo ( char * metal )
{
// http://finance.yahoo.com/webservice/v1/symbols/allcurrencies/quote?format=json
// http://finance.yahoo.com/webservice/v1/symbols/XAU=X/quote?format=json
// http://finance.yahoo.com/webservice/v1/symbols/XAG=X/quote?format=json
// http://finance.yahoo.com/webservice/v1/symbols/XPT=X/quote?format=json
// http://finance.yahoo.com/webservice/v1/symbols/XPD=X/quote?format=json
char url [ 1024 ] , * jsonstr ; cJSON * json , * obj , * robj , * item , * field ; double price = 0. ;
sprintf ( url , " http://finance.yahoo.com/webservice/v1/symbols/%s=X/quote?format=json " , metal ) ;
if ( ( jsonstr = issue_curl ( url ) ) ! = 0 )
{
//printf("(%s)\n",jsonstr);
if ( ( json = cJSON_Parse ( jsonstr ) ) ! = 0 )
{
if ( ( obj = jobj ( json , " list " ) ) ! = 0 & & ( robj = jobj ( obj , " resources " ) ) ! = 0 & & ( item = jitem ( robj , 0 ) ) ! = 0 )
{
if ( ( robj = jobj ( item , " resource " ) ) ! = 0 & & ( field = jobj ( robj , " fields " ) ) ! = 0 & & ( price = jdouble ( field , " price " ) ) ! = 0 )
price = 1. / price ;
}
free_json ( json ) ;
}
free ( jsonstr ) ;
}
if ( Debuglevel > 2 )
printf ( " (%s %f) " , metal , price ) ;
return ( price ) ;
}
cJSON * url_json ( char * url )
{
char * jsonstr ; cJSON * json = 0 ;
if ( ( jsonstr = issue_curl ( url ) ) ! = 0 )
{
//printf("(%s) -> (%s)\n",url,jsonstr);
json = cJSON_Parse ( jsonstr ) ;
free ( jsonstr ) ;
}
return ( json ) ;
}
cJSON * url_json2 ( char * url )
{
char * jsonstr ; cJSON * json = 0 ;
if ( ( jsonstr = issue_curl ( url ) ) ! = 0 )
{
//printf("(%s) -> (%s)\n",url,jsonstr);
json = cJSON_Parse ( jsonstr ) ;
free ( jsonstr ) ;
}
return ( json ) ;
}
void prices777_btcprices ( int32_t enddatenum , int32_t numdates )
{
int32_t i , n , year , month , day , seconds , datenum ; char url [ 1024 ] , date [ 64 ] , * dstr , * str ; uint32_t timestamp , utc32 [ MAX_SPLINES ] ;
cJSON * coindesk , * quandl , * btcdhist , * bpi , * array , * item ;
double btcddaily [ MAX_SPLINES ] , cdaily [ MAX_SPLINES ] , qdaily [ MAX_SPLINES ] , ask , high , low , bid , close , vol , quotevol , open , price = 0. ;
coindesk = url_json ( " http://api.coindesk.com/v1/bpi/historical/close.json " ) ;
sprintf ( url , " https://poloniex.com/public?command=returnChartData¤cyPair=BTC_BTCD&start=%ld&end=9999999999&period=86400 " , ( long ) ( time ( NULL ) - numdates * 3600 * 24 ) ) ;
if ( ( bpi = jobj ( coindesk , " bpi " ) ) ! = 0 )
{
datenum = enddatenum ;
memset ( utc32 , 0 , sizeof ( utc32 ) ) ;
memset ( cdaily , 0 , sizeof ( cdaily ) ) ;
if ( datenum = = 0 )
{
datenum = OS_conv_unixtime ( & seconds , ( uint32_t ) time ( NULL ) ) ;
printf ( " got datenum.%d %d %d %d \n " , datenum , seconds / 3600 , ( seconds / 60 ) % 24 , seconds % 60 ) ;
}
for ( i = 0 ; i < numdates ; i + + )
{
expand_datenum ( date , datenum ) ;
if ( ( price = jdouble ( bpi , date ) ) ! = 0 )
{
utc32 [ numdates - 1 - i ] = OS_conv_datenum ( datenum , 12 , 0 , 0 ) ;
cdaily [ numdates - 1 - i ] = price * .001 ;
//printf("(%s %u %f) ",date,utc32[numdates - 1 - i],price);
}
datenum = ecb_decrdate ( & year , & month , & day , date , datenum ) ;
}
prices777_genspline ( & BUNDLE . splines [ MAX_CURRENCIES ] , MAX_CURRENCIES , " coindesk " , utc32 , cdaily , numdates , cdaily ) ;
} else printf ( " no bpi \n " ) ;
quandl = url_json ( " https://www.quandl.com/api/v1/datasets/BAVERAGE/USD.json?rows=64 " ) ;
if ( ( str = jstr ( quandl , " updated_at " ) ) ! = 0 & & ( datenum = conv_date ( & seconds , str ) ) > 0 & & ( array = jarray ( & n , quandl , " data " ) ) ! = 0 )
{
printf ( " datenum.%d data.%d %d \n " , datenum , n , cJSON_GetArraySize ( array ) ) ;
memset ( utc32 , 0 , sizeof ( utc32 ) ) , memset ( qdaily , 0 , sizeof ( qdaily ) ) ;
for ( i = 0 ; i < n & & i < MAX_SPLINES ; i + + )
{
// ["Date","24h Average","Ask","Bid","Last","Total Volume"]
// ["2015-07-25",289.27,288.84,288.68,288.87,44978.61]
item = jitem ( array , i ) ;
if ( Debuglevel > 2 )
printf ( " (%s) " , cJSON_Print ( item ) ) ;
if ( ( dstr = jstr ( jitem ( item , 0 ) , 0 ) ) ! = 0 & & ( datenum = conv_date ( & seconds , dstr ) ) > 0 )
{
price = jdouble ( jitem ( item , 1 ) , 0 ) , ask = jdouble ( jitem ( item , 2 ) , 0 ) , bid = jdouble ( jitem ( item , 3 ) , 0 ) ;
close = jdouble ( jitem ( item , 4 ) , 0 ) , vol = jdouble ( jitem ( item , 5 ) , 0 ) ;
if ( Debuglevel > 2 )
fprintf ( stderr , " %d.[%d %f %f %f %f %f].%d " , i , datenum , price , ask , bid , close , vol , n ) ;
utc32 [ numdates - 1 - i ] = OS_conv_datenum ( datenum , 12 , 0 , 0 ) , qdaily [ numdates - 1 - i ] = price * .001 ;
}
}
prices777_genspline ( & BUNDLE . splines [ MAX_CURRENCIES + 1 ] , MAX_CURRENCIES + 1 , " quandl " , utc32 , qdaily , n < MAX_SPLINES ? n : MAX_SPLINES , qdaily ) ;
}
btcdhist = url_json ( url ) ;
//{"date":1406160000,"high":0.01,"low":0.00125,"open":0.01,"close":0.001375,"volume":1.50179994,"quoteVolume":903.58818412,"weightedAverage":0.00166204},
if ( ( array = jarray ( & n , btcdhist , 0 ) ) ! = 0 )
{
memset ( utc32 , 0 , sizeof ( utc32 ) ) , memset ( btcddaily , 0 , sizeof ( btcddaily ) ) ;
//printf("GOT.(%s)\n",cJSON_Print(array));
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( array , i ) ;
timestamp = juint ( item , " date " ) , high = jdouble ( item , " high " ) , low = jdouble ( item , " low " ) , open = jdouble ( item , " open " ) ;
close = jdouble ( item , " close " ) , vol = jdouble ( item , " volume " ) , quotevol = jdouble ( item , " quoteVolume " ) , price = jdouble ( item , " weightedAverage " ) ;
//printf("[%u %f %f %f %f %f %f %f]",timestamp,high,low,open,close,vol,quotevol,price);
if ( Debuglevel > 2 )
printf ( " [%u %d %f] " , timestamp , OS_conv_unixtime ( & seconds , timestamp ) , price ) ;
utc32 [ i ] = timestamp - 12 * 3600 , btcddaily [ i ] = price * 100. ;
}
if ( Debuglevel > 2 )
printf ( " poloniex.%d \n " , n ) ;
prices777_genspline ( & BUNDLE . splines [ MAX_CURRENCIES + 2 ] , MAX_CURRENCIES + 2 , " btcdhist " , utc32 , btcddaily , n < MAX_SPLINES ? n : MAX_SPLINES , btcddaily ) ;
}
// https://poloniex.com/public?command=returnChartData¤cyPair=BTC_BTCD&start=1405699200&end=9999999999&period=86400
}
int32_t prices777_calcmatrix ( double matrix [ 32 ] [ 32 ] )
{
int32_t basenum , relnum , nonz , vnum , iter , numbase , numerrs = 0 ; double sum , vsum , price , price2 , basevals [ 32 ] , errsum = 0 ;
memset ( basevals , 0 , sizeof ( basevals ) ) ;
for ( iter = 0 ; iter < 2 ; iter + + )
{
numbase = 32 ;
for ( basenum = 0 ; basenum < numbase ; basenum + + )
{
for ( vsum = sum = vnum = nonz = relnum = 0 ; relnum < numbase ; relnum + + )
{
if ( basenum ! = relnum )
{
if ( ( price = matrix [ basenum ] [ relnum ] ) ! = 0. )
{
price / = ( MINDENOMS [ relnum ] * .001 ) ;
price * = ( MINDENOMS [ basenum ] * .001 ) ;
if ( iter = = 0 )
sum + = ( price ) , nonz + + ; //, printf("%.8f ",price);
else sum + = fabs ( ( price ) - ( basevals [ basenum ] / basevals [ relnum ] ) ) , nonz + + ;
}
if ( ( price2 = matrix [ relnum ] [ basenum ] ) ! = 0. )
{
price2 * = ( MINDENOMS [ relnum ] * .001 ) ;
price2 / = ( MINDENOMS [ basenum ] * .001 ) ;
if ( iter = = 0 )
vsum + = ( price2 ) , vnum + + ;
else vsum + = fabs ( price2 - ( basevals [ relnum ] / basevals [ basenum ] ) ) , vnum + + ;
}
//if ( iter == 0 && 1/price2 > price )
// printf("base.%d rel.%d price2 %f vs %f\n",basenum,relnum,1/price2,price);
}
}
if ( iter = = 0 )
sum + = 1. , vsum + = 1. ;
if ( nonz ! = 0 )
sum / = nonz ;
if ( vnum ! = 0 )
vsum / = vnum ;
if ( iter = = 0 )
basevals [ basenum ] = ( sum + 1. / vsum ) / 2. ;
else errsum + = ( sum + vsum ) / 2 , numerrs + + ; //, printf("(%.8f %.8f) ",sum,vsum);
//printf("date.%d (%.8f/%d %.8f/%d).%02d -> %.8f\n",i,sum,nonz,vsum,vnum,basenum,basevals[basenum]);
}
if ( iter = = 0 )
{
for ( sum = relnum = 0 ; relnum < numbase ; relnum + + )
sum + = ( basevals [ relnum ] ) ; //, printf("%.8f ",(basevals[relnum]));
//printf("date.%d sums %.8f and vsums iter.%d\n",i,sum/7,iter);
sum / = ( numbase - 1 ) ;
for ( relnum = 0 ; relnum < numbase ; relnum + + )
basevals [ relnum ] / = sum ; //, printf("%.8f ",basevals[relnum]);
//printf("date.%d sums %.8f and vsums iter.%d\n",i,sum,iter);
}
else
{
for ( basenum = 0 ; basenum < numbase ; basenum + + )
matrix [ basenum ] [ basenum ] = basevals [ basenum ] ;
}
}
if ( numerrs ! = 0 )
errsum / = numerrs ;
return ( errsum ) ;
}
int32_t ecb_matrix ( double matrix [ 32 ] [ 32 ] , char * date )
{
FILE * fp = 0 ; int32_t n = 0 , datenum , year = 0 , seconds , month = 0 , day = 0 , loaded = 0 ; char fname [ 64 ] , _date [ 64 ] ;
if ( date = = 0 )
date = _date , memset ( _date , 0 , sizeof ( _date ) ) ;
sprintf ( fname , " ECB/%s " , date ) , iguana_compatible_path ( fname ) ;
if ( date [ 0 ] ! = 0 & & ( fp = fopen ( fname , " rb " ) ) ! = 0 )
{
if ( fread ( matrix , 1 , sizeof ( matrix [ 0 ] [ 0 ] ) * 32 * 32 , fp ) = = sizeof ( matrix [ 0 ] [ 0 ] ) * 32 * 32 )
loaded = 1 ;
else printf ( " fread error \n " ) ;
fclose ( fp ) ;
} else printf ( " ecb_matrix.(%s) load error fp.%p \n " , fname , fp ) ;
if ( loaded = = 0 )
{
datenum = conv_date ( & seconds , date ) ;
year = datenum / 10000 , month = ( datenum / 100 ) % 100 , day = ( datenum % 100 ) ;
if ( ( n = prices777_ecb ( date , & matrix [ 0 ] [ 0 ] , year , month , day ) ) > 0 )
{
sprintf ( fname , " ECB/%s " , date ) , iguana_compatible_path ( fname ) ;
if ( ( fp = fopen ( fname , " wb " ) ) ! = 0 )
{
if ( fwrite ( matrix , 1 , sizeof ( matrix [ 0 ] [ 0 ] ) * 32 * 32 , fp ) = = sizeof ( matrix [ 0 ] [ 0 ] ) * 32 * 32 )
loaded = 1 ;
fclose ( fp ) ;
}
} else printf ( " peggy_matrix error loading %d.%d.%d \n " , year , month , day ) ;
}
if ( loaded = = 0 & & n = = 0 )
{
printf ( " peggy_matrix couldnt process loaded.%d n.%d \n " , loaded , n ) ;
return ( - 1 ) ;
}
//"2000-01-03"
if ( ( datenum = conv_date ( & seconds , date ) ) < 0 )
return ( - 1 ) ;
printf ( " loaded.(%s) nonz.%d (%d %d %d) datenum.%d \n " , date , n , year , month , day , datenum ) ;
return ( datenum ) ;
}
void price777_update ( double * btcusdp , double * btcdbtcp )
{
int32_t i , n , seconds , datenum ; uint32_t timestamp ; char url [ 1024 ] , * dstr , * str ;
double btcddaily = 0. , btcusd = 0. , ask , high , low , bid , close , vol , quotevol , open , price = 0. ;
//cJSON *btcdtrades,*btcdtrades2,*,*bitcoincharts,;
cJSON * quandl , * btcdhist , * array , * item , * bitcoinave , * blockchaininfo , * coindesk = 0 ;
//btcdtrades = url_json("https://poloniex.com/public?command=returnTradeHistory¤cyPair=BTC_BTCD");
//btcdtrades2 = url_json("https://bittrex.com/api/v1.1/public/getmarkethistory?market=BTC-BTCD&count=50");
bitcoinave = url_json ( " https://api.bitcoinaverage.com/ticker/USD/ " ) ;
//bitcoincharts = url_json("http://api.bitcoincharts.com/v1/weighted_prices.json");
blockchaininfo = url_json ( " https://blockchain.info/ticker " ) ;
coindesk = url_json ( " http://api.coindesk.com/v1/bpi/historical/close.json " ) ;
sprintf ( url , " https://poloniex.com/public?command=returnChartData¤cyPair=BTC_BTCD&start=%ld&end=9999999999&period=86400 " , ( long ) ( time ( NULL ) - 2 * 3600 * 24 ) ) ;
quandl = url_json ( " https://www.quandl.com/api/v1/datasets/BAVERAGE/USD.json?rows=1 " ) ;
if ( quandl ! = 0 & & ( str = jstr ( quandl , " updated_at " ) ) ! = 0 & & ( datenum = conv_date ( & seconds , str ) ) > 0 & & ( array = jarray ( & n , quandl , " data " ) ) ! = 0 )
{
//printf("datenum.%d data.%d %d\n",datenum,n,cJSON_GetArraySize(array));
for ( i = 0 ; i < 1 ; i + + )
{
// ["Date","24h Average","Ask","Bid","Last","Total Volume"]
// ["2015-07-25",289.27,288.84,288.68,288.87,44978.61]
item = jitem ( array , i ) ;
if ( ( dstr = jstr ( jitem ( item , 0 ) , 0 ) ) ! = 0 & & ( datenum = conv_date ( & seconds , dstr ) ) > 0 )
{
btcusd = price = jdouble ( jitem ( item , 1 ) , 0 ) , ask = jdouble ( jitem ( item , 2 ) , 0 ) , bid = jdouble ( jitem ( item , 3 ) , 0 ) ;
close = jdouble ( jitem ( item , 4 ) , 0 ) , vol = jdouble ( jitem ( item , 5 ) , 0 ) ;
//fprintf(stderr,"%d.[%d %f %f %f %f %f].%d ",i,datenum,price,ask,bid,close,vol,n);
}
}
}
price = 0. ;
for ( i = n = 0 ; i < BUNDLE . num ; i + + )
{
if ( strcmp ( BUNDLE . ptrs [ i ] - > lbase , " btcd " ) = = 0 & & strcmp ( BUNDLE . ptrs [ i ] - > lrel , " btc " ) = = 0 & & BUNDLE . ptrs [ i ] - > lastprice ! = 0. )
{
price + = BUNDLE . ptrs [ i ] - > lastprice ;
n + + ;
}
}
if ( n ! = 0 )
{
price / = n ;
* btcdbtcp = price ;
//printf("set BTCD price %f\n",price);
BUNDLE . btcdbtc = price ;
}
else
{
btcdhist = url_json ( url ) ;
//{"date":1406160000,"high":0.01,"low":0.00125,"open":0.01,"close":0.001375,"volume":1.50179994,"quoteVolume":903.58818412,"weightedAverage":0.00166204},
if ( btcdhist ! = 0 & & ( array = jarray ( & n , btcdhist , 0 ) ) ! = 0 )
{
//printf("GOT.(%s)\n",cJSON_Print(array));
for ( i = 0 ; i < 1 ; i + + )
{
item = jitem ( array , i ) ;
timestamp = juint ( item , " date " ) , high = jdouble ( item , " high " ) , low = jdouble ( item , " low " ) , open = jdouble ( item , " open " ) ;
close = jdouble ( item , " close " ) , vol = jdouble ( item , " volume " ) , quotevol = jdouble ( item , " quoteVolume " ) , price = jdouble ( item , " weightedAverage " ) ;
//printf("[%u %f %f %f %f %f %f %f]",timestamp,high,low,open,close,vol,quotevol,price);
//printf("[%u %d %f]",timestamp,OS_conv_unixtime(&seconds,timestamp),price);
btcddaily = price ;
if ( btcddaily ! = 0 )
BUNDLE . btcdbtc = * btcdbtcp = btcddaily ;
}
//printf("poloniex.%d\n",n);
}
if ( btcdhist ! = 0 )
free_json ( btcdhist ) ;
}
// https://blockchain.info/ticker
/*
{
" USD " : { " 15m " : 288.22 , " last " : 288.22 , " buy " : 288.54 , " sell " : 288.57 , " symbol " : " $ " } ,
" ISK " : { " 15m " : 38765.88 , " last " : 38765.88 , " buy " : 38808.92 , " sell " : 38812.95 , " symbol " : " kr " } ,
" HKD " : { " 15m " : 2234 , " last " : 2234 , " buy " : 2236.48 , " sell " : 2236.71 , " symbol " : " $ " } ,
" TWD " : { " 15m " : 9034.19 , " last " : 9034.19 , " buy " : 9044.22 , " sell " : 9045.16 , " symbol " : " NT$ " } ,
" CHF " : { " 15m " : 276.39 , " last " : 276.39 , " buy " : 276.69 , " sell " : 276.72 , " symbol " : " CHF " } ,
" EUR " : { " 15m " : 262.46 , " last " : 262.46 , " buy " : 262.75 , " sell " : 262.78 , " symbol " : " € " } ,
" DKK " : { " 15m " : 1958.92 , " last " : 1958.92 , " buy " : 1961.1 , " sell " : 1961.3 , " symbol " : " kr " } ,
" CLP " : { " 15m " : 189160.6 , " last " : 189160.6 , " buy " : 189370.62 , " sell " : 189390.31 , " symbol " : " $ " } ,
" CAD " : { " 15m " : 375.45 , " last " : 375.45 , " buy " : 375.87 , " sell " : 375.91 , " symbol " : " $ " } ,
" CNY " : { " 15m " : 1783.67 , " last " : 1783.67 , " buy " : 1785.65 , " sell " : 1785.83 , " symbol " : " ¥ " } ,
" THB " : { " 15m " : 10046.98 , " last " : 10046.98 , " buy " : 10058.14 , " sell " : 10059.18 , " symbol " : " ฿ " } ,
" AUD " : { " 15m " : 394.77 , " last " : 394.77 , " buy " : 395.2 , " sell " : 395.25 , " symbol " : " $ " } ,
" SGD " : { " 15m " : 395.08 , " last " : 395.08 , " buy " : 395.52 , " sell " : 395.56 , " symbol " : " $ " } ,
" KRW " : { " 15m " : 335991.51 , " last " : 335991.51 , " buy " : 336364.55 , " sell " : 336399.52 , " symbol " : " ₩ " } ,
" JPY " : { " 15m " : 35711.99 , " last " : 35711.99 , " buy " : 35751.64 , " sell " : 35755.35 , " symbol " : " ¥ " } ,
" PLN " : { " 15m " : 1082.74 , " last " : 1082.74 , " buy " : 1083.94 , " sell " : 1084.06 , " symbol " : " zł " } ,
" GBP " : { " 15m " : 185.84 , " last " : 185.84 , " buy " : 186.04 , " sell " : 186.06 , " symbol " : " £ " } ,
" SEK " : { " 15m " : 2471.02 , " last " : 2471.02 , " buy " : 2473.76 , " sell " : 2474.02 , " symbol " : " kr " } ,
" NZD " : { " 15m " : 436.89 , " last " : 436.89 , " buy " : 437.37 , " sell " : 437.42 , " symbol " : " $ " } ,
" BRL " : { " 15m " : 944.91 , " last " : 944.91 , " buy " : 945.95 , " sell " : 946.05 , " symbol " : " R$ " } ,
" RUB " : { " 15m " : 16695.05 , " last " : 16695.05 , " buy " : 16713.58 , " sell " : 16715.32 , " symbol " : " RUB " }
} */
/*{
" 24h_avg " : 281.22 ,
" ask " : 280.12 ,
" bid " : 279.33 ,
" last " : 279.58 ,
" timestamp " : " Sun, 02 Aug 2015 09:36:34 -0000 " ,
" total_vol " : 39625.8
} */
if ( bitcoinave ! = 0 )
{
if ( ( price = jdouble ( bitcoinave , " 24h_avg " ) ) > SMALLVAL )
{
//printf("bitcoinave %f %f\n",btcusd,price);
dxblend ( & btcusd , price , 0.5 ) ;
}
free_json ( bitcoinave ) ;
}
if ( quandl ! = 0 )
free_json ( quandl ) ;
if ( coindesk ! = 0 )
free_json ( coindesk ) ;
if ( blockchaininfo ! = 0 )
{
if ( ( item = jobj ( blockchaininfo , " USD " ) ) ! = 0 & & item ! = 0 & & ( price = jdouble ( item , " 15m " ) ) > SMALLVAL )
{
//printf("blockchaininfo %f %f\n",btcusd,price);
dxblend ( & btcusd , price , 0.5 ) ;
}
free_json ( blockchaininfo ) ;
}
if ( btcusd ! = 0 )
BUNDLE . btcusd = * btcusdp = btcusd ;
// https://poloniex.com/public?command=returnChartData¤cyPair=BTC_BTCD&start=1405699200&end=9999999999&period=86400
// https://poloniex.com/public?command=returnTradeHistory¤cyPair=BTC_BTCD
//https://bittrex.com/api/v1.1/public/getmarkethistory?market=BTC-BTCD&count=50
/*{"success":true,"message":"","result":[{"Id":8551089,"TimeStamp":"2015-07-25T16:00:41.597","Quantity":59.60917089,"Price":0.00642371,"Total":0.38291202,"FillType":"FILL","OrderType":"BUY"},{"Id":8551088,"TimeStamp":"2015-07-25T16:00:41.597","Quantity":7.00000000,"Price":0.00639680,"Total":0.04477760,"FillType":"PARTIAL_FILL","OrderType":"BUY"},{"Id":8551087,"TimeStamp":"2015-07-25T16:00:41.597","Quantity":6.51000000,"Price":0.00639679,"Total":0.04164310,"FillType":"PARTIAL_FILL","OrderType":"BUY"},{"Id":8551086,"TimeStamp":"2015-07-25T16:00:41.597","Quantity":6.00000000,"Price":0.00633300,"Total":0.03799800,"FillType":"PARTIAL_FILL","OrderType":"BUY"},{"Id":8551085,"TimeStamp":"2015-07-25T16:00:41.593","Quantity":4.76833955,"Price":0.00623300,"Total":0.02972106,"FillType":"PARTIAL_FILL","OrderType":"BUY"},{"Id":8551084,"TimeStamp":"2015-07-25T16:00:41.593","Quantity":5.00000000,"Price":0.00620860,"Total":0.03104300,"FillType":"PARTIAL_FILL","OrderType":"BUY"},{"Id":8551083,"TimeStamp":"2015-07-25T16:00:41.593","Quantity":4.91803279,"Price":0.00620134,"Total":0.03049839,"FillType":"PARTIAL_FILL","OrderType":"BUY"},{"Id":8551082,"TimeStamp":"2015-07-25T16:00:41.593","Quantity":4.45166432,"Price":0.00619316,"Total":0.02756986,"FillType":"PARTIAL_FILL","OrderType":"BUY"},{"Id":8551081,"TimeStamp":"2015-07-25T16:00:41.59","Quantity":2.00000000,"Price":0.00619315,"Total":0.01238630,"FillType":"PARTIAL_FILL","OrderType":"BUY"},{"Id":8547525,"TimeStamp":"2015-07-25T06:20:43.69","Quantity":1.23166045,"Price":0.00623300,"Total":0.00767693,"FillType":"FILL","OrderType":"BUY"},{"Id":8547524,"TimeStamp":"2015-07-25T06:20:43.69","Quantity":5.00000000,"Price":0.00613300,"Total":0.03066500,"FillType":"PARTIAL_FILL","OrderType":"BUY"},{"Id":8547523,"TimeStamp":"2015-07-25T06:20:43.687","Quantity":10.00000000,"Price":0.00609990,"Total":0.06099900,"FillType":"PARTIAL_FILL","OrderType":"BUY"},{"Id":8547522,"TimeStamp":"2015-07-25T06:20:43.687","Quantity":0.12326502,"Price":0.00609989,"Total":0.00075190,"FillType":"PARTIAL_FILL","OrderType":"BUY"},{"Id":8547521,"TimeStamp":"2015-07-25T06:20:43.687","Quantity":3.29000000,"Price":0.00609989,"Total":0.02006863,"FillType":"PARTIAL_FILL","OrderType":"BUY"},{"Id":8547520,"TimeStamp":"2015-07-25T06:20:43.687","Quantity":5.00000000,"Price":0.00604400,"Total":0.03022000,"FillType":"PARTIAL_FILL","OrderType":"BUY"},{"Id":8547519,"TimeStamp":"2015-07-25T06:20:43.683","Quantity":12.80164947,"Price":0.00603915,"Total":0.07731108,"FillType":"PARTIAL_FILL","OrderType":"BUY"},{"Id":8547518,"TimeStamp":"2015-07-25T06:20:43.683","Quantity":10.00000000,"Price":0.00602715,"Total":0.06027150,"FillType":"PARTIAL_FILL","OrderType":"BUY"},{"Id":8547517,"TimeStamp":"2015-07-25T06:20:43.683","Quantity":4.29037397,"Price":0.00600000,"Total":0.02574224,"FillType":"PARTIAL_FILL","OrderType":"BUY"},{"Id":8547516,"TimeStamp":"2015-07-25T06:20:43.683","Quantity":77.55994092,"Price":0.00598921,"Total":0.46452277,"FillType":"PARTIAL_FILL","OrderType":"BUY"},{"Id":8547515,"TimeStamp":"2015-07-25T06:20:43.68","Quantity":0.08645064,"Price":0.00598492,"Total":0.00051740,"FillType":"PARTIAL_FILL","OrderType":"BUY"}]}
*/
// https://api.bitcoinaverage.com/ticker/global/all
/* {
" AED " : {
" ask " : 1063.28 ,
" bid " : 1062.1 ,
" last " : 1062.29 ,
" timestamp " : " Sat, 25 Jul 2015 17:13:14 -0000 " ,
" volume_btc " : 0.0 ,
" volume_percent " : 0.0
} , */
// http://api.bitcoincharts.com/v1/weighted_prices.json
// {"USD": {"7d": "279.79", "30d": "276.05", "24h": "288.55"}, "IDR": {"7d": "3750799.88", "30d": "3636926.02", "24h": "3860769.92"}, "ILS": {"7d": "1033.34", "30d": "1031.58", "24h": "1092.36"}, "GBP": {"7d": "179.51", "30d": "175.30", "24h": "185.74"}, "DKK": {"30d": "1758.61"}, "CAD": {"7d": "364.04", "30d": "351.27", "24h": "376.12"}, "MXN": {"30d": "4369.33"}, "XRP": {"7d": "35491.70", "30d": "29257.39", "24h": "36979.02"}, "SEK": {"7d": "2484.50", "30d": "2270.94"}, "SGD": {"7d": "381.93", "30d": "373.69", "24h": "393.94"}, "HKD": {"7d": "2167.99", "30d": "2115.77", "24h": "2232.12"}, "AUD": {"7d": "379.42", "30d": "365.85", "24h": "394.93"}, "CHF": {"30d": "250.61"}, "timestamp": 1437844509, "CNY": {"7d": "1724.99", "30d": "1702.32", "24h": "1779.48"}, "LTC": {"7d": "67.46", "30d": "51.97", "24h": "61.61"}, "NZD": {"7d": "425.01", "30d": "409.33", "24h": "437.86"}, "THB": {"30d": "8632.82"}, "EUR": {"7d": "257.32", "30d": "249.88", "24h": "263.42"}, "ARS": {"30d": "3271.98"}, "NOK": {"30d": "2227.54"}, "RUB": {"7d": "16032.32", "30d": "15600.38", "24h": "16443.39"}, "INR": {"30d": "16601.17"}, "JPY": {"7d": "34685.73", "30d": "33617.77", "24h": "35652.79"}, "CZK": {"30d": "6442.13"}, "BRL": {"7d": "946.76", "30d": "900.77", "24h": "964.09"}, "NMC": {"7d": "454.06", "30d": "370.39", "24h": "436.71"}, "PLN": {"7d": "1041.81", "30d": "1024.96", "24h": "1072.49"}, "ZAR": {"30d": "3805.55"}}
}
double blend_price ( double * volp , double wtA , cJSON * jsonA , double wtB , cJSON * jsonB )
{
//A.{"ticker":{"base":"BTS","target":"CNY","price":"0.02958291","volume":"3128008.39295500","change":"0.00019513","markets":[{"market":"BTC38","price":"0.02960000","volume":3051650.682955},{"market":"Bter","price":"0.02890000","volume":76357.71}]},"timestamp":1438490881,"success":true,"error":""}
// B.{"id":"bts\/cny","price":"0.02940000","price_before_24h":"0.02990000","volume_first":"3048457.6857147217","volume_second":"90629.45859575272","volume_btc":"52.74","best_market":"btc38","latest_trade":"2015-08-02 03:57:38","coin1":"BitShares","coin2":"CNY","markets":[{"market":"btc38","price":"0.02940000","volume":"3048457.6857147217","volume_btc":"52.738317962865"},{"market":"bter","price":"0.04350000","volume":"0","volume_btc":"0"}]}
double priceA , priceB , priceB24 , price , volA , volB ; cJSON * obj ;
priceA = priceB = priceB24 = price = volA = volB = 0. ;
if ( jsonA ! = 0 & & ( obj = jobj ( jsonA , " ticker " ) ) ! = 0 )
{
priceA = jdouble ( obj , " price " ) ;
volA = jdouble ( obj , " volume " ) ;
}
if ( jsonB ! = 0 )
{
priceB = jdouble ( jsonB , " price " ) ;
priceB24 = jdouble ( jsonB , " price_before_24h " ) ;
volB = jdouble ( jsonB , " volume_first " ) ;
}
//printf("priceA %f volA %f, priceB %f %f volB %f\n",priceA,volA,priceB,priceB24,volB);
if ( priceB > SMALLVAL & & priceB24 > SMALLVAL )
priceB = ( priceB * .1 ) + ( priceB24 * .9 ) ;
else if ( priceB < SMALLVAL )
priceB = priceB24 ;
if ( priceA * volA < SMALLVAL )
price = priceB ;
else if ( priceB * volB < SMALLVAL )
price = priceA ;
else price = ( wtA * priceA ) + ( wtB * priceB ) ;
* volp = ( volA + volB ) ;
return ( price ) ;
}
void _crypto_update ( double cryptovols [ 2 ] [ 8 ] [ 2 ] , struct prices777_data * dp , int32_t selector , int32_t peggyflag )
{
char * cryptonatorA = " https://www.cryptonator.com/api/full/%s-%s " ; //unity-btc
char * cryptocoinchartsB = " http://api.cryptocoincharts.info/tradingPair/%s_%s " ; //bts_btc
char * cryptostrs [ 9 ] = { " btc " , " nxt " , " unity " , " eth " , " ltc " , " xmr " , " bts " , " xcp " , " etc " } ;
int32_t iter , i , j ; double btcusd , btcdbtc , cnyusd , prices [ 8 ] [ 2 ] , volumes [ 8 ] [ 2 ] ;
char base [ 16 ] , rel [ 16 ] , url [ 512 ] , * str ; cJSON * jsonA , * jsonB ;
if ( peggyflag ! = 0 )
{
cnyusd = BUNDLE . cnyusd ;
btcusd = BUNDLE . btcusd ;
btcdbtc = BUNDLE . btcdbtc ;
//printf("update with btcusd %f btcd %f cnyusd %f cnybtc %f\n",btcusd,btcdbtc,cnyusd,cnyusd/btcusd);
if ( btcusd < SMALLVAL | | btcdbtc < SMALLVAL )
{
price777_update ( & btcusd , & btcdbtc ) ;
printf ( " price777_update with btcusd %f btcd %f \n " , btcusd , btcdbtc ) ;
}
memset ( prices , 0 , sizeof ( prices ) ) ;
memset ( volumes , 0 , sizeof ( volumes ) ) ;
for ( j = 0 ; j < sizeof ( cryptostrs ) / sizeof ( * cryptostrs ) ; j + + )
{
str = cryptostrs [ j ] ;
if ( strcmp ( str , " etc " ) = = 0 )
{
if ( prices [ 3 ] [ 0 ] > SMALLVAL )
break ;
i = 3 ;
} else i = j ;
for ( iter = 0 ; iter < 1 ; iter + + )
{
if ( i = = 0 & & iter = = 0 )
strcpy ( base , " btcd " ) , strcpy ( rel , " btc " ) ;
else strcpy ( base , str ) , strcpy ( rel , iter = = 0 ? " btc " : " cny " ) ;
//if ( selector == 0 )
{
sprintf ( url , cryptonatorA , base , rel ) ;
jsonA = url_json ( url ) ;
}
//else
{
sprintf ( url , cryptocoinchartsB , base , rel ) ;
jsonB = url_json ( url ) ;
}
prices [ i ] [ iter ] = blend_price ( & volumes [ i ] [ iter ] , 0.4 , jsonA , 0.6 , jsonB ) ;
if ( iter = = 1 )
{
if ( btcusd > SMALLVAL )
{
prices [ i ] [ iter ] * = cnyusd / btcusd ;
volumes [ i ] [ iter ] * = cnyusd / btcusd ;
} else prices [ i ] [ iter ] = volumes [ i ] [ iter ] = 0. ;
}
cryptovols [ 0 ] [ i ] [ iter ] = _pairaved ( cryptovols [ 0 ] [ i ] [ iter ] , prices [ i ] [ iter ] ) ;
cryptovols [ 1 ] [ i ] [ iter ] = _pairaved ( cryptovols [ 1 ] [ i ] [ iter ] , volumes [ i ] [ iter ] ) ;
if ( Debuglevel > 2 )
printf ( " (%f %f).%d:%d " , cryptovols [ 0 ] [ i ] [ iter ] , cryptovols [ 1 ] [ i ] [ iter ] , i , iter ) ;
//if ( cnyusd < SMALLVAL || btcusd < SMALLVAL )
// break;
}
}
}
}
void crypto_update ( int32_t peggyflag )
{
_crypto_update ( BUNDLE . cryptovols , & BUNDLE . data , 1 , peggyflag ) ;
while ( 1 )
{
_crypto_update ( BUNDLE . cryptovols , & BUNDLE . data , 1 , peggyflag ) ;
sleep ( 100 ) ;
}
}
void prices777_RTupdate ( double cryptovols [ 2 ] [ 8 ] [ 2 ] , double RTmetals [ 4 ] , double * RTprices , struct prices777_data * dp )
{
char * cryptostrs [ 8 ] = { " btc " , " nxt " , " unity " , " eth " , " ltc " , " xmr " , " bts " , " xcp " } ;
int32_t iter , i , c , baserel , basenum , relnum ; double cnyusd , btcusd , btcdbtc , bid , ask , price , vol , prices [ 8 ] [ 2 ] , volumes [ 8 ] [ 2 ] ;
char base [ 16 ] , rel [ 16 ] ;
price777_update ( & btcusd , & btcdbtc ) ;
memset ( prices , 0 , sizeof ( prices ) ) ;
memset ( volumes , 0 , sizeof ( volumes ) ) ;
for ( i = 0 ; i < sizeof ( cryptostrs ) / sizeof ( * cryptostrs ) ; i + + )
for ( iter = 0 ; iter < 2 ; iter + + )
prices [ i ] [ iter ] = cryptovols [ 0 ] [ i ] [ iter ] , volumes [ i ] [ iter ] = cryptovols [ 1 ] [ i ] [ iter ] ;
if ( prices [ 0 ] [ 0 ] > SMALLVAL )
dxblend ( & btcdbtc , prices [ 0 ] [ 0 ] , .9 ) ;
dxblend ( & dp - > btcdbtc , btcdbtc , .995 ) ;
if ( BUNDLE . btcdbtc < SMALLVAL )
BUNDLE . btcdbtc = dp - > btcdbtc ;
if ( ( cnyusd = BUNDLE . cnyusd ) > SMALLVAL )
{
if ( prices [ 0 ] [ 1 ] > SMALLVAL )
{
//printf("cnyusd %f, btccny %f -> btcusd %f %f\n",cnyusd,prices[0][1],prices[0][1]*cnyusd,btcusd);
btcusd = prices [ 0 ] [ 1 ] * cnyusd ;
if ( dp - > btcusd < SMALLVAL )
dp - > btcusd = btcusd ;
else dxblend ( & dp - > btcusd , btcusd , .995 ) ;
if ( BUNDLE . btcusd < SMALLVAL )
BUNDLE . btcusd = dp - > btcusd ;
if ( BUNDLE . data . btcusd < SMALLVAL )
BUNDLE . data . btcusd = dp - > btcusd ;
printf ( " cnyusd %f, btccny %f -> btcusd %f %f -> %f %f %f \n " , cnyusd , prices [ 0 ] [ 1 ] , prices [ 0 ] [ 1 ] * cnyusd , btcusd , dp - > btcusd , BUNDLE . btcusd , BUNDLE . data . btcusd ) ;
}
}
for ( i = 1 ; i < sizeof ( cryptostrs ) / sizeof ( * cryptostrs ) ; i + + )
{
if ( ( vol = volumes [ i ] [ 0 ] + volumes [ i ] [ 1 ] ) > SMALLVAL )
{
price = ( ( prices [ i ] [ 0 ] * volumes [ i ] [ 0 ] ) + ( prices [ i ] [ 1 ] * volumes [ i ] [ 1 ] ) ) / vol ;
if ( Debuglevel > 2 )
printf ( " %s %f v%f + %f v%f -> %f %f \n " , cryptostrs [ i ] , prices [ i ] [ 0 ] , volumes [ i ] [ 0 ] , prices [ i ] [ 1 ] , volumes [ i ] [ 1 ] , price , dp - > cryptos [ i ] ) ;
dxblend ( & dp - > cryptos [ i ] , price , .995 ) ;
}
}
btcusd = BUNDLE . btcusd ;
btcdbtc = BUNDLE . btcdbtc ;
if ( Debuglevel > 2 )
printf ( " update with btcusd %f btcd %f \n " , btcusd , btcdbtc ) ;
if ( btcusd < SMALLVAL | | btcdbtc < SMALLVAL )
{
price777_update ( & btcusd , & btcdbtc ) ;
if ( Debuglevel > 2 )
printf ( " price777_update with btcusd %f btcd %f \n " , btcusd , btcdbtc ) ;
} else BUNDLE . btcusd = btcusd , BUNDLE . btcdbtc = btcdbtc ;
for ( c = 0 ; c < sizeof ( CONTRACTS ) / sizeof ( * CONTRACTS ) ; c + + )
{
for ( iter = 0 ; iter < 3 ; iter + + )
{
switch ( iter )
{
case 0 : bid = dp - > tbids [ c ] , ask = dp - > tasks [ c ] ; break ;
case 1 : bid = dp - > fbids [ c ] , ask = dp - > fasks [ c ] ; break ;
case 2 : bid = dp - > ibids [ c ] , ask = dp - > iasks [ c ] ; break ;
}
if ( ( price = _pairaved ( bid , ask ) ) > SMALLVAL )
{
if ( Debuglevel > 2 )
printf ( " %.6f " , price ) ;
dxblend ( & RTprices [ c ] , price , .995 ) ;
if ( 0 & & ( baserel = prices777_ispair ( base , rel , CONTRACTS [ c ] ) ) > = 0 )
{
basenum = ( baserel > > 8 ) & 0xff , relnum = baserel & 0xff ;
if ( basenum < 32 & & relnum < 32 )
{
//printf("%s.%d %f <- %f\n",CONTRACTS[c],c,RTmatrix[basenum][relnum],RTprices[c]);
//dxblend(&RTmatrix[basenum][relnum],RTprices[c],.999);
}
}
if ( strcmp ( CONTRACTS [ c ] , " XAUUSD " ) = = 0 )
dxblend ( & RTmetals [ 0 ] , price , .995 ) ;
}
}
}
for ( i = 0 ; i < sizeof ( Yahoo_metals ) / sizeof ( * Yahoo_metals ) ; i + + )
if ( BUNDLE . data . metals [ i ] ! = 0 )
dxblend ( & RTmetals [ i ] , BUNDLE . data . metals [ i ] , .995 ) ;
}
int32_t prices777_getmatrix ( double * basevals , double * btcusdp , double * btcdbtcp , double Hmatrix [ 32 ] [ 32 ] , double * RTprices , char * contracts [ ] , int32_t num , uint32_t timestamp )
{
int32_t i , j , c ; char name [ 65 ] ; double btcusd , btcdbtc ;
memcpy ( Hmatrix , BUNDLE . data . ecbmatrix , sizeof ( BUNDLE . data . ecbmatrix ) ) ;
prices777_calcmatrix ( Hmatrix ) ;
/*for (i=0; i<32; i++)
{
for ( j = 0 ; j < 32 ; j + + )
printf ( " %.6f " , Hmatrix [ i ] [ j ] ) ;
printf ( " %s \n " , CURRENCIES [ i ] ) ;
} */
btcusd = BUNDLE . btcusd ;
btcdbtc = BUNDLE . btcdbtc ;
if ( btcusd > SMALLVAL )
dxblend ( btcusdp , btcusd , .9 ) ;
if ( btcdbtc > SMALLVAL )
dxblend ( btcdbtcp , btcdbtc , .9 ) ;
// char *cryptostrs[8] = { "btc", "nxt", "unity", "eth", "ltc", "xmr", "bts", "xcp" };
// "BTCUSD", "NXTBTC", "SuperNET", "ETHBTC", "LTCBTC", "XMRBTC", "BTSBTC", "XCPBTC", // BTC priced
for ( i = 0 ; i < num ; i + + )
{
if ( contracts [ i ] = = 0 )
continue ;
if ( i = = num - 1 & & strcmp ( contracts [ i ] , " BTCUSD " ) = = 0 )
{
RTprices [ i ] = * btcusdp ;
continue ;
}
else if ( i = = num - 2 & & strcmp ( contracts [ i ] , " BTCCNY " ) = = 0 )
{
continue ;
}
else if ( i = = num - 3 & & strcmp ( contracts [ i ] , " BTCRUB " ) = = 0 )
{
continue ;
}
else if ( i = = num - 4 & & strcmp ( contracts [ i ] , " XAUUSD " ) = = 0 )
{
continue ;
}
if ( strcmp ( contracts [ i ] , " NXTBTC " ) = = 0 )
RTprices [ i ] = BUNDLE . data . cryptos [ 1 ] ;
else if ( strcmp ( contracts [ i ] , " SuperNET " ) = = 0 )
RTprices [ i ] = BUNDLE . data . cryptos [ 2 ] ;
else if ( strcmp ( contracts [ i ] , " ETHBTC " ) = = 0 )
RTprices [ i ] = BUNDLE . data . cryptos [ 3 ] ;
else if ( strcmp ( contracts [ i ] , " LTCBTC " ) = = 0 )
RTprices [ i ] = BUNDLE . data . cryptos [ 4 ] ;
else if ( strcmp ( contracts [ i ] , " XMRBTC " ) = = 0 )
RTprices [ i ] = BUNDLE . data . cryptos [ 5 ] ;
else if ( strcmp ( contracts [ i ] , " BTSBTC " ) = = 0 )
RTprices [ i ] = BUNDLE . data . cryptos [ 6 ] ;
else if ( strcmp ( contracts [ i ] , " XCPBTC " ) = = 0 )
RTprices [ i ] = BUNDLE . data . cryptos [ 7 ] ;
else if ( i < 32 )
{
basevals [ i ] = Hmatrix [ i ] [ i ] ;
if ( Debuglevel > 2 )
printf ( " (%s %f).%d " , CURRENCIES [ i ] , basevals [ i ] , i ) ;
}
else if ( ( c = prices777_contractnum ( contracts [ i ] , 0 ) ) > = 0 )
{
RTprices [ i ] = BUNDLE . data . RTprices [ c ] ;
//if ( is_decimalstr(contracts[i]+strlen(contracts[i])-2) != 0 )
// cprices[i] *= .0001;
}
else
{
for ( j = 0 ; j < sizeof ( Yahoo_metals ) / sizeof ( * Yahoo_metals ) ; j + + )
{
sprintf ( name , " %sUSD " , Yahoo_metals [ j ] ) ;
if ( contracts [ i ] ! = 0 & & strcmp ( name , contracts [ i ] ) = = 0 )
{
RTprices [ i ] = BUNDLE . data . RTmetals [ j ] ;
break ;
}
}
}
if ( Debuglevel > 2 )
printf ( " (%f %f) i.%d num.%d %s %f \n " , * btcusdp , * btcdbtcp , i , num , contracts [ i ] , RTprices [ i ] ) ;
//printf("RT.(%s %f) ",contracts[i],RTprices[i]);
}
return ( BUNDLE . data . ecbdatenum ) ;
}
int32_t prices_idle ( int32_t peggyflag , int32_t idlegap )
{
static double lastupdate , lastdayupdate ; static int32_t didinit ; static portable_mutex_t mutex ;
int32_t i , datenum ; struct prices777_data * dp = & BUNDLE . tmp ;
* dp = BUNDLE . data ;
if ( didinit = = 0 )
{
portable_mutex_init ( & mutex ) ;
prices777_init ( BUNDLE . jsonstr , peggyflag ) ;
didinit = 1 ;
if ( peggyflag ! = 0 )
{
int32_t opreturns_init ( uint32_t blocknum , uint32_t blocktimestamp , char * path ) ;
opreturns_init ( 0 , ( uint32_t ) time ( NULL ) , " peggy " ) ;
}
}
if ( peggyflag ! = 0 & & milliseconds ( ) > lastupdate + ( 1000 * idlegap ) )
{
lastupdate = milliseconds ( ) ;
if ( milliseconds ( ) > lastdayupdate + 60000 * 60 )
{
lastdayupdate = milliseconds ( ) ;
printf ( " call ecb_matrix.(%s) \n " , dp - > edate ) ;
if ( ( datenum = ecb_matrix ( dp - > ecbmatrix , dp - > edate ) ) > 0 )
{
dp - > ecbdatenum = datenum ;
dp - > ecbyear = dp - > ecbdatenum / 10000 , dp - > ecbmonth = ( dp - > ecbdatenum / 100 ) % 100 , dp - > ecbday = ( dp - > ecbdatenum % 100 ) ;
expand_datenum ( dp - > edate , datenum ) ;
memcpy ( dp - > RTmatrix , dp - > ecbmatrix , sizeof ( dp - > RTmatrix ) ) ;
}
}
for ( i = 0 ; i < sizeof ( Yahoo_metals ) / sizeof ( * Yahoo_metals ) ; i + + )
BUNDLE . data . metals [ i ] = prices777_yahoo ( Yahoo_metals [ i ] ) ;
BUNDLE . truefxidnum = prices777_truefx ( dp - > tmillistamps , dp - > tbids , dp - > tasks , dp - > topens , dp - > thighs , dp - > tlows , BUNDLE . truefxuser , BUNDLE . truefxpass , ( uint32_t ) BUNDLE . truefxidnum ) ;
prices777_fxcm ( dp - > flhlogmatrix , dp - > flogmatrix , dp - > fbids , dp - > fasks , dp - > fhighs , dp - > flows ) ;
prices777_instaforex ( dp - > ilogmatrix , dp - > itimestamps , dp - > ibids , dp - > iasks ) ;
double btcdbtc , btcusd ;
price777_update ( & btcusd , & btcdbtc ) ;
if ( btcusd > SMALLVAL )
dxblend ( & dp - > btcusd , btcusd , 0.99 ) ;
if ( btcdbtc > SMALLVAL )
dxblend ( & dp - > btcdbtc , btcdbtc , 0.99 ) ;
if ( BUNDLE . data . btcusd = = 0 )
BUNDLE . data . btcusd = dp - > btcusd ;
if ( BUNDLE . data . btcdbtc = = 0 )
BUNDLE . data . btcdbtc = dp - > btcdbtc ;
if ( dp - > ecbmatrix [ USD ] [ USD ] > SMALLVAL & & dp - > ecbmatrix [ CNY ] [ CNY ] > SMALLVAL )
BUNDLE . cnyusd = ( dp - > ecbmatrix [ CNY ] [ CNY ] / dp - > ecbmatrix [ USD ] [ USD ] ) ;
portable_mutex_lock ( & mutex ) ;
BUNDLE . data = * dp ;
portable_mutex_unlock ( & mutex ) ;
//kv777_write(BUNDLE.kv,"data",5,&BUNDLE.data,sizeof(BUNDLE.data));
prices777_RTupdate ( BUNDLE . cryptovols , BUNDLE . data . RTmetals , BUNDLE . data . RTprices , & BUNDLE . data ) ;
//printf("update finished\n");
void peggy ( ) ;
peggy ( ) ;
didinit = 1 ;
}
return ( 0 ) ;
}
void prices777_sim ( uint32_t now , int32_t numiters )
{
double btca , btcb , btcd , btc , btcdusd , basevals [ MAX_CURRENCIES ] , btcdprices [ MAX_CURRENCIES + 1 ] ;
int32_t i , j , datenum , seconds ; uint32_t timestamp , starttime = ( uint32_t ) time ( NULL ) ;
for ( i = 0 ; i < numiters ; i + + )
{
timestamp = now - ( rand ( ) % ( 3600 * 24 * 64 ) ) ;
btca = 1000. * prices777_splineval ( & BUNDLE . splines [ MAX_CURRENCIES + 0 ] , timestamp , 0 ) ;
btcb = 1000. * prices777_splineval ( & BUNDLE . splines [ MAX_CURRENCIES + 1 ] , timestamp , 0 ) ;
btc = _pairaved ( btca , btcb ) ;
btcd = .01 * prices777_splineval ( & BUNDLE . splines [ MAX_CURRENCIES + 2 ] , timestamp , 0 ) ;
btcdusd = ( btc * btcd ) ;
datenum = OS_conv_unixtime ( & seconds , timestamp ) ;
for ( j = 0 ; j < MAX_CURRENCIES ; j + + )
{
basevals [ j ] = prices777_splineval ( & BUNDLE . splines [ j ] , timestamp , 0 ) ;
btcdprices [ j ] = basevals [ j ] / ( btcdusd * basevals [ USD ] ) ;
}
if ( ( i % 100000 ) = = 0 )
{
printf ( " %d:%02d:%02d %.8f %.8f -> USD %.8f (EURUSD %.8f %.8f) " , datenum , seconds / 3600 , ( seconds % 3600 ) / 60 , btc , btcd , btcdusd , btcdprices [ EUR ] / btcdprices [ USD ] , basevals [ EUR ] / basevals [ USD ] ) ;
for ( j = 0 ; j < MAX_CURRENCIES ; j + + )
printf ( " %.8f " , btcdprices [ j ] ) ;
printf ( " \n " ) ;
}
}
printf ( " sim took %ld seconds \n " , ( long ) ( time ( NULL ) - starttime ) ) ;
}
void prices777_getlist ( char * retbuf )
{
int32_t i , j ; struct prices777 * prices ; char pair [ 130 ] , * jsonstr ; cJSON * json , * array , * item ;
json = cJSON_CreateObject ( ) ;
array = cJSON_CreateArray ( ) ;
for ( i = 0 ; i < sizeof ( CURRENCIES ) / sizeof ( * CURRENCIES ) ; i + + )
cJSON_AddItemToArray ( array , cJSON_CreateString ( CURRENCIES [ i ] ) ) ;
cJSON_AddItemToObject ( json , " currency " , array ) ;
array = cJSON_CreateArray ( ) ;
for ( i = 0 ; i < 32 ; i + + )
for ( j = 0 ; j < 32 ; j + + )
{
if ( i ! = j )
{
sprintf ( pair , " %s%s " , CURRENCIES [ i ] , CURRENCIES [ j ] ) ;
cJSON_AddItemToArray ( array , cJSON_CreateString ( pair ) ) ;
}
}
cJSON_AddItemToObject ( json , " pairs " , array ) ;
array = cJSON_CreateArray ( ) ;
for ( i = 0 ; i < sizeof ( CONTRACTS ) / sizeof ( * CONTRACTS ) ; i + + )
cJSON_AddItemToArray ( array , cJSON_CreateString ( CONTRACTS [ i ] ) ) ;
cJSON_AddItemToObject ( json , " contract " , array ) ;
array = cJSON_CreateArray ( ) ;
for ( i = 0 ; i < BUNDLE . num ; i + + )
{
if ( ( prices = BUNDLE . ptrs [ i ] ) ! = 0 )
{
item = cJSON_CreateObject ( ) ;
cJSON_AddItemToObject ( item , prices - > exchange , cJSON_CreateString ( prices - > contract ) ) ;
cJSON_AddItemToObject ( item , " base " , cJSON_CreateString ( prices - > base ) ) ;
if ( prices - > rel [ 0 ] ! = 0 )
cJSON_AddItemToObject ( item , " rel " , cJSON_CreateString ( prices - > rel ) ) ;
//printf("(%s) (%s) (%s)\n",prices->contract,prices->base,prices->rel);
cJSON_AddItemToArray ( array , item ) ;
}
}
cJSON_AddItemToObject ( json , " result " , cJSON_CreateString ( " success " ) ) ;
cJSON_AddItemToObject ( json , " list " , array ) ;
jsonstr = cJSON_Print ( json ) , _stripwhite ( jsonstr , ' ' ) , free_json ( json ) ;
strcpy ( retbuf , jsonstr ) , free ( jsonstr ) ;
printf ( " list -> (%s) \n " , retbuf ) ;
}
# endif