@ -20,32 +20,17 @@
# define LP_STATSLOG_FNAME "stats.log"
struct LP_swapstats
{
UT_hash_handle hh ;
struct LP_quoteinfo Q ;
bits256 bobdeposit , alicepayment , bobpayment , paymentspent , Apaymentspent , depositspent ;
double qprice ;
uint64_t aliceid ;
uint32_t ind , methodind , finished , expired ;
char alicegui [ 32 ] , bobgui [ 32 ] ;
} * LP_swapstats ;
struct LP_swapstats * LP_swapstats , * LP_RTstats ;
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 )
{
static FILE * logfp ; char * jsonstr ;
portable_mutex_lock ( & LP_logmutex ) ;
if ( logfp = = 0 )
{
if ( ( logfp = fopen ( LP_STATSLOG_FNAME , " rb+ " ) ) ! = 0 )
@ -59,6 +44,7 @@ void LP_tradecommand_log(cJSON *argjson)
free ( jsonstr ) ;
fflush ( logfp ) ;
}
portable_mutex_unlock ( & LP_logmutex ) ;
}
void LP_statslog_parseline ( cJSON * lineobj )
@ -130,18 +116,22 @@ int32_t LP_statslog_parse()
struct LP_swapstats * LP_swapstats_find ( uint64_t aliceid )
{
struct LP_swapstats * sp ;
HASH_FIND ( hh , LP_swapstats , & aliceid , sizeof ( aliceid ) , sp ) ;
HASH_FIND ( hh , LP_RTstats , & aliceid , sizeof ( aliceid ) , sp ) ;
if ( sp = = 0 )
HASH_FIND ( hh , LP_swapstats , & aliceid , sizeof ( aliceid ) , sp ) ;
return ( sp ) ;
}
struct LP_swapstats * LP_swapstats_add ( uint64_t aliceid )
struct LP_swapstats * LP_swapstats_add ( uint64_t aliceid , int32_t RTflag )
{
struct LP_swapstats * sp ;
if ( ( sp = LP_swapstats_find ( aliceid ) ) = = 0 )
{
sp = calloc ( 1 , sizeof ( * sp ) ) ;
sp - > aliceid = aliceid ;
HASH_ADD ( hh , LP_swapstats , aliceid , sizeof ( aliceid ) , sp ) ;
if ( RTflag ! = 0 )
HASH_ADD ( hh , LP_RTstats , aliceid , sizeof ( aliceid ) , sp ) ;
else HASH_ADD ( hh , LP_swapstats , aliceid , sizeof ( aliceid ) , sp ) ;
}
return ( LP_swapstats_find ( aliceid ) ) ;
}
@ -180,6 +170,7 @@ bits256 LP_swapstats_txid(cJSON *argjson,char *name,bits256 oldtxid)
int32_t LP_swapstats_update ( struct LP_swapstats * sp , struct LP_quoteinfo * qp , cJSON * lineobj )
{
char * statusstr , * base , * rel , gui [ 64 ] ; uint32_t requestid , quoteid ; uint64_t satoshis , destsatoshis ;
sp - > lasttime = ( uint32_t ) time ( NULL ) ;
safecopy ( gui , sp - > Q . gui , sizeof ( gui ) ) ;
if ( strcmp ( LP_stats_methods [ sp - > methodind ] , " tradestatus " ) = = 0 )
{
@ -189,7 +180,7 @@ int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSO
quoteid = juint ( lineobj , " quoteid " ) ;
satoshis = jdouble ( lineobj , " srcamount " ) * SATOSHIDEN ;
destsatoshis = jdouble ( lineobj , " destamount " ) * SATOSHIDEN ;
if ( base ! = 0 & & strcmp ( base , sp - > Q . srccoin ) = = 0 & & rel ! = 0 & & strcmp ( rel , sp - > Q . destcoin ) = = 0 & & requestid = = sp - > Q . R . requestid & & quoteid = = sp - > Q . R . quoteid & & ( ( satoshis + 2 * sp - > Q . txfee ) | 1 ) = = ( sp - > Q . satoshis | 1 ) & & ( ( destsatoshis + 2 * sp - > Q . desttxfee ) | 1 ) = = ( sp - > Q . destsatoshis | 1 ) )
if ( base ! = 0 & & strcmp ( base , sp - > Q . srccoin ) = = 0 & & rel ! = 0 & & strcmp ( rel , sp - > Q . destcoin ) = = 0 & & requestid = = sp - > Q . R . requestid & & quoteid = = sp - > Q . R . quoteid & & llabs ( ( int64_t ) ( satoshis + 2 * sp - > Q . txfee ) - ( int64_t ) sp - > Q . satoshis ) < = sp - > Q . txfee & & llabs ( ( int64_t ) ( destsatoshis + 2 * sp - > Q . desttxfee ) - ( int64_t ) sp - > Q . destsatoshis ) < = sp - > Q . desttxfee )
{
sp - > bobdeposit = LP_swapstats_txid ( lineobj , " bobdeposit " , sp - > bobdeposit ) ;
sp - > alicepayment = LP_swapstats_txid ( lineobj , " alicepayment " , sp - > alicepayment ) ;
@ -208,7 +199,7 @@ int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSO
}
else
{
if ( requestid = = sp - > Q . R . requestid & & quoteid = = sp - > Q . R . quoteid )
//if ( requestid == sp->Q.R.requestid && quoteid == sp->Q.R.quoteid )
printf ( " mismatched tradestatus aliceid.%22llu b%s/%s r%s/%s r%u/%u q%u/%u %.8f/%.8f -> %.8f/%.8f \n " , ( long long ) sp - > aliceid , base , sp - > Q . srccoin , rel , sp - > Q . destcoin , requestid , sp - > Q . R . requestid , quoteid , sp - > Q . R . quoteid , dstr ( satoshis + 2 * sp - > Q . txfee ) , dstr ( sp - > Q . satoshis ) , dstr ( destsatoshis + 2 * sp - > Q . desttxfee ) , dstr ( sp - > Q . destsatoshis ) ) ;
return ( - 1 ) ;
}
@ -222,7 +213,7 @@ int32_t LP_swapstats_update(struct LP_swapstats *sp,struct LP_quoteinfo *qp,cJSO
int32_t LP_statslog_parsequote ( char * method , cJSON * lineobj )
{
static uint32_t unexpected ;
struct LP_swapstats * sp , * tmp ; double qprice ; uint32_t requestid , quoteid , timestamp ; int32_t i , flag , numtrades [ LP_MAXPRICEINFOS ] , methodind , destvout , feevout , duplicate = 0 ; char * gui , * base , * rel ; uint64_t aliceid , txfee , satoshis , destsatoshis ; bits256 desttxid , feetxid ; struct LP_quoteinfo Q ; uint64_t basevols [ LP_MAXPRICEINFOS ] , relvols [ LP_MAXPRICEINFOS ] ;
struct LP_swapstats * sp , * tmp ; struct LP_pubkey_info * pubp ; struct LP_pubswap * ptr ; double qprice ; uint32_t requestid , quoteid , timestamp ; int32_t i , RTflag , flag , numtrades [ LP_MAXPRICEINFOS ] , methodind , destvout , feevout , duplicate = 0 ; char * statusstr , * gui , * base , * rel ; uint64_t aliceid , txfee , satoshis , destsatoshis ; bits256 desttxid , feetxid ; struct LP_quoteinfo Q ; uint64_t basevols [ LP_MAXPRICEINFOS ] , relvols [ LP_MAXPRICEINFOS ] ;
memset ( numtrades , 0 , sizeof ( numtrades ) ) ;
memset ( basevols , 0 , sizeof ( basevols ) ) ;
memset ( relvols , 0 , sizeof ( relvols ) ) ;
@ -242,8 +233,11 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj)
if ( ( sp = LP_swapstats_find ( aliceid ) ) ! = 0 )
{
sp - > methodind = methodind ;
sp - > Q . R . requestid = requestid ;
sp - > Q . R . quoteid = quoteid ;
if ( LP_swapstats_update ( sp , & Q , lineobj ) = = 0 )
flag = 1 ;
//else printf("LP_swapstats_update error\n");
}
if ( flag = = 0 )
{
@ -253,14 +247,16 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj)
{
sp - > methodind = methodind ;
if ( LP_swapstats_update ( sp , & Q , lineobj ) = = 0 )
{
flag = 1 ;
else printf ( " error after delayed match \n " ) ;
break ;
break ;
}
printf ( " error after delayed match \n " ) ;
}
}
}
if ( flag = = 0 )
printf ( " unexpected.%d tradestatus.(%s) \n " , unexpected + + , jprint ( lineobj , 0 ) ) ;
printf ( " unexpected.%d tradestatus aliceid.%llu requestid.%u quoteid.%u \n " , unexpected + + , ( long long ) aliceid , requestid , quoteid ) ; //,jprint(lineobj,0));
return ( 0 ) ;
}
if ( LP_quoteparse ( & Q , lineobj ) < 0 )
@ -290,6 +286,9 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj)
destvout = jint ( lineobj , " destvout " ) ;
feetxid = jbits256 ( lineobj , " feetxid " ) ;
feevout = jint ( lineobj , " feevout " ) ;
if ( ( statusstr = jstr ( lineobj , " status " ) ) ! = 0 & & strcmp ( statusstr , " finished " ) = = 0 )
RTflag = 0 ;
else RTflag = 1 ;
qprice = ( ( double ) destsatoshis / ( satoshis - txfee ) ) ;
//printf("%s/v%d %s/v%d\n",bits256_str(str,desttxid),destvout,bits256_str(str2,feetxid),feevout);
aliceid = LP_aliceid_calc ( desttxid , destvout , feetxid , feevout ) ;
@ -305,16 +304,31 @@ int32_t LP_statslog_parsequote(char *method,cJSON *lineobj)
}
else
{
if ( ( sp = LP_swapstats_add ( aliceid ) ) ! = 0 )
//printf("create aliceid.%llu\n",(long long)aliceid);
if ( ( sp = LP_swapstats_add ( aliceid , RTflag ) ) ! = 0 )
{
sp - > Q = Q ;
sp - > qprice = qprice ;
sp - > methodind = methodind ;
sp - > ind = LP_aliceids + + ;
sp - > lasttime = ( uint32_t ) time ( NULL ) ;
strcpy ( sp - > bobgui , " nogui " ) ;
strcpy ( sp - > alicegui , " nogui " ) ;
//LP_swapstats_line(numtrades,basevols,relvols,line,sp);
//printf("%s\n",line);
if ( sp - > finished = = 0 & & sp - > expired = = 0 )
{
if ( ( pubp = LP_pubkeyadd ( sp - > Q . srchash ) ) ! = 0 )
{
ptr = calloc ( 1 , sizeof ( * ptr ) ) ;
ptr - > swap = sp ;
DL_APPEND ( pubp - > bobswaps , ptr ) ;
}
if ( ( pubp = LP_pubkeyadd ( sp - > Q . desthash ) ) ! = 0 )
{
ptr = calloc ( 1 , sizeof ( * ptr ) ) ;
ptr - > swap = sp ;
DL_APPEND ( pubp - > aliceswaps , ptr ) ;
}
}
} else printf ( " unexpected LP_swapstats_add failure \n " ) ;
}
if ( sp ! = 0 )
@ -330,11 +344,103 @@ 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_swapstats_json ( struct LP_swapstats * sp )
{
cJSON * 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 ) ;
jaddnum ( item , " basevol " , dstr ( sp - > Q . satoshis ) ) ;
jaddbits256 ( item , " dest " , sp - > Q . desthash ) ;
jaddstr ( item , " rel " , sp - > Q . destcoin ) ;
jaddnum ( item , " relvol " , dstr ( sp - > Q . destsatoshis ) ) ;
jaddnum ( item , " price " , sp - > qprice ) ;
jaddnum ( item , " requestid " , sp - > Q . R . requestid ) ;
jaddnum ( item , " quoteid " , sp - > Q . R . quoteid ) ;
jaddnum ( item , " finished " , sp - > finished ) ;
jaddnum ( item , " expired " , sp - > expired ) ;
jaddnum ( item , " ind " , sp - > methodind ) ;
//jaddstr(item,"line",line);
return ( item ) ;
}
char * LP_swapstatus_recv ( cJSON * argjson )
{
struct LP_swapstats * sp ; int32_t methodind ;
//printf("swapstatus.(%s)\n",jprint(argjson,0));
if ( ( sp = LP_swapstats_find ( j64bits ( argjson , " aliceid " ) ) ) ! = 0 )
{
sp - > lasttime = ( uint32_t ) time ( NULL ) ;
if ( ( methodind = jint ( argjson , " ind " ) ) > sp - > methodind & & methodind < sizeof ( LP_stats_methods ) / sizeof ( * LP_stats_methods ) )
{
if ( sp - > finished = = 0 & & sp - > expired = = 0 )
printf ( " SWAPSTATUS updated %llu %s %u %u \n " , ( long long ) sp - > aliceid , LP_stats_methods [ sp - > methodind ] , juint ( argjson , " finished " ) , juint ( argjson , " expired " ) ) ;
sp - > methodind = methodind ;
sp - > finished = juint ( argjson , " finished " ) ;
sp - > expired = juint ( argjson , " expired " ) ;
}
}
return ( clonestr ( " { \" result \" : \" success \" } " ) ) ;
}
char * LP_gettradestatus ( uint64_t aliceid )
{
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 ] ;
struct LP_swapstats * sp ; cJSON * reqjson ; bits256 zero ;
//printf("gettradestatus.(%llu)\n",(long long)aliceid);
if ( ( sp = LP_swapstats_find ( aliceid ) ) ! = 0 & & time ( NULL ) > sp - > lasttime + 60 )
{
if ( ( reqjson = LP_swapstats_json ( sp ) ) ! = 0 )
{
jaddstr ( reqjson , " method " , " swapstatus " ) ;
memset ( zero . bytes , 0 , sizeof ( zero ) ) ;
LP_reserved_msg ( 0 , " " , " " , zero , jprint ( reqjson , 1 ) ) ;
}
}
return ( clonestr ( " { \" error \" : \" cant find aliceid \" } " ) ) ;
}
int32_t LP_stats_dispiter ( cJSON * array , struct LP_swapstats * sp , uint32_t starttime , uint32_t endtime , char * refbase , char * refrel , char * refgui , bits256 refpubkey )
{
int32_t dispflag , retval = 0 ;
if ( sp - > finished = = 0 & & sp - > expired = = 0 & & time ( NULL ) > sp - > Q . timestamp + LP_atomic_locktime ( sp - > Q . srccoin , sp - > Q . destcoin ) * 2 )
sp - > expired = ( uint32_t ) time ( NULL ) ;
if ( sp - > finished ! = 0 | | sp - > expired ! = 0 )
retval = 1 ;
dispflag = 0 ;
if ( starttime = = 0 & & endtime = = 0 )
dispflag = 1 ;
else if ( starttime > time ( NULL ) & & endtime = = starttime & & sp - > finished = = 0 & & sp - > expired = = 0 )
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 ;
if ( refgui = = 0 | | refgui [ 0 ] = = 0 | | strcmp ( refgui , sp - > bobgui ) = = 0 | | strcmp ( refgui , sp - > alicegui ) = = 0 )
{
if ( bits256_nonz ( refpubkey ) = = 0 | | bits256_cmp ( refpubkey , sp - > Q . srchash ) = = 0 | | bits256_cmp ( refpubkey , sp - > Q . desthash ) = = 0 )
dispflag = 1 ;
}
}
if ( dispflag ! = 0 )
jaddi ( array , LP_swapstats_json ( sp ) ) ;
return ( retval ) ;
}
cJSON * LP_statslog_disp ( uint32_t starttime , uint32_t endtime , char * refgui , bits256 refpubkey , char * refbase , char * refrel )
{
static int32_t rval ;
cJSON * retjson , * array , * item , * reqjson ; struct LP_pubkey_info * pubp , * ptmp ; bits256 zero ; uint32_t now ; struct LP_swapstats * sp , * tmp ; int32_t i , n , numtrades [ LP_MAXPRICEINFOS ] ; uint64_t basevols [ LP_MAXPRICEINFOS ] , relvols [ LP_MAXPRICEINFOS ] ;
if ( rval = = 0 )
rval = ( LP_rand ( ) % 300 ) + 60 ;
if ( starttime > endtime )
starttime = endtime ;
n = LP_statslog_parse ( ) ;
memset ( basevols , 0 , sizeof ( basevols ) ) ;
memset ( relvols , 0 , sizeof ( relvols ) ) ;
memset ( numtrades , 0 , sizeof ( numtrades ) ) ;
@ -342,45 +448,41 @@ char *LP_statslog_disp(int32_t n,uint32_t starttime,uint32_t endtime,char *refgu
jaddstr ( retjson , " result " , " success " ) ;
jaddnum ( retjson , " newlines " , n ) ;
array = cJSON_CreateArray ( ) ;
HASH_ITER ( hh , LP_swapstats , sp , tmp )
LP_RTcount = LP_swapscount = 0 ;
now = ( uint32_t ) time ( NULL ) ;
HASH_ITER ( hh , LP_RTstats , sp , tmp )
{
if ( sp - > finished = = 0 & & time ( NULL ) > sp - > Q . timestamp + LP_atomic_locktime ( sp - > Q . srccoin , sp - > Q . destcoin ) * 2 )
sp - > expired = ( uint32_t ) time ( NULL ) ;
dispflag = 0 ;
if ( starttime = = 0 & & endtime = = 0 )
dispflag = 1 ;
else if ( starttime > time ( NULL ) & & endtime = = starttime & & sp - > finished = = 0 & & sp - > expired = = 0 )
dispflag = 1 ;
else if ( sp - > Q . timestamp > = starttime & & sp - > Q . timestamp < = endtime )
dispflag = 1 ;
if ( dispflag ! = 0 )
if ( LP_stats_dispiter ( array , sp , starttime , endtime , refbase , refrel , refgui , refpubkey ) > 0 )
{
dispflag = 0 ;
if ( refgui = = 0 | | refgui [ 0 ] = = 0 | | strcmp ( refgui , sp - > bobgui ) = = 0 | | strcmp ( refgui , sp - > alicegui ) = = 0 )
{
if ( bits256_nonz ( refpubkey ) = = 0 | | bits256_cmp ( refpubkey , sp - > Q . srchash ) = = 0 | | bits256_cmp ( refpubkey , sp - > Q . desthash ) = = 0 )
dispflag = 1 ;
}
HASH_DELETE ( hh , LP_RTstats , sp ) ;
HASH_ADD ( hh , LP_swapstats , aliceid , sizeof ( sp - > aliceid ) , sp ) ;
}
if ( dispflag ! = 0 )
else
{
LP_swapstats_line ( numtrades , basevols , relvols , line , sp ) ;
item = cJSON_CreateObject ( ) ;
jadd64bits ( item , " aliceid " , sp - > aliceid ) ;
jaddbits256 ( item , " src " , sp - > Q . srchash ) ;
jaddstr ( item , " base " , sp - > Q . srccoin ) ;
jaddnum ( item , " basevol " , dstr ( sp - > Q . satoshis ) ) ;
jaddbits256 ( item , " dest " , sp - > Q . desthash ) ;
jaddstr ( item , " rel " , sp - > Q . destcoin ) ;
jaddnum ( item , " relvol " , dstr ( sp - > Q . destsatoshis ) ) ;
jaddnum ( item , " price " , sp - > qprice ) ;
jaddnum ( item , " requestid " , sp - > Q . R . requestid ) ;
jaddnum ( item , " quoteid " , sp - > Q . R . quoteid ) ;
jaddstr ( item , " line " , line ) ;
jaddi ( array , item ) ;
LP_RTcount + + ;
if ( now > sp - > lasttime + rval )
{
reqjson = cJSON_CreateObject ( ) ;
jaddstr ( reqjson , " method " , " gettradestatus " ) ;
jadd64bits ( reqjson , " aliceid " , sp - > aliceid ) ;
memset ( zero . bytes , 0 , sizeof ( zero ) ) ;
LP_reserved_msg ( 0 , " " , " " , zero , jprint ( reqjson , 1 ) ) ;
}
}
}
HASH_ITER ( hh , LP_swapstats , sp , tmp )
{
LP_stats_dispiter ( array , sp , starttime , endtime , refbase , refrel , refgui , refpubkey ) ;
LP_swapscount + + ;
}
HASH_ITER ( hh , LP_pubkeyinfos , pubp , ptmp )
{
pubp - > dynamictrust = LP_dynamictrust ( pubp - > pubkey , 0 ) ;
}
//printf("RT.%d completed.%d\n",LP_RTcount,LP_swapscount);
jadd ( retjson , " swaps " , array ) ;
jaddnum ( retjson , " RTcount " , LP_RTcount ) ;
jaddnum ( retjson , " swapscount " , LP_swapscount ) ;
array = cJSON_CreateArray ( ) ;
for ( i = 0 ; i < LP_MAXPRICEINFOS ; i + + )
{
@ -405,7 +507,99 @@ 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=<now>-timescale*1024, endtime=<now>, 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 ( item ) ;
}
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 + + ;
//printf("%d %.8f/%.8f -> %.8f\n",bar->numtrades,basevol,relvol,price);
}
}
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 )
starttime = ( endtime - LP_SCREENWIDTH * timescale ) ;
numbars = ( ( endtime - starttime ) / timescale ) + 1 ;
bars = calloc ( numbars , sizeof ( * bars ) ) ;
for ( bari = 0 ; bari < numbars ; bari + + )
bars [ bari ] . timestamp = starttime + bari * timescale ;
if ( ( statsjson = LP_statslog_disp ( starttime , endtime , " " , zero , base , rel ) ) ! = 0 )
{
if ( ( swaps = jarray ( & n , statsjson , " swaps " ) ) ! = 0 )
{
for ( i = 0 ; i < n ; i + + )
{
item = jitem ( swaps , i ) ;
if ( ( timestamp = juint ( item , " timestamp " ) ) ! = 0 & & timestamp > = starttime & & timestamp < = endtime )
{
bari = ( timestamp - starttime ) / timescale ;
LP_ohlc_update ( & bars [ bari ] , timestamp , jdouble ( item , " basevol " ) , jdouble ( item , " relvol " ) ) ;
} else printf ( " skip.(%s) \n " , jprint ( item , 0 ) ) ;
}
}
free_json ( statsjson ) ;
}
array = cJSON_CreateArray ( ) ;
for ( bari = 0 ; bari < numbars ; bari + + )
if ( ( item = LP_ohlc_json ( & bars [ bari ] ) ) ! = 0 )
jaddi ( array , item ) ;
free ( bars ) ;
return ( array ) ;
}