Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Large fluctuations in the present value #588

Closed
jalextowle opened this issue Sep 25, 2023 · 1 comment
Closed

Large fluctuations in the present value #588

jalextowle opened this issue Sep 25, 2023 · 1 comment
Assignees
Labels
bug Something isn't working question Further information is requested

Comments

@jalextowle
Copy link
Contributor

jalextowle commented Sep 25, 2023

While I was working on path independence tests in #537, I wrote an improved version of the present value tests. The following test requires an extremely high tolerance and still fails occasionally. There may be problems with the testing methodology that is leading to these failures, but it seems real enough to warrant investigation:


    function test_present_value(bytes32 __seed) external {
        // TODO: This seems a little high, but is fine considering the size of
        // the pool. This is something to investigate further with different
        // contribution sizes.
        uint256 tolerance = 1_000_000e18;

        // Set the seed.
        _seed = __seed;

        // Initialize the pool.
        initialize(alice, 0.02e18, 500_000_000e18);

        // Execute a series of random open trades. We ensure that the present
        // value stays within a given tolerance.
        uint256 nextPresentValue;
        uint256 currentPresentValue = HyperdriveUtils.presentValue(hyperdrive);
        uint256 maturityTime0 = hyperdrive.maturityTimeFromLatestCheckpoint();
        Trade[] memory trades0 = randomOpenTrades();
        for (uint256 i = 0; i < trades0.length; i++) {
            executeTrade(trades0[i]);
            nextPresentValue = HyperdriveUtils.presentValue(hyperdrive);
            assertApproxEqAbs(nextPresentValue, currentPresentValue, tolerance);
            currentPresentValue = nextPresentValue;
        }

        // Time passes and interest accrues.
        {
            uint256 timeDelta = uint256(seed()).normalizeToRange(0, POSITION_DURATION.mulDown(0.99e18));
            int256 variableRate = int256(uint256(seed())).normalizeToRange(-0.1e18, 2e18);
            advanceTime(timeDelta, variableRate);
        }

        // Execute a series of random open trades. We ensure that the present
        // value stays within a given tolerance.
        currentPresentValue = HyperdriveUtils.presentValue(hyperdrive);
        uint256 maturityTime1 = hyperdrive.maturityTimeFromLatestCheckpoint();
        Trade[] memory trades1 = randomOpenTrades();
        for (uint256 i = 0; i < trades1.length; i++) {
            executeTrade(trades1[i]);
            nextPresentValue = HyperdriveUtils.presentValue(hyperdrive);
            assertApproxEqAbs(nextPresentValue, currentPresentValue, tolerance);
            currentPresentValue = nextPresentValue;
        }

        // Construct a set of close trades.
        Trade[] memory closeTrades;
        {
            Trade[] memory closeTrades0 = randomCloseTrades(
                maturityTime0,
                hyperdrive.balanceOf(
                    AssetId.encodeAssetId(AssetId.AssetIdPrefix.Long, maturityTime0),
                    alice
                ),
                maturityTime0,
                hyperdrive.balanceOf(
                    AssetId.encodeAssetId(
                        AssetId.AssetIdPrefix.Short,
                        maturityTime0
                    ),
                    alice
                )
            );
            Trade[] memory closeTrades1 = randomCloseTrades(
                maturityTime1,
                hyperdrive.balanceOf(
                    AssetId.encodeAssetId(AssetId.AssetIdPrefix.Long, maturityTime1),
                    alice
                ),
                maturityTime1,
                hyperdrive.balanceOf(
                    AssetId.encodeAssetId(
                        AssetId.AssetIdPrefix.Short,
                        maturityTime1
                    ),
                    alice
                )
            );
            closeTrades = combineTrades(closeTrades0, closeTrades1);
        }

        // Execute a series of random close trades. We ensure that the present
        // value stays within a given tolerance.
        currentPresentValue = HyperdriveUtils.presentValue(hyperdrive);
        for (uint256 i = 0; i < closeTrades.length; i++) {
            executeTrade(closeTrades[i]);
            nextPresentValue = HyperdriveUtils.presentValue(hyperdrive);
            assertApproxEqAbs(nextPresentValue, currentPresentValue, tolerance);
            currentPresentValue = nextPresentValue;
        }
    }

A helper function that needs to be implemented for this to work is:

    function combineTrades(
        Trade[] memory a,
        Trade[] memory b
    ) internal returns (Trade[] memory result) {
        result = new Trade[](a.length + b.length);

        uint256 aIdx = 0;
        uint256 bIdx = 0;
        for (uint256 i = 0; i < result.length; i++) {
            if (aIdx >= a.length) {
                result[i] = b[bIdx++];
            } else if (bIdx >= b.length) {
                result[i] = a[aIdx++];
            } else if (uint256(seed()) % 2 == 0) {
                result[i] = a[aIdx++];
            } else {
                result[i] = b[bIdx++];
            }
        }
    }
@jalextowle jalextowle added bug Something isn't working question Further information is requested labels Sep 25, 2023
@jalextowle jalextowle self-assigned this Sep 25, 2023
@jalextowle
Copy link
Contributor Author

Closing this because this was addressed by #688.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working question Further information is requested
Projects
None yet
Development

No branches or pull requests

1 participant