Overall Statistics
Total Orders
382
Average Win
0.35%
Average Loss
-0.38%
Compounding Annual Return
26.342%
Drawdown
23.800%
Expectancy
0.393
Start Equity
100000
End Equity
162611.09
Net Profit
62.611%
Sharpe Ratio
0.781
Sortino Ratio
1.057
Probabilistic Sharpe Ratio
41.537%
Loss Rate
28%
Win Rate
72%
Profit-Loss Ratio
0.93
Alpha
0.14
Beta
0.945
Annual Standard Deviation
0.216
Annual Variance
0.047
Information Ratio
0.834
Tracking Error
0.166
Treynor Ratio
0.178
Total Fees
$537.94
Estimated Strategy Capacity
$3900000.00
Lowest Capacity Asset
ACWI U1BQSAW6XI79
Portfolio Turnover
3.78%
#region imports
from AlgorithmImports import *
#endregion
#https://chat.openai.com/share/923ff83d-011b-4416-b37f-3f586510e37d


from QuantConnect.Algorithm import QCAlgorithm
from QuantConnect import Resolution

class VXXMOMENTUMPredictsStockIndexReturns(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2022, 3, 1)
        self.SetEndDate(2024, 3, 31)
        self.SetCash(100000)
        
        self.oef = "ACWI"
        self.vxx = "VXX"
        self.AddEquity(self.oef, Resolution.Daily)
        self.AddEquity(self.vxx, Resolution.Daily)
        
        # Set OEF as the benchmark
        self.SetBenchmark(self.oef)

        # Parameters
        params = ['ema-slow', 'ema-fast', 'leverage_up', 'leverage_down']
        self.params = {p: int(self.GetParameter(p)) for p in params}

        # Indicators
        self.emaFast = self.EMA(self.vxx, self.params['ema-fast'])
        self.emaSlow = self.EMA(self.vxx, self.params['ema-slow'])

        # To simulate a full investment in OEF from the start
        self.initialOEFPrice = None  # This will be set on the first available price
        self.hypotheticalOEFInvestment = self.Portfolio.Cash

    def OnData(self, data):
        if not data.ContainsKey(self.vxx) or data[self.vxx] is None or data[self.vxx].Close is None:
            self.Log("VXX data is missing or incomplete.")
            return

        if not data.ContainsKey(self.oef) or data[self.oef] is None or data[self.oef].Close is None:
            self.Log("OEF data is missing or incomplete.")
            return

        vxx_close = data[self.vxx].Close
        oef_close = data[self.oef].Close
        self.PlotIndicators(vxx_close, oef_close)
        self.EvaluatePositions()

    def PlotIndicators(self, vxx_close, oef_close):
        self.Plot("My Indicators", "slow Signal", self.emaSlow.Current.Value)
        self.Plot("My Indicators", "Fast Signal", self.emaFast.Current.Value)
        self.Plot("My Indicators", "VXX", vxx_close)
        
        # Initial OEF price setting
        if self.initialOEFPrice is None:
            self.initialOEFPrice = oef_close
        
        # Hypothetical investment value
        hypotheticalValue = self.hypotheticalOEFInvestment / self.initialOEFPrice * oef_close
        
        # Plot Strategy Equity and Benchmark with two scales
        self.Plot("Strategy Equity", "Portfolio Value", self.Portfolio.TotalPortfolioValue)
        self.Plot("Strategy Equity", "Hypothetical ACWI Investment", hypotheticalValue)

    def EvaluatePositions(self):
        if self.emaFast.Current.Value > self.emaSlow.Current.Value:
            self.SetHoldings(self.oef, -1.5 * self.params['leverage_up'])
        elif self.emaFast.Current.Value < self.emaSlow.Current.Value:
            self.SetHoldings(self.oef, 1.5 * self.params['leverage_down'])
        else:
            self.SetHoldings(self.oef, 1.0)