Navigation

    Quantiacs Community

    • Register
    • Login
    • Search
    • Categories
    • News
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    1. Home
    2. antinomy
    A
    • Profile
    • Following 0
    • Followers 1
    • Topics 11
    • Posts 75
    • Best 32
    • Groups 0
    • Blog

    antinomy

    @antinomy

    36
    Reputation
    38
    Profile views
    75
    Posts
    1
    Followers
    0
    Following
    Joined Last Online

    antinomy Follow

    Best posts made by antinomy

    • RE: Bollinger Bands

      @anthony_m
      Bollinger Bands are actually quite easy to calculate.
      The middle band is just the simple moving average, the default period is 20.
      For the other bands you need the standard deviation for the same period.
      The upper band is middle + multiplier * std
      The lower band is middle - multiplier * std
      Where the default for the multiplier is 2.

      There's an article on the formula for Bollinger Bands on Investopedia - they use the 'typical price' (high + low + close) / 3 but I think most people just use the close price.

      For the code it depends if you only need the latest values or the history.
      Using pandas the code for the first alternative could be:

      def strategy(data):
          close = data.sel(field='close').copy().to_pandas().ffill().bfill().fillna(0) 
      
          # let's just use the default 20 period:
          period = 20
          sma = close.iloc[-period:].mean()
          std = close.iloc[-period:].std()
      
          # and the default multiplier of 2:
          multiplier = 2
          upper = sma + multiplier * std
          lower = sma - multiplier * std
      

      If you need more than the last values you can use pandas.rolling:

      def strategy(data):
          close = data.sel(field='close').copy().to_pandas().ffill().bfill().fillna(0)
      
          # let's just use the default 20 period:
          period = 20
          sma = close.rolling(period).mean()
          std = close.rolling(period).std()
      
          # and the default multiplier of 2:
          multiplier = 2
          upper = sma + multiplier * std
          lower = sma - multiplier * std
      
      posted in Strategy help
      A
      antinomy
    • RE: Announcing the Winners of the Q14 Contest

      Thank you very much, this is awesome!
      And I also congratulate the other 2 winners!
      I got notified by e-mail 2 days ago and have been totally excited since then 🎉

      posted in News and Feature Releases
      A
      antinomy
    • External Libraries

      Hello @support ,

      I've been using cvxpy in the server environment which I installed by running

      !conda install -y -c conda-forge cvxpy
      

      in init.ipynb. But whenever this environment is newly initialized, the module is gone and I have to run this cell again (which takes awfully long).

      Is this normal or is there something wrong with my environment?
      My current workaround is placing these lines before the import

      try:
          import cvxpy as cp
      except ImportError:
          import subprocess
      
          cmd = 'conda install -y -c conda-forge cvxpy'.split()
          rn = subprocess.run(cmd)
      
          import cvxpy as cp
      

      Is there a better way?

      Best regards.

      posted in Support
      A
      antinomy
    • Different Sharpe ratios in backtest and competition filter

      When I run my futures strategy in a notebook on the server starting 2006-01-01 I get this result:

      Check the sharpe ratio...
      Period: 2006-01-01 - 2021-03-01
      Sharpe Ratio = 1.3020322470218595

      However, it gets rejected from the competition because the Sharpe is below 1. When I click on its chart in the "Filtered" tab it shows

      Sharpe Ratio 0.85

      When I copy the code from the html-previev of the rejected algo and paste it into a notebook, I get exactly the same result as above (Sharpe 1.3), so it doesn't seem to be a saving error.

      Why is there such a big difference? I thought the backtest results from the notebook shuld indicate if the strategy is elegible for the competition.
      How can I calculate the Sharpe ratio used for the competition in the notebook so I will know beforehand if the algo gets accepted or not?

      posted in Support
      A
      antinomy
    • RE: The Q16 Contest is open!

      @support
      First of all, having looked at various sources for crypto data myself, I know this can be a pain in the neck, so I can appreciate the effort you took to provide it.

      I get the method for avoiding lookahead-bias by including delisted symbols. The key point would be what you mean exactly by disappeared and from where.
      Do you mean they were delisted from the exchange where the winning algos will be traded or did the data source you used just not have data?

      To name 2 examples: DASH and XMR don't have recent prices but I don't know of an exchange they were delisted from. When I look them up on tradingview they do have prices on all the exchanges available there and are still traded with normal volumes.

      Charts for their closing price on quantiacs:

      import qnt.data as qndata
      
      data = qndata.cryptodaily_load_data(min_date='2020')
      close = data.sel(field='close').to_pandas()
      close[['DASH', 'XMR']].plot()
      

      Figure_1.png

      On tradingview:

      UDGfbmYT.png

      There are many reasons why we might need prices for symbols that are currently not among the top 10 in terms of market cap. An obvious one would be that they might be included in the filter again any second and algorithms do need historical data. Also, there are many ways to include symbols in computations without trading them: as indicators, to calculate market averages and so on.

      posted in News and Feature Releases
      A
      antinomy
    • RE: Data for Futures

      @support Yes, it's working now. Thanks!

      posted in News and Feature Releases
      A
      antinomy
    • RE: The Q16 Contest is open!

      @support
      I totally agree that the indicator usage is not trivial at all regarding lookahead-bias, still trying to wrap my head around it 😉
      The symbol list alone could already lead to lookahead bias - in theory, I don't have a realistic example.
      Because if the symbol is in the dataset, the algo could know it will be among the top 10 at some point, thus probably go up in price.
      I guess we really need to be extra careful avoiding these pitfalls, but they might also become apparent after the submission...

      From what I understand this contest is kind of a trial run for the stocks contest, so may I make a suggestion?
      On Quantopian there was data for around 8000 assets, including non-stocks like ETFs but for the daily contest for instance, the symbols had to be in the subset of liquid stocks they defined (around 2000 I think).

      The scenarios

      1. there's a price for that stock, it will become large
      2. it's included in the asset list, it must go up some day

      were not really a problem because there was no way to infer from prices or the symbol being present that it will be included in the filter some day.

      Maybe you could do something like that, too?
      It doesn't have to be those kind of numbers, but simply providing data for a larger set of assets containing symbols which will never be included in the filter could avoid this problem (plus of course including delisted stocks).

      For this contest I think your suggestion to retroactively fill the data if a symbol makes it on top again is a good idea.

      posted in News and Feature Releases
      A
      antinomy
    • RE: The Q16 Contest is open!

      @support In my posts I was merely thinking about unintentional lookahead bias because when it comes to the intentional kind, there are lots of ways to do that and I believe you never can make all of them impossible.
      But I think that's what the rules are for and the live test is also a good measure to call out intentional or unintentional lookahead bias as well as simple innocent overfitting.

      To clarify the Quantopian example a bit, I don't think what I described was meant to prevent lookahead bias. The 8000 something symbols just was all what they had and the rules for the tradable universe were publicly available (QTradableStocksUS on archive.org). I just thought, providing data for a larger set than what's actually tradable would make the scenarios I mentioned less likely. For that purpose I think both sets could also be openly defined. Let's say the larger one has the top 100 symbols in terms of market cap, dollar volume or whatever and the tradable ones could be the top 10 out of them with the same measurement.

      On the other hand, I still don't know if those scenarios could become a real problem. Because what good does this foreknowledge if you can't trade them yet? And after they're in the top 10 it would be legitimate to use the fact that they just entered, because we would also have known this at that time in real life.

      posted in News and Feature Releases
      A
      antinomy
    • RE: The Quantiacs Referral Program

      @news-quantiacs
      Hello,
      about that link, the important part is the one that starts with the question mark, with utm_medium being our unique identifier, right?
      So, can we change the link to point to the contest description instead of the login-page, like this?
      https://quantiacs.com/contest?utm_source=reference&utm_medium=19014
      Then interested people could first read more details about the contest before signing up...

      posted in News and Feature Releases
      A
      antinomy
    • RE: Optimizer for simple MA crypto strategy

      @magenta-grimer Your strategy selects only the last MA values but you need them all to get full backtest results (single pass). By changing these lines

          ma_slow= qnta.lwma(close, ma_slow_param)#.isel(time=-1)   
          ma_fast= qnta.lwma(close, ma_fast_param)#.isel(time=-1)
      

      I get

      ---
      Best iteration:

      {'args': {'ma_slow_param': 125, 'ma_fast_param': 10},
      'result': {'equity': 149.87344883417938,
      'relative_return': -0.07047308274265918,
      'volatility': 0.6090118757480503,
      'underwater': -0.07047308274265918,
      'max_drawdown': -0.7355866115241121,
      'sharpe_ratio': 0.9776088443081092,
      'mean_return': 0.5953753960199653,
      'bias': -1.0,
      'instruments': 1.0,
      'avg_turnover': 0.06404024691932551,
      'avg_holding_time': 72.70270270270271},
      'weight': 0.9776088443081092,
      'exception': None}

      posted in Strategy help
      A
      antinomy

    Latest posts made by antinomy

    • RE: Has my strategy been rejected from Q23?

      And what if a strategy uses the following rules to select assets to trade:

      • the primary exchange is NAS
      • the sector is not finance
      • has price data for at least the previous 3 months
      • has an average daily trading volume of at least 200 k based on the previous 3 months
      • belongs to the top 100 of the thus far selected assets in terms of market capitalization

      Would you say any of these rules violate the contest rules?

      Because these are the selection criteria for the N100 constituents. The only difference in my strategy is that I'm using qnt.data.stocks_load_ndx_data.sel(field='is_liquid') instead.
      Sure, the first of the rules above manually selects the exchange and the second one manually excludes a sector. But still none of these manually select assets and neither does the filter is_liquid from another dataset.

      Also, lets take a look why you prohibited manual asset selection in the first place. Wasn't this to avoid lookahead bias? And isn't this also the reason for the existence of the field is_liquid in any of your datasets? Are you saying that the exact field you introduced to avoid lookahead bias is now the reason you disqualify a strategy because of lookahead bias just because it's from a dataset other than the one for the contest?

      posted in Support
      A
      antinomy
    • RE: Has my strategy been rejected from Q23?

      @support
      Thanks for your reply.

      My strategy trades a subset of assets from the S&P 500 universe, selected with certain filter rules. Most are technical and one of them is that they also belong to the Nasdaq 100 index.
      Which contest rule would be violated when a strategy selects stocks which are part of the contest universe and also part of another index?

      Is selecting assets based on them being part of an index considered as "manual selection"? This would mean every strategy for all the Nasdaq 100 and S&P 500 contests is against the rules and the contest rules would contradict themselves.

      posted in Support
      A
      antinomy
    • RE: Has my strategy been rejected from Q23?

      Out of curiosity I just cloned the strategy to run it again and see if I get any correlations. And yes:

      WARNING! This strategy correlates with other strategies and will be rejected.
      Modify the strategy to produce the different output.
      
      The number of systems with a larger Sharpe ratio and correlation larger than 0.9: 2
      The max correlation value (with systems with a larger Sharpe ratio): 0.9818594562862993
      

      Then I wanted to know to which strategies it correlates and simply put a print(json.dumps(cr_list, indent=4)) inside qnt.stats.check_correlation and got this:

      [
          {
              "id": 18701501,
              "name": null,
              "my": false,
              "template": false,
              "cofactor": 0.9818594562862993,
              "sharpe_ratio": 2.364183164325061
          },
          {
              "id": 18701502,
              "name": null,
              "my": false,
              "template": false,
              "cofactor": 0.9559821139736059,
              "sharpe_ratio": 2.49988419656187
          }
      ]
      

      The first one is my q23_4 and the other one is my q23_4a (funny that it correlates with itself by 0.98 and not 1.0). However, no correlation with any template is showing up there.

      posted in Support
      A
      antinomy
    • Has my strategy been rejected from Q23?

      Hi @support

      My strategy q23_4 would have made the 3rd place in the Q23 contest but now instead of the allocation there is a red dot whose mouseover reads "The strategy uses manual asset selection or has very high correlation with standard templates; therefore, it has been rejected."

      Screenshot 2026-03-17 at 23-55-47 Quantiacs - The Leading Platform for Quantitative Trading and Algorithmic Strategy Development.png

      There is definitely no manual selection in any of my strategies and the ones that took part in the contest had to pass the correlation check which also checks against templates.

      Could you please tell me what's going on there?

      posted in Support
      A
      antinomy
    • RE: Strategy passes correlation check in backtester but fails correlation filter after submission

      Hi @support ,
      sorry to bother you again but I have a new issue with my submissions.
      On 2025-07-14 I submitted 3 strategies and they have been stuck at 99 % for 3 days now.
      Yesterday I submitted another one and it's also stuck at 99 %
      Could you please have a look?
      One odd thing: meanwhile the ones from 2025-07-14 have processed the trading day for 2025-07-15 - I hope they don't wait for new data every day 😉

      posted in Support
      A
      antinomy
    • RE: Strategy passes correlation check in backtester but fails correlation filter after submission

      @support All is looking good now, thanks!

      posted in Support
      A
      antinomy
    • RE: Strategy passes correlation check in backtester but fails correlation filter after submission

      Hi @support ,
      unfortunately the strategy is still not eligible for the contest, now it says "Competitions for the specified type are not running" and it's not selected to run in the contest.

      81207649-425e-43c0-902f-0a8bfb1dc0bc-image.png

      Just out of curiousity I cloned the strategy and submitted the clone, the result is the same as the original issue:
      b2e45ea3-334d-4562-8aeb-dcc3dad45036-image.png
      (the cloned stragegy can be deleted, I will eventually do so before the deadline)

      Can you share any insights as to why this happens at all?
      Thanks.

      posted in Support
      A
      antinomy
    • Strategy passes correlation check in backtester but fails correlation filter after submission

      Hi @support,
      When I run my strategy with qnt.backtester.backtest setting check_correlation=True it passes the correlation test.

      correlation_test.png

      When I submitted it to the contest it got rejected and in the candidates tab it has a message about high correlation:
      q23_01.png

      Looking at the short description in the strategy history it passes all tests on every trading day except for the last one (2025-06-24):
      history_short_description.png

      I don't quite understand why it passes the correlation check in the backtester but fails it after submission on the last day.
      Which correlation test is wrong, the one from the backtester or the one running after submission?
      If it helps, the strategy in question is a q 19 submission by another user and when I look at it there are only 87 data points.
      My strategy is 18633730 and the one it has or has not a high correlation with is 11938152.

      posted in Support
      A
      antinomy
    • RE: ERROR! The max exposure is too high

      @vyacheslav_b Hi, I agree that diversification is always a good idea for trading. It might be helpful if there was an additional function like check_diversification whith a parameter for the minimum number of assets you want to trade. But this function should only warn you and not fix an undiversified portfolio, because the only way would be to add more assets to trade and asset selection should be done by the strategy itself in my opinion.

      @support Hi, I just checked out qnt 0.0.504 and the problem I mentioned seems to be fixed now, thanks!
      Would you perhaps consider to add a leverage check to the check function?
      Because one might think "qnout.check says everything is OK, so I have a valid portfolio" while actually having vastly overleveraged like in my 2nd example where weights.sum('asset').values.max() is 505.0.
      Adding something like this to check would tell us about it:

      log_info("Check max portfolio leverage...")
      max_leverage = abs(output).sum(ds.ASSET).values.max()
      if max_leverage > 1 + 1e-13: # (give some leeway for rounding errors and such)
          log_err("ERROR! The max portfolio leverage is too high.")
          log_err(f"Max leverage: {max_leverage} Limit: 1.0")
          log_err("Use qnt.output.clean() or normalize() to fix.")
      else:
          log_info("Ok.")
      
      
      posted in Support
      A
      antinomy
    • RE: ERROR! The max exposure is too high

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

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