Overall Statistics
Total Trades
715
Average Win
0.19%
Average Loss
-0.09%
Compounding Annual Return
14.629%
Drawdown
19.800%
Expectancy
0.609
Net Profit
22.093%
Sharpe Ratio
1.006
Probabilistic Sharpe Ratio
46.866%
Loss Rate
48%
Win Rate
52%
Profit-Loss Ratio
2.08
Alpha
0.045
Beta
0.506
Annual Standard Deviation
0.16
Annual Variance
0.026
Information Ratio
-0.44
Tracking Error
0.157
Treynor Ratio
0.319
Total Fees
$935.20
import pandas as pd
# from GetUncorrelatedAssets import GetUncorrelatedAssets

class ModulatedOptimizedEngine(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2019, 1, 1)  # Set Start Date

        self.SetCash(100000)  # Set Strategy Cash
        
        self.AddEquity("SPY", Resolution.Minute)
        self.Schedule.On(self.DateRules.EveryDay('SPY'), self.TimeRules.AfterMarketOpen("SPY", 5), self.Recalibrate) 
        
        self.UniverseSettings.Resolution = Resolution.Minute 
        self.tickers = ["SPY", "FXI", "EWI", "VGK", "GLD", "SHY"]
        self.symbols = [Symbol.Create(t, SecurityType.Equity, Market.USA) for t in self.tickers]
        self.AddUniverseSelection( ManualUniverseSelectionModel(self.symbols) )
 
        self.Settings.RebalancePortfolioOnInsightChanges = False
        self.Settings.RebalancePortfolioOnSecurityChanges = False
        self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
        
        self.SetExecution(ImmediateExecutionModel()) 
        self.SetBenchmark('SPY')

    def Recalibrate(self):
        
        # copy/paste from notebook, minus documentation
        def get_most_uncorrelated_asset(book_or_algorithm, window):
            qb = book_or_algorithm  # this is self when used in the Framework
            
            # get the history of the window size
            history = qb.History(qb.Securities.Keys, window, Resolution.Daily)
            returns = history.unstack(level=0).close.pct_change().dropna() 
            
            # for each ticker/symbol, compute correlation to SPY
            spy = returns["SPY R735QTJ8XC9X"]  # there's probably a better way to encode this
            correlations = {symbol: abs(spy.corr(returns[symbol])) for symbol in returns.columns}
            
            # return the most uncorrelated one
            symbol, correlation = sorted(correlations.items(), key=lambda x: x[1])[0]
            return symbol, correlation
        
        
        # note that while this looks like a method because we pass self, it's a function
        uncorrelated_asset, correlation = get_most_uncorrelated_asset(self, window=10)  
        
        spyweight = 1 - correlation
        
        insights = [Insight.Price("SPY", timedelta(5), InsightDirection.Up, None, None, None, spyweight),
            Insight.Price(self.Symbol(uncorrelated_asset), timedelta(5), InsightDirection.Up, None, None, None, correlation)]

        self.EmitInsights(insights)