Just wanted to share a little fun strategy.
Premise: 3X leveraged ETFs always decay over time. For example, if you have an ETF that starts at 100%, goes up 25% to 125% and then goes back down 20% to 100% you are back at square one. But the 3X ETF will go up 75% and go down 60%, ending up at 70%.
So we know that shorting a 3X ETF will make money when it eventually decays, but if it spikes up suddenly we lose a lot of money. Hence we hedge by shorting both the 3X ETF and the inverse 3X ETF.
In this backtest we short 3 pairs of 3X ETFs ("JNUG", "JDST", "DUST", "NUGT","DGAZ","UGAZ”) in equal proportions and rebalance every 60 days.
Caveat: This strategy will lose money when the 3X ETFs go out of sync, which happens often in periods of high volatility (although this is a statistical arbitrage opportunity, which is a separate strategy in itself). IB’s margin maintenance for 3X ETFs is 90%, so a 10% drawdown is enough for a margin call. Hence don’t actually trade this strategy unless you add some protection for situations where the ETFs are going out of sync.
Returns are neutral of market direction. Lower during calm periods and higher when the ETFs move more, and hence decay more. CAGR 27% / Sharpe 0.942 in backtest period.
It’s not possible to model the carry cost of shorting in the backtest. But the stock should not be too hard to borrow, since people who want to short an ETF will just buy the inverse.
Douglas Stridsberg
Impressive! Are there any indications on IB for the cost of borroow on these? Also, have you tried different rebalancing periods, out of interest? I'm thinking a lower rebalance period would potentially yield more stable results, but I'm not sure.
Yujun Tang
IB's borrow cost starts at 0.25%, their statistics say the average is 0.3% but can go up to 30% during a short squeeze. They don't have statistics for individual stocks but I don't worry too much about it, and I'm short more often than long.
The 3X ETF short strategy is somewhat sensitive to starting and rebalancing periods. If you happen to rebalance when the ETF pair is out of sync (and you are at a loss), when they eventually sync again you will lose even more. But if you hold the pair throughout the correction you'll get your money back and more.
I would be wary of tuning the rebalancing frequency as it's literally the only parameter of the strategy and you'll likely introduce a lot of overfitting bias into the backtest.
Abhishek Sharma
What instrument you are using for shorting ? Is it options ?
Douglas Stridsberg
The algorithm uses the Inverse version of the ETFs to short. Look up the tickers "NUGT","DGAZ","UGAZ" to read more.
Brascano
Shorting these ETFs tend to trigger frequent Hard to Borrow interest penalties which can make shorting very costly. Correct me if I am wrong but it seems these particular ETFs were cherry picked… other 3x ETF pairs don’t yield very good results… http://www.3xetf.com/ try the 3x Crude ETFs OILU/OILD
Apollos Hill
Hi Yujun,
Thanks for presenting this to the community. I am trying this now with slightly out of the money PUT options with over 100 days to expire on my IRA account. I'll probably be in the red for a few days because the market is moving sideways. But im hoping that this proves fruitful since the backtests performed so well.Â
Genevieve Odette Rona Magnan
Longer period is not so great.
Â
Stephen Hammond
"3X leveraged ETFs always decay over time. For example, if you have an ETF that starts at 100%, goes up 25% to 125% and then goes back down 20% to 100% you are back at square one. But the 3X ETF will go up 75% and go down 60%, ending up at 70%."
Â
I don't know if I'm allowed to revive this, but this is just faulty b.s. logic. 3x commodity ETFs trend down because of contango/backwardation but volatility drag, if you actually crunch the numbers is not a big enough factor to cause 3x stock etfs to trend down as long as the underlying assets trend up. The reason your strategy is working is because you're cherrypicking ETFs that inversely correlate with the market or commodity ETFs.
Brandon Goyette
I have a similar stratgy that uses long/short pairs and rebalances every day - I used it live in Quantpian but havent tried to rebuild it here - had very good results
def initialize(context):
  """
  Called once at the start of the algorithm.
  """  Â
  Â
  # Rebalance every day, 1 hour after market open.
  schedule_function(rebalance, date_rules.every_day(), time_rules.market_open(hours=1.5))
  Â
  # Record tracking variables at the end of each day.
  schedule_function(record_vars, date_rules.every_day(), time_rules.market_close())
  Â
  # IB parameters
  set_commission(commission.PerShare(cost=0.005, min_trade_cost=1.00))
  Â
  context.leverage = -1.0 # short both pairs
  Â
  context.etfs_long=[ sid(37049), sid(37515),  sid(41969), sid(42470), sid(39214),sid(45570)]
           #  FAS, TNA, UVXY, DGAZ, TQQQ, JDST
           Â
  context.etfs_short=[  sid(37048), sid(37133), sid(41968),sid(39211), sid(42477), sid(45571)]
           #  FAZ, TZA, SVXY, UGAZ, SQQQ, JNUG  Â
    Â
  context.sim = -1 # change to index of any pair obove (0 - 4) to trade that single pair
    Â
  Â
def compute_weights(context, data):
  """
  Assign weights to securities that we want to order.
  """
  num = 0
  Â
  for (l,s) in zip(context.etfs_long, context.etfs_short):
    if data.can_trade(l) and data.can_trade(s):
      num+=1
      Â
  if (num>0):
    return context.leverage/(num*2) # we have pairs so half for each
  else:
    return 0
Â
Â
def rebalance(context,data):
  """
  Execute orders according to our schedule_function() timing.Â
  """
  if context.sim >= 0 : # trade single pair
    if (data.can_trade(context.etfs_long[context.sim]) and data.can_trade(context.etfs_short[context.sim])):
      order_target_percent(context.etfs_long[context.sim], context.leverage/2)
      order_target_percent(context.etfs_short[context.sim],context.leverage/2)
      Â
  else: # trade all as a basket
    weight=compute_weights(context, data)
    Â
    if weight:
      for (l,s) in zip(context.etfs_long, context.etfs_short):
        if data.can_trade(l) and data.can_trade(s):
          order_target_percent(l, weight)Â
          order_target_percent(s, weight)
    Â
Â
def record_vars(context, data):
  """
  Plot variables at the end of each day.
  """
  Â
  record(leverage=context.account.leverage)
  record(positions=len(context.portfolio.positions))
Â
Â
def handle_data(context,data):
  """
  Called every minute.
  """
  pass
Brandon Goyette
Same idea except a daily rebalnace and 6 3x long and opposite 3x short ETFsÂ
Brandon Goyette
Sharpe Ratio
2.858
Jack Pizza
this has some larger drawdowns, think if a dual momentum type filter is added to stop trading if cash > a bond fund go into cash.Â
Yujun Tang
The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by QuantConnect. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. QuantConnect makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances. All investments involve risk, including loss of principal. You should consult with an investment professional before making any investment decisions.
To unlock posting to the community forums please complete at least 30% of Boot Camp.
You can continue your Boot Camp training progress from the terminal. We hope to see you in the community soon!