Skip to content
This repository has been archived by the owner on Sep 17, 2021. It is now read-only.

vNext Feature Request: Moving Average Price Feed Data #31

Open
MicahZoltu opened this issue May 25, 2019 · 3 comments
Open

vNext Feature Request: Moving Average Price Feed Data #31

MicahZoltu opened this issue May 25, 2019 · 3 comments

Comments

@MicahZoltu
Copy link

A dapp wanting to know the approximate price of an asset can get the current exchange rate from Uniswap pretty easily. The problem is that someone can move the price reported by Uniswap at relatively little cost (0.6%) by sandwiching the price read transaction with a large Uniswap buy and a large Uniswap sell. This will cause the price to move up dramatically, followed by the price read, followed by restoring the price to its original level.

In order for Uniswap to be used as an Oracle, it needs to be sufficiently expensive to manipulate the current price reported by Uniswap. To achieve this, we can do a simple moving average or an exponential moving average of the price over time that can then be queried externally. This price will be "delayed" a bit, in the sense that it is more of a rough guess of about what the price is right now rather than an exact value, but for many tools that need an oracle this is sufficient. Manipulating it becomes much more expensive because in order to manipulate the price you must do so you must fight against arbitrageurs who are arbitraging your manipulated price back into line with everything else.

1 Hour Exponential Moving Average (EMA)

Every time someone buys or sells some particular asset, the EMA is updated like so:

const secondsSinceLastUpdate = now() - this.lastUpdateTimestamp
const historicWeight = Max(3600 - secondsSinceLastUpdate, 0)
const currentWeight = Min(secondsSinceLastUpdate, 3600)
this.ema = this.ema * historicWeight / 3600 + getCurrentPrice() * currentWeight / 3600
this.lastUpdateTimestamp = now()
executeTrade(...)

You would apply the same basic formula, just without the state updates or the executeTrade line anytime someone queried for the EMA.

Simple Moving Average (SMA) With 1 Hour Buckets

Every time someone buys or sells some particular asset, the SMA is updated like so:

const secondsSinceLastUpdate = now() - this.lastUpdateTimestamp
const secondsSinceBeginningOfHour = now() - now() % 3600
const historicWeight = Max(secondsSinceBeginningOfHour - secondsSinceLastUpdate, 0)
const currentWeight = Max(secondsSinceLastUpdate, secondsSinceBeginningOfHour)
this.sma = this.sma * historicWeight / secondsSinceBeginningOfHour + getCurrentPrice() * currentWeight / secondsSinceBeginningOfHour
this.lastUpdateTimestamp = now()
executeTrade(...)

Note: The current bucket should probably not be used for an oracle because at the beginning of the hour it is very cheap to manipulate, compared to the end of the hour.

The SMA version has the advantage of the cost of manipulation being higher because there are no points during the time period where manipulation is cheaper, it is expensive anytime during the hour. However, it has the disadvantage of being only reliable for historic hours (previous period), since the current hour will start off heavily manipulable.

The EMA version has the advantage of being continuous, it is always up to date and able to be used as an oracle at any time, and will trail the actual price closer than SMA. However, it has the disadvantage of manipulation being notably cheaper if done during the most recent minutes. For example, if you can control the price for a couple of blocks (e.g. buying blocks) you can have a fairly large impact on the EMA feed price since it weighs recent prices heavier than historic prices.

@moodysalem
Copy link

Can a price oracle like this easily be built on top of Uniswap V1 via permissionless checkpointPrice(address token) method, or does its reliability depend on the volume of each trade, i.e. the effective price of each trade?

I would also like to see a mechanism like this that measures price volatility, which is important in pricing derivatives like options

@MicahZoltu
Copy link
Author

@moodysalem It requires being built into the contracts because you need to update the data every block that contains a Uniswap transaction.

@MicahZoltu
Copy link
Author

I also have a desire for volatility tracking (likely for the same reasons). I don't think there has been discussion on how to extract such information though.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants