The Moving Average - EMA

The Moving Average - EMA

A moving average is utilized as a security measure, where sudden changes in the pool reserves can be detected, and prevent abuse of the protocol’s features. The moving average (ema) is updated with the first trade of the block, for any asset according to the following formula:

where r is the spot rate in units of BNT/TKN as determined by the trading liquidity balances of the pool, and α is an arbitrary constant that determines the responsiveness of the moving average. The α term is a global variable, set at 0.2 (or 20%) at launch of Bancor 3, and is intended to provide a consensus rate for the pool that is resistant to virtual price manipulation attacks. The following chart is an arbitrary depiction of the ema behavior relative to the spot price on a per-block basis. The ema is measured and updated before an action is executed; therefore, the ema response is delayed by a minimum of one action (e.g. a trade or add/remove liquidity event). Further, the ema is only adjusted once per pool, per block.

v3.describe()
Trading Liquidity Vault Staking ERC20 Contracts Vortex External Protection Protocol WalletState
0 bnt=60000.000000 bnt=60000.000000 bnbnt=60000.000000 bnt=0.000000 bnt=0.000000 bnbnt=60000.000000
1 bnt=20000.000000 eth=20.000000 eth=101.000000 eth=101.000000 bneth=101.000000 eth=0.000000
2 bnt=20000.000000 wbtc=1.250000 wbtc=101.000000 wbtc=101.000000 bnwbtc=101.000000 wbtc=0.000000
3 bnt=20000.000000 link=3333.333333 link=10001.000000 link=10001.000000 bnlink=10001.000000 link=0.000000
4

At genesis, the ema rate is set equal to the spot rate. Therefore, in the above scenario each of the liquidity pools began with the following rates:

v3.describe(rates=True, decimals=4)
index 0
0 bnt Spot Rate=0.0000, EMA Rate=0.0000
1 eth Spot Rate=1000.0000, EMA Rate=1000.0000
2 wbtc Spot Rate=16000.0000, EMA Rate=16000.0000
3 link Spot Rate=6.0000, EMA Rate=6.0000

However, the trading situations do have an effect. To demonstrate, assume that the trades described above happen on consecutive blocks. For the LINK trading pool, both the spot rate and the ema begin at 6, as set at the genesis of the pool. Since the ema is adjusted before the trade is executed, the first trade has no effect on the ema; the spot price changes as expected. The new spot price becomes relevant in the next block, as the ema is updated prior to performing the second trade. First, the ema is updated using the new spot rate, then the second trade is processed. In this example, the lag of the ema means there is a significant gap between it and the spot price after the first block; however, the adjustment in the second block, prior to executing the second trade, results in a close agreement thereafter.

timestep = v3.timestep

v3.trade(swap_amount=2000, source_token='bnt',  target_token='link', user_name='Trader', timestep=timestep)

v3.describe(rates=True, decimals=4)
index 0
0 bnt Spot Rate=0.0000, EMA Rate=0.0000
1 eth Spot Rate=1000.0000, EMA Rate=1000.0000
2 wbtc Spot Rate=16000.0000, EMA Rate=16000.0000
3 link Spot Rate=7.2513, EMA Rate=6.0000
#TODO: Mark to verify link EMA rate=6.00 (conflicts with doc 5.9998)

v3.trade(swap_amount=302.9981, source_token='link',  target_token='bnt', user_name='Trader', timestep=timestep + 1)

v3.describe(rates=True, decimals=4)
index 0
0 bnt Spot Rate=0.0000, EMA Rate=0.0000
1 eth Spot Rate=1000.0000, EMA Rate=1000.0000
2 wbtc Spot Rate=16000.0000, EMA Rate=16000.0000
3 link Spot Rate=5.9988, EMA Rate=6.0000
v3.trade(swap_amount=1, source_token='eth',  target_token='wbtc', user_name='Trader', timestep=timestep)

v3.describe(rates=True, decimals=4)
index 0
0 bnt Spot Rate=0.0000, EMA Rate=0.0000
1 eth Spot Rate=907.3923, EMA Rate=1000.0000
2 wbtc Spot Rate=17534.2111, EMA Rate=16000.0000
3 link Spot Rate=5.9988, EMA Rate=6.0000