the calculation of the channel following is complex having multiple exponents and negative signs giving these equation to calculate the channel following
focusing on normalizationFactor and the trend normalizationFactor is a sum of channels + trend (incase of scalar not vector)
this leads to negative value arise as normalizationFactor > every (channel[i] + trend][i])
incase of a vector kappa there is a guard require to insure no negative values appear in newWeights
File: ChannelFollowingUpdateRule.sol
225:
226: if (locals.kappa.length == 1) {
227: locals.normalizationFactor /= int256(locals.prevWeightLength);
228: for (locals.i = 0; locals.i < locals.prevWeightLength; ) {
229: newWeightsConverted[locals.i] =
230: _prevWeights[locals.i] +
231: locals.kappa[0].mul(locals.signal[locals.i] - locals.normalizationFactor);
232:
233: unchecked {
234: ++locals.i;
235: }
236: }
237: } else {
238: for (locals.i = 0; locals.i < locals.kappa.length; ) {
239: locals.sumKappa += locals.kappa[locals.i];
240: unchecked {
241: ++locals.i;
242: }
243: }
244:
245: locals.normalizationFactor = locals.normalizationFactor.div(locals.sumKappa);
246: for (locals.i = 0; locals.i < locals.prevWeightLength; ) {
247: int256 weightUpdate = locals.kappa[locals.i].mul(locals.signal[locals.i] - locals.normalizationFactor);
248: newWeightsConverted[locals.i] = _prevWeights[locals.i] + weightUpdate;
249:@> require(newWeightsConverted[locals.i] >= 0, "Invalid weight");
function testCorrectWeightsWithHigherPricesNegativeWeights() public {
int256[][] memory parameters = new int256[][]();
parameters[0] = new int256[]();
parameters[0][0] = PRBMathSD59x18.fromInt(200);
parameters[1] = new int256[]();
parameters[1][0] = 0.5e18;
parameters[2] = new int256[]();
parameters[2][0] = 0.1e18;
parameters[3] = new int256[]();
parameters[3][0] = PRBMathSD59x18.fromInt(3);
parameters[4] = new int256[]();
parameters[4][0] = PRBMathSD59x18.fromInt(1);
parameters[5] = new int256[]();
parameters[5][0] = 0.5e18;
parameters[6] = new int256[]();
parameters[6][0] = PRBMathSD59x18.fromInt(1);
int256[] memory prevAlphas = new int256[]();
prevAlphas[0] = PRBMathSD59x18.fromInt(1);
prevAlphas[1] = PRBMathSD59x18.fromInt(2);
int256[] memory prevMovingAverages = new int256[]();
prevMovingAverages[0] = PRBMathSD59x18.fromInt(3);
prevMovingAverages[1] = PRBMathSD59x18.fromInt(4);
int256[] memory movingAverages = new int256[]();
movingAverages[0] = PRBMathSD59x18.fromInt(3);
movingAverages[1] = PRBMathSD59x18.fromInt(4);
int128[] memory lambdas = new int128[]();
lambdas[0] = int128(0.9e18);
int256[] memory prevWeights = new int256[]();
prevWeights[0] = 0.005e18;
prevWeights[1] = 0.995e18;
int256[] memory data = new int256[]();
data[0] = PRBMathSD59x18.fromInt(5);
data[1] = PRBMathSD59x18.fromInt(6);
int256[] memory expectedResults = new int256[]();
expectedResults[0] = -0.007719543735408600e18;
expectedResults[1] = 1.007719543735408600e18;
mockPool.setNumberOfAssets(2);
rule.initialisePoolRuleIntermediateValues(
address(mockPool),
prevMovingAverages,
prevAlphas,
mockPool.numAssets()
);
rule.CalculateUnguardedWeights(prevWeights, data, address(mockPool), parameters, lambdas, movingAverages);
int256[] memory resultWeights = rule.GetResultWeights();
checkResult(resultWeights, expectedResults);
}