fix(backtest): guard zero cost_ratio in _get_buy_amount_by_cash_limit - #2324
Open
mateosandoval10 wants to merge 1 commit into
Open
fix(backtest): guard zero cost_ratio in _get_buy_amount_by_cash_limit#2324mateosandoval10 wants to merge 1 commit into
mateosandoval10 wants to merge 1 commit into
Conversation
`Exchange._get_buy_amount_by_cash_limit` computes the cash level at which the
proportional fee overtakes `min_cost`:
critical_price = self.min_cost / cost_ratio + self.min_cost
`cost_ratio` is `open_cost + impact_cost`, and `impact_cost` defaults to 0.0, so
any backtest configured with `open_cost=0` raises ZeroDivisionError as soon as a
buy order exceeds available cash — the branch that calls this helper. Setting
`min_cost=0` as well does not help, since 0.0 / 0.0 raises too.
A zero-cost run is a routine baseline for isolating how much of a strategy's
result is being consumed by frictions, and it currently crashes.
When there is no proportional fee the service fee is always `min_cost`, so no
critical price exists and the min_cost branch is the correct one. Returning it
directly keeps every non-zero `cost_ratio` path byte-identical.
Adds unit tests over the default fee schedule, the above/below critical-price
branches, zero cost_ratio with and without min_cost, and cash below min_cost.
Author
|
@microsoft-github-policy-service agree |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Exchange._get_buy_amount_by_cash_limitraisesZeroDivisionErrorwhenever the backtest is configured without a proportional trading fee.The helper works out the cash level at which the proportional fee overtakes the flat
min_costfloor:cost_ratioisopen_cost + adj_cost_ratio, andadj_cost_ratioderives fromimpact_cost, which defaults to0.0. SoExchange(open_cost=0, close_cost=0)makescost_ratioexactly zero and the division raises. Settingmin_cost=0as well does not help —0.0 / 0.0raises too.When there is no proportional fee the service fee is always
min_cost, so no critical price exists and themin_costbranch is already the correct answer. This PR returns it directly, which leaves every non-zerocost_ratiopath byte-identical:Motivation and Context
No related issue — found while reading the backtest cost model.
The helper is reached from the buy branch of
_calc_trade_info_by_orderwhen an order is larger than the available cash:With
cost_ratio == 0that condition reduces tocash < trade_val + min_cost, the ordinary "order doesn't quite fit in the account" case — so the crash fires on the first partially-funded buy rather than in some corner of the parameter space.A zero-cost run is a routine baseline: it is how you separate how much of a strategy's result comes from the signal and how much is being consumed by frictions. That configuration currently cannot complete a backtest.
Minimal reproduction:
How Has This Been Tested?
pytest qlib/tests/test_all_pipeline.pyunder upper directory ofqlib.I was not able to run
test_all_pipeline.py, since it needs the official dataset that the README notes is currently disabled. Happy to run it if there is a data source you would like me to use.Added
tests/backtest/test_exchange_cost.py— five unit tests, no data dependency:cost_ratiowith a non-zeromin_cost,cost_ratiowithmin_cost=0, where the full balance is investable,min_cost, which buys nothing.Screenshots of Test Results (if appropriate):
Pipeline test: not run — see above.
Your own tests:
Against unpatched
mainthe two zero-cost_ratiotests fail withZeroDivisionErrorand the other three pass, which confirms the existing behaviour is unchanged:black . -l 120 --check --exclude qlib/_version.pyis clean across the repository (334 files unchanged).Types of changes