ERROR! The max exposure is too high
-
@support
After I tested my strategy,
I got the warnings below:
It stated that:- WARNING! The kind of the data and the output are different.
The kind of the data is None and the kind of the output is stocks_s&p500
The output will be cleaned with the data kind. - ERROR! The max exposure is too high.
Max exposure: [0.05555556 0.05555556 0.05555556 ... 0.05882353 0.05882353 0.05882353] Hard limit: 0.1
Use qnt.output.cut_big_positions() or normalize_by_max_exposure() to fix.
Do I need to fix the exposure? Exposure of 0.0588 is below the hard limit 0.1, so it seems that I don't need to decrease the current weights. Am I correct?
BTW, can I just ignore the warning " WARNING! The kind of the data and the output are different." ?
I don't know what should I fix according to this warning. - WARNING! The kind of the data and the output are different.
-
This post is deleted! -
@omohyoid Hello.
1. Check which dataset you're loading
You might have loaded
stocks_nasdaq100
, but are checking it as if it werestocks_s&p500
.Incorrect:
import qnt.data as qndata import qnt.ta as qnta import qnt.stats as qnstats import qnt.output as qnout import xarray as xr data = qndata.stocks.load_ndx_data(min_date="2005-06-01") qnout.check(weights, data, kind="stocks_s&p500")
Correct:
data = qndata.stocks.load_spx_data(min_date="2005-06-01") qnout.check(weights, data, kind="stocks_s&p500")
️
kind
must match the actual dataset being used, otherwise some checks (e.g., liquidity or available dates) will not behave correctly.
2. Handling Exposure
If your exposure does exceed the limit on some days, you can fix it using one of the following methods (see the documentation — Applying Exposure Filters:
import qnt.output as qnout import qnt.exposure as qnexp weights_1 = qnexp.cut_big_positions(weights=weights, max_weight=0.049) weights_2 = qnexp.drop_bad_days(weights=weights, max_weight=0.049) weights_3 = qnexp.normalize_by_max_exposure(weights, max_exposure=0.049) weights_4 = qnout.clean(weights, data, "stocks_s&p500")
3. Use
clean()
instead ofcheck()
for auto-correctionIf you want the system to automatically fix issues like exposure or normalization, replace
check()
withclean()
:import qnt.output as qnout weights = qnout.clean(weights, data, "stocks_s&p500")
Exposure of 0.0588 is below the hard limit of 0.1, so in this particular case, it does not violate any constraints. The error may have been triggered by other days or higher values elsewhere in the data — it's worth double-checking.
-
This script provides valuable insights into portfolio optimization, especially for managing exposure limits. Thank you for sharing! To address the max exposure error, consider adjusting the optimization parameters, reducing position sizes, or exploring alternative asset allocation strategies. qnt.output.cut_big_positions() is a good suggestion, and perhaps also tweaking risk tolerance settings.
-
@vyacheslav_b Thanks for ur help!
- I checked my code, and I found that I loaded the data by using load_spx_data() instead of load_ndx_data()
But I added the next trading date to the original data in order to write the latest weight. Does this operation cause the warning? - I checked the dataframe of the final weights, and I use the MAX() and the MIN() in excel to check the maximum and the minimum value of the weights, the maximum weight is 0.05, and the minimum weight is -0.05, which is different from the value 0.05882353 showing on the screen.
- I checked my code, and I found that I loaded the data by using load_spx_data() instead of load_ndx_data()
-
@support,
Either something about the exposure calculation is wrong or I really need clarification on the rules. About the position limit I only find rule 7. o. in the contest rules which states "The evaluation system limits the maximum position size for a single financial instrument to 10%"I always assumed this would mean the maximum weight for an asset would be 0.1 meaning 10 % of the portfolio. However the exposure calculation suggests the following:
Either we trade no asset or at least 10 assets per trading day, regardless of the actual weights assigned to each asset.Consider this example:
import qnt.data as qndata import qnt.output as qnout from qnt.filter import filter_sharpe_ratio data = qndata.stocks.load_spx_data(min_date="2005-01-01") weights = data.sel(field='is_liquid').fillna(0) weights *= filter_sharpe_ratio(data, weights, 3) * .01 # assign 1 % to each asset using the top 3 assets by sharpe qnout.check(weights, data, "stocks_s&p500")
which results in an exposure error:
Check max exposure for index stocks (nasdaq100, s&p500)… ERROR! The max exposure is too high. Max exposure: [0. 0. 0. ... 0.33333333 0.33333333 0.33333333] Hard limit: 0.1 Use qnt.output.cut_big_positions() or normalize_by_max_exposure() to fix.
even though the maximum weight per asset is only 0.01
abs(weights).values.max() 0.01
(By the way, the 4 functions mentioned by @Vyacheslav_B also result in weights which dont't pass the exposure check when used with this example, except
drop_bad_days
which results in empty weights.)And if we assign 100 % to every liquid asset, the exposure check passes:
weights = data.sel(field='is_liquid').fillna(0) qnout.check(weights, data, "stocks_s&p500")
Check max exposure for index stocks (nasdaq100, s&p500)… Ok.
So, does rule 7. o. mean we have to trade at least 10 assets or none at all each trading day to satisfy the exposure check?
-
This post is deleted! -
@antinomy Hi,
You are absolutely correct, we will fix check() function ASAP. It should only cut weights which exceed 0.1 allocation by asset, and normalize the sum of allocation to maximum 1, on every timestamp. If sum was < 1, and weight of an asset < 0.1, the output remains the same.
Thanks a lot for pointing this out with examples.