@@ -17,10 +17,8 @@ typedef struct pc_qset
17
17
pd_t uprice_ [PC_COMP_SIZE ];
18
18
pd_t lprice_ [PC_COMP_SIZE ];
19
19
pd_t weight_ [PC_COMP_SIZE ];
20
- pd_t cumwgt_ [PC_COMP_SIZE ];
21
20
int64_t decay_ [1 + PC_MAX_SEND_LATENCY ];
22
21
int64_t fact_ [PC_FACTOR_SIZE ];
23
- uint32_t num_ ;
24
22
int32_t expo_ ;
25
23
} pc_qset_t ;
26
24
@@ -78,7 +76,6 @@ static pc_qset_t *qset_new( int expo )
78
76
qs -> fact_ [16 ] = 10000000000000000L ;
79
77
qs -> fact_ [17 ] = 100000000000000000L ;
80
78
81
- qs -> num_ = 0 ;
82
79
qs -> expo_ = expo ;
83
80
84
81
return qs ;
@@ -136,10 +133,25 @@ static inline void upd_twap(
136
133
}
137
134
138
135
// compute weighted percentile
139
- static void wgt_ptile ( pd_t * res , pd_t * prices , pd_t * ptile , pc_qset_t * qs )
136
+ static void wgt_ptile (
137
+ pd_t * const res
138
+ , const pd_t * const prices , const pd_t * const weights , const uint32_t num
139
+ , const pd_t * const ptile , pc_qset_t * qs )
140
140
{
141
- pd_t * cumwgt = qs -> cumwgt_ ;
142
- uint32_t i = 0 , num = qs -> num_ ;
141
+ pd_t cumwgt [ PC_COMP_SIZE ];
142
+
143
+ pd_t cumwgta [ 1 ], half [ 1 ];
144
+ pd_new ( cumwgta , 0 , 0 );
145
+ pd_new ( half , 5 , -1 );
146
+ for ( uint32_t i = 0 ; i < num ; ++ i ) {
147
+ const pd_t * const wptr = & weights [ i ];
148
+ pd_t weight [ 1 ];
149
+ pd_mul ( weight , wptr , half );
150
+ pd_add ( & cumwgt [ i ], cumwgta , weight , qs -> fact_ );
151
+ pd_add ( cumwgta , cumwgta , wptr , qs -> fact_ );
152
+ }
153
+
154
+ uint32_t i = 0 ;
143
155
for ( ; i != num && pd_lt ( & cumwgt [i ], ptile , qs -> fact_ ); ++ i );
144
156
if ( i == num ) {
145
157
pd_set ( res , & prices [num - 1 ] );
@@ -254,7 +266,6 @@ static inline void upd_aggregate( pc_price_t *ptr, uint64_t slot )
254
266
pd_new ( one , 100000000L , -8 );
255
267
pd_new ( wsum , 0 , 0 );
256
268
int64_t ldiff = INT64_MAX ;
257
- qs -> num_ = numa ;
258
269
pd_t * wptr = qs -> weight_ ;
259
270
for ( uint32_t i = 0 ;i != numa ; ++ i ) {
260
271
pc_price_comp_t * iptr = & ptr -> comp_ [aidx [i ]];
@@ -292,9 +303,10 @@ static inline void upd_aggregate( pc_price_t *ptr, uint64_t slot )
292
303
293
304
// bound weights at 1/sqrt(Nquotes) and redeistribute the remaining weight
294
305
// among the remaining quoters proportional to their weights
295
- pd_t wmax [1 ], rnumer [1 ], rdenom [1 ], half [ 1 ], cumwgt [ 1 ] ;
306
+ pd_t wmax [1 ], rnumer [1 ], rdenom [1 ];
296
307
pd_set ( rnumer , one );
297
308
pd_new ( rdenom , 0 , 0 );
309
+ // wmax = 1 / sqrt( numa )
298
310
pd_new ( wmax , numa , 0 );
299
311
pd_sqrt ( wmax , wmax , qs -> fact_ );
300
312
pd_div ( wmax , one , wmax );
@@ -313,38 +325,58 @@ static inline void upd_aggregate( pc_price_t *ptr, uint64_t slot )
313
325
if ( rdenom -> v_ ) {
314
326
pd_div ( rnumer , rnumer , rdenom );
315
327
}
316
- pd_new ( cumwgt , 0 , 0 );
317
- pd_new ( half , 5 , -1 );
318
- for ( uint32_t i = 0 ;i != numa ; ++ i ) {
319
- wptr = & qs -> weight_ [i ];
320
- if ( aidx [i ] == 0 ) {
328
+ for ( uint32_t i = 0 ; i != numa ; ++ i ) {
329
+ wptr = & qs -> weight_ [ i ];
330
+ if ( aidx [ i ] == 0 ) {
321
331
pd_mul ( wptr , wptr , rnumer );
322
332
}
323
- pd_mul ( weight , wptr , half );
324
- pd_add ( & qs -> cumwgt_ [i ], cumwgt , weight , qs -> fact_ );
325
- pd_add ( cumwgt , cumwgt , wptr , qs -> fact_ );
326
333
}
327
334
335
+ const pd_t half = { .e_ = -1 , .v_ = 5 };
336
+
328
337
// compute aggregate price as weighted median
329
338
pd_t iprice [1 ], lprice [1 ], uprice [1 ], q3price [1 ], q1price [1 ], ptile [1 ];
330
339
pd_new ( ptile , 5 , -1 );
331
- wgt_ptile ( iprice , qs -> iprice_ , ptile , qs );
340
+ wgt_ptile ( iprice , qs -> iprice_ , qs -> weight_ , numa , ptile , qs );
332
341
pd_adjust ( iprice , ptr -> expo_ , qs -> fact_ );
333
342
ptr -> agg_ .price_ = iprice -> v_ ;
334
343
335
344
// compute diff in weighted median between upper and lower price bounds
336
- wgt_ptile ( uprice , qs -> uprice_ , ptile , qs );
337
- wgt_ptile ( lprice , qs -> lprice_ , ptile , qs );
345
+ pd_t prices [ PC_COMP_SIZE ];
346
+ pd_t weights [ PC_COMP_SIZE ];
347
+ // sort upper prices and weights
348
+ for ( uint32_t i = 0 ; i < numa ; ++ i ) {
349
+ uint32_t j = i ;
350
+ for ( ; j > 0 && pd_lt ( & qs -> uprice_ [ i ], & prices [ j - 1 ], qs -> fact_ ); -- j ) {
351
+ prices [ j ] = prices [ j - 1 ];
352
+ weights [ j ] = weights [ j - 1 ];
353
+ }
354
+ prices [ j ] = qs -> uprice_ [ i ];
355
+ weights [ j ] = qs -> weight_ [ i ];
356
+ }
357
+ wgt_ptile ( uprice , prices , weights , numa , ptile , qs );
358
+ // sort lower prices and weights
359
+ for ( uint32_t i = 0 ; i < numa ; ++ i ) {
360
+ uint32_t j = i ;
361
+ for ( ; j > 0 && pd_lt ( & qs -> lprice_ [ i ], & prices [ j - 1 ], qs -> fact_ ); -- j ) {
362
+ prices [ j ] = prices [ j - 1 ];
363
+ weights [ j ] = weights [ j - 1 ];
364
+ }
365
+ prices [ j ] = qs -> lprice_ [ i ];
366
+ weights [ j ] = qs -> weight_ [ i ];
367
+ }
368
+ wgt_ptile ( lprice , prices , weights , numa , ptile , qs );
369
+
338
370
pd_sub ( uprice , uprice , lprice , qs -> fact_ );
339
- pd_mul ( uprice , uprice , half );
371
+ pd_mul ( uprice , uprice , & half );
340
372
341
373
// compute weighted iqr of prices
342
374
pd_new ( ptile , 75 , -2 );
343
- wgt_ptile ( q3price , qs -> iprice_ , ptile , qs );
375
+ wgt_ptile ( q3price , qs -> iprice_ , qs -> weight_ , numa , ptile , qs );
344
376
pd_new ( ptile , 25 , -2 );
345
- wgt_ptile ( q1price , qs -> iprice_ , ptile , qs );
377
+ wgt_ptile ( q1price , qs -> iprice_ , qs -> weight_ , numa , ptile , qs );
346
378
pd_sub ( q3price , q3price , q1price , qs -> fact_ );
347
- pd_mul ( q3price , q3price , half );
379
+ pd_mul ( q3price , q3price , & half );
348
380
349
381
// take confidence interval as larger
350
382
pd_t * cptr = pd_gt ( uprice , q3price , qs -> fact_ ) ? uprice : q3price ;
0 commit comments