Skip to content

Commit 9be8581

Browse files
committed
add median logic
1 parent d0f8d94 commit 9be8581

File tree

1 file changed

+116
-0
lines changed

1 file changed

+116
-0
lines changed

x/feeds/README.md

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ This module is used in the BandChain.
3939
- [MsgSubmitSignals](#msgsubmitsignals)
4040
- [End-Block](#end-block)
4141
- [Update Prices](#update-prices)
42+
- [Price aggregation logic](#price-aggregation-logic)
4243
- [Update Supported Feeds](#update-supported-feeds)
4344
- [Events](#events)
4445
- [EndBlocker](#endblocker)
@@ -316,6 +317,121 @@ Any validator that does not submit a price within this period is considered to h
316317
Accepted Validator Prices of the same SignalID will be weighted and median based on the recency of the price and the power of the validator who submitted the price.
317318
The median price is then set as the Price.
318319

320+
#### Price Aggregation logic
321+
322+
**Input**
323+
324+
A list of PriceFeedInfo objects, each containing:
325+
- `Price`: The reported price from the feeder
326+
- `Deviation`: The price deviation
327+
- `Power`: The feeder's power
328+
- `Timestamp`: The time at which the price is reported
329+
330+
**Objective**
331+
332+
An aggregated price from the list of priceFeedInfo.
333+
334+
**Assumption**
335+
336+
1. No PriceFeedInfo has a power that exceeds 25% of the total power in the list.
337+
338+
**Procedure**
339+
340+
1. Order the List:
341+
342+
- Sort the list by `Timestamp` in descending order (latest timestamp first).
343+
- For entries with the same `Timestamp`, sort by `Power` in descending order.
344+
345+
2. Apply Power Weights:
346+
347+
- Calculate the total power from the list.
348+
- Assign weights to the powers in segments as follows:
349+
- The first 1/32 of the total power is multiplied by 6.
350+
- The next 1/16 of the total power is multiplied by 4.
351+
- The next 1/8 of the total power is multiplied by 2.
352+
- The next 1/4 of the total power is multiplied by 1.1.
353+
- If PriceFeedInfo overlaps between segments, split it into parts corresponding to each segment and assign the respective multiplier.
354+
- Any power that falls outside these segments will have a multiplier of 1.
355+
356+
3. Generate Points:
357+
358+
- For each PriceFeedInfo (or its parts if split), generate three points:
359+
- One at the `Price` with the assigned `Power`.
360+
- One at `Price + Deviation` with the assigned `Power`.
361+
- One at `Price - Deviation` with the assigned `Power`.
362+
363+
4. Calculating Weight Median
364+
365+
- Compute the weighted median of the generated points to determine the final aggregated price.
366+
- The weighted median price is the price at which the cumulative power (sorted by increasing price) crosses half of the total weighted power.
367+
368+
**Example**
369+
370+
Input
371+
372+
```
373+
PriceFeedInfos = [
374+
{Price=100, Deviation=5, Power=16, Timestamp=2024-05-23 12:00:00},
375+
{Price=105, Deviation=3, Power=16, Timestamp=2024-05-23 12:05:00},
376+
{Price=110, Deviation=2, Power=16, Timestamp=2024-05-23 12:10:00},
377+
{Price=120, Deviation=1, Power=16, Timestamp=2024-05-23 12:15:00},
378+
]
379+
```
380+
381+
Procedure
382+
383+
1. Order the List:
384+
385+
```
386+
PriceFeedInfos = [
387+
{Price=120, Deviation=1, Power=16, Timestamp=2024-05-23 12:15:00},
388+
{Price=110, Deviation=2, Power=16, Timestamp=2024-05-23 12:10:00},
389+
{Price=105, Deviation=3, Power=16, Timestamp=2024-05-23 12:05:00},
390+
{Price=100, Deviation=5, Power=16, Timestamp=2024-05-23 12:00:00},
391+
]
392+
```
393+
394+
with a total power of 64
395+
396+
2. Applying weight.
397+
398+
- First 1/32 (of 64 = 2) goes to `{Price=120, Deviation=1, Power=2*6=12}`
399+
- Next 1/16 (of 64 = 4) goest to `{Price=120, Deviation=1,Power=4*4=16}`
400+
- Next 1/8 (of 64 = 8) goes to `{Price=120, Deviation=1, Power=8*2=16}`
401+
- Next 1/4 (of 64 = 16) goes to
402+
```
403+
{Price=120, Deviation=1, Power=2*1.1=2.2}
404+
{Price=110, Deviation=2, Power=14*1.1=15.4}
405+
```
406+
- The Remaining `{Price=110, Deviation=2, Power=2*1=2}`
407+
- The remaining power for all subsequent segments is 1.
408+
409+
3. Generating Points
410+
411+
There will be the following:
412+
413+
```
414+
[{Price=120, Power=12}, {Price=119, Power=12}, {Price=121, Power=12},
415+
{Price=120, Power=16}, {Price=119, Power=16}, {Price=121, Power=16},
416+
{Price=120, Power=16}, {Price=119, Power=16}, {Price=121, Power=16},
417+
{Price=120, Power=2.2}, {Price=119, Power=2.2}, {Price=121, Power=2.2},
418+
{Price=110, Power=15.4}, {Price=108, Power=15.4}, {Price=112, Power=15.4},
419+
...,
420+
{Price=105, Power=16}, {Price=102, Power=16}, {Price=108, Power=16}
421+
{Price=100, Power=16}, {Price=95, Power=16}, {Price=105, Power=16}]
422+
```
423+
424+
4. Calculating Weight Median
425+
426+
Points and Weights are
427+
```
428+
(95,16),(100,16),(102,16),(105,32),(108,33.6),(110,17.6),(112,17.6),
429+
(119,46.4),(120,46.4),(121,46.4)(95,16),(100,16),(102,16),(105,32),
430+
(108,33.6),(110,17.6),(112,17.6),(119,46.4),(120,46.4),(121,46.4)
431+
```
432+
433+
Finding the weighted median at Price=110
434+
319435
### Update supported feeds
320436

321437
At every `BlocksPerFeedsUpdate` block(s), the supported feeds will be re-calculated based on the parameters of the module (e.g. `MinInterval`, `MaxSupportedFeeds`).

0 commit comments

Comments
 (0)