Navigation

    Quantiacs Community

    • Register
    • Login
    • Search
    • Categories
    • News
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    1. Home
    2. Vyacheslav_B
    3. Posts
    V
    • Profile
    • Following 0
    • Followers 0
    • Topics 3
    • Posts 76
    • Best 18
    • Groups 0
    • Blog

    Posts made by Vyacheslav_B

    • RE: ERROR! The max exposure is too high

      @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.

      posted in Support
      V
      Vyacheslav_B
    • RE: ERROR! The max exposure is too high

      @antinomy Hello. If you look at how the function works, it limits exposure based on the invested capital, not the total capital — which is stricter than what's stated in the rules. However, in my opinion, this approach has advantages: strategies end up being more diversified, and you won’t be able to trade with just a few assets.

      posted in Support
      V
      Vyacheslav_B
    • RE: ERROR! The max exposure is too high

      @omohyoid Hi.

      I don’t quite understand why you’re calculating the next trading date manually. According to the documentation and this official example, it works like this:

      Strategy. Weights allocation
      Every day, the algorithm determines how much of each asset should be in the portfolio for the next trading day.
      These are called the portfolio weights.
      A positive weight means you'll be buying that asset, while a negative weight means you'll be selling it.
      These decisions are made at the end of each day and put into effect at the beginning of the next trading day.

      There’s a clear visual example in the notebook showing how this works. So there’s no need to manually add or compute the next date — the platform takes care of that automatically.

      As for the max weights — I didn’t quite understand what the issue is. If you look at the source code of a function like cut_big_positions, you’ll see something like this:

      weights_1 = xr.where(abs(weights) > 0.05, np.sign(weights) * 0.05, weights)
      

      This simply limits all weights that are greater than ±0.05 to exactly ±0.05. So if you’re seeing a value like 0.05882353, it’s likely either before this restriction is applied, or maybe you're looking at a version of the weights before post-processing.

      posted in Support
      V
      Vyacheslav_B
    • RE: Strategy trades illiquid instruments

      @illustrious-felice Hello. The reason you're still seeing a large number of tickers (e.g., around 300) even after applying the filter is that the "best" instrument by Sharpe ratio changes over time. The rank_assets_by function returns a time-dependent mask, selecting the top N assets at each time step. So the total number of unique assets that were selected at any point in time may be much larger than top_assets.

      This is expected behavior.

      To illustrate this more clearly, let's consider a minimal working example that selects only 1 top asset at each point in time and shows all the intermediate steps:

      import qnt.data as qndata
      import qnt.ta as qnta
      import qnt.stats as qnstats
      import qnt.output as qnout
      import qnt.filter as qnfilter
      import xarray as xr
      import pandas as pd
      
      top_assets = 1
      
      data = qndata.stocks.load_spx_data(min_date="2005-06-01")
      weights = data.sel(field="is_liquid")
      
      stats_per_asset = qnstats.calc_stat(data, weights, per_asset=True)
      sharpe_ratio = stats_per_asset.sel(field="sharpe_ratio")
      asset_filter = qnfilter.rank_assets_by(data, sharpe_ratio, top_assets, ascending=False)
      
      weights = weights * asset_filter
      stats = qnstats.calc_stat(data, weights.sel(time=slice("2005-06-01", None)))
      
      display(asset_filter.to_pandas().tail())
      display(stats.to_pandas().tail())
      display(sharpe_ratio.to_pandas().tail())
      display(weights.to_pandas().tail())
      

      If you want to see which asset was the best on specific dates, you can do something like this:

      dates = ["2015-01-15", "2020-01-15", "2025-01-15"]
      records = []
      
      for date_str in dates:
          best_mask = asset_filter.sel(time=date_str)
          assets = best_mask.where(best_mask > 0, drop=True).asset.values
          srs = sharpe_ratio.sel(time=date_str, asset=assets).values
          for a, s in zip(assets, srs):
              records.append({"time": date_str, "asset": a.item(), "sharpe_ratio": float(s)})
      
      df = pd.DataFrame(records).set_index("time")
      display(df)
      
      asset	sharpe_ratio
      time		
      2025-05-22	NYS:HRL	1.084683
      2025-05-22	NAS:KDP	1.093528
      2025-05-22	NAS:AAPL 0.968039
      

      Or simply for a single date:

      date = "2020-05-22"
      best_mask = asset_filter.sel(time=date)
      best_assets = best_mask.where(best_mask > 0, drop=True).asset
      best_sr = sharpe_ratio.sel(time=date, asset=best_assets)
      print(best_sr.to_pandas())
      

      This shows clearly that only one asset is selected at each time step, but over the full time range, many different assets can appear in the top list depending on how their Sharpe ratios change.

      posted in Support
      V
      Vyacheslav_B
    • RE: ERROR! The max exposure is too high

      @omohyoid Hello.

      1. Check which dataset you're loading

      You might have loaded stocks_nasdaq100, but are checking it as if it were stocks_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 of check() for auto-correction

      If you want the system to automatically fix issues like exposure or normalization, replace check() with clean():

      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.

      posted in Support
      V
      Vyacheslav_B
    • RE: toolbox not working in colab

      @alexeigor Hello. Version 0.0.501 of the qnt library works correctly in Colab. Python version support has been extended from 3.10 to 3.13. The basic functionality of the library should work without issues.

      To install, use the following command:

      !pip install git+https://github.com/quantiacs/toolbox.git 2>/dev/null
      

      Note: Installing ta-lib in Colab is not working for me at the moment.

      posted in Support
      V
      Vyacheslav_B
    • RE: AttributeError: module 'qnt.data' has no attribute 'stocks_load_spx_data'

      @nosaai Hi.

      Instructions on how to update the library can be found in the README: https://github.com/quantiacs/toolbox

      Updating the conda environment

      • Regularly update the QNT library for the latest features and fixes:
      ## you can remove the old one before that
          # conda remove -n qntdev quantiacs-source::qnt
      
          conda install -n qntdev quantiacs-source::qnt
      

      Updating the pip environment

      Use this command in your environment to install the latest version from the git repository:

      python -m pip install --upgrade git+https://github.com/quantiacs/toolbox.git
      
      posted in Support
      V
      Vyacheslav_B
    • RE: Q18 Quick start guide not working anymore

      @angusslq Hi. Try cloning the template or restarting JupyterLab. The error was fixed in the new version of the qnt library.

      posted in Support
      V
      Vyacheslav_B
    • RE: Fundamental data loading does not work

      @lookman Hello. Try cloning your strategy and running it again. It should work correctly with the new version of the qnt library.

      import qnt.data as qndata
      import qnt.data.secgov_fundamental as fundamental
      
      market_data = qndata.stocks.load_spx_data(min_date="2005-01-01")
      
      indicators_data = fundamental.load_indicators_for(market_data, indicator_names=['roe'])
      
      display(indicators_data.sel(field="roe").to_pandas().tail(2))
      display(indicators_data.sel(asset='NAS:AAPL').to_pandas().tail(2))
      display(indicators_data.sel(asset=['NAS:AAPL']).sel(field="roe").to_pandas().tail(2))
      

      https://quantiacs.com/documentation/en/data/fundamental.html

      posted in Support
      V
      Vyacheslav_B
    • RE: Struggle creating local dev environment

      @dark-pidgeot Hi! After the release of version qnt “0.0.402” the issue with data loading in the local environment has been resolved. The library now uses newer dependencies, including pandas version 2.2.2.

      posted in Support
      V
      Vyacheslav_B
    • RE: Accessing both market and index data in strategy()

      @buyers_are_back Hello.
      Here is a new example of stock prediction using index data.
      I recommend using the single-pass version.
      https://quantiacs.com/documentation/en/data/indexes.html

      posted in Support
      V
      Vyacheslav_B
    • RE: Acess previous weights

      @blackpearl Hello. I don’t use machine learning in trading, and I don’t have similar examples. If you know Python and know how to develop such systems, or if you use ChatGPT (or similar tools) for development, you should not have difficulties modifying existing examples. You will need to change the model training and prediction functions.

      One of the competitive advantages of the Quantiacs platform is the ability to test machine learning models from a financial performance perspective.

      I haven’t encountered similar tools. Typically, models are evaluated using metrics like F1 score and cross-validation (for example, in the classification task of predicting whether the price will rise tomorrow).

      However, there are several problems:

      • It is unclear how much profit this model can generate. In real trading, there will be commissions, slippage, data errors, and the F1 score doesn’t account for these factors.
      • It is possible to inadvertently look into the future. For instance, data preprocessing techniques like standardization can leak future information into the past. If you subtract the mean or maximum value from each point in the time series, the maximum value reached in 2021 would be known in 2015, which is unacceptable.

      The Quantiacs platform provides a tool for evaluating models from a financial performance perspective.

      However, practice shows that finding a good machine learning model requires significant computational resources and time for training and testing. My results when testing strategies on real data have not been very good.

      posted in Support
      V
      Vyacheslav_B
    • RE: Acess previous weights

      @machesterdragon Hello. I have already answered this question for you. see a few posts above.

      Single-pass Version for Participation in the Contest
      This code helps submissions get processed faster in the contest. The backtest system calculates the weights for each day, while the provided function calculates weights for only one day.

      posted in Support
      V
      Vyacheslav_B
    • RE: Acess previous weights

      @illustrious-felice Hi,

      https://github.com/quantiacs/strategy-ml_lstm_state/blob/master/strategy.ipynb

      This repository provides an example of using state, calculating complex indicators, dynamically selecting stocks for trading, and implementing basic risk management measures, such as normalizing and reducing large positions. It also includes recommendations for submitting strategies to the competition.

      posted in Support
      V
      Vyacheslav_B
    • RE: Does evaluation only start from one year back?

      @buyers_are_back Hello. Look at the bottom of the table. Only 5 rows are displayed there. At the bottom right you can click a button to scroll to the first row

      posted in Support
      V
      Vyacheslav_B
    • RE: Acess previous weights

      @illustrious-felice Hello.

      Show me an example of the code.

      I don't quite understand what you are trying to do.

      Maybe you just don't have enough data in the functions to get the value.

      Please note that in the lines I intentionally reduce the data size to 1 day to predict only the last day.

      last_time = data.time.values[-1]
      data_last = data.sel(time=slice(last_time, None))
      

      Calculate your indicators before this code, and then slice the values.

      posted in Support
      V
      Vyacheslav_B
    • RE: WARNING: some dates are missed in the portfolio_history

      @multi_byte-wildebeest Hi. Without an example, it's unclear what the problem might be.

      If you use a state and a function that returns the prediction for one day, you will not get correct results with precheck.

      This was discussed here: https://quantiacs.com/community/topic/555/access-previous-weights/18

      posted in Support
      V
      Vyacheslav_B
    • RE: Accessing both market and index data in strategy()

      @buyers_are_back Hello.

      Here is an example: example link.

      You can view the list of available indexes here.

      If you want to use the load_data function, take a look at this example. You can implement the index download by analogy:

      example link.

      posted in Support
      V
      Vyacheslav_B
    • RE: Acess previous weights

      @machesterdragon
      That's how it should be. This code is needed so that submissions are processed faster when sent to the contest. The backtest system will calculate the weights for each day. The function I provided calculates weights for only one day.

      posted in Support
      V
      Vyacheslav_B
    • RE: Acess previous weights

      @machesterdragon Hello.

      If you use a state and a function that returns the prediction for one day, you will not get correct results with precheck.

      Theoretically, you can specify the number of partitions as all available days. or you can return all predictions

      I have not checked how the precheck works.

      If it works in parallel, you will not see the correct result even more so.

      State in strategy limits you. I recommend not using it.

      Here is an example of a version for one pass; I couldn't test it because my submission did not calculate even one day.

      init.ipynb

      ! pip install torch==2.2.1
      

      strategy.ipynb

      import gzip
      import pickle
      
      from qnt.data import get_env
      from qnt.log import log_err, log_info
      
      
      def state_write(state, path=None):
          if path is None:
              path = get_env("OUT_STATE_PATH", "state.out.pickle.gz")
          try:
              with gzip.open(path, 'wb') as gz:
                  pickle.dump(state, gz)
              log_info("State saved: " + str(state))
          except Exception as e:
              log_err(f"Error saving state: {e}")
      
      
      def state_read(path=None):
          if path is None:
              path = get_env("OUT_STATE_PATH", "state.out.pickle.gz")
          try:
              with gzip.open(path, 'rb') as gz:
                  state = pickle.load(gz)
              log_info("State loaded.")
              return state
          except Exception as e:
              log_err(f"Can't load state: {e}")
              return None
      
      
      state = state_read()
      print(state)
      
      
      # separate cell
      
      def print_stats(data, weights):
          stats = qns.calc_stat(data, weights)
          display(stats.to_pandas().tail())
          performance = stats.to_pandas()["equity"]
          qngraph.make_plot_filled(performance.index, performance, name="PnL (Equity)", type="log")
      
      
      data_train = load_data(train_period)
      models = train_model(data_train)
      
      data_predict = load_data(lookback_period)
      
      last_time = data_predict.time.values[-1]
      
      if last_time < np.datetime64('2006-01-02'):
          print("The first state should be None")
          state_write(None)
          state = state_read()
          print(state)
      
      weights_predict, state_new = predict(models, data_predict, state)
      
      print_stats(data_predict, weights_predict)
      state_write(state_new)
      print(state_new)
      qnout.write(weights_predict)  # To participate in the competition, save this code in a separate cell.
      
      

      But I hope it will work correctly.

      Do not expect any responses from me during this week.

      posted in Support
      V
      Vyacheslav_B
    • Documentation
    • About
    • Career
    • My account
    • Privacy policy
    • Terms and Conditions
    • Cookies policy
    Home
    Copyright © 2014 - 2021 Quantiacs LLC.
    Powered by NodeBB | Contributors