From e4007d8cb7922dc83ffbb73e5e7de4a4c5290de0 Mon Sep 17 00:00:00 2001 From: jl777 Date: Wed, 22 Nov 2017 13:25:49 +0400 Subject: [PATCH] Trades array --- iguana/exchanges/LP_RTmetrics.c | 18 ++--- iguana/exchanges/LP_commands.c | 22 +++---- iguana/exchanges/LP_include.h | 4 +- iguana/exchanges/LP_nativeDEX.c | 8 ++- iguana/exchanges/LP_stats.c | 113 ++++++++++++++++++++++++++++---- iguana/exchanges/LP_swap.c | 7 ++ 6 files changed, 134 insertions(+), 38 deletions(-) diff --git a/iguana/exchanges/LP_RTmetrics.c b/iguana/exchanges/LP_RTmetrics.c index a3485c9f9..24d98eec8 100644 --- a/iguana/exchanges/LP_RTmetrics.c +++ b/iguana/exchanges/LP_RTmetrics.c @@ -149,7 +149,7 @@ void LP_RTmetrics_swapsinfo(char *refbase,char *refrel,cJSON *swaps,int32_t nums void LP_RTmetrics_update(char *base,char *rel) { - struct LP_pubkeyinfo *pubp,*tmp; uint32_t futuretime; int32_t i,numswaps; bits256 pubkey,zero; char *retstr; cJSON *statsjson,*swaps; + struct LP_pubkeyinfo *pubp,*tmp; uint32_t futuretime; int32_t i,numswaps; bits256 pubkey,zero; cJSON *statsjson,*swaps; memset(&LP_RTmetrics,0,sizeof(LP_RTmetrics)); HASH_ITER(hh,LP_pubkeyinfos,pubp,tmp) { @@ -161,19 +161,15 @@ void LP_RTmetrics_update(char *base,char *rel) } futuretime = (uint32_t)time(NULL) + 3600*100; memset(zero.bytes,0,sizeof(zero)); - if ( (retstr= LP_statslog_disp(100,futuretime,futuretime,"",zero)) != 0 ) + if ( (statsjson= LP_statslog_disp(futuretime,futuretime,"",zero,0,0)) != 0 ) { - if ( (statsjson= cJSON_Parse(retstr)) != 0 ) + if ( (swaps= jarray(&numswaps,statsjson,"swaps")) != 0 ) { - if ( (swaps= jarray(&numswaps,statsjson,"swaps")) != 0 ) - { - //printf("LP_RTmetrics_update for (%s)\n",jprint(swaps,0)); - if ( numswaps > 0 ) - LP_RTmetrics_swapsinfo(base,rel,swaps,numswaps); - } - free_json(statsjson); + //printf("LP_RTmetrics_update for (%s)\n",jprint(swaps,0)); + if ( numswaps > 0 ) + LP_RTmetrics_swapsinfo(base,rel,swaps,numswaps); } - free(retstr); + free_json(statsjson); } for (i=0; i [timestamp, avebid, aveask, highbid, lowask]\n\ setprice(base, rel, price, broadcast=1)\n\ autoprice(base, rel, fixed, minprice, margin, refbase, refrel, factor, offset)*\n\ goal(coin=*, val=)\n\ @@ -103,7 +102,9 @@ enable(coin)\n\ disable(coin)\n\ notarizations(coin)\n\ parselog()\n\ -statsdisp(starttime=0, endtime=0, gui="", pubkey="")\n\ +statsdisp(starttime=0, endtime=0, gui="", pubkey="", base="", rel="")\n\ +tradesarray(base, rel, starttime=-timescale*1024, endtime=, timescale=60) -> [timestamp, high, low, open, close, relvolume, basevolume, aveprice]\n\ +pricearray(base, rel, starttime=0, endtime=0, timescale=60) -> [timestamp, avebid, aveask, highbid, lowask]\n\ getrawtransaction(coin, txid)\n\ inventory(coin, reset=0, [passphrase=])\n\ bestfit(rel, relvolume)\n\ @@ -263,14 +264,13 @@ zeroconf_claim(address, expiration=0)\n\ } else if ( strcmp(method,"parselog") == 0 ) { - bits256 zero; int32_t n = LP_statslog_parse(); + bits256 zero; memset(zero.bytes,0,sizeof(zero)); - return(LP_statslog_disp(n,2000000000,2000000000,"",zero)); + return(jprint(LP_statslog_disp(2000000000,2000000000,"",zero,0,0),1)); } else if ( strcmp(method,"statsdisp") == 0 ) { - int32_t n = LP_statslog_parse(); - return(LP_statslog_disp(n,juint(argjson,"starttime"),juint(argjson,"endtime"),jstr(argjson,"gui"),jbits256(argjson,"pubkey"))); + return(jprint(LP_statslog_disp(juint(argjson,"starttime"),juint(argjson,"endtime"),jstr(argjson,"gui"),jbits256(argjson,"pubkey"),jstr(argjson,"base"),jstr(argjson,"rel")),1)); } else if ( strcmp(method,"secretaddresses") == 0 ) { @@ -321,15 +321,15 @@ zeroconf_claim(address, expiration=0)\n\ uint32_t firsttime; if ( base[0] != 0 && rel[0] != 0 ) { - if ( (firsttime= juint(argjson,"firsttime")) < time(NULL)-30*24*3600 ) + if ( (firsttime= juint(argjson,"starttime")) < time(NULL)-30*24*3600 ) firsttime = (uint32_t)(time(NULL)-30*24*3600); - return(jprint(LP_pricearray(base,rel,firsttime,juint(argjson,"lasttime"),jint(argjson,"timescale")),1)); + return(jprint(LP_pricearray(base,rel,firsttime,juint(argjson,"endtime"),jint(argjson,"timescale")),1)); } else return(clonestr("{\"error\":\"pricearray needs base and rel\"}")); } - /*else if ( strcmp(method,"pricearray") == 0 ) + else if ( strcmp(method,"tradesarray") == 0 ) { - return(jprint(LP_pricearray(base,rel,juint(argjson,"starttime"),juint(argjson,"endtime"),jint(argjson,"timescale")),1)); - }*/ + return(jprint(LP_tradesarray(base,rel,juint(argjson,"starttime"),juint(argjson,"endtime"),jint(argjson,"timescale")),1)); + } else if ( strcmp(method,"orderbook") == 0 ) return(LP_orderbook(base,rel,jint(argjson,"duration"))); else if ( strcmp(method,"myprice") == 0 ) diff --git a/iguana/exchanges/LP_include.h b/iguana/exchanges/LP_include.h index c0453e460..3961ca051 100644 --- a/iguana/exchanges/LP_include.h +++ b/iguana/exchanges/LP_include.h @@ -49,6 +49,7 @@ void emscripten_usleep(int32_t x); // returns immediate, no sense for sleeping #define LP_ELECTRUM_KEEPALIVE 60 #define LP_ELECTRUM_MAXERRORS 777 #define LP_MEMPOOL_TIMEINCR 10 +#define LP_SCREENWIDTH 1024 #define LP_MIN_PEERS 8 #define LP_MAX_PEERS 32 @@ -458,7 +459,7 @@ int32_t iguana_signrawtransaction(void *ctx,char *symbol,uint8_t wiftaddr,uint8_ struct LP_address_utxo *LP_address_utxofind(struct iguana_info *coin,char *coinaddr,bits256 txid,int32_t vout); int32_t LP_destaddr(char *destaddr,cJSON *item); int32_t LP_waitmempool(char *symbol,char *coinaddr,bits256 txid,int32_t vout,int32_t duration); -char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey); +cJSON *LP_statslog_disp(uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey,char *refbase,char *refrel); uint32_t LP_heighttime(char *symbol,int32_t height); uint64_t LP_unspents_load(char *symbol,char *addr); int32_t LP_validSPV(char *symbol,char *coinaddr,bits256 txid,int32_t vout); @@ -477,6 +478,7 @@ cJSON *LP_gettxout(char *symbol,char *coinaddr,bits256 txid,int32_t vout); void LP_postutxos(char *symbol,char *coinaddr); int32_t LP_listunspent_both(char *symbol,char *coinaddr,int32_t fullflag); uint16_t LP_randpeer(char *destip); +uint32_t LP_atomic_locktime(char *base,char *rel); struct LP_pubkeyinfo *LP_pubkeyfind(bits256 pubkey); char *issue_LP_psock(char *destip,uint16_t destport,int32_t ispaired); char *LP_unspents_filestr(char *symbol,char *addr); diff --git a/iguana/exchanges/LP_nativeDEX.c b/iguana/exchanges/LP_nativeDEX.c index 11d542cb2..7858e91d9 100644 --- a/iguana/exchanges/LP_nativeDEX.c +++ b/iguana/exchanges/LP_nativeDEX.c @@ -17,16 +17,18 @@ // LP_nativeDEX.c // marketmaker // -// feature requests +// feature requests: // alice waiting for bestprice -// pricearray [{"date":1405699200,"high":0.0045388,"low":0.00403001,"open":0.00404545,"close":0.00435873,"volume":44.34555992,"quoteVolume":10311.88079097,"weightedAverage":0.00430043}, // USD paxprice based USDvalue in portfolio -// portfolio value based on ask? // cancel bid/ask // https://github.com/bitcoin/bips/blob/master/bip-0143.mediawiki for signing BCH/BTG // // bugs, validations: +// waiting for alice and alice disconnects // MNZ getcoin strangeness +// portfolio value based on ask? +// listunspent triplicate +// RTmetrics update from tradecommand // verify encrypted destpubkey, broadcast:0 setprice // [{"date":1405699200,"high":0.0045388,"low":0.00403001,"open":0.00404545,"close":0.00435873,"relvol":44.34555992,"basevol":10311.88079097,"aveprice":0.00430043}, // minute, diff --git a/iguana/exchanges/LP_stats.c b/iguana/exchanges/LP_stats.c index 40569f027..d37d5da56 100644 --- a/iguana/exchanges/LP_stats.c +++ b/iguana/exchanges/LP_stats.c @@ -34,13 +34,6 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj); char *LP_stats_methods[] = { "unknown", "request", "reserved", "connect", "connected", "tradestatus" }; -uint32_t LP_atomic_locktime(char *base,char *rel) -{ - if ( strcmp(base,"BTC") != 0 && strcmp(rel,"BTC") != 0 ) - return(INSTANTDEX_LOCKTIME); - else return(INSTANTDEX_LOCKTIME * 10); -} - static uint32_t LP_requests,LP_reserveds,LP_connects,LP_connecteds,LP_tradestatuses,LP_parse_errors,LP_unknowns,LP_duplicates,LP_aliceids; void LP_tradecommand_log(cJSON *argjson) @@ -330,11 +323,12 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj) return(duplicate == 0); } -char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey) +cJSON *LP_statslog_disp(uint32_t starttime,uint32_t endtime,char *refgui,bits256 refpubkey,char *refbase,char *refrel) { - cJSON *retjson,*array,*item; struct LP_swapstats *sp,*tmp; int32_t i,dispflag,numtrades[LP_MAXPRICEINFOS]; char line[1024]; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS]; + cJSON *retjson,*array,*item; struct LP_swapstats *sp,*tmp; int32_t i,n,dispflag,numtrades[LP_MAXPRICEINFOS]; uint64_t basevols[LP_MAXPRICEINFOS],relvols[LP_MAXPRICEINFOS]; if ( starttime > endtime ) starttime = endtime; + n = LP_statslog_parse(); memset(basevols,0,sizeof(basevols)); memset(relvols,0,sizeof(relvols)); memset(numtrades,0,sizeof(numtrades)); @@ -353,6 +347,10 @@ char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgu dispflag = 1; else if ( sp->Q.timestamp >= starttime && sp->Q.timestamp <= endtime ) dispflag = 1; + if ( refbase != 0 && strcmp(refbase,sp->Q.srccoin) != 0 && strcmp(refbase,sp->Q.destcoin) != 0 ) + dispflag = 0; + if ( refrel != 0 && strcmp(refrel,sp->Q.srccoin) != 0 && strcmp(refrel,sp->Q.destcoin) != 0 ) + dispflag = 0; if ( dispflag != 0 ) { dispflag = 0; @@ -364,8 +362,9 @@ char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgu } if ( dispflag != 0 ) { - LP_swapstats_line(numtrades,basevols,relvols,line,sp); + //LP_swapstats_line(numtrades,basevols,relvols,line,sp); item = cJSON_CreateObject(); + jaddnum(item,"timestamp",sp->Q.timestamp); jadd64bits(item,"aliceid",sp->aliceid); jaddbits256(item,"src",sp->Q.srchash); jaddstr(item,"base",sp->Q.srccoin); @@ -376,7 +375,7 @@ char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgu jaddnum(item,"price",sp->qprice); jaddnum(item,"requestid",sp->Q.R.requestid); jaddnum(item,"quoteid",sp->Q.R.quoteid); - jaddstr(item,"line",line); + //jaddstr(item,"line",line); jaddi(array,item); } } @@ -405,7 +404,97 @@ char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgu jaddnum(retjson,"uniques",LP_aliceids); jaddnum(retjson,"tradestatus",LP_tradestatuses); jaddnum(retjson,"unknown",LP_unknowns); - return(jprint(retjson,1)); + return(retjson); +} + +//tradesarray(base, rel, starttime=-timescale*1024, endtime=, timescale=60) -> [timestamp, high, low, open, close, relvolume, basevolume, aveprice, numtrades] + +struct LP_ohlc +{ + uint32_t timestamp,firsttime,lasttime,numtrades; + double high,low,open,close,relsum,basesum; +}; + +cJSON *LP_ohlc_json(struct LP_ohlc *bar) +{ + cJSON *item; + if ( bar->numtrades != 0 && bar->relsum > SMALLVAL && bar->basesum > SMALLVAL ) + { + item = cJSON_CreateArray(); + jaddinum(item,bar->timestamp); + jaddinum(item,bar->high); + jaddinum(item,bar->low); + jaddinum(item,bar->open); + jaddinum(item,bar->close); + jaddinum(item,bar->relsum); + jaddinum(item,bar->basesum); + jaddinum(item,bar->relsum / bar->basesum); + jaddinum(item,bar->numtrades); + } + return(0); } +void LP_ohlc_update(struct LP_ohlc *bar,uint32_t timestamp,double basevol,double relvol) +{ + double price; + if ( basevol > SMALLVAL && relvol > SMALLVAL ) + { + price = relvol / basevol; + if ( bar->firsttime == 0 || timestamp < bar->firsttime ) + { + bar->firsttime = timestamp; + bar->open = price; + } + if ( bar->lasttime == 0 || timestamp > bar->lasttime ) + { + bar->lasttime = timestamp; + bar->close = price; + } + if ( bar->low == 0. || price < bar->low ) + bar->low = price; + if ( bar->high == 0. || price > bar->high ) + bar->high = price; + bar->basesum += basevol; + bar->relsum += relvol; + bar->numtrades++; + } +} + +cJSON *LP_tradesarray(char *base,char *rel,uint32_t starttime,uint32_t endtime,int32_t timescale) +{ + struct LP_ohlc *bars; cJSON *array,*item,*statsjson,*swaps; uint32_t timestamp; bits256 zero; int32_t i,n,numbars,bari; + if ( timescale < 60 ) + return(cJSON_Parse("{\"error\":\"one minute is shortest timescale\"}")); + memset(zero.bytes,0,sizeof(zero)); + if ( endtime == 0 ) + endtime = (((uint32_t)time(NULL) / timescale) * timescale); + if ( starttime == 0 ) + starttime = (endtime - LP_SCREENWIDTH*timescale); + numbars = ((endtime - starttime) / timescale) + 1; + bars = calloc(numbars,sizeof(*bars)); + for (bari=0; bari= starttime && timestamp <= endtime ) + { + bari = (timestamp - starttime) / timescale; + LP_ohlc_update(&bars[bari],timestamp,jdouble(item,"basevol"),jdouble(item,"relvol")); + } + } + } + free_json(statsjson); + } + array = cJSON_CreateArray(); + for (bari=0; barivins != 0 )