@ -18,9 +18,139 @@
// marketmaker
// marketmaker
//
//
cJSON * LP_RTmetrics_sort ( cJSON * rawasks , int32_t numasks , double maxprice , double relvolume )
struct LP_metricinfo
{
{
cJSON * array , * item , * statsjson , * swaps = 0 ; int32_t i , numswaps = 0 ; bits256 zero ; uint32_t futuretime ; double price ; char * retstr ;
bits256 pubkey ;
double metric , price , balance , minvol , maxvol ;
int32_t ind , numutxos , age , pendingswaps ;
} ;
struct LP_RTmetrics_pendings
{
char refbase [ 16 ] , refrel [ 16 ] ;
int32_t numswaps , numavoidtxids , numwhitelist , numblacklist , numpendings , pending_swaps [ 1024 ] ;
bits256 avoidtxids [ 8192 ] , whitelist [ 1024 ] , blacklist [ 1024 ] , pending_pubkeys [ 1024 ] ;
} LP_RTmetrics ;
int32_t LP_bits256_find ( bits256 * list , int32_t num , bits256 val )
{
int32_t i ;
if ( bits256_nonz ( val ) ! = 0 )
{
for ( i = 0 ; i < num ; i + + )
if ( bits256_cmp ( list [ i ] , val ) = = 0 )
return ( i ) ;
}
return ( - 1 ) ;
}
int32_t LP_bits256_add ( char * debugstr , bits256 * list , int32_t * nump , int32_t maxnum , bits256 val )
{
if ( bits256_nonz ( val ) ! = 0 & & * nump < maxnum )
{
if ( LP_bits256_find ( list , * nump , val ) < 0 )
list [ ( * nump ) + + ] = val ;
return ( * nump ) ;
} else printf ( " %s[%d] overflow \n " , debugstr , * nump ) ;
return ( - 1 ) ;
}
int32_t LP_RTmetrics_avoidadd ( bits256 txid )
{
return ( LP_bits256_add ( " LP_RTmetrics_avoidadd avoidtxids " , LP_RTmetrics . avoidtxids , & LP_RTmetrics . numavoidtxids , ( int32_t ) ( sizeof ( LP_RTmetrics . avoidtxids ) / sizeof ( * LP_RTmetrics . avoidtxids ) ) , txid ) ) ;
}
int32_t LP_RTmetrics_whitelistadd ( bits256 pubkey )
{
return ( LP_bits256_add ( " LP_RTmetrics_whitelistadd whitelist " , LP_RTmetrics . whitelist , & LP_RTmetrics . numwhitelist , ( int32_t ) ( sizeof ( LP_RTmetrics . whitelist ) / sizeof ( * LP_RTmetrics . whitelist ) ) , pubkey ) ) ;
}
int32_t LP_RTmetrics_blacklistadd ( bits256 pubkey )
{
return ( LP_bits256_add ( " LP_RTmetrics_blacklistadd blacklist " , LP_RTmetrics . blacklist , & LP_RTmetrics . numblacklist , ( int32_t ) ( sizeof ( LP_RTmetrics . blacklist ) / sizeof ( * LP_RTmetrics . blacklist ) ) , pubkey ) ) ;
}
int32_t LP_RTmetrics_pendingswap ( bits256 pubkey )
{
int32_t ind ;
if ( ( ind = LP_bits256_add ( " LP_RTmetrics_pendingswap " , LP_RTmetrics . pending_pubkeys , & LP_RTmetrics . numpendings , ( int32_t ) ( sizeof ( LP_RTmetrics . pending_pubkeys ) / sizeof ( * LP_RTmetrics . pending_pubkeys ) ) , pubkey ) ) > = 0 )
LP_RTmetrics . pending_swaps [ ind ] + + ;
return ( ind ) ;
}
int32_t LP_RTmetrics_pendingswaps ( bits256 pubkey )
{
int32_t ind ;
if ( ( ind = LP_bits256_find ( LP_RTmetrics . pending_pubkeys , LP_RTmetrics . numpendings , pubkey ) ) > = 0 )
return ( LP_RTmetrics . pending_swaps [ ind ] ) ;
else return ( 0 ) ;
}
int32_t LP_RTmetrics_avoidtxid ( bits256 txid )
{
return ( LP_bits256_find ( LP_RTmetrics . avoidtxids , LP_RTmetrics . numavoidtxids , txid ) ) ;
}
int32_t LP_RTmetrics_whitelisted ( bits256 pubkey )
{
return ( LP_bits256_find ( LP_RTmetrics . whitelist , LP_RTmetrics . numwhitelist , pubkey ) ) ;
}
int32_t LP_RTmetrics_blacklisted ( bits256 pubkey )
{
return ( LP_bits256_find ( LP_RTmetrics . blacklist , LP_RTmetrics . numblacklist , pubkey ) ) ;
}
void LP_RTmetrics_swapsinfo ( char * refbase , char * refrel , cJSON * swaps , int32_t numswaps )
{
int32_t i ; char * base , * rel , * retstr ; cJSON * item , * swapjson ; bits256 srcpub , destpub ; uint64_t aliceid , basesatoshis , relsatoshis ; uint32_t requestid , quoteid ; double price ;
for ( i = 0 ; i < numswaps ; i + + )
{
item = jitem ( swaps , i ) ;
if ( ( base = jstr ( item , " base " ) ) = = 0 )
base = " " ;
if ( ( rel = jstr ( item , " rel " ) ) = = 0 )
rel = " " ;
if ( strcmp ( base , refbase ) ! = 0 & & strcmp ( base , refrel ) ! = 0 & & strcmp ( rel , refbase ) ! = 0 & & strcmp ( rel , refrel ) ! = 0 )
continue ;
aliceid = j64bits ( item , " aliceid " ) ;
basesatoshis = SATOSHIDEN * jdouble ( item , " basevol " ) ;
srcpub = jbits256 ( item , " src " ) ;
relsatoshis = SATOSHIDEN * jdouble ( item , " relvol " ) ;
destpub = jbits256 ( item , " dest " ) ;
price = jdouble ( item , " price " ) ;
requestid = juint ( item , " requestid " ) ;
quoteid = juint ( item , " quoteid " ) ;
LP_RTmetrics_pendingswap ( srcpub ) ;
LP_RTmetrics_pendingswap ( destpub ) ;
if ( ( retstr = basilisk_swapentry ( requestid , quoteid ) ) ! = 0 )
{
if ( ( swapjson = cJSON_Parse ( retstr ) ) ! = 0 )
{
LP_RTmetrics_avoidadd ( jbits256 ( swapjson , " bobdeposit " ) ) ;
LP_RTmetrics_avoidadd ( jbits256 ( swapjson , " alicepayment " ) ) ;
LP_RTmetrics_avoidadd ( jbits256 ( swapjson , " bobpayment " ) ) ;
LP_RTmetrics_avoidadd ( jbits256 ( swapjson , " paymentspent " ) ) ;
LP_RTmetrics_avoidadd ( jbits256 ( swapjson , " Apaymentspent " ) ) ;
LP_RTmetrics_avoidadd ( jbits256 ( swapjson , " depositspent " ) ) ;
free_json ( swapjson ) ;
}
free ( retstr ) ;
}
}
}
void LP_RTmetrics_update ( char * base , char * rel )
{
struct LP_pubkeyinfo * pubp , * tmp ; uint32_t futuretime ; int32_t i , numswaps ; bits256 zero ; char * retstr ; cJSON * statsjson , * swaps ;
memset ( & LP_RTmetrics , 0 , sizeof ( LP_RTmetrics ) ) ;
HASH_ITER ( hh , LP_pubkeyinfos , pubp , tmp )
{
if ( pubp - > istrusted > 0 )
LP_RTmetrics_whitelistadd ( pubp - > pubkey ) ;
else if ( pubp - > istrusted < 0 )
LP_RTmetrics_blacklistadd ( pubp - > pubkey ) ;
}
futuretime = ( uint32_t ) time ( NULL ) + 3600 * 100 ;
futuretime = ( uint32_t ) time ( NULL ) + 3600 * 100 ;
memset ( zero . bytes , 0 , sizeof ( zero ) ) ;
memset ( zero . bytes , 0 , sizeof ( zero ) ) ;
if ( ( retstr = LP_statslog_disp ( 100 , futuretime , futuretime , " " , zero ) ) ! = 0 )
if ( ( retstr = LP_statslog_disp ( 100 , futuretime , futuretime , " " , zero ) ) ! = 0 )
@ -29,37 +159,110 @@ cJSON *LP_RTmetrics_sort(cJSON *rawasks,int32_t numasks,double maxprice,double r
{
{
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 )
if ( numswaps > 0 )
swaps = jduplicate ( swaps ) ;
LP_RTmetrics_swapsinfo ( base , rel , swaps , numswaps ) ;
else swaps = 0 ;
}
}
free_json ( statsjson ) ;
free_json ( statsjson ) ;
}
}
free ( retstr ) ;
free ( retstr ) ;
}
}
//if ( numswaps == 0 || swaps == 0 )
for ( i = 0 ; i < LP_RTmetrics . numpendings ; i + + )
return ( 0 ) ;
if ( LP_RTmetrics . pending_swaps [ i ] > LP_MAXPENDING_SWAPS )
printf ( " calc RTmetrics for (%s) \n " , jprint ( swaps , 0 ) ) ;
{
/*jadd64bits(item,"aliceid",sp->aliceid);
char str [ 65 ] ; printf ( " %s has %d pending swaps! which is more than %d \n " , bits256_str ( str , LP_RTmetrics . pending_pubkeys [ i ] ) , LP_RTmetrics . pending_swaps [ i ] , LP_MAXPENDING_SWAPS ) ;
jaddbits256 ( item , " src " , sp - > Q . srchash ) ;
LP_RTmetrics_blacklistadd ( LP_RTmetrics . pending_pubkeys [ i ] ) ;
jaddstr ( item , " base " , sp - > Q . srccoin ) ;
}
jaddnum ( item , " basevol " , dstr ( sp - > Q . satoshis ) ) ;
printf ( " %d pubkeys have pending swaps, whitelist.%d blacklist.%d avoidtxids.%d \n " , LP_RTmetrics . numpendings , LP_RTmetrics . numwhitelist , LP_RTmetrics . numblacklist , LP_RTmetrics . numavoidtxids ) ;
jaddbits256 ( item , " dest " , sp - > Q . desthash ) ;
}
jaddstr ( item , " rel " , sp - > Q . destcoin ) ;
jaddnum ( item , " relvol " , dstr ( sp - > Q . destsatoshis ) ) ;
double _LP_RTmetric_calc ( struct LP_metricinfo * mp , double bestprice , double maxprice , double relvolume )
jaddnum ( item , " price " , sp - > qprice ) ;
{
jaddnum ( item , " requestid " , sp - > Q . R . requestid ) ;
int32_t n ; double metric , origmetric = ( bestprice / mp - > price ) ;
jaddnum ( item , " quoteid " , sp - > Q . R . quoteid ) ;
metric = origmetric ;
*/
if ( mp - > numutxos = = 0 | | relvolume = = 0. | | mp - > maxvol = = 0. | | mp - > balance = = 0. )
array = cJSON_CreateArray ( ) ;
return ( metric * 100. ) ;
for ( i = 0 ; i < numasks ; i + + )
if ( relvolume < mp - > minvol )
{
metric * = ( mp - > minvol / relvolume ) ;
}
else if ( relvolume > mp - > maxvol )
{
metric * = ( relvolume / mp - > maxvol ) ;
}
if ( relvolume < mp - > balance / LP_MINVOL )
{
metric * = ( mp - > balance / relvolume ) ;
}
else if ( relvolume > mp - > balance / mp - > numutxos )
{
metric * = ( relvolume / ( mp - > balance / mp - > numutxos ) ) ;
}
if ( mp - > age > LP_ORDERBOOK_DURATION * 0.8 )
metric * = 2 ;
else if ( mp - > age > 60 )
metric * = 1.03 ;
if ( ( n = mp - > pendingswaps ) > 0 )
while ( n - - > 0 )
metric * = 1.1 ;
if ( metric ! = origmetric )
printf ( " price %.8f orig %.8f -> %.8f relvol %.8f min %.8f max %.8f bal %.8f age.%d pend.%d \n " , mp - > price , origmetric , metric , relvolume , mp - > minvol , mp - > maxvol , mp - > balance , mp - > age , mp - > pendingswaps ) ;
return ( metric ) ;
}
void LP_RTmetric_calc ( struct LP_metricinfo * sortbuf , int32_t ind , cJSON * item , double bestprice , double maxprice , double relvolume , double prevdepth )
{
sortbuf [ ind ] . pubkey = jbits256 ( item , " pubkey " ) ;
sortbuf [ ind ] . price = jdouble ( item , " price " ) ;
sortbuf [ ind ] . maxvol = jdouble ( item , " maxvolume " ) ;
sortbuf [ ind ] . minvol = jdouble ( item , " minvolume " ) ;
sortbuf [ ind ] . balance = jdouble ( item , " depth " ) - prevdepth ;
sortbuf [ ind ] . numutxos = juint ( item , " numutxos " ) ;
sortbuf [ ind ] . age = juint ( item , " age " ) ;
sortbuf [ ind ] . ind = ind ;
sortbuf [ ind ] . pendingswaps = LP_RTmetrics_pendingswaps ( sortbuf [ ind ] . pubkey ) ;
sortbuf [ ind ] . metric = _LP_RTmetric_calc ( & sortbuf [ ind ] , bestprice , maxprice , relvolume ) ;
}
cJSON * LP_RTmetrics_sort ( char * base , char * rel , cJSON * rawasks , int32_t numasks , double maxprice , double relvolume )
{
cJSON * array , * item ; int32_t i , num , groupi ; double price , prevdepth , bestprice ; struct LP_metricinfo * sortbuf ;
groupi = - 1 ;
bestprice = 0. ;
for ( num = i = 0 ; i < numasks ; i + + )
{
{
item = jitem ( rawasks , i ) ;
item = jitem ( rawasks , i ) ;
price = jdouble ( item , " price " ) ;
price = jdouble ( item , " price " ) ;
if ( price > maxprice )
if ( price > maxprice )
break ;
break ;
jaddi ( array , jduplicate ( item ) ) ;
if ( i = = 0 )
bestprice = price ;
else if ( price < bestprice * 1.01 )
groupi = i ;
num + + ;
}
}
free_json ( swaps ) ;
if ( groupi > 0 )
{
sortbuf = calloc ( groupi + 1 , sizeof ( * sortbuf ) ) ;
prevdepth = 0. ;
for ( i = 0 ; i < = groupi ; i + + )
{
item = jitem ( rawasks , i ) ;
LP_RTmetric_calc ( sortbuf , i , item , bestprice , maxprice , relvolume , prevdepth ) ;
prevdepth = jdouble ( item , " depth " ) ;
}
revsortds ( & sortbuf [ 0 ] . metric , groupi + 1 , sizeof ( * sortbuf ) ) ;
array = cJSON_CreateArray ( ) ;
for ( i = 0 ; i < = groupi ; i + + )
{
printf ( " (%d -> %d) " , i , sortbuf [ i ] . ind ) ;
item = jitem ( rawasks , sortbuf [ i ] . ind ) ;
jaddi ( array , jduplicate ( item ) ) ;
}
free ( sortbuf ) ;
for ( ; i < num ; i + + )
jaddi ( array , jduplicate ( jitem ( rawasks , i ) ) ) ;
printf ( " new ask order for %d of %d, capped at num.%d \n " , groupi , numasks , num ) ;
} else array = rawasks ;
return ( array ) ;
return ( array ) ;
}
}