Skip to content

Commit b49f73a

Browse files
authored
Store value of previous price aggregate if the status is trading (#152)
* Only update value of previous aggregate price if it was trading * Remove redundant usage of drv1_ field. This is always 1 for all currently deployed price accounts which have had upd_ema ran once, which covers all accounts. Therefore the condition inside upd_ema will always be true. We can therefore remove the usage of drv1_, freeing it up to be used for other 64-bit data in the future. * Store current and previous aggregate price timestamps * Use the pub_slot of the previous aggregate as the value of prev_slot, for consistency. This effectively makes prev_slot_, prev_price_ and prev_conf_ a cache of the ptr->agg_ fields. * Add tests for storing previous aggregate price * Add test showing that the prev_* fields don't update if the aggregate status is UNKNOWN
1 parent d443c23 commit b49f73a

File tree

7 files changed

+73
-36
lines changed

7 files changed

+73
-36
lines changed

pctest/fuzz.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -266,9 +266,7 @@ void test_upd_ema(int64_t n, int64_t d, pd_t* val) {
266266
}
267267
qs->expo_ = -9;
268268

269-
pc_price_t prc[1];
270-
prc->drv1_ = 1;
271-
upd_ema(ema, val, conf, 1, qs, prc);
269+
upd_ema(ema, val, conf, 1, qs);
272270

273271
pd_t result[1];
274272
result->v_ = ema->val_;

pctest/test_qset.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,7 @@ int main( int argc,char** argv )
149149
ptr->latest_.pub_slot_ =
150150
static_cast< uint64_t >( static_cast< int64_t >( slot ) + pub_slot );
151151
}
152-
upd_aggregate( px, slot+1 );
152+
upd_aggregate( px, slot+1, 1234 );
153153

154154
char const* status = "invalid value";
155155
switch ( px->agg_.status_ ) {

pctest/test_twap.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,11 @@ int main( int argc,char** argv )
7777
pc_price_t px[1];
7878
__builtin_memset( px, 0, sizeof( pc_price_t ) );
7979
uint64_t slot = 1000;
80+
int64_t timestamp = 1234;
8081
px->last_slot_ = slot;
8182
px->agg_.pub_slot_ = slot;
8283
px->num_ = 0;
83-
upd_aggregate( px, slot+1 );
84+
upd_aggregate( px, slot+1, timestamp );
8485
pc_qset_t *qs = nullptr;
8586

8687
// skip first line

program/src/oracle/oracle.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -459,6 +459,7 @@ static uint64_t upd_test( SolParameters *prm, SolAccountInfo *ka )
459459

460460
// compute aggregate price
461461
uint64_t slot = 1000UL;
462+
int64_t timestamp = 5678;
462463
px->last_slot_= slot;
463464
px->agg_.pub_slot_ = slot;
464465
px->expo_ = cmd->expo_;
@@ -470,7 +471,7 @@ static uint64_t upd_test( SolParameters *prm, SolAccountInfo *ka )
470471
ptr->latest_.conf_ = cmd->conf_[i];
471472
ptr->latest_.pub_slot_ = slot + (uint64_t)cmd->slot_diff_[i];
472473
}
473-
upd_aggregate( px, slot+1 );
474+
upd_aggregate( px, slot+1, timestamp );
474475

475476
return SUCCESS;
476477
}
@@ -527,7 +528,7 @@ static uint64_t upd_price( SolParameters *prm, SolAccountInfo *ka )
527528

528529
// update aggregate price as necessary
529530
if ( sptr->slot_ > pptr->agg_.pub_slot_ ) {
530-
upd_aggregate( pptr, sptr->slot_ );
531+
upd_aggregate( pptr, sptr->slot_, sptr->unix_timestamp_ );
531532
}
532533

533534
// update component price if required

program/src/oracle/oracle.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -157,17 +157,17 @@ typedef struct pc_price
157157
uint64_t valid_slot_; // valid on-chain slot of agg. price
158158
pc_ema_t twap_; // time-weighted average price
159159
pc_ema_t twac_; // time-weighted average conf interval
160-
int64_t drv1_; // space for future derived values
160+
int64_t timestamp_; // unix timestamp of aggregate price
161161
uint8_t min_pub_; // min publishers for valid price
162162
int8_t drv2_; // space for future derived values
163163
int16_t drv3_; // space for future derived values
164164
int32_t drv4_; // space for future derived values
165165
pc_pub_key_t prod_; // product id/ref-account
166166
pc_pub_key_t next_; // next price account in list
167-
uint64_t prev_slot_; // valid slot of previous update
168-
int64_t prev_price_; // aggregate price of previous update
169-
uint64_t prev_conf_; // confidence interval of previous update
170-
uint64_t drv5_; // space for future derived values
167+
uint64_t prev_slot_; // valid slot of previous aggregate with TRADING status
168+
int64_t prev_price_; // aggregate price of previous aggregate with TRADING status
169+
uint64_t prev_conf_; // confidence interval of previous aggregate with TRADING status
170+
int64_t prev_timestamp_; // unix timestamp of previous aggregate with TRADING status
171171
pc_price_info_t agg_; // aggregate price information
172172
pc_price_comp_t comp_[PC_COMP_SIZE];// component prices
173173
} pc_price_t;

program/src/oracle/test_oracle.c

Lines changed: 47 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -562,25 +562,35 @@ Test( oracle, upd_aggregate ) {
562562
px->last_slot_ = 1000;
563563
px->agg_.pub_slot_ = 1000;
564564
px->comp_[0].latest_ = p1;
565-
upd_aggregate( px, 1001 );
565+
upd_aggregate( px, 1001, 1 );
566566
cr_assert( px->agg_.price_ == 100 );
567567
cr_assert( px->agg_.conf_ == 10 );
568568
cr_assert( px->twap_.val_ == 100 );
569569
cr_assert( px->twac_.val_ == 10 );
570570
cr_assert( px->num_qt_ == 1 );
571+
cr_assert( px->timestamp_ == 1 );
572+
cr_assert( px->prev_slot_ == 0 );
573+
cr_assert( px->prev_price_ == 0 );
574+
cr_assert( px->prev_conf_ == 0 );
575+
cr_assert( px->prev_timestamp_ == 0 );
571576

572577
// two publishers
573578
px->num_ = 0;
574579
px->last_slot_ = 1000;
575580
px->agg_.pub_slot_ = 1000;
576581
px->comp_[px->num_++].latest_ = p2;
577582
px->comp_[px->num_++].latest_ = p1;
578-
upd_aggregate( px, 1001 );
583+
upd_aggregate( px, 1001, 2 );
579584
cr_assert( px->agg_.price_ == 147 );
580585
cr_assert( px->agg_.conf_ == 48 );
581586
cr_assert( px->twap_.val_ == 108 );
582587
cr_assert( px->twac_.val_ == 16 );
583588
cr_assert( px->num_qt_ == 2 );
589+
cr_assert( px->timestamp_ == 2 );
590+
cr_assert( px->prev_slot_ == 1000 );
591+
cr_assert( px->prev_price_ == 100 );
592+
cr_assert( px->prev_conf_ == 10 );
593+
cr_assert( px->prev_timestamp_ == 1 );
584594

585595
// three publishers
586596
px->num_ = 0;
@@ -589,12 +599,17 @@ Test( oracle, upd_aggregate ) {
589599
px->comp_[px->num_++].latest_ = p2;
590600
px->comp_[px->num_++].latest_ = p1;
591601
px->comp_[px->num_++].latest_ = p3;
592-
upd_aggregate( px, 1001 );
602+
upd_aggregate( px, 1001, 3 );
593603
cr_assert( px->agg_.price_ == 191 );
594604
cr_assert( px->agg_.conf_ == 74 );
595605
cr_assert( px->twap_.val_ == 116 );
596606
cr_assert( px->twac_.val_ == 22 );
597607
cr_assert( px->num_qt_ == 3 );
608+
cr_assert( px->timestamp_ == 3 );
609+
cr_assert( px->prev_slot_ == 1000 );
610+
cr_assert( px->prev_price_ == 147 );
611+
cr_assert( px->prev_conf_ == 48 );
612+
cr_assert( px->prev_timestamp_ == 2 );
598613

599614
// four publishers
600615
px->num_ = 0;
@@ -604,24 +619,50 @@ Test( oracle, upd_aggregate ) {
604619
px->comp_[px->num_++].latest_ = p1;
605620
px->comp_[px->num_++].latest_ = p4;
606621
px->comp_[px->num_++].latest_ = p2;
607-
upd_aggregate( px, 1001 );
622+
upd_aggregate( px, 1001, 4 );
608623
cr_assert( px->agg_.price_ == 235 );
609624
cr_assert( px->agg_.conf_ == 99 );
610625
cr_assert( px->twap_.val_ == 124 );
611626
cr_assert( px->twac_.val_ == 27 );
612627
cr_assert( px->last_slot_ == 1001 );
613628
cr_assert( px->num_qt_ == 4 );
629+
cr_assert( px->timestamp_ == 4 );
630+
cr_assert( px->prev_slot_ == 1000 );
631+
cr_assert( px->prev_price_ == 191 );
632+
cr_assert( px->prev_conf_ == 74 );
633+
cr_assert( px->prev_timestamp_ == 3 );
614634

615-
upd_aggregate( px, 1025 );
635+
upd_aggregate( px, 1025, 5 );
616636
cr_assert( px->agg_.status_ == PC_STATUS_TRADING );
617637
cr_assert( px->last_slot_ == 1025 );
618638
cr_assert( px->num_qt_ == 4 );
639+
cr_assert( px->timestamp_ == 5 );
640+
cr_assert( px->prev_slot_ == 1001 );
641+
cr_assert( px->prev_price_ == 235 );
642+
cr_assert( px->prev_conf_ == 99 );
643+
cr_assert( px->prev_timestamp_ == 4 );
619644

620645
// check what happens when nothing publishes for a while
621-
upd_aggregate( px, 1026 );
646+
upd_aggregate( px, 1026, 10 );
622647
cr_assert( px->agg_.status_ == PC_STATUS_UNKNOWN );
623648
cr_assert( px->last_slot_ == 1025 );
624649
cr_assert( px->num_qt_ == 0 );
650+
cr_assert( px->timestamp_ == 10 );
651+
cr_assert( px->prev_slot_ == 1025 );
652+
cr_assert( px->prev_timestamp_ == 5 );
653+
654+
// Check that the prev_* fields don't update if the aggregate status is UNKNOWN
655+
uint64_t prev_slot_ = px->prev_slot_;
656+
int64_t prev_price_ = px->prev_price_;
657+
uint64_t prev_conf_ = px->prev_conf_;
658+
int64_t prev_timestamp_ = px->prev_timestamp_;
659+
upd_aggregate( px, 1028, 12 );
660+
cr_assert( px->agg_.status_ == PC_STATUS_UNKNOWN );
661+
cr_assert( px->timestamp_ == 12 );
662+
cr_assert( px->prev_slot_ == prev_slot_ );
663+
cr_assert( px->prev_price_ == prev_price_ );
664+
cr_assert( px->prev_conf_ == prev_conf_ );
665+
cr_assert( px->prev_timestamp_ == prev_timestamp_ );
625666
}
626667

627668
Test( oracle, del_publisher ) {

program/src/oracle/upd_aggregate.h

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ static pc_qset_t *qset_new( int expo )
8282

8383
static void upd_ema(
8484
pc_ema_t *ptr, pd_t *val, pd_t *conf, int64_t nslot, pc_qset_t *qs
85-
, pc_price_t *prc_ptr)
85+
)
8686
{
8787
pd_t numer[1], denom[1], cwgt[1], wval[1], decay[1], diff[1], one[1];
8888
pd_new( one, 100000000L, -8 );
@@ -103,15 +103,8 @@ static void upd_ema(
103103
pd_add( decay, decay, one, qs->fact_ );
104104

105105
// compute numer/denom and new value from decay factor
106-
if ( prc_ptr->drv1_ ) {
107-
pd_load( numer, ptr->numer_ );
108-
pd_load( denom, ptr->denom_ );
109-
}
110-
else {
111-
// temporary upgrade code
112-
pd_new_scale( numer, ptr->numer_, PD_EMA_EXPO );
113-
pd_new_scale( denom, ptr->denom_, PD_EMA_EXPO );
114-
}
106+
pd_load( numer, ptr->numer_ );
107+
pd_load( denom, ptr->denom_ );
115108
if ( numer->v_ < 0 || denom->v_ < 0 ) {
116109
// temporary reset twap on negative value
117110
pd_set( numer, val );
@@ -135,7 +128,6 @@ static void upd_ema(
135128
ptr->numer_ = numer1;
136129
ptr->denom_ = denom1;
137130
}
138-
prc_ptr->drv1_ = 1;
139131
}
140132

141133
static inline void upd_twap(
@@ -144,8 +136,8 @@ static inline void upd_twap(
144136
pd_t px[1], conf[1];
145137
pd_new_scale( px, ptr->agg_.price_, ptr->expo_ );
146138
pd_new_scale( conf, ( int64_t )( ptr->agg_.conf_ ), ptr->expo_ );
147-
upd_ema( &ptr->twap_, px, conf, nslots, qs, ptr );
148-
upd_ema( &ptr->twac_, conf, conf, nslots, qs, ptr );
139+
upd_ema( &ptr->twap_, px, conf, nslots, qs );
140+
upd_ema( &ptr->twac_, conf, conf, nslots, qs );
149141
}
150142

151143
// compute weighted percentile
@@ -185,7 +177,7 @@ static void wgt_ptile(
185177
}
186178

187179
// update aggregate price
188-
static inline void upd_aggregate( pc_price_t *ptr, uint64_t slot )
180+
static inline void upd_aggregate( pc_price_t *ptr, uint64_t slot, int64_t timestamp )
189181
{
190182
// only re-compute aggregate in next slot
191183
if ( slot <= ptr->agg_.pub_slot_ ) {
@@ -196,14 +188,18 @@ static inline void upd_aggregate( pc_price_t *ptr, uint64_t slot )
196188
// get number of slots from last published valid price
197189
int64_t agg_diff = ( int64_t )slot - ( int64_t )( ptr->last_slot_ );
198190

199-
// copy previous price
200-
ptr->prev_slot_ = ptr->valid_slot_;
201-
ptr->prev_price_ = ptr->agg_.price_;
202-
ptr->prev_conf_ = ptr->agg_.conf_;
191+
// Update the value of the previous price, if it had TRADING status.
192+
if ( ptr->agg_.status_ == PC_STATUS_TRADING ) {
193+
ptr->prev_slot_ = ptr->agg_.pub_slot_;
194+
ptr->prev_price_ = ptr->agg_.price_;
195+
ptr->prev_conf_ = ptr->agg_.conf_;
196+
ptr->prev_timestamp_ = ptr->timestamp_;
197+
}
203198

204199
// update aggregate details ready for next slot
205200
ptr->valid_slot_ = ptr->agg_.pub_slot_;// valid slot-time of agg. price
206201
ptr->agg_.pub_slot_ = slot; // publish slot-time of agg. price
202+
ptr->timestamp_ = timestamp;
207203

208204
uint32_t numv = 0;
209205
uint32_t vidx[ PC_COMP_SIZE ];

0 commit comments

Comments
 (0)