Tokenize a smart contract managed multiple moving average crossover trading strategy with Set Protocol V2 and Uniswap V3 oracles.
npm install @openzeppelin/contracts@3.1.0
npm install @setprotocol/set-protocol-v2
npm install @setprotocol/index-coop-contracts
npm install @uniswap/v3-core
The Indicator
contract utilizes a Uniswap V3 Pool
as an on-chain oracle.
The Manager
contract has two key functions for the Keeper
getIndicatorIsChanged()
, which can be called for free and checks if theIndicator
signal has changed since the last rebalancerebalance()
, which can only be called by theKeeper
and utilizes theTrade Module
to change the allocation of theSet Token
The Keeper
can be set to periodically call getIndicatorIsChanged()
for free, and subsequently call rebalance()
if the indicator signal has changed.
Consider two groups of moving averages: S, a group of n short term moving averages and L, a group of m long term moving averages.
S = [S1, S2, ..., Sn]
L = [L1, L2, ..., Lm]
An indicator MMA() can be constructed as follows
- bullish if min(S) > max(L)
- bearish if max(S) < min(L)
- uncertain otherwise
The uncertain case, when the short term and long term groups of moving averages overlap, can be considered either bullish (risk-on) or bearish (risk-off) depending on manager preference.
This indicator uses a Uniswap V3 pool as on-chain oracle by deriving the arithmetic mean tick over an interval and using that as a moving average. The arithmetic mean tick over a given interval is derived with values stored in the tick accumulator.
With a risk-on asset (ex: $ETH) and a risk-off asset (ex: $USDC) the trading strategy is as follows
- hold $ETH when MMA() using the Uniswap V3 ETHUSDC pool is bullish
- hold $USDC when MMA() using the Uniswap V3 ETHUSDC pool is bearish or uncertain
- Place calls to tradeModule in a more optimal way (reduce slippage)
- Gas optimization in indicator
- Add Aave/Compound lending (wrapModule) to manager