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

add relative tolerance to allocate outlay check #430

Merged
merged 1 commit into from
Dec 1, 2023

Conversation

0xEljh
Copy link
Contributor

@0xEljh 0xEljh commented Nov 29, 2023

This PR is to address issues #376 #416 and #368 where the use of non-integer positions and floating point errors result in the np.isclose condition of allocate in SecurityBase to fail to be met, resulting in the "Potentially infinite loop detected..." error being thrown.

def allocate(self, amount, update=True):

       ...

        if not q == -self._position:
            full_outlay, _, _, _ = self.outlay(q)

            ...

            while not np.isclose(full_outlay, amount, rtol=TOL) and q != 0:
                dq_wout_considering_tx_costs = (full_outlay - amount) / (self._price * self.multiplier)
                q = q - dq_wout_considering_tx_costs

                ...

                i = i + 1
                if i > 1e4:
                    raise Exception(
                        "Potentially infinite loop detected. This occurred "
                        "while trying to reduce the amount of shares purchased"
                        " to respect the outlay <= amount rule. This is most "
                        "likely due to a commission function that outputs a "
                        "commission that is greater than the amount of cash "
                        "a short sale can raise."
                    )

As described in #368 and #416, setting rtol to a non-zero, minuscule value like rtol=1e-14 addresses this issue, though in my experience with this error, it sometimes needs to be relaxed up to rtol=1e12.

I think setting rtol=TOL where TOL=1e-16 as per its use in is_zero is a good first step towards resolving this issue.

def is_zero(x):
    """
    Test for zero that is robust against floating point precision errors
    """
    return abs(x) < TOL

The global value for TOL = 1e-16 is never used anywhere else and is perhaps best also applied here since they are both floating point issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants