diff --git a/basilisk/basilisk.c b/basilisk/basilisk.c index 82803763a..7ab92ec0a 100755 --- a/basilisk/basilisk.c +++ b/basilisk/basilisk.c @@ -14,6 +14,7 @@ ******************************************************************************/ #include "../iguana/iguana777.h" +#include "exchanges777.h" typedef char *basilisk_servicefunc(struct supernet_info *myinfo,char *CMD,void *addr,char *remoteaddr,uint32_t basilisktag,cJSON *valsobj,uint8_t *data,int32_t datalen,bits256 hash,int32_t from_basilisk); @@ -482,6 +483,7 @@ int32_t basilisk_relayid(struct supernet_info *myinfo,uint32_t ipbits) #include "basilisk_lisk.c" #include "basilisk_MSG.c" +#include "tradebots_liquidity.c" #include "basilisk_tradebot.c" #include "basilisk_swap.c" #include "basilisk_DEX.c" diff --git a/basilisk/basilisk.h b/basilisk/basilisk.h index e4bd8c5ef..68da72a3c 100755 --- a/basilisk/basilisk.h +++ b/basilisk/basilisk.h @@ -79,6 +79,7 @@ struct basilisk_swapinfo struct basilisk_swap { struct supernet_info *myinfo; struct iguana_info *bobcoin,*alicecoin; + void (*balancingtrade)(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t iambob); struct basilisk_swapinfo I; struct basilisk_rawtx bobdeposit,bobpayment,alicepayment,myfee,otherfee,aliceclaim,alicespend,bobreclaim,bobspend,bobrefund,alicereclaim; bits256 privkeys[INSTANTDEX_DECKSIZE]; diff --git a/basilisk/basilisk_swap.c b/basilisk/basilisk_swap.c index 7b1966bc9..2e55bc46a 100755 --- a/basilisk/basilisk_swap.c +++ b/basilisk/basilisk_swap.c @@ -1558,7 +1558,7 @@ int32_t basilisk_swapiteration(struct supernet_info *myinfo,struct basilisk_swap printf("Bob error spending alice payment\n"); else { - basilisk_swap_balancingtrade(myinfo,swap,1); + tradebot_swap_balancingtrade(myinfo,swap,1); printf("Bob spends alicepayment\n"); swap->I.statebits |= 0x40000; while ( basilisk_numconfirms(myinfo,&swap->bobspend) < swap->I.aliceconfirms ) @@ -1629,7 +1629,7 @@ int32_t basilisk_swapiteration(struct supernet_info *myinfo,struct basilisk_swap if ( basilisk_swapget(myinfo,swap,0x8000,data,maxlen,basilisk_verify_bobpaid) == 0 ) { printf("got bobpayment\n"); - basilisk_swap_balancingtrade(myinfo,swap,0); + tradebot_swap_balancingtrade(myinfo,swap,0); // verify payment and submit, set confirmed height swap->I.statebits |= 0x8000; } diff --git a/basilisk/basilisk_tradebot.c b/basilisk/basilisk_tradebot.c index ab606d6fb..23290c8d4 100755 --- a/basilisk/basilisk_tradebot.c +++ b/basilisk/basilisk_tradebot.c @@ -14,60 +14,6 @@ ******************************************************************************/ // included from basilisk.c -void basilisk_swap_balancingtrade(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t iambob) -{ - // update balance, compare to target balance, issue balancing trade via central exchanges, if needed - double price,volume,srcamount,destamount,profitmargin,dir=0.,dotrade=1.; char base[64],rel[64]; - srcamount = swap->I.req.srcamount; - destamount = swap->I.req.destamount; - profitmargin = (double)swap->I.req.profitmargin / 1000000.; - if ( srcamount <= SMALLVAL || destamount <= SMALLVAL ) - { - printf("illegal amount for balancing %f %f\n",srcamount,destamount); - return; - } - strcpy(rel,"BTC"); - if ( strcmp(swap->I.req.src,"BTC") == 0 ) - { - strcpy(base,swap->I.req.dest); - price = (srcamount / destamount); - volume = destamount / SATOSHIDEN; - dir = -1.; - } - else if ( strcmp(swap->I.req.dest,"BTC") == 0 ) - { - strcpy(base,swap->I.req.src); - price = (destamount / srcamount); - volume = srcamount / SATOSHIDEN; - dir = 1.; - } - else - { - printf("only BTC trades can be balanced, not (%s/%s)\n",swap->I.req.src,swap->I.req.dest); - return; - } - if ( iambob != 0 ) - { - if ( myinfo->IAMLP != 0 ) - { - printf("BOB: price %f * vol %f -> %s newprice %f margin %.2f%%\n",price,volume,dir < 0. ? "buy" : "sell",price + dir * price * profitmargin,100*profitmargin); - if ( dir < 0. ) - InstantDEX_buy(myinfo,0,0,0,"poloniex",base,rel,price,volume,dotrade); - else InstantDEX_sell(myinfo,0,0,0,"poloniex",base,rel,price,volume,dotrade); - } - } - else - { - if ( myinfo->IAMLP != 0 ) - { - printf("ALICE: price %f * vol %f -> %s newprice %f margin %.2f%%\n",price,volume,dir > 0. ? "buy" : "sell",price - dir * price * profitmargin,100*profitmargin); - if ( dir > 0. ) - InstantDEX_buy(myinfo,0,0,0,"poloniex",base,rel,price,volume,dotrade); - else InstantDEX_sell(myinfo,0,0,0,"poloniex",base,rel,price,volume,dotrade); - } - } -} - cJSON *basilisk_rawtxobj(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *rawtx) { @@ -170,12 +116,13 @@ struct basilisk_swap *basilisk_swapstore(struct supernet_info *myinfo,struct bas struct basilisk_swap *basilisk_swapload(struct supernet_info *myinfo,struct basilisk_swap *swap,uint32_t requestid,uint32_t quoteid) { - return(swap); + // set swap fields and return it if found + return(0); } void basilisk_swapstart(struct supernet_info *myinfo) // scan saved tmpswap, purge if complete, else Q { - + // for resuming pending swaps } void basilisk_txlog(struct supernet_info *myinfo,struct basilisk_swap *swap,struct basilisk_rawtx *rawtx,int32_t delay) @@ -329,53 +276,6 @@ int32_t basilisk_request_cmpref(struct basilisk_request *ref,struct basilisk_req } else return(0); } -void tradebot_liquidity_command(struct supernet_info *myinfo,char *base,bits256 hash,cJSON *vals) -{ - struct liquidity_info li,refli; int32_t i; - memset(&li,0,sizeof(li)); - strcpy(li.base,base), strcpy(li.rel,"BTC"); - li.profit = jdouble(vals,"profit"); - li.refprice = jdouble(vals,"refprice"); - for (i=0; ilinfos)/sizeof(*myinfo->linfos); i++) - { - refli = myinfo->linfos[i]; - if ( strcmp(li.rel,refli.base) == 0 && strcmp(li.base,refli.rel) == 0 ) - { - strcpy(li.base,refli.base); - strcpy(li.rel,refli.rel); - if ( fabs(li.refprice) > SMALLVAL ) - li.refprice = (1. / li.refprice); - else li.refprice = 0.; - printf("Set rev linfo[%d] (%s/%s) %.6f %.8f\n",i,li.base,li.rel,li.profit,li.refprice); - myinfo->linfos[i] = li; - return; - } - else if ( refli.base[0] == 0 || (strcmp(li.base,refli.base) == 0 && strcmp(li.rel,refli.rel) == 0) ) - { - myinfo->linfos[i] = li; - printf("Set linfo[%d] (%s/%s) %.6f %.8f\n",i,li.base,li.rel,li.profit,li.refprice); - return; - } - } - printf("ERROR: too many linfos %d\n",i); -} - -double tradebot_liquidity_active(struct supernet_info *myinfo,double *refpricep,char *base,char *rel) -{ - int32_t i; struct liquidity_info refli; - *refpricep = 0.; - for (i=0; ilinfos)/sizeof(*myinfo->linfos); i++) - { - refli = myinfo->linfos[i]; - if ( (strcmp(base,refli.base) == 0 && strcmp(rel,refli.rel) == 0) || (strcmp(rel,refli.base) == 0 && strcmp(base,refli.rel) == 0 )) - { - *refpricep = refli.refprice; - return(refli.profit); - } - } - return(0.); -} - double basilisk_request_listprocess(struct supernet_info *myinfo,struct basilisk_request *issueR,struct basilisk_request *list,int32_t n) { int32_t i,noquoteflag=0,havequoteflag=0,myrequest=0,maxi=-1; int64_t balance=0,destamount,minamount = 0,maxamount = 0; uint32_t pendingid=0; struct basilisk_swap *active; double metric = 0.; @@ -414,7 +314,7 @@ double basilisk_request_listprocess(struct supernet_info *myinfo,struct basilisk } //printf("%s -> %s myrequest.%d pendingid.%u noquoteflag.%d havequoteflag.%d maxi.%d %.8f\n",list[0].src,list[0].dest,myrequest,pendingid,noquoteflag,havequoteflag,maxi,dstr(maxamount)); double retvals[4],refprice,profitmargin,aveprice; cJSON *retjson; char *retstr; - if ( myinfo->IAMLP != 0 && myrequest == 0 && pendingid == 0 && noquoteflag != 0 && (profitmargin= tradebot_liquidity_active(myinfo,&refprice,list[0].src,list[0].dest)) > 0. ) + if ( maxi >= 0 && myinfo->IAMLP != 0 && myrequest == 0 && pendingid == 0 && noquoteflag != 0 && (profitmargin= tradebot_liquidity_active(myinfo,&refprice,"DEX",list[maxi].src,list[maxi].dest,(double)maxamount/SATOSHIDEN)) > 0. ) { if ( (aveprice= instantdex_avehbla(myinfo,retvals,list[0].src,list[0].dest,1.3 * dstr(list[0].srcamount))) == 0. || refprice > aveprice ) aveprice = refprice; diff --git a/basilisk/tradebots_liquidity.c b/basilisk/tradebots_liquidity.c new file mode 100755 index 000000000..28b551f61 --- /dev/null +++ b/basilisk/tradebots_liquidity.c @@ -0,0 +1,869 @@ +/****************************************************************************** + * 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. * + * * + ******************************************************************************/ + +// included from basilisk.c +/* + In order to provide liquidity from central exchanges, we need to issue balancing trades, however to do this properly, we need to know what the desired balance is. If unspecified, then a neutral balance is assumed. + The liquidity_info interface is quite flexible, there is a single function liquidity_active() which returns non-zero if the LP node should respond. The model is that the liquidity_command() is used to configure the liquidity_active()'s response. + In order for dynamic adaptiveness to work, the liquidity_command/liquidity_active needs to interact with the balancing. + A simplistic default trio of functions are provided, but any level of complexity is possible with the liquidity interface. + */ + +#define TRADEBOTS_NUMANSWERS 8 +#define TRADEBOTS_NUMDECAYS 8 +#define TRADEBOTS_RAWFEATURESINCR 7 +#define TRADEBOTS_MAXPAIRS 1024 + +double Tradebots_decays[TRADEBOTS_NUMDECAYS] = { 0.5, 0.666, 0.8, 0.9, 0.95, 0.99, 0.995, 0.999 }; +int32_t Tradebots_answergaps[TRADEBOTS_NUMANSWERS] = { 5, 10, 15, 20, 30, 60, 120, 720 }; + +struct tradebot_arbentry +{ + char exchange[16]; + double price,volume,profitmargin; + uint32_t timestamp; +}; + +struct tradebot_arbexchange +{ + char name[16]; + struct tradebot_arbentry trades[2]; +}; + +struct tradebot_arbpair +{ + char base[32],rel[32]; + uint32_t lasttime,lastanswertime; FILE *fp; + int32_t numexchanges,counter,btccounter,usdcounter,cnycounter; + double highbid,lowask,hblavolume,btcbid,btcask,btcvol,usdbid,usdask,usdvol,cnybid,cnyask,cnyvol; + double bidaves[TRADEBOTS_NUMDECAYS],askaves[TRADEBOTS_NUMDECAYS]; + double bidslopes[TRADEBOTS_NUMDECAYS],askslopes[TRADEBOTS_NUMDECAYS]; + struct tradebot_arbexchange exchanges[16]; + uint8_t dirmasks[2],slopedirs[2]; + char *svmpairs[TRADEBOTS_MAXPAIRS][2]; + int32_t RTgood[TRADEBOTS_NUMANSWERS],RTbad[TRADEBOTS_NUMANSWERS],numrawfeatures,numsvmfeatures,numpairs; + float rawfeatures[TRADEBOTS_NUMANSWERS+64],prevrawfeatures[TRADEBOTS_NUMANSWERS+64],*svms; // svms is coeffs vector[TRADEBOTS_NUMANSWERS] + float RTpreds[TRADEBOTS_NUMANSWERS],svmpreds[TRADEBOTS_NUMANSWERS],answers[TRADEBOTS_NUMANSWERS]; +}; +struct tradebot_arbpair Arbpairs[TRADEBOTS_MAXPAIRS],*Pair_NXTBTC,*Pair_BTCUSD,*Pair_BTCCNY; +int32_t Tradebot_numarbpairs; + +struct tradebot_arbpair *tradebot_arbpair_find(char *base,char *rel) +{ + int32_t i; + for (i=0; irel,rel); + strcpy(pair->base,base); + if ( strcmp(base,"NXT") == 0 && strcmp(rel,"BTC") == 0 ) + Pair_NXTBTC = pair, printf("Pair_NXTBTC <- %p\n",pair); + else if ( strcmp(base,"BTC") == 0 && strcmp(rel,"USD") == 0 ) + Pair_BTCUSD = pair; + else if ( strcmp(base,"BTC") == 0 && strcmp(rel,"CNY") == 0 ) + Pair_BTCCNY = pair; + sprintf(fname,"SVM/rawfeatures/%s_%s",base,rel); + pair->fp = OS_appendfile(fname); + return(pair); + } else return(0); +} + +int32_t tradebots_calcrawfeatures(struct tradebot_arbpair *pair) +{ + int32_t starti,i,n = 0; double ave; uint32_t timestamp; + n = TRADEBOTS_NUMANSWERS; + memcpy(pair->prevrawfeatures,pair->rawfeatures,sizeof(pair->prevrawfeatures)); + memset(pair->rawfeatures,0,sizeof(pair->rawfeatures)); + if ( fabs(pair->highbid) < SMALLVAL || fabs(pair->lowask) < SMALLVAL ) + return(-1); + ave = _pairaved(pair->highbid,pair->lowask); + timestamp = (uint32_t)time(NULL); + n = TRADEBOTS_NUMANSWERS; + memcpy(&pair->rawfeatures[TRADEBOTS_NUMANSWERS],×tamp,sizeof(*pair->rawfeatures)), n++; + pair->rawfeatures[n++] = pair->highbid; + pair->rawfeatures[n++] = pair->lowask; + pair->rawfeatures[n++] = pair->hblavolume / ave; + n = TRADEBOTS_RAWFEATURESINCR + TRADEBOTS_NUMANSWERS; + for (i=0; ibidaves[i]) < SMALLVAL || fabs(pair->askaves[i]) < SMALLVAL ) + return(-1); + starti = n; + pair->rawfeatures[n++] = (pair->bidaves[i] / ave) - 1.; + pair->rawfeatures[n++] = (pair->askaves[i] / ave) - 1.; + pair->rawfeatures[n++] = 10000. * (pair->bidslopes[i] / ave); + pair->rawfeatures[n++] = 10000. * (pair->askslopes[i] / ave); + if ( n < starti+TRADEBOTS_RAWFEATURESINCR ) + n = starti+TRADEBOTS_RAWFEATURESINCR; + } + if ( pair->fp != 0 ) + { + if ( fwrite(pair->rawfeatures,1,sizeof(pair->rawfeatures),pair->fp) != sizeof(pair->rawfeatures) ) + printf("fwrite error for %s/%s rawfeatures[%d]\n",pair->base,pair->rel,n); + else fflush(pair->fp); + } + if ( n > sizeof(pair->rawfeatures)/sizeof(*pair->rawfeatures) ) + { + printf("n.%d too many for rawfeatures %ld\n",n,sizeof(pair->rawfeatures)/sizeof(*pair->rawfeatures)); + exit(-1); + } + return(n); +} + +uint32_t tradebots_featureset(double *highbidp,double *lowaskp,double *avep,double *volp,double *bidaves,double *askaves,double *bidslopes,double *askslopes,float *rawfeatures) +{ + uint32_t timestamp; int32_t i,n,starti; + memcpy(×tamp,&rawfeatures[TRADEBOTS_NUMANSWERS],sizeof(timestamp)); + n = TRADEBOTS_NUMANSWERS + 1; + *highbidp = rawfeatures[n++]; + *lowaskp = rawfeatures[n++]; + *avep = _pairaved(*highbidp,*lowaskp); + *volp = rawfeatures[n++]; + n = TRADEBOTS_RAWFEATURESINCR + TRADEBOTS_NUMANSWERS; + for (i=0; i= reftimestamp+60 ) + return(-1); + factor = sqrt(reftimestamp - timestamp); + if ( factor > 60. ) + factor = 60.; + else if ( factor < 1. ) + factor = 1.; + factor = 1. / factor; + if ( refhighbid == 0. || highbid == 0. || lowask == 0. || reflowask == 0. ) + return(-1); + svmfeatures[n++] = highbid; + svmfeatures[n++] = (highbid / ave) - 1.; + svmfeatures[n++] = lowask; + svmfeatures[n++] = (lowask / ave) - 1.; + svmfeatures[n++] = (lowask - highbid); + svmfeatures[n++] = (lowask - highbid) / ave; + svmfeatures[n++] = vol; + starti = n; + svmfeatures[n++] = refhighbid; + svmfeatures[n++] = (refhighbid / refave) - 1.; + svmfeatures[n++] = reflowask; + svmfeatures[n++] = (reflowask / refave) - 1.; + svmfeatures[n++] = (reflowask - refhighbid); + svmfeatures[n++] = (reflowask - refhighbid) / refave; + svmfeatures[n++] = refvol; + for (i=0; i SMALLVAL ) + { + for (i=starti; irawfeatures,sizeof(reftimestamp)); + if ( reftimestamp == 0 ) + return(-1); + numpairfeatures = n = tradebots_expandrawfeatures(svmfeatures,pair->rawfeatures,reftimestamp,pair->prevrawfeatures); + if ( pair->numsvmfeatures != (1+pair->numpairs)*n ) + { + for (i=0; inumpairs; i++) + { + flag = -1; + if ( (ptr= tradebot_arbpair_find(pair->svmpairs[i][0],pair->svmpairs[i][1])) != 0 ) + flag = tradebots_expandrawfeatures(&svmfeatures[n],ptr->rawfeatures,reftimestamp,pair->rawfeatures); + if ( flag < 0 ) + { + for (j=0; jnumsvmfeatures ) + { + printf("unexpected numsvmfeatures %d vs %d\n",n,pair->numsvmfeatures); + return(-1); + } + return(n); +} + +int32_t tradebots_calcpreds(float *RTpreds,struct tradebot_arbpair *pair,double *svmfeatures) +{ + int32_t i,j,n=0; double feature,preds[TRADEBOTS_NUMANSWERS]; + memset(preds,0,sizeof(preds)); + for (i=n=0; inumsvmfeatures; i++) + { + feature = svmfeatures[i]; + for (j=0; jsvms[n++]; + } + return(n); +} + +void tradebots_calcanswers(struct tradebot_arbpair *pair) +{ + double highbid,lowask,futurebid,futureask,ave,vol,bidaves[TRADEBOTS_NUMDECAYS],askaves[TRADEBOTS_NUMDECAYS],bidslopes[TRADEBOTS_NUMDECAYS],askslopes[TRADEBOTS_NUMDECAYS]; + float rawfeatures[sizeof(pair->rawfeatures)/sizeof(*pair->rawfeatures)],futuremin,futuremax,minval,maxval,*hblas = 0; + uint32_t timestamp,firsttime = 0; long fpos,savepos; int32_t flag,i,iter,j,ind,maxi; + if ( pair->fp != 0 ) + { + for (iter=0; iter<2; iter++) + { + rewind(pair->fp); + fpos = 0; + while ( fread(rawfeatures,1,sizeof(pair->rawfeatures),pair->fp) == sizeof(pair->rawfeatures) ) + { + savepos = ftell(pair->fp); + timestamp = tradebots_featureset(&highbid,&lowask,&ave,&vol,bidaves,askaves,bidslopes,askslopes,rawfeatures); + if ( firsttime == 0 ) + { + firsttime = timestamp; + maxi = (int32_t)((time(NULL) - firsttime) / 60 + 1); + hblas = calloc(maxi,sizeof(*hblas)*2); + } + if ( (i= (timestamp - firsttime)/60) >= 0 && i < maxi ) + { + if ( iter == 0 ) + { + _xblend(&hblas[i << 1],highbid,0.5); + _xblend(&hblas[(i << 1) + 1],lowask,0.5); + } + else + { + highbid = hblas[i << 1]; + lowask = hblas[(i << 1) + 1]; + if ( fabs(highbid) > SMALLVAL && fabs(lowask) > SMALLVAL ) + { + memset(pair->answers,0,sizeof(pair->answers)); + flag = 0; + for (j=0; j maxval ) + { + if ( futuremax < minval ) + printf("%s/%s A%d: highly volatile minmax.(%f %f) -> (%f %f) %d of %d\n",pair->base,pair->rel,j,minval,maxval,futuremin,futuremax,i,maxi); + else + { + pair->answers[j] = (futuremin - maxval); + flag++; + } + } + else if ( futuremax < minval ) + pair->answers[j] = (futuremax - minval), flag++; + } + if ( flag != 0 ) + { + fseek(pair->fp,fpos,SEEK_SET); + if ( fwrite(pair->answers,1,sizeof(pair->answers),pair->fp) != sizeof(pair->answers) ) + printf("error writing answers for %s/%s t%u i.%d of %d\n",pair->base,pair->rel,timestamp,i,maxi); + else + { + for (j=0; janswers[i]); + printf("%s/%s answers %d of %d\n",pair->base,pair->rel,i,maxi); + } + fseek(pair->fp,savepos,SEEK_SET); + } + } + } + } + fpos = ftell(pair->fp); + } + if ( iter == 0 ) + { + highbid = hblas[0]; + lowask = hblas[1]; + for (i=1; i SMALLVAL && fabs(hblas[(i << 1) + 1]) > SMALLVAL ) + { + highbid = hblas[i << 1]; + lowask = hblas[(i << 1) + 1]; + } + else + { + hblas[i << 1] = highbid; + hblas[(i << 1) + 1] = lowask; + } + } + } + } + if ( hblas != 0 ) + free(hblas); + } +} + +static char *assetids[][2] = +{ + { "12071612744977229797", "UNITY" }, + { "15344649963748848799", "DEX" }, + { "6883271355794806507", "PANGEA" }, + { "17911762572811467637", "JUMBLR" }, + { "17083334802666450484", "BET" }, + { "13476425053110940554", "CRYPTO" }, + { "6932037131189568014", "HODL" }, + { "3006420581923704757", "SHARK" }, + { "17571711292785902558", "BOTS" }, + { "10524562908394749924", "MGW" }, +}; + +uint64_t NXT_assetidfind(char *base) +{ + int32_t i; + for (i=0; iexchange[0] == 0 ) + strcpy(arb->exchange,exchange); + if ( strcmp(arb->exchange,exchange) == 0 ) + { + arb->price = price; + arb->volume = volume; + arb->timestamp = timestamp; + arb->profitmargin = profitmargin; + } else printf("mismatched arbexchange? (%s vs %s)\n",arb->exchange,exchange); +} + +struct tradebot_arbexchange *tradebot_arbexchange_find(struct tradebot_arbpair *pair,char *exchange) +{ + int32_t i; + for (i=0; inumexchanges; i++) + if ( strcmp(pair->exchanges[i].name,exchange) == 0 ) + return(&pair->exchanges[i]); + return(0); +} + +struct tradebot_arbexchange *tradebot_arbexchange_create(struct tradebot_arbpair *pair,char *exchange) +{ + if ( pair->numexchanges < sizeof(pair->exchanges)/sizeof(*pair->exchanges) ) + { + strcpy(pair->exchanges[pair->numexchanges].name,exchange); + return(&pair->exchanges[pair->numexchanges++]); + } else return(0); +} + +void tradebot_arbcandidate(struct supernet_info *myinfo,char *exchange,int32_t tradedir,char *base,char *rel,double price,double volume,uint32_t timestamp,double profitmargin) +{ + int32_t i,offset,flag; double highbid,lowask,lastbid,lastask,arbval; + struct tradebot_arbentry *bid,*ask; struct tradebot_arbexchange *arbex; struct tradebot_arbpair *pair = 0; + if ( strcmp(rel,"BTC") != 0 && strcmp(rel,"NXT") != 0 && strcmp(rel,"USD") != 0 && strcmp(rel,"CNY") != 0 ) + { + printf("reject non-BTC arbcandidate (%s/%s)\n",base,rel); + return; + } + offset = (tradedir > 0) ? 0 : 1; + if ( (pair= tradebot_arbpair_find(base,rel)) == 0 ) + pair = tradebot_arbpair_create(base,rel); + if ( pair == 0 ) + { + printf("cant get pair for %s %s/%s\n",exchange,base,rel); + return; + } + if ( (arbex= tradebot_arbexchange_find(pair,exchange)) == 0 ) + arbex = tradebot_arbexchange_create(pair,exchange); + if ( arbex != 0 ) + { + //printf("cand.%d %16s %s %12.6f (%5s/%-5s) at %12.8f profit %.03f\n",pair->numexchanges,exchange,tradedir<0?"ask":"bid",volume,base,rel,price,profitmargin); + tradebot_arbentry(&arbex->trades[offset],exchange,price,volume,timestamp,profitmargin); + bid = ask = 0; + pair->highbid = pair->lowask = highbid = lowask = 0.; + //if ( pair->numexchanges >= 2 ) + { + for (i=0; inumexchanges; i++) + { + arbex = &pair->exchanges[i]; + if ( arbex->trades[0].price != 0. && (highbid == 0. || arbex->trades[0].price >= highbid) ) + { + bid = &arbex->trades[0]; + highbid = bid->price; + } + if ( arbex->trades[1].price != 0. && (lowask == 0. || arbex->trades[1].price <= lowask) ) + { + ask = &arbex->trades[1]; + lowask = ask->price; + } + //printf("%p %s %s %f %f -> %p %p %f %f (%f %f)\n",pair,pair->base,arbex->name,arbex->trades[0].price,arbex->trades[1].price,bid,ask,highbid,lowask,pair->highbid,pair->lowask); + } + flag = 0; + if ( Pair_NXTBTC != 0 && pair->btccounter != Pair_NXTBTC->counter ) + flag |= 1; + if ( Pair_BTCUSD != 0 && pair->usdcounter != Pair_BTCUSD->counter ) + flag |= 2; + if ( Pair_BTCCNY != 0 && pair->cnycounter != Pair_BTCCNY->counter ) + flag |= 4; + //printf("%s %s/%s flag.%d (%d %d) %p %p\n",exchange,base,rel,flag,pair->btccounter,Pair_NXTBTC!=0?Pair_NXTBTC->counter:-1,bid,ask); + if ( bid != 0 && ask != 0 && (fabs(bid->price - pair->highbid) > SMALLVAL || fabs(ask->price - pair->lowask) > SMALLVAL || (strcmp(pair->rel,"NXT") == 0 && flag != 0)) ) + { + pair->counter++; + pair->hblavolume = volume = MIN(bid->volume,ask->volume); + arbval = lastbid = lastask = 0.; + memset(pair->dirmasks,0,sizeof(pair->dirmasks)); + memset(pair->slopedirs,0,sizeof(pair->slopedirs)); + if ( strcmp(pair->rel,"NXT") == 0 ) + { + if ( Pair_NXTBTC != 0 && Pair_NXTBTC->highbid != 0. && Pair_NXTBTC->lowask != 0. ) + { + pair->btccounter = Pair_NXTBTC->counter; + pair->btcbid = highbid * Pair_NXTBTC->highbid; + pair->btcask = lowask * Pair_NXTBTC->lowask; + pair->btcvol = volume * _pairaved(pair->btcbid,pair->btcask); + } + } + else if ( strcmp(pair->rel,"BTC") == 0 ) + { + pair->btcbid = highbid; + pair->btcask = lowask; + pair->btcvol = volume; + } + if ( strcmp(pair->rel,"USD") == 0 ) + { + pair->usdbid = highbid; + pair->usdask = lowask; + pair->usdvol = volume; + } + if ( strcmp(pair->rel,"CNY") == 0 ) + { + pair->cnybid = highbid; + pair->cnyask = lowask; + pair->cnyvol = volume; + } + if ( pair->btcbid != 0. && pair->btcask != 0. ) + { + if ( strcmp(pair->rel,"USD") != 0 && Pair_BTCUSD != 0 && Pair_BTCUSD->highbid != 0. && Pair_BTCUSD->lowask != 0. ) + { + pair->usdcounter = Pair_BTCUSD->counter; + pair->usdbid = pair->btcbid * Pair_BTCUSD->highbid; + pair->usdask = pair->btcask * Pair_BTCUSD->lowask; + pair->usdvol = pair->btcvol * _pairaved(pair->usdbid,pair->usdask); + } + if ( strcmp(pair->rel,"CNY") != 0 && Pair_BTCCNY != 0 && Pair_BTCCNY->highbid != 0. && Pair_BTCCNY->lowask != 0. ) + { + pair->cnycounter = Pair_BTCCNY->counter; + pair->cnybid = pair->btcbid * Pair_BTCCNY->highbid; + pair->cnyask = pair->btcask * Pair_BTCCNY->lowask; + pair->cnyvol = pair->btcvol * _pairaved(pair->cnybid,pair->cnyask); + } + } + for (i=0; ibidslopes[i]= dxblend(&pair->bidaves[i],highbid,Tradebots_decays[i])) > 0. ) + pair->slopedirs[0] |= (1 << i); + if ( (pair->askslopes[i]= dxblend(&pair->askaves[i],lowask,Tradebots_decays[i])) > 0. ) + pair->slopedirs[1] |= (1 << i); + lastbid = pair->bidaves[i]; + lastask = pair->askaves[i]; + //printf("(%.8f %.8f) ",lastbid,lastask); + } + for (i=0; i lastbid ) + pair->dirmasks[0] |= (1 << i); + if ( lowask > lastask ) + pair->dirmasks[1] |= (1 << i); + } + else + { + if ( pair->bidaves[i-1] > lastbid ) + pair->dirmasks[0] |= (1 << i); + if ( pair->askaves[i-1] > lastask ) + pair->dirmasks[1] |= (1 << i); + } + } + printf("%12.6f %7s/%-3s %8s %14.8f %8s %14.8f spread %6.2f%% %02x:%02x %02x:%02x %d\n",volume,base,rel,bid->exchange,highbid,ask->exchange,lowask,100.*(lowask-highbid)/_pairaved(highbid,lowask),pair->dirmasks[0],pair->slopedirs[0],pair->dirmasks[1],pair->slopedirs[1],pair->counter); + //printf("BTC.(%.8f %.8f) %.8f %.8f USD.(%.4f %.4f) CNY.(%.3f %.3f)\n",pair->btcbid,pair->btcask,Pair_BTCUSD!=0?Pair_BTCUSD->highbid:0,Pair_BTCUSD!=0?Pair_BTCUSD->lowask:0,pair->usdbid,pair->usdask,pair->cnybid,pair->cnyask); + } + if ( highbid != 0 ) + pair->highbid = highbid; + if ( lowask != 0 ) + pair->lowask = lowask; + //printf(">>>>>>> %s (%s/%s) BTC %.8f %.8f v%f counter.%d btc.%d (%d)\n",exchange,pair->base,pair->rel,pair->btcbid,pair->btcask,pair->btcvol,pair->counter,pair->btccounter,Pair_NXTBTC!=0?Pair_NXTBTC->counter:-1); + if ( bid != 0 && ask != 0 && highbid > lowask && strcmp(bid->exchange,ask->exchange) != 0 && strcmp(rel,"BTC") == 0 ) + { + volume = MIN(bid->volume,ask->volume); + if ( volume*_pairaved(highbid,lowask) > 0.1 ) + volume = 0.1 / _pairaved(highbid,lowask); + if ( highbid * (1. - bid->profitmargin) > lowask * (1. + ask->profitmargin) ) + { + arbval = highbid * (1. - bid->profitmargin) - lowask * (1. + ask->profitmargin); + printf(">>>>>>>> FOUND ARB %s/%s highbid.%s %.8f lowask.%s %.8f volume %f (%.8f %.8f) %.4f%%\n",pair->base,pair->rel,bid->exchange,bid->price,ask->exchange,ask->price,volume,highbid,lowask,100.*(highbid-lowask)/_pairaved(highbid,lowask)); + InstantDEX_buy(myinfo,0,0,0,ask->exchange,pair->base,"BTC",ask->price,volume,1); + InstantDEX_sell(myinfo,0,0,0,bid->exchange,pair->base,"BTC",bid->price,volume,1); + printf("finished trades %s/%s volume %f\n",pair->base,pair->rel,volume); + } + } + if ( pair->counter > TRADEBOTS_NUMDECAYS ) + { + if ( pair->lasttime != time(NULL) ) + { + if ( (pair->numrawfeatures= tradebots_calcrawfeatures(pair)) > 0 ) + { + if ( pair->numsvmfeatures != 0 ) + { + if ( myinfo->svmfeatures == 0 ) + myinfo->svmfeatures = calloc(sizeof(*myinfo->svmfeatures),pair->numsvmfeatures); + if ( tradebots_calcsvmfeatures(myinfo->svmfeatures,pair) > 0 ) + tradebots_calcpreds(pair->RTpreds,pair,myinfo->svmfeatures); + } + } + pair->lasttime = (uint32_t)time(NULL); + } + if ( time(NULL) > pair->lastanswertime+3600 ) + { + tradebots_calcanswers(pair); + pair->lastanswertime = (uint32_t)time(NULL); + } + } + } + } +} + +void _default_swap_balancingtrade(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t iambob) +{ + // update balance, compare to target balance, issue balancing trade via central exchanges, if needed + double price,volume,srcamount,destamount,profitmargin,dir=0.,dotrade=1.; char base[64],rel[64]; + srcamount = swap->I.req.srcamount; + destamount = swap->I.req.destamount; + profitmargin = (double)swap->I.req.profitmargin / 1000000.; + if ( srcamount <= SMALLVAL || destamount <= SMALLVAL ) + { + printf("illegal amount for balancing %f %f\n",srcamount,destamount); + return; + } + strcpy(rel,"BTC"); + if ( strcmp(swap->I.req.src,"BTC") == 0 ) + { + strcpy(base,swap->I.req.dest); + price = (srcamount / destamount); + volume = destamount / SATOSHIDEN; + dir = -1.; + } + else if ( strcmp(swap->I.req.dest,"BTC") == 0 ) + { + strcpy(base,swap->I.req.src); + price = (destamount / srcamount); + volume = srcamount / SATOSHIDEN; + dir = 1.; + } + else + { + printf("only BTC trades can be balanced, not (%s/%s)\n",swap->I.req.src,swap->I.req.dest); + return; + } + if ( iambob != 0 ) + { + if ( myinfo->IAMLP != 0 ) + { + printf("BOB: price %f * vol %f -> %s newprice %f margin %.2f%%\n",price,volume,dir < 0. ? "buy" : "sell",price + dir * price * profitmargin,100*profitmargin); + if ( dir < 0. ) + InstantDEX_buy(myinfo,0,0,0,"poloniex",base,rel,price,volume,dotrade); + else InstantDEX_sell(myinfo,0,0,0,"poloniex",base,rel,price,volume,dotrade); + } + } + else + { + if ( myinfo->IAMLP != 0 ) + { + printf("ALICE: price %f * vol %f -> %s newprice %f margin %.2f%%\n",price,volume,dir > 0. ? "buy" : "sell",price - dir * price * profitmargin,100*profitmargin); + if ( dir > 0. ) + InstantDEX_buy(myinfo,0,0,0,"poloniex",base,rel,price,volume,dotrade); + else InstantDEX_sell(myinfo,0,0,0,"poloniex",base,rel,price,volume,dotrade); + } + } +} + +void _default_liquidity_command(struct supernet_info *myinfo,char *base,bits256 hash,cJSON *vals) +{ + struct liquidity_info li,refli; int32_t i; char *exchange,*relstr,numstr[32]; + if ( (exchange= jstr(vals,"exchange")) == 0 ) + exchange = "DEX"; + else if ( strcmp(exchange,"*") == 0 ) + exchange = ""; + else if ( exchanges777_find(exchange) == 0 ) + { + printf("cant find exchange.(%s)\n",exchange); + return; + } + if ( (relstr= jstr(vals,"rel")) == 0 ) + relstr = "BTC"; + if ( base == 0 || base[0] == 0 ) + base = jstr(vals,"base"); + if ( base == 0 || base[0] == 0 ) + return; + memset(&li,0,sizeof(li)); + safecopy(li.base,base,sizeof(li.base)); + safecopy(li.rel,relstr,sizeof(li.rel)); + safecopy(li.exchange,exchange,sizeof(li.exchange)); + li.profit = jdouble(vals,"profit"); + li.refprice = jdouble(vals,"refprice"); + li.dir = jint(vals,"dir"); // positive -> buy, negative -> sell, 0 or missing -> both + // li.theoretical = ... dotproduct + // li.filter = ... + // li.trigger = ... + // PAX response + if ( strcmp("NXT",li.rel) == 0 ) + li.assetid = NXT_assetidfind(base); + else if ( strcmp("UNITY",base) == 0 ) + li.assetid = NXT_assetidfind(base); + if ( strcmp(li.base,"BTC") == 0 && strcmp("USD",li.rel) != 0 && strcmp("CNY",li.rel) != 0 ) + { + printf("unsupported base BTC (%s/%s)\n",li.base,li.rel); + return; + } + if ( strcmp(li.base,"BTC") != 0 && strcmp("BTC",li.rel) != 0 && + strcmp(li.base,"NXT") != 0 && strcmp("NXT",li.rel) != 0 && + strcmp(li.base,"USD") != 0 && strcmp("USD",li.rel) != 0 && + strcmp(li.base,"CNY") != 0 && strcmp("CNY",li.rel) != 0 && + strcmp(li.exchange,"DEX") != 0 ) // filter out most invalids + { + printf("unsupported base/rel %s/%s\n",li.base,li.rel); + return; + } + for (i=0; ilinfos)/sizeof(*myinfo->linfos); i++) + { + refli = myinfo->linfos[i]; + /*if ( strcmp(li.rel,refli.base) == 0 && strcmp(li.base,refli.rel) == 0 ) + { + li = refli; + strcpy(li.base,refli.base); + strcpy(li.rel,refli.rel); + if ( fabs(li.refprice) > SMALLVAL ) + li.refprice = (1. / li.refprice); + else li.refprice = 0.; + li.dir = -li.dir; + printf("Set rev linfo[%d] (%s/%s) %.6f %.8f\n",i,li.base,li.rel,li.profit,li.refprice); + myinfo->linfos[i] = li; + return; + } + else*/ if ( refli.base[0] == 0 || (strcmp(li.base,refli.base) == 0 && strcmp(li.rel,refli.rel) == 0 && strcmp(li.exchange,refli.exchange) == 0) ) + { + if ( refli.base[0] == 0 && li.exchange[0] != 0 && strcmp(li.exchange,"DEX") != 0 ) + { + if ( strcmp("NXT",li.rel) == 0 && li.assetid != 0 ) + { + sprintf(numstr,"%llu",(long long)li.assetid); + printf("monitor %s %s\n",li.rel,numstr); + tradebot_monitor(myinfo,0,0,0,li.exchange,numstr,li.rel,0.); + } else tradebot_monitor(myinfo,0,0,0,li.exchange,li.base,li.rel,0.); + } + myinfo->linfos[i] = li; + printf("Set linfo[%d] %s (%s/%s) %.6f %.8f\n",i,li.exchange,li.base,li.rel,li.profit,li.refprice); + return; + } + } + printf("ERROR: too many linfos %d\n",i); +} + +int32_t _default_volume_ok(struct supernet_info *myinfo,struct liquidity_info *li,int32_t dir,double volume) +{ + // check order exposure + // check cumulative exposure + return(0); +} + +double _default_liquidity_active(struct supernet_info *myinfo,double *refpricep,char *exchange,char *base,char *rel,double volume) +{ + int32_t i,dir; struct liquidity_info refli; + *refpricep = 0.; + //printf("%s %s/%s\n",exchange,base,rel); + for (i=sizeof(myinfo->linfos)/sizeof(*myinfo->linfos)-1; i>=0; i--) + { + refli = myinfo->linfos[i]; + if ( refli.base[0] == 0 ) + continue; + if ( strcmp(base,refli.base) == 0 && strcmp(rel,refli.rel) == 0 ) + dir = 1; + else if ( strcmp(rel,refli.base) == 0 && strcmp(base,refli.rel) == 0 ) + dir = -1; + else dir = 0; + if ( exchange[0] != 0 && refli.exchange[0] != 0 && strcmp(exchange,refli.exchange) != 0 ) + { + //printf("continue %s %s/%s [%d] dir.%d refli.dir %d vs %s %s/%s\n",exchange,base,rel,i,dir,refli.dir,refli.exchange,refli.base,refli.rel); + continue; + } + //printf(">>>>>>>> %s %s/%s [%d] dir.%d refli.dir %d vs %s/%s\n",exchange,base,rel,i,dir,refli.dir,refli.base,refli.rel); + if ( dir != 0 && dir * refli.dir <= 0 ) + { + if ( _default_volume_ok(myinfo,&refli,dir,volume) == 0 ) + { + *refpricep = refli.refprice; + return(refli.profit); + } else break; + } + } + return(0.); +} + +void tradebot_swap_balancingtrade(struct supernet_info *myinfo,struct basilisk_swap *swap,int32_t iambob) +{ + if ( swap->balancingtrade == 0 ) + _default_swap_balancingtrade(myinfo,swap,iambob); + else (*swap->balancingtrade)(myinfo,swap,iambob); +} + +void tradebot_liquidity_command(struct supernet_info *myinfo,char *base,bits256 hash,cJSON *vals) +{ + // processed in LIFO manner which allows to override existing command + if ( myinfo->liquidity_command == 0 ) + _default_liquidity_command(myinfo,base,hash,vals); + else (*myinfo->liquidity_command)(myinfo,base,hash,vals); +} + +double tradebot_liquidity_active(struct supernet_info *myinfo,double *refpricep,char *exchange,char *base,char *rel,double destvolume) +{ + if ( myinfo->liquidity_active == 0 ) + return(_default_liquidity_active(myinfo,refpricep,exchange,base,rel,destvolume)); + else return((*myinfo->liquidity_active)(myinfo,refpricep,exchange,base,rel,destvolume)); +} + +// struct exchange_quote { uint64_t satoshis,orderid,offerNXT,exchangebits; double price,volume; uint32_t timestamp,val; }; + +void tradebots_processprices(struct supernet_info *myinfo,struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t numbids,int32_t numasks) +{ + double price,profitmargin,volume; struct tradebot_arbpair *pair; + if ( strcmp(rel,"NXT") == 0 && strcmp(base,"BTC") != 0 && (base= NXT_assetnamefind(base)) == 0 ) + { + //printf("reject %s %s/%s\n",exchange,base,rel); + return; + } + else if ( strcmp(base,"NXT") == 0 && strcmp(rel,"BTC") != 0 && (rel= NXT_assetnamefind(rel)) == 0 ) + { + //printf("reject %s %s/%s\n",exchange,base,rel); + return; + } + //printf("%s %s/%s bids.%d asks.%d\n",exchange->name,base,rel,numbids,numasks); + if ( numbids > 0 && (volume= bidasks[0].volume) > 0. && (profitmargin= + tradebot_liquidity_active(myinfo,&price,exchange->name,base,rel,volume)) > 0. ) + { + if ( price == 0. ) + price = bidasks[0].price; + tradebot_arbcandidate(myinfo,exchange->name,1,base,rel,price,volume,(uint32_t)time(NULL),profitmargin); + } + if ( numasks > 0 && (volume= bidasks[1].volume) > 0. && (profitmargin= + tradebot_liquidity_active(myinfo,&price,exchange->name,rel,base,volume)) > 0. ) + { + if ( price == 0. ) + price = bidasks[1].price; + tradebot_arbcandidate(myinfo,exchange->name,-1,base,rel,price,volume,(uint32_t)time(NULL),profitmargin); + } + if ( (pair= tradebot_arbpair_find(base,rel)) == 0 ) + pair = tradebot_arbpair_create(base,rel); + if ( pair != 0 ) + { + if ( strcmp(rel,"NXT") == 0 ) + { + if ( pair->btcbid != 0. && pair->btcask != 0. ) + { + tradebot_arbcandidate(myinfo,"arb",1,base,"BTC",pair->btcbid,pair->btcvol,(uint32_t)time(NULL),profitmargin); + tradebot_arbcandidate(myinfo,"arb",-1,base,"BTC",pair->btcask,pair->btcvol,(uint32_t)time(NULL),profitmargin); + } + } + if ( strcmp(rel,"USD") != 0 && pair->usdbid != 0. && pair->usdask != 0. ) + { + tradebot_arbcandidate(myinfo,"arb",1,base,"USD",pair->usdbid,pair->usdvol,(uint32_t)time(NULL),profitmargin); + tradebot_arbcandidate(myinfo,"arb",-1,base,"USD",pair->usdask,pair->usdvol,(uint32_t)time(NULL),profitmargin); + } + if ( strcmp(rel,"CNY") != 0 && pair->cnybid != 0. && pair->cnyask != 0. ) + { + tradebot_arbcandidate(myinfo,"arb",1,base,"CNY",pair->cnybid,pair->cnyvol,(uint32_t)time(NULL),profitmargin); + tradebot_arbcandidate(myinfo,"arb",-1,base,"CNY",pair->cnyask,pair->cnyvol,(uint32_t)time(NULL),profitmargin); + } + } +} diff --git a/crypto777/OS_portable.c b/crypto777/OS_portable.c index ff16d4a65..c06dfb545 100755 --- a/crypto777/OS_portable.c +++ b/crypto777/OS_portable.c @@ -94,6 +94,17 @@ char *OS_portable_path(char *str) #endif } +FILE *OS_appendfile(char *origfname) +{ + char fname[1024]; FILE *fp; + strcpy(fname,origfname); + OS_portable_path(fname); + if ( (fp= fopen(fname,"rb+")) == 0 ) + fp = fopen(fname,"wb"); + else fseek(fp,0,SEEK_END); + return(fp); +} + int32_t OS_portable_renamefile(char *fname,char *newfname) { #ifdef _WIN32 diff --git a/crypto777/OS_portable.h b/crypto777/OS_portable.h index f0d61365e..68a59b0a7 100755 --- a/crypto777/OS_portable.h +++ b/crypto777/OS_portable.h @@ -219,6 +219,7 @@ uint32_t OS_conv_datenum(int32_t datenum,int32_t hour,int32_t minute,int32_t sec int32_t OS_conv_unixtime(struct tai *t,int32_t *secondsp,time_t timestamp); char *OS_compatible_path(char *str); +FILE *OS_appendfile(char *origfname); int32_t OS_compare_files(char *fname,char *fname2); int64_t OS_copyfile(char *src,char *dest,int32_t cmpflag); diff --git a/crypto777/bitcoind_RPC.c b/crypto777/bitcoind_RPC.c index ed69962c6..5960a16c0 100755 --- a/crypto777/bitcoind_RPC.c +++ b/crypto777/bitcoind_RPC.c @@ -155,6 +155,7 @@ try_again: curl_easy_setopt(curl_handle,CURLOPT_WRITEDATA, &s); // we pass our 's' struct to the callback curl_easy_setopt(curl_handle,CURLOPT_NOSIGNAL, 1L); // supposed to fix "Alarm clock" and long jump crash curl_easy_setopt(curl_handle,CURLOPT_NOPROGRESS, 1L); // no progress callback + //curl_easy_setopt(curl_handle,CURLOPT_TIMEOUT, 60L); if ( strncmp(url,"https",5) == 0 ) { curl_easy_setopt(curl_handle,CURLOPT_SSL_VERIFYPEER,0); diff --git a/crypto777/hmac_sha512.c b/crypto777/hmac_sha512.c index 68c428189..e1fe4e523 100755 --- a/crypto777/hmac_sha512.c +++ b/crypto777/hmac_sha512.c @@ -506,7 +506,7 @@ char *hmac_sha512_str(char *dest,char *key,int32_t key_size,char *message) hmac_memory(&sha512_desc,(void *)key,key_size,(void *)message,strlen(message),checkbuf,&size); init_hexbytes_noT(dest,mac,SHA512_DIGEST_SIZE); init_hexbytes_noT(dest2,checkbuf,SHA512_DIGEST_SIZE); - //if ( memcmp(checkbuf,mac,SHA512_DIGEST_SIZE) != 0 ) + if ( memcmp(checkbuf,mac,SHA512_DIGEST_SIZE) != 0 ) printf("hmac_512 : %s vs %s\n",dest,dest2); return(dest); } diff --git a/crypto777/iguana_utils.c b/crypto777/iguana_utils.c index 700cd73cc..aa532d699 100755 --- a/crypto777/iguana_utils.c +++ b/crypto777/iguana_utils.c @@ -193,6 +193,14 @@ void calc_OP_HASH160(char hexstr[41],uint8_t rmd160[20],char *pubkey) init_hexbytes_noT(hexstr,rmd160,20); } +double _xblend(float *destp,double val,double decay) +{ + double oldval; + if ( (oldval = *destp) != 0. ) + return((oldval * decay) + ((1. - decay) * val)); + else return(val); +} + double _dxblend(double *destp,double val,double decay) { double oldval; diff --git a/iguana/dpow/dpow_tx.c b/iguana/dpow/dpow_tx.c index 653e633c2..2b3b8b23b 100755 --- a/iguana/dpow/dpow_tx.c +++ b/iguana/dpow/dpow_tx.c @@ -558,7 +558,7 @@ int32_t dpow_signedtxgen(struct supernet_info *myinfo,struct dpow_info *dp,struc void dpow_sigscheck(struct supernet_info *myinfo,struct dpow_info *dp,struct dpow_block *bp,int32_t myind,int32_t src_or_dest,int8_t bestk,uint64_t bestmask,uint8_t pubkeys[64][33],int32_t numratified) { - bits256 txid,srchash,zero,signedtxid; struct iguana_info *coin; int32_t j,len,numsigs; char *retstr=0,str[65],str2[65]; uint8_t txdata[32768]; uint32_t channel; + bits256 txid,srchash,zero,signedtxid; struct iguana_info *coin; int32_t j,len,numsigs; char *retstr=0,str[65],str2[65]; uint8_t txdata[32768]; uint32_t channel,state; coin = (src_or_dest != 0) ? bp->destcoin : bp->srccoin; memset(zero.bytes,0,sizeof(zero)); channel = (src_or_dest != 0) ? DPOW_SIGBTCCHANNEL : DPOW_SIGCHANNEL; @@ -586,9 +586,13 @@ void dpow_sigscheck(struct supernet_info *myinfo,struct dpow_info *dp,struct dpo decode_hex(txdata+32,len,bp->signedtx); for (j=0; jhashmsg,(src_or_dest != 0) ? DPOW_BTCTXIDCHANNEL : DPOW_TXIDCHANNEL,bp->height,txdata,len+32); - bp->state = src_or_dest != 0 ? 1000 : 0xffffffff; - printf("complete statemachine.%s ht.%d state.%d (%x %x)\n",coin->symbol,bp->height,bp->state,bp->hashmsg.uints[0],txid.uints[0]); + state = src_or_dest != 0 ? 1000 : 0xffffffff; + if ( bp->state < state ) + { + bp->state = state; + dpow_send(myinfo,dp,bp,txid,bp->hashmsg,(src_or_dest != 0) ? DPOW_BTCTXIDCHANNEL : DPOW_TXIDCHANNEL,bp->height,txdata,len+32); + printf("complete statemachine.%s ht.%d state.%d (%x %x)\n",coin->symbol,bp->height,bp->state,bp->hashmsg.uints[0],txid.uints[0]); + } } else printf("sendtxid mismatch got %s instead of %s\n",bits256_str(str,txid),bits256_str(str2,signedtxid)); } free(retstr); diff --git a/iguana/exchanges/bittrex.c b/iguana/exchanges/bittrex.c index f032b764b..4e1ee5c63 100755 --- a/iguana/exchanges/bittrex.c +++ b/iguana/exchanges/bittrex.c @@ -77,7 +77,7 @@ double UPDATE(struct exchange_info *exchange,char *base,char *rel,struct exchang { cJSON *json,*obj; char *jsonstr,market[128],url[1024]; double hbla = 0.; sprintf(market,"%s-%s",rel,base); - sprintf(url,"https://bittrex.com/api/v1.1/public/getorderbook?market=%s&type=both&depth=%d",market,maxdepth); + sprintf(url,"http://bittrex.com/api/v1.1/public/getorderbook?market=%s&type=both&depth=%d",market,maxdepth); jsonstr = issue_curl(url); if ( jsonstr != 0 ) { @@ -166,8 +166,11 @@ uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,cha return(0); } sprintf(payload,"https://bittrex.com/api/v1.1/market/%slimit?apikey=%s&nonce=%llu&market=%s&rate=%.8f&quantity=%.8f",dir>0?"buy":"sell",exchange->apikey,(long long)exchange_nonce(exchange),pairstr,price,volume); - if ( CHECKBALANCE(retstrp,dotrade,exchange,dir,base,rel,price,volume,argjson) == 0 && (json= SIGNPOST(&exchange->cHandle,dotrade,retstrp,exchange,payload,payload)) != 0 ) + if ( //CHECKBALANCE(retstrp,dotrade,exchange,dir,base,rel,price,volume,argjson) == 0 && + (json= SIGNPOST(&exchange->cHandle,dotrade,retstrp,exchange,payload,payload)) != 0 ) { + if ( *retstrp != 0 ) + printf("SIGNPOST returned.(%s) %s\n",*retstrp,jprint(json,0)); if ( is_cJSON_True(cJSON_GetObjectItem(json,"success")) != 0 && (resultobj= cJSON_GetObjectItem(json,"result")) != 0 ) { copy_cJSON(&uuidstr,cJSON_GetObjectItem(resultobj,"uuid")); diff --git a/iguana/exchanges/poloniex.c b/iguana/exchanges/poloniex.c index 0e4061d99..037db3715 100755 --- a/iguana/exchanges/poloniex.c +++ b/iguana/exchanges/poloniex.c @@ -166,10 +166,11 @@ uint64_t TRADE(int32_t dotrade,char **retstrp,struct exchange_info *exchange,cha typestr = (dir > 0) ? "marginBuy":"marginSell"; else typestr = (dir > 0) ? "buy":"sell"; sprintf(payload,"command=%s&nonce=%lld¤cyPair=%s&rate=%.8f&amount=%.8f",typestr,(long long)nonce,pairstr,price,volume); - if ( CHECKBALANCE(retstrp,dotrade,exchange,dir,base,rel,price,volume,argjson) == 0 && (json= SIGNPOST(&exchange->cHandle,dotrade,retstrp,exchange,EXCHANGE_AUTHURL,payload)) != 0 ) + if ( //CHECKBALANCE(retstrp,dotrade,exchange,dir,base,rel,price,volume,argjson) == 0 && + (json= SIGNPOST(&exchange->cHandle,dotrade,retstrp,exchange,EXCHANGE_AUTHURL,payload)) != 0 ) { txid = (get_API_nxt64bits(cJSON_GetObjectItem(json,"orderNumber")) << 32) | get_API_nxt64bits(cJSON_GetObjectItem(json,"tradeID")); - printf("poloniex.%llu (%s)\n",(long long)txid,jprint(json,0)); + printf("poloniex.%llu (%s) %s\n",(long long)txid,jprint(json,0),*retstrp!=0?*retstrp:""); free_json(json); } return(txid); diff --git a/iguana/exchanges777.h b/iguana/exchanges777.h index b1b632660..2d1ba66a7 100755 --- a/iguana/exchanges777.h +++ b/iguana/exchanges777.h @@ -46,7 +46,7 @@ #define EXCHANGES777_MINPOLLGAP 1 #define EXCHANGES777_MAXDEPTH 200 -#define EXCHANGES777_DEFAULT_TIMEOUT 30 +#define EXCHANGES777_DEFAULT_TIMEOUT 60 typedef void CURL; struct exchange_info; struct exchange_quote; @@ -179,7 +179,7 @@ char *exchanges777_Qtrade(struct exchange_info *exchange,char *base,char *rel,in struct exchange_request *exchanges777_baserelfind(struct exchange_info *exchange,char *base,char *rel,int32_t func); struct exchange_info *exchanges777_find(char *exchangestr); -void prices777_processprice(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth); +void tradebots_processprices(struct supernet_info *myinfo,struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t numbids,int32_t numasks); double truefx_price(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert); double fxcm_price(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth,double commission,cJSON *argjson,int32_t invert); diff --git a/iguana/iguana777.h b/iguana/iguana777.h index 52d136d2f..d5a8e6f32 100755 --- a/iguana/iguana777.h +++ b/iguana/iguana777.h @@ -84,7 +84,7 @@ struct supernet_address char NXTADDR[32],BTC[64],BTCD[64]; }; -struct liquidity_info { char base[64],rel[64]; double profit,refprice; }; +struct liquidity_info { char base[16],rel[16],exchange[16]; uint64_t assetid; double profit,refprice; int dir; }; struct message_info { int32_t msgcount; bits256 refhash,msghashes[64]; uint32_t timestamps[64]; }; struct supernet_info @@ -94,6 +94,8 @@ struct supernet_info uint8_t persistent_pubkey33[33]; char ipaddr[64],NXTAPIURL[512],secret[4096],password[4096],rpcsymbol[64],handle[1024],permanentfile[1024]; char *decryptstr; + void (*liquidity_command)(struct supernet_info *myinfo,char *base,bits256 hash,cJSON *vals); + double (*liquidity_active)(struct supernet_info *myinfo,double *refpricep,char *exchange,char *base,char *rel,double volume); int32_t maxdelay,IAMRELAY,IAMNOTARY,IAMLP,publicRPC,basilisk_busy,genesisresults,remoteorigin; uint32_t expiration,dirty,DEXactive,DEXpoll,totalcoins,nanoinit,dexcrcs[1024]; uint16_t argport,rpcport; @@ -124,6 +126,7 @@ struct supernet_info bits256 pangea_category,instantdex_category; uint8_t logs[256],exps[510]; struct message_info msgids[8192]; + double *svmfeatures; }; #include "../includes/iguana_funcs.h" diff --git a/iguana/iguana_exchanges.c b/iguana/iguana_exchanges.c index 306d72315..d6f7409cd 100755 --- a/iguana/iguana_exchanges.c +++ b/iguana/iguana_exchanges.c @@ -184,11 +184,6 @@ double instantdex_avehbla(struct supernet_info *myinfo,double retvals[4],char *_ else return(0); } -void prices777_processprice(struct exchange_info *exchange,char *base,char *rel,struct exchange_quote *bidasks,int32_t maxdepth) -{ - -} - cJSON *exchanges777_allpairs(char *baserels[][2],int32_t num) { int32_t i; char str[32]; cJSON *json,*item,*array = cJSON_CreateArray(); @@ -339,11 +334,11 @@ double exchange_setquote(struct exchange_quote *bidasks,int32_t *numbidsp,int32_ } if ( commission != 0. ) { - //printf("price %f fee %f -> ",price,prices->commission * price); + printf("price %f fee %f -> ",price,commission * price); if ( bidask == 0 ) price -= commission * price; else price += commission * price; - //printf("%f\n",price); + printf("%f\n",price); } quote = (bidask == 0) ? &bidasks[(*numbidsp)<<1] : &bidasks[((*numasksp)<<1) + 1]; quote->price = price, quote->volume = volume, quote->timestamp = timestamp, quote->orderid = orderid, quote->offerNXT = offerNXT; @@ -400,6 +395,7 @@ void exchanges777_json_quotes(struct exchange_info *exchange,double commission,c if ( strcmp(exchange->name,"kraken") == 0 ) timestamp = juint(jitem(item,2),0); else orderid = j64bits(jitem(item,2),0); + //printf("{%s} (%.8f %.8f) %f\n",jprint(item,0),price,volume,commission); } else { @@ -456,7 +452,7 @@ double exchanges777_standardprices(struct exchange_info *exchange,double commiss if ( (jsonstr= issue_curl(url)) != 0 ) { //if ( strcmp(exchangestr,"btc38") == 0 ) - //printf("(%s) -> (%s)\n",url,jsonstr); + //printf("%f (%s) -> (%s)\n",commission,url,jsonstr); if ( (json= cJSON_Parse(jsonstr)) != 0 ) { hbla = exchanges777_json_orderbook(exchange,commission,base,rel,quotes,maxdepth,json,field,"bids","asks",price,volume,invert); @@ -859,7 +855,7 @@ void exchanges777_loop(void *ptr) if ( req->bidasks[(i << 1) + 1].price > SMALLVAL ) req->numasks++; //printf("%-10s %s/%s numbids.%d numasks.%d\n",exchange->name,req->base,req->rel,req->numbids,req->numasks); - prices777_processprice(exchange,req->base,req->rel,req->bidasks,req->depth); + tradebots_processprices(myinfo,exchange,req->base,req->rel,req->bidasks,req->numbids,req->numasks); } queue_enqueue("pricesQ",&exchange->pricesQ,&req->DL); } @@ -954,7 +950,7 @@ char *exchanges777_Qprices(struct exchange_info *exchange,char *base,char *rel,i } if ( base[0] == 0 || rel[0] == 0 || (polarity= (*exchange->issue.supports)(exchange,base,rel,argjson)) == 0 ) { - //printf("%s invalid (%s) or (%s)\n",exchange->name,base,rel); + printf("%s invalid (%s) or (%s)\n",exchange->name,base,rel); return(clonestr("{\"error\":\"invalid base or rel\"}")); } if ( depth <= 0 ) @@ -977,7 +973,7 @@ char *exchanges777_Qprices(struct exchange_info *exchange,char *base,char *rel,i req->commission = exchange->commission; if ( monitor == 0 ) { - printf("%s submit (%s) (%s)\n",exchange->name,base,rel); + //printf("%s submit (%s) (%s)\n",exchange->name,base,rel); return(exchanges777_submit(exchange,req,'Q',maxseconds)); } else diff --git a/iguana/iguana_notary.c b/iguana/iguana_notary.c index 03cf58c38..ae4cffadb 100755 --- a/iguana/iguana_notary.c +++ b/iguana/iguana_notary.c @@ -71,9 +71,9 @@ void dpow_srcupdate(struct supernet_info *myinfo,struct dpow_info *dp,int32_t he else { freq = 1; - minsigs = 7;//(komodo_notaries(dp->symbol,pubkeys,height) >> 1) + 1; + //minsigs = 7;//(komodo_notaries(dp->symbol,pubkeys,height) >> 1) + 1; //if ( minsigs < DPOW_MINSIGS ) - // minsigs = DPOW_MINSIGS; + minsigs = DPOW_MINSIGS; } printf("%s/%s src ht.%d dest.%u nonz.%d %s minsigs.%d\n",dp->symbol,dp->dest,checkpoint.blockhash.height,dp->destupdated,bits256_nonz(checkpoint.blockhash.hash),bits256_str(str,dp->last.blockhash.hash),minsigs); dpow_fifoupdate(myinfo,dp->srcfifo,dp->last); diff --git a/iguana/main.c b/iguana/main.c index fbbdf2a63..15fe34b9f 100755 --- a/iguana/main.c +++ b/iguana/main.c @@ -676,6 +676,8 @@ void iguana_ensuredirs() sprintf(dirname,"%s/ECB",GLOBAL_DBDIR), OS_ensure_directory(dirname); sprintf(dirname,"%s/BTC",GLOBAL_VALIDATEDIR), OS_ensure_directory(dirname); sprintf(dirname,"%s/BTCD",GLOBAL_VALIDATEDIR), OS_ensure_directory(dirname); + sprintf(dirname,"SVM"), OS_ensure_directory(dirname); + sprintf(dirname,"SVM/rawfeatures"), OS_ensure_directory(dirname); } void iguana_Qinit() @@ -1619,9 +1621,10 @@ void iguana_main(void *arg) portable_mutex_init(&myinfo->dpowmutex); portable_mutex_init(&myinfo->notarymutex); #if LIQUIDITY_PROVIDER + myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("nxtae"),0); myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("bitcoin"),0); myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("poloniex"),0); - //myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("bittrex"),0); + myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("bittrex"),0); myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("btc38"),0); myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("huobi"),0); myinfo->tradingexchanges[myinfo->numexchanges++] = exchange_create(clonestr("coinbase"),0); diff --git a/iguana/tests/arbinit b/iguana/tests/arbinit new file mode 100755 index 000000000..428ea64d6 --- /dev/null +++ b/iguana/tests/arbinit @@ -0,0 +1,64 @@ +#!/bin/bash +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"amlp\"}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"BTCD\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"BTCD\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"CLOAK\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"CLOAK\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"SYS\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"SYS\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"GAME\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"GAME\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"XMR\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"XMR\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"ETH\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"ETH\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"ETC\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"ETC\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"DASH\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"DASH\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"ZEC\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"ZEC\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"FCT\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"FCT\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"STRAT\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"STRAT\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"DGD\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"DGD\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"NAV\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"NAV\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"LTC\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"LTC\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"SDC\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"SDC\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"STEEM\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"STEEM\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"SBD\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"SBD\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"XRP\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"XRP\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"LSK\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"LSK\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"NXT\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"NXT\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"MAID\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"MAID\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"BLK\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"BLK\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"POT\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"POT\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"XEM\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"XEM\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"VRC\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"VRC\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"VTC\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"VTC\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"BTS\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"BTS\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"NAUT\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"NAUT\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"AUR\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"AUR\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"REP\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"REP\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"AMP\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"AMP\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" diff --git a/iguana/tests/arbnxt b/iguana/tests/arbnxt new file mode 100755 index 000000000..e63056d60 --- /dev/null +++ b/iguana/tests/arbnxt @@ -0,0 +1,26 @@ +#!/bin/bash +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"amlp\"}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"NXT\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"NXT\",\"vals\":{\"profit\":0.004,\"exchange\":\"bittrex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"UNITY\",\"vals\":{\"profit\":0.01,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"UNITY\",\"vals\":{\"rel\":\"NXT\",\"profit\":0.01,\"exchange\":\"nxtae\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"DEX\",\"vals\":{\"rel\":\"NXT\",\"profit\":0.01,\"exchange\":\"nxtae\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"PANGEA\",\"vals\":{\"rel\":\"NXT\",\"profit\":0.01,\"exchange\":\"nxtae\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"JUMBLR\",\"vals\":{\"rel\":\"NXT\",\"profit\":0.01,\"exchange\":\"nxtae\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"BET\",\"vals\":{\"rel\":\"NXT\",\"profit\":0.01,\"exchange\":\"nxtae\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"CRYPTO\",\"vals\":{\"rel\":\"NXT\",\"profit\":0.01,\"exchange\":\"nxtae\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"HODL\",\"vals\":{\"rel\":\"NXT\",\"profit\":0.01,\"exchange\":\"nxtae\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"SHARK\",\"vals\":{\"rel\":\"NXT\",\"profit\":0.01,\"exchange\":\"nxtae\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"BOTS\",\"vals\":{\"rel\":\"NXT\",\"profit\":0.01,\"exchange\":\"nxtae\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"MGW\",\"vals\":{\"rel\":\"NXT\",\"profit\":0.01,\"exchange\":\"nxtae\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"NXT\",\"vals\":{\"profit\":0.004,\"exchange\":\"poloniex\"}}" + +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"BTC\",\"vals\":{\"rel\":\"USD\",\"profit\":0.004,\"exchange\":\"poloniex\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"BTC\",\"vals\":{\"rel\":\"USD\",\"profit\":0.004,\"exchange\":\"coinbase\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"BTC\",\"vals\":{\"rel\":\"USD\",\"profit\":0.004,\"exchange\":\"lakebtc\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"BTC\",\"vals\":{\"rel\":\"USD\",\"profit\":0.004,\"exchange\":\"quadriga\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"BTC\",\"vals\":{\"rel\":\"USD\",\"profit\":0.004,\"exchange\":\"btcd\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"BTC\",\"vals\":{\"rel\":\"USD\",\"profit\":0.004,\"exchange\":\"bitstamp\"}}" + +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"BTC\",\"vals\":{\"rel\":\"CNY\",\"profit\":0.004,\"exchange\":\"huobi\"}}" +curl --url "http://127.0.0.1:7778" --data "{\"agent\":\"tradebot\",\"method\":\"liquidity\",\"targetcoin\":\"BTC\",\"vals\":{\"rel\":\"CNY\",\"profit\":0.004,\"exchange\":\"btc38\"}}" diff --git a/includes/iguana_funcs.h b/includes/iguana_funcs.h index a90ca45b8..5ed16af94 100755 --- a/includes/iguana_funcs.h +++ b/includes/iguana_funcs.h @@ -134,6 +134,7 @@ double PoW_from_compact(uint32_t nBits,uint8_t unitval); void calc_rmd160(char *hexstr,uint8_t buf[20],uint8_t *msg,int32_t len); void calc_OP_HASH160(char *hexstr,uint8_t hash160[20],char *msg); double dxblend(double *destp,double val,double decay); +double _xblend(float *destp,double val,double decay); // json int32_t iguana_processjsonQ(struct iguana_info *coin); // reentrant, can be called during any idletime