| Overall Statistics |
|
Total Orders 49 Average Win 14.99% Average Loss -9.60% Compounding Annual Return 31.718% Drawdown 46.800% Expectancy 0.601 Start Equity 100000 End Equity 396784.22 Net Profit 296.784% Sharpe Ratio 0.676 Sortino Ratio 0.638 Probabilistic Sharpe Ratio 18.562% Loss Rate 38% Win Rate 62% Profit-Loss Ratio 1.56 Alpha 0.193 Beta 1.283 Annual Standard Deviation 0.417 Annual Variance 0.174 Information Ratio 0.563 Tracking Error 0.378 Treynor Ratio 0.22 Total Fees $1290.18 Estimated Strategy Capacity $240000.00 Lowest Capacity Asset SVXY V0H08FY38ZFP Portfolio Turnover 2.59% Drawdown Recovery 511 |
# region imports
from AlgorithmImports import *
# endregion
class VolailityTradingAlgorithm(QCAlgorithm):
def initialize(self):
self.set_start_date(self.end_date - timedelta(5*365))
self.set_cash(100_000)
self.settings.automatic_indicator_warm_up = True
self.settings.seed_initial_prices = True
# Add the assets we'll trade.
self._uvxy = self.add_equity("UVXY")
self._svxy = self.add_equity("SVXY")
self._tqqq = self.add_equity("TQQQ")
# Add SPY and some indicators to inform our trading decisions.
self._spy = self.add_equity("SPY")
self._spy.sma = self.sma(self._spy, 25, Resolution.DAILY, Field.OPEN)
self._spy.macd = self.macd(self._spy, 12, 26, 6, MovingAverageType.EXPONENTIAL, Resolution.DAILY, Field.OPEN)
self._spy.session.size = 3
for bar in self.history[TradeBar](self._spy, 3, Resolution.DAILY):
self._spy.session.update(bar)
# Add VIX data to inform our trading decisions.
self._vix = self.add_data(CBOE, "VIX", Resolution.DAILY)
self._vix3m = self.add_data(CBOE, "VIX3M", Resolution.DAILY)
self._vix9d = self.add_data(CBOE, "VIX9D", Resolution.DAILY)
# Add a Scheduled Event to rebalance the portfolio every morning.
self._target = None
self.schedule.on(
self.date_rules.every_day(self._spy),
self.time_rules.after_market_open(self._spy),
self._rebalance
)
def on_data(self, data):
# Only trade on new VIX data.
if self._vix not in data.bars:
return
# Calculate some trading factors.
vix_ratio = self._vix.open / self._vix3m.open
vix_cross_up = self._vix9d.open > self._vix.open
# Scan for entries.
short_entry = (
vix_ratio < 0.95 and
not vix_cross_up and
not (
self._spy.session[1].open <= self._spy.sma.current.value and
self._spy.session[2].open > self._spy.sma.previous.value
)
)
long_entry = (
vix_ratio > 1.05 and
vix_cross_up and
self._spy.macd.current.value < self._spy.macd.signal.current.value
)
# Scan for exits.
in_long = self._uvxy.holdings.is_long
in_short = self._svxy.holdings.is_short
in_rest = self._tqqq.holdings.is_long
short_exit = in_short and (not short_entry)
long_exit = in_long and (not long_entry)
# Set the target asset.
if (short_exit or long_exit) and not self._tqqq.invested:
self._target = self._tqqq
elif short_entry and not self._svxy.invested:
self._target = self._svxy
elif long_entry and not self._uvxy.invested:
self._target = self._uvxy
def _rebalance(self):
# Place trades to rebalance the portfolio.
if self._target:
self.set_holdings(self._target, 1, liquidate_existing_holdings=True)
self._target = None