-
Notifications
You must be signed in to change notification settings - Fork 1
Home
Welcome to the set-protocol-strategies wiki!
The Strategies repo contains information about Set Protocol’s Smart Contract Managed Rebalancing Sets and any supporting smart contracts (i.e. oracles). Smart Contract Managed Rebalancing Sets are tokenized portfolio management strategies, built as an extension to Set Protocol. Rebalancing Sets enable strategies to be programmed into ERC20 compliant tokens. For the end user, no action is required to have underlying allocations periodically updated based on the predefined strategy. Anyone with an Ethereum public/private key pair can create, issue, redeem, purchase, and rebalance a Rebalancing Set. To learn more about Managed Sets, see the whitepaper here.
Each Smart Contract Managed Rebalancing Set system is made of three distinct parts: 1) Manager Contract that generates rebalancing proposals based off on-chain data, 2) Oracles that are used to provide data to the Manager Contract and, 3) the Rebalancing Set Token that stores state (balances, allocations, etc.) regarding the strategy.
The implementation of this system follows the same general pattern for all Smart Contract Managed Rebalancing Sets with some differences based on strategies (see specific strategy implementations below):
- Manager checks that enough time has passed since last rebalance and that there isn’t a new proposal currently under way.
- Manager queries its respective Oracles and determines whether price triggers have been met for a new rebalance
- Manager selects new allocations for the strategy (represented by Set Tokens) by either creating a new Set Token or selecting between previously created Set Tokens.
- Manager calculates auction parameters based off the difference in value between the old collateral and new collateral. 5.Manager sends proposal to Rebalancing Set Token which puts Rebalancing Set Token into Proposal state and starts the countdown to the beginning of the auction.
Currently all of Set’s oracles are in one way or another reliant on oracles used by MakerDAO (Maker) to secure their system, at present Set uses WETH and WBTC oracles deployed by Maker. Set uses Maker’s Oracles in two ways, 1) to read current price data for use in the Manager contracts and 2) to log data for use in “Meta” oracles that use historic price data to calculate various price indicators used in the Manager contracts.
At a high level, Maker’s oracles (also known as medianizer
) read from a set of approved price feeds and choose the median price from those feeds. Price feeds are meant to be updated 1) when the source price feed is greater than 1% away from current price, or 2) 6 hours has passed since last update. It should be noted, as a consequence, that Maker’s oracles do not provide instantaneous “live” prices and as a result there can be a lag or delay in accounting for price movements in Set’s system. For more on Maker's oracles read here.
Currently, HistoricalPriceFeeds use data from Maker’s oracles to build a price history for the underlying asset, but any oracle adhering to Maker's interface could be used. The HistoricalPriceFeed is intended to represent the historical prices of one asset at consistent time intervals. Additionally there is a defined upper limit to the amount of historical data, after which old data is overwritten. The HistoricalPriceFeed’s functions are as follows:
constructor(uint256 _updateFrequency, address _medianizerAddress, string _dataDescription, uint256[] _seededArray): Upon instantiation the parameters of the price feed are set. The _updateFrequency sets the minimum amount of time allowed to pass between data points and the _medianizerAddress gives what oracle to read data from (thus implying the underlying asset it’s gathering data for). Additionally a _dataDescription is passed so that one can easily tell the parameters of the HistoricalPriceFeed off-chain, and the price feed can be seeded with values in order for immediate use in production.
poke(): Requires lastUpdatedAt + updateFrequency < current block timestamp. Assuming condition is met the underlying oracle’s price is logged and the lastUpdatedAt timestamp is updated. Anyone can call this function to update the HistoricalPriceFeed.
read(uint256 _dataDays): Returns array of _dataDays amount of historical price data. The returned array starts with the most recent price. If not enough data has been logged to satisfy _dataDays then the call will revert.
changeMedianizer(address _newMedianizerAddress): Allow for an update to the underlying medianizer address in case old medianizer is corrupted or not maintained. Only owner of price feed can call.
The MovingAverageOracle leverages data available from the HistoricalPriceFeed to calculate a simple moving average of a desired amount of data points. The MovingAverageOracle’s functions are as follows:
constructor(address _priceFeed, string _dataDescription): Sets the address of the HistoricalPriceFeed to read from and _dataDescription is passed so that one can easily tell the parameters of the MovingAverageOracle off-chain.
read(uint256 _dataPoints): Queries array of data from HistoricalPriceFeed of length _dataPoints and calculates the simple moving average of those data points.
getSourceMedianizer(): Returns the medianizer that the HistoricalPriceFeed underlying the MovingAverageOracle uses.
HistoricalPriceFeed
Network | Address | updateFrequency | Asset | medianizerAddress |
---|---|---|---|---|
Mainnet | 0x7956cE4fbA992987A11bd44ff0Ddb62504711Be8 | Daily | Wrapped Ethereum | 0x729D19f657BD0614b4985Cf1D82531c67569197B |
Kovan | 0x44Fd7B522255d6Ff8DF234488F9031e5c91373d7 | Daily | Wrapped Ethereum | 0x9Fe3077E4468e503a304909B6005E69D5C5B8907 |
MovingAverageOracle
Network | Address | Asset | priceFeedAddress |
---|---|---|---|
Mainnet | 0x90b242eDd278E636E02C2054C861Fd46A7B96271 | Wrapped Ethereum | 0x7956cE4fbA992987A11bd44ff0Ddb62504711Be8 |
Kovan | 0x813F19236b7d241A6a3b42384DEd85bc159549Da | Wrapped Ethereum | 0x44Fd7B522255d6Ff8DF234488F9031e5c91373d7 |
Manager contracts encode the logic for determining new allocations. Each manager has its own little quirks based on the assets and strategies involved but in general maintain a similar proposal process. The steps found in each proposal process can be found below, for some Managers certain parts will be repeated, the math may vary, or additional checks may be required, you can find those deviations illuminated below.
-
Check Rebalancing Set conditions: A user calls the “propose” function on the Manager with the address of the associated Rebalancing Set Token. The Manager validates 1) the rebalanceInterval has elapsed since the last rebalance and 2) that the rebalancing Set address is tracked by Core.
-
Query data from oracles: The Manager pulls the most current price information (represented as an 18 decimal unsigned integer) from its associated oracles.
-
Verify price triggers met: Once the price data has been received, a series of calculations are run to verify that the percent allocations of the current Set are outside the allocation bounds.
-
Determine next allocation: Following the allocation verification, the nextSet is created by determining the units and naturalUnit (for more on unit and naturalUnits see our white paper) required to meet the target allocation. Once this math is completed, the nextSet address to rebalance into is created by calling Core’s external
createSet
function with the SetTokenFactory address. -
Determine proposal parameters: The Manager next calculates the auction price parameters. The auctionTimeToPivot is hard-coded into the contract upon instantiation. The auctionStartPrice and the auctionPivotPrice are determined as a function of the “fair price” of the auction and the auctionTimeToPivot.
fairValue
is the ratio of the total cost of the nextSet to the total cost of the currentSet. If the nextSet is worth $1,500 and the currentSet SetToken is worth $1,200, thenfairValue = 1500 / 1200 = 1.25
.To maintain granularity a
priceDenominator
from the LinearAuctionPriceCurve, is applied to thefairValue
, thus if thepriceDenominator
is1000
,fairValue = 1.25 * 1000 = 1250
.In order to aid price discovery there must be ample granularity in auction prices. Most Managers target 30 minutes spent within every 1% range. Using this target the total price range of the auction is calculated with the formula:
priceRange = (auctionTimeToPivot/THIRTY_MINUTES_IN_SECONDS) * (fairValue/100)
By placing
fairValue
at the center of the range, the auctionStartPrice and the auctionPivotPrice can be calculated. With the returned address from the nextSet creation, all the parameters can be derived for the proposal.
The BTCETHRebalancingManager contains logic for managing rebalances of Sets containing BTC and ETH. These Sets can be used to implement any buy/sell strategy with the two but generally are used for Buy and Hold strategies. Its functions are as follows:
constructor(see params below)
Property | Type | Description |
---|---|---|
_coreAddress | address | Address of Core in the Set Protocol system. |
_btcPriceFeedAddress | address | Address of the MakerDAO Bitcoin-USD medianizer contract. Data from this feed will be used to create the nextSet address, and calculate proposal parameters. |
_ethPriceFeedAddress | address | Address of the MakerDAO Ether-USD medianizer contract. Data from this feed will be used to create the nextSet address, and calculate proposal parameters. |
_btcAddress | address | Address of Wrapped Bitcoin, an ERC20 compliant Bitcoin token, used to create the nextSet during manager proposals. |
_ethAddress | address | Address of Wrapped Ethereum, an ERC20 compliant Ether token, used to create the nextSet during manager proposals. |
_setTokenFactory | address | Address of the SetTokenFactory tracked by Core, which will be used to deploy the nextSet address. |
_auctionLibrary | address | Address of the auction price library to be used for Dutch Auction pricing. The Auction Library must be tracked by Core. |
_auctionTimeToPivot | uint256 | The time in seconds after the auction start time in which the price pivots from a Linear to Exponential curve. The time to pivot must be within the range specified on the Rebalancing Set Token's associated Rebalancing Set Token factory. |
_multipliers | uint256[2] | Token multipliers used to determine relative allocations between Bitcoin and Ether. Target allocation is determined by a simple equation, btcAllocation = btcMultiplier / (btcMultiplier + ethMultiplier) . The input should correspond to [btcMultiplier , ethMultiplier ]. |
_allocationBounds | uint256[2] | Minimum percent deviation from expected allocation before a proposal can be triggered. The input should correspond to [lowerBound, upperBound]. |
propose(address _rebalancingSetTokenAddress): The implementation for propose
is as follows:
-
Check Rebalancing Set conditions: Proceeds as outlined in the above section.
-
Query data from oracles: In this case we query the MakerDAO WBTC and WETH oracles.
-
Verify Price Triggers Met: For the BTCETHRebalancingManager the current USD allocation of BTC is calculated. If the BTC allocation is outside of the allocationBounds defined on contract creation then the rebalance moves forward.
-
Determine next allocation: Following the allocation verification, the nextSet is created by determining the units required to meet the target allocation. In order to simplify the math, the nextSet targets a USD value equal to:
(ethMultiplier + btcMultiplier) * max(ETH price, BTC price)
The units of the more expensive token (“maxToken”) is set to
1 * assetMultiplier
and the other token (“minToken”) units is calculated as the exchange rate of(maxToken/minToken) * assetMultiplier
. Additionally, aDECIMAL_DIFFERENCE_MULTIPLIER
must be applied to the ETH units due to the difference in token decimals between WETH (18) and WBTC (8). The nextSet uses10 ** 10
for a natural unit.In the event that ETH’s price exceeds BTC, a price precision constant (
PRICE_PRECISION
) of100
is multiplied to both units so that there are not big rounding errors for the BTC units. Additionally, the naturalUnit of the resulting nextSet is bumped to10 ** 12
in order to keep it’s dollar valuation close to the currentSet.uint256 nextSetNaturalUnit; uint256[] memory nextSetUnits = new uint256[](2); if (_btcPrice >= _ethPrice) { // Calculate ethereum nextSetUnits, determined by the following equation: // (btcPrice / ethPrice) * (10 ** (ethDecimal - btcDecimal)) uint256 ethUnits = _btcPrice.mul(DECIMAL_DIFF_MULTIPLIER).div(_ethPrice); // Create unit array and define natural unit nextSetUnits[0] = btcMultiplier; nextSetUnits[1] = ethUnits.mul(ethMultiplier); nextSetNaturalUnit = 10 ** 10; } else { // Calculate btc nextSetUnits as (ethPrice / btcPrice) * 100. 100 is used to add // precision. The increase in unit amounts is offset by increasing the // nextSetNaturalUnit by two orders of magnitude so that issuance cost is still // roughly the same uint256 ethBtcPrice = _ethPrice.mul(PRICE_PRECISION).div(_btcPrice); // Create unit array and define natural unit nextSetUnits[0] = ethBtcPrice.mul(btcMultiplier); nextSetUnits[1] = PRICE_PRECISION.mul(DECIMAL_DIFF_MULTIPLIER).mul(ethMultiplier); nextSetNaturalUnit = 10 ** 12; }
Once this math is completed, the nextSet address to rebalance into is created by calling Core’s external
createSet
function with the SetTokenFactory address. -
Determine Proposal Parameters: Proceeds as outlined in the above section.
The BTCDAIRebalancingManager contains logic for managing rebalances of Sets containing BTC and DAI. These Sets can be used to implement any buy/sell strategy with the two but generally are used for Range Bound strategies. Its functions are as follows:
constructor(see below for params):
Property | Type | Description |
---|---|---|
_coreAddress | address | Address of Core in the Set Protocol system. |
_btcPriceFeedAddress | address | Address of the MakerDAO Bitcoin-USD medianizer contract. Data from this feed will be used to create the nextSet address, and calculate proposal parameters. |
_daiAddress | address | Address of Dai, an ERC20 compliant stable token, used to create the nextSet during manager proposals. |
_btcAddress | address | Address of Wrapped Bitcoin, an ERC20 compliant Bitcoin token, used to create the nextSet during manager proposals. |
_setTokenFactory | address | Address of the SetTokenFactory tracked by Core, which will be used to deploy the nextSet address. |
_auctionLibrary | address | Address of the auction price library to be used for Dutch Auction pricing. The Auction Library must be tracked by Core. |
_auctionTimeToPivot | uint256 | The time in seconds after the auction start time in which the price pivots from a Linear to Exponential curve. The time to pivot must be within the range specified on the Rebalancing Set Token's associated Rebalancing Set Token factory. |
_multipliers | uint256[2] | Token multipliers used to determine relative allocations between Bitcoin and Ether. Target allocation is determined by a simple equation, daiAllocation = daiMultiplier / (btcMultiplier + daiMultiplier) . The input should correspond to [daiMultiplier , btcMultiplier ]. |
_allocationBounds | uint256[2] | Minimum percent deviation from expected allocation before a proposal can be triggered. The input should correspond to [lowerBound, upperBound]. |
propose(address _rebalancingSetTokenAddress): The implementation for propose
is as follows:
-
Check Rebalancing Set conditions: Proceeds as outlined in the above section.
-
Query data from oracles: In this case we query the MakerDAO WBTC oracle. Dai is fixed at $1 (represented by a constant
10 ** 18
). -
Verify Price Triggers Met: For the BTCDAIRebalancingManager the current USD allocation of Dai is calculated. If the Dai allocation is outside of the allocationBounds defined on contract creation then the rebalance moves forward. (Note: This means that the allocation lowerBound represents the required BTC price increase to rebalance).
-
Determine next allocation: Following the allocation verification, the nextSet is created by determining the units required to meet the target allocation. In order to simplify the math, the nextSet targets a USD value equal to:
(daiMultiplier + btcMultiplier) * max(Dai price, BTC price)
The units of the more expensive token (“maxToken”) is set to
1 * assetMultiplier * PRICE_PRECISION
and the other token (“minToken”) units is calculated as the exchange rate of(maxToken/minToken) * assetMultiplier * PRICE_PRECISION
(Note:PRICE_PRECISION
is hard-coded to 1). Additionally, aDECIMAL_DIFFERENCE_MULTIPLIER
must be applied to the Dai units due to the difference in token decimals between Dai (18) and WBTC (8). The nextSet uses10 ** 10
for a natural unit.uint256[] memory nextSetUnits = new uint256[](2); uint256 nextSetNaturalUnit = DECIMAL_DIFF_MULTIPLIER.mul(PRICE_PRECISION); if (_btcPrice >= DAI_PRICE) { // Dai nextSetUnits is equal the USD Bitcoin price uint256 daiUnits = _btcPrice.mul(DECIMAL_DIFF_MULTIPLIER).div(DAI_PRICE); // Create unit array and define natural unit nextSetUnits[0] = daiUnits.mul(daiMultiplier).mul(PRICE_PRECISION); nextSetUnits[1] = btcMultiplier.mul(PRICE_PRECISION); } else { // Calculate btc nextSetUnits as (daiPrice/btcPrice)*100. 100 is used to add // precision. uint256 btcDaiPrice = DAI_PRICE.mul(PRICE_PRECISION).div(_btcPrice); // Create unit array and define natural unit nextSetUnits[0] = daiMultiplier.mul(DECIMAL_DIFF_MULTIPLIER).mul(PRICE_PRECISION); nextSetUnits[1] = btcDaiPrice.mul(btcMultiplier); }
Once this math is completed, the nextSet address to rebalance into is created by calling Core’s external
createSet
function with the SetTokenFactory address. -
Determine Proposal Parameters: Proceeds as outlined in the above section.
The ETHDAIRebalancingManager contains logic for managing rebalances of Sets containing ETH and DAI. These Sets can be used to implement any buy/sell strategy with the two but generally are used for Range Bound strategies. Its functions are as follows:
constructor(see below for params):
Property | Type | Description |
---|---|---|
_coreAddress | address | Address of Core in the Set Protocol system. |
_ethPriceFeedAddress | address | Address of the MakerDAO Ethereum-USD medianizer contract. Data from this feed will be used to create the nextSet address, and calculate proposal parameters. |
_daiAddress | address | Address of Dai, an ERC20 compliant stable token, used to create the nextSet during manager proposals. |
_ethAddress | address | Address of Wrapped Ethereum, an ERC20 compliant Ethereum token, used to create the nextSet during manager proposals. |
_setTokenFactory | address | Address of the SetTokenFactory tracked by Core, which will be used to deploy the nextSet address. |
_auctionLibrary | address | Address of the auction price library to be used for Dutch Auction pricing. The Auction Library must be tracked by Core. |
_auctionTimeToPivot | uint256 | The time in seconds after the auction start time in which the price pivots from a Linear to Exponential curve. The time to pivot must be within the range specified on the Rebalancing Set Token's associated Rebalancing Set Token factory. |
_multipliers | uint256[2] | Token multipliers used to determine relative allocations between Bitcoin and Ether. Target allocation is determined by a simple equation, daiAllocation = daiMultiplier / (ethMultiplier + daiMultiplier) . The input should correspond to [daiMultiplier , ethMultiplier ]. |
_allocationBounds | uint256[2] | Minimum percent deviation from expected allocation before a proposal can be triggered. The input should correspond to [lowerBound, upperBound]. |
propose(address _rebalancingSetTokenAddress): The implementation for propose
is as follows:
-
Check Rebalancing Set conditions: Proceeds as outlined in the above section.
-
Query data from oracles: In this case we query the MakerDAO WETH oracle. Dai is fixed at $1 (represented by a constant
10 ** 18
). -
Verify Price Triggers Met: For the ETHDAIRebalancingManager the current USD allocation of Dai is calculated. If the Dai allocation is outside of the allocationBounds defined on contract creation then the rebalance moves forward. (Note: This means that the allocation lowerBound represents the required ETH price increase to rebalance).
-
Determine next allocation: Following the allocation verification, the nextSet is created by determining the units required to meet the target allocation. In order to simplify the math, the nextSet targets a USD value equal to:
(daiMultiplier + ethMultiplier) * max(Dai price, ETH price)
The units of the more expensive token (“maxToken”) is set to
1 * assetMultiplier * PRICE_PRECISION
and the other token (“minToken”) units is calculated as the exchange rate of(maxToken/minToken) * assetMultiplier * PRICE_PRECISION
(Note:PRICE_PRECISION
is hard-coded to100
). The nextSet uses10 ** 10
for a natural unit.uint256[] memory nextSetUnits = new uint256[](2); uint256 nextSetNaturalUnit = PRICE_PRECISION; if (_ethPrice >= DAI_PRICE) { // Dai nextSetUnits is equal the USD Ethereum price uint256 daiUnits = _ethPrice.mul(PRICE_PRECISION).div(DAI_PRICE); // Create unit array and define natural unit nextSetUnits[0] = daiUnits.mul(daiMultiplier); nextSetUnits[1] = ethMultiplier.mul(PRICE_PRECISION); } else { // Calculate dai nextSetUnits as (daiPrice/ethPrice)*100. 100 is used to add // precision. uint256 ethDaiPrice = DAI_PRICE.mul(PRICE_PRECISION).div(_ethPrice); // Create unit array and define natural unit nextSetUnits[0] = daiMultiplier.mul(PRICE_PRECISION); nextSetUnits[1] = ethDaiPrice.mul(ethMultiplier); }
Once this math is completed, the nextSet address to rebalance into is created by calling Core’s external
createSet
function with the SetTokenFactory address. -
Determine Proposal Parameters: Proceeds as outlined in the above section.
The MACOStrategyManager contains logic to execute a moving average crossover (MACO) strategy for any asset. The strategy flips entirely between a volatile asset and a stable asset unlike either ETHDAI or BTCDAI which only reallocate back to a set percentage. Additionally, the proposal process requires two function calls instead of the usual one in order for the signal to be confirmed. Consequently, there will be additional logic required to execute proposals.
** constructor(see below for params):**
Property | Type | Description |
---|---|---|
_coreAddress | address | Address of Core in the Set Protocol system. |
_movingAveragePriceFeed | address | Address of the MovingAverageOracle defined in the previous section. The underlying asset’s oracle can be retrieved from the MovingAverageOracle. |
_stableAssetAddress | address | Address of stable asset used in strategy. Could be Dai, USDC, etc. |
_riskAssetAddress | address | Address of risk asset used in strategy. |
_initialStableCollateralAddress | address | Address of the Set Token representing the strategy’s stable collateral. |
_initialRiskCollateralAddress | address | Address of the Set Token representing the strategy’s risk collateral. |
_setTokenFactory | address | Address of the SetTokenFactory tracked by Core, which will be used to deploy the nextSet address. |
_auctionLibrary | address | Address of the auction price library to be used for Dutch Auction pricing. The Auction Library must be tracked by Core. |
_movingAverageDays | uint256 | The amount of days to use in moving average calculation. |
_auctionTimeToPivot | uint256 | The time in seconds after the auction start time in which the price pivots from a Linear to Exponential curve. The time to pivot must be within the range specified on the Rebalancing Set Token's associated Rebalancing Set Token factory. |
_crossoverConfirmationBounds | uint256[2] | The minimum and maximum time in seconds confirm confirmation can be called after the last initial crossover confirmation. |
initialize(address _rebalancingSetTokenAddress): This function sets the Rebalancing Set Token address that the manager is associated with. This function can only be called once during initialization by the contract deployer, after which no address has the ability to change the Rebalancing Set Token address.
initialPropose(): initialPropose
is called to kick off the rebalance process. If conditions are met, the block time stamp is logged and begins a "confirmation period" where the manager checks to see that the price remains crossed over the moving average. The implementation for initialPropose
is as follows:
-
Check Rebalancing Set conditions: Proceeds as outlined in the above section however a check is made to make sure that the manager is not within
crossoverConfirmationMaxTime
of last successfulinitialPropose
call, without this check someone could continually callinitalPropose
and never allow the manager to create a proposal. -
Query data from oracles: In this case we query the riskAsset's price oracle and the risk asset's MovingAverageOracle associated with the manager. The MovingAverageOracle is queried for the
movingAverageDays
moving average. -
Verify Price Triggers Met: The manager checks to see what collateral the Rebalancing Set is currently using. If currently using risk collateral then checks to see if the risk asset price has crossed below the moving average (and vice versa).
if (usingRiskCollateral()) { // If currently holding risk asset (riskOn) check to see if price is below MA, otherwise revert. require( _movingAveragePrice > _riskAssetPrice, "MACOStrategyManager.checkPriceTriggerMet: Risk asset price must be below moving average price" ); } else { // If currently holding stable asset (not riskOn) check to see if price is above MA, otherwise revert. require( _movingAveragePrice < _riskAssetPrice, "MACOStrategyManager.checkPriceTriggerMet: Risk asset price must be above moving average price" ); }
If price trigger met then
lastCrossoverConfirmationTimestamp
is logged and the manager waits to confirm the signal.
confirmPropose(): confirmPropose
is called to confirm the signal first seen when initialPropose
was called. The crossover must be reconfirmed once between the time frame passed into the manager as _crossoverConfirmationBounds
in the constructor. Once confirmed a proposal will be generated and sent to the Rebalancing Set Token. If the crossover does not reoccur within that time period then initialPropose
must be called to reset the time stamp and restart the proposal process, any confirmPropose
calls before or after the confirmation time period will revert. The implementation for confirmPropose
is as follows:
-
Check Rebalancing Set conditions: Proceeds as outlined in the above section however a check is made to make sure that the manager is currently in a "confirmation period" (
block.timestamp >= lastCrossoverConfirmationTimestamp.add(crossoverConfirmationMinTime) && block.timestamp <= lastCrossoverConfirmationTimestamp.add(crossoverConfirmationMaxTime)
). -
Query data from oracles: In this case we query the riskAsset's price oracle and the risk asset's MovingAverageOracle associated with the manager. The MovingAverageOracle is queried for the
movingAverageDays
moving average. -
Verify Price Triggers Met: See same step in
initialPropose
for logic. -
Determine next allocation:
-
Determine Proposal Parameters: Proceeds mostly outlined in the above section, however due to the more price-sensitive nature of the strategy the auction is sped up to 1% move every 10 minutes. This means that a similar range of prices are explored during the auction (which is generally shorter in duration than the other managers), however this comes with a loss in price granularity. Formula for
priceRange
is as follows:priceRange = (auctionTimeToPivot/TEN_MINUTES_IN_SECONDS) * (fairValue/100)