# How does oracle contract calculate UOS conversion rate

On-chain UOS conversion oracle contract is required to process conversion rates from multiple possible registered exchanges and needs to provide accurate information and on top of that needs to be resilient to gaps in data and potential deviation.

## Updating `feeddata`

of associated exchange

When `pushrate`

action is executed the oracle will update the `feeddata`

table to add the new rate pushed by the exchange to the cache. Each exchange has a dedicated cache for rates which is later used for calculating the moving averages.

## Calculating moving average for `finalrates`

table

When UTC minute changes (so 60 seconds have passed) the oracle will finalize the accumulated rates when the next `pushrate`

occurs.

During the finalization process the oracle will perform outlier detection for the rates received from exchanges and will calculate the weighted average based on the 24 hours trading volume of each exchange. Calculated value in this way is considered a 1 minute moving average and is inserted into the `finalrates`

table for level 1 (minutes) and will update the `rolling_moving_average`

stored there.

Oracle utilizes median absolute deviation algorithm to detect and reject outliers from the available set of conversion rates from different exchanges.

Another finalization step occurs at the end of each UTC hour and day. The oracle will use the moving average stored in `rolling_moving_average`

for level 1 (minutes) of `finalrates`

table to update the level 2 (hours) of `finalrates`

table each hour. And it will do a similar update between level 2 (hours) and level 3 (days) at the end of each day. In the process the rates and `rolling_moving_average`

of the `finalrates`

table will be update.

For each exchange oracle stores 2 sets of 60 seconds worth of conversion rates. After the finalization the `feeddata`

table will be updated to delete the oldest set of rates (located at the bottom half of the 120 elements array).

## Updating moving averages stored in `finalaverage`

table

During each finalization step done by the oracle (either for minutes, hours or days levels) the oracle will additionally update moving averages stored in `finalaverage`

table at the associated level. This means that when level 1 of `finalrates`

is updated the `finalaverage`

table at the scope of `MINUTES`

will also be updated. Similar for 2 - `HOURS`

and 3 - `DAYS`

.

## Handling gaps in data

In case there were no rates provided to the oracle contract the next time any rate appears from any of the exchanges the oracle will perform the calculations based on the available rates only. In case there is not enough rates to calculate the 1 minute average - it will be skipped. Similar thing is done for hours and days - in case there is a large gap in data the moving averages will be left unchanged.

You can utilize the timestamp to figure out how old the moving average is and whether you can consider it up-to-date or outdated. For more details see this section

## Updating seconds moving averages on demand

To trigger the update it is necessary to manually execute the `calcsecma`

action.

When the action is executed it will retrieve the most recent rates from the `feeddata`

table for all exchanges, will perform outlier detection and will calculate the weighted average based on the 24 hours trading volume for each exchange. This step is done for multiple `feeddata`

entries based on the window size of the moving average that is updated.

After the update the moving average stored at the `SECONDS`

level of the `finalaverage`

table will be updated.