@antinomy
Hi! Don’t worry about leverage — it isn’t allowed on the Quantiacs platform: all user-supplied weights are automatically normalized when your strategy is saved. Here’s how that works with two instruments.
Source code of the normalize function https://github.com/quantiacs/toolbox/blob/main/qnt/output.py:
def normalize(output, per_asset=False):
from qnt.data.common import ds
output = output.where(np.isfinite(output)).fillna(0)
if ds.TIME in output.dims:
output = output.transpose(ds.TIME, ds.ASSET)
output = output.loc[
np.sort(output.coords[ds.TIME].values),
np.sort(output.coords[ds.ASSET].values)
]
if per_asset:
output = xr.where(output > 1, 1, output)
output = xr.where(output < -1, -1, output)
else:
s = abs(output).sum(ds.ASSET)
if ds.TIME in output.dims:
s[s < 1] = 1
else:
s = 1 if s < 1 else s
output = output / s
try:
output = output.drop_vars(ds.FIELD)
except ValueError:
pass
return output
Example with two assets
import xarray as xr
from qnt.data.common import ds
from qnt.output import normalize
times = ['2025-06-16']
assets = ['Asset1', 'Asset2']
out1 = xr.DataArray([[1.5, 0.5]],
coords={ds.TIME: times, ds.ASSET: assets},
dims=[ds.TIME, ds.ASSET])
print(normalize(out1).values)
out2 = xr.DataArray([[0.3, -0.2]],
coords={ds.TIME: times, ds.ASSET: assets},
dims=[ds.TIME, ds.ASSET])
print(normalize(out2).values)
Console output
[[0.75 0.25]]
[[ 0.3 -0.2 ]]
Example 1: The absolute exposure is 2 > 1, so every weight is divided by 2, yielding 0.75 and 0.25.
Example 2: The exposure is 0.5 < 1, so the scaling factor is set to 1 and the weights stay 0.3 and –0.2.
In short, even if your strategy outputs more than 100 % exposure, normalize
always scales it back so the total absolute exposure never exceeds 1—preventing leverage on the Quantiacs platform.