Overall Statistics
Total Trades
3591
Average Win
0.34%
Average Loss
-0.26%
Compounding Annual Return
0.675%
Drawdown
33.800%
Expectancy
0.009
Net Profit
0.726%
Sharpe Ratio
0.161
Probabilistic Sharpe Ratio
16.847%
Loss Rate
56%
Win Rate
44%
Profit-Loss Ratio
1.28
Alpha
-0.082
Beta
0.585
Annual Standard Deviation
0.285
Annual Variance
0.081
Information Ratio
-0.615
Tracking Error
0.281
Treynor Ratio
0.078
Total Fees
$77770.85
import numpy as np
import pandas as pd

def GetUncorrelatedAssets(returns, num_assets):
    # Get correlation
    correlation = returns.corr()
    
    # Find assets with lowest mean correlation, scaled by STD
    selected = []
    for index, row in correlation.iteritems():
        corr_rank = row.abs().mean()/row.abs().std()
        selected.append((index, corr_rank))

    # Sort and take the top num_assets
    selected = sorted(selected, key = lambda x: x[1])[:num_assets]
    
    return selected
# Import custom function
from GetUncorrelatedAssets import GetUncorrelatedAssets

class ModulatedOptimizedEngine(QCAlgorithm):

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

        self.SetCash(1000000)  # Set Strategy Cash
        
        self.UniverseSettings.Resolution = Resolution.Minute
        self.AddUniverse(self.CoarseSelectionFunction)

        self.SetBrokerageModel(AlphaStreamsBrokerageModel())

        self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
        
        self.SetExecution(ImmediateExecutionModel())
        
        self.AddEquity('SPY')
        self.SetBenchmark('SPY')
        
        self.Schedule.On(self.DateRules.EveryDay('SPY'), self.TimeRules.AfterMarketOpen("SPY", 5), self.Recalibrate)
        
        self.symbols = []

    def CoarseSelectionFunction(self, coarse):
        sortedByDollarVolume = sorted(coarse, key=lambda x: x.DollarVolume, reverse=True)
        return [ x.Symbol for x in sortedByDollarVolume ][:100]
        

    def Recalibrate(self):
        
        insights = [Insight.Price(symbol, timedelta(5), InsightDirection.Up, 0.03)
            for symbol in self.symbols]

        self.EmitInsights(insights)
        
    def OnSecuritiesChanged(self, changes):
        
        symbols = [x.Symbol for x in self.ActiveSecurities.Values 
            if x.Symbol not in changes.RemovedSecurities]

        qb = self
        
        # Copied from research notebook
        #---------------------------------------------------------------------------
        # Fetch history
        history = qb.History(symbols, 150, Resolution.Hour)
        
        # Get hourly returns
        returns = history.unstack(level = 1).close.transpose().pct_change().dropna()
        
        # Get 5 assets with least overall correlation
        selected = GetUncorrelatedAssets(returns, 5)
        #---------------------------------------------------------------------------
        
        # Add to symbol dictionary for use in Recalibrate
        self.symbols = [symbol for symbol, corr_rank in selected]
        
        # Emit flat insights for invested securities that were not selected above
        insights = [Insight.Price(x.Symbol, timedelta(5), InsightDirection.Flat)
            for x in self.Portfolio.Values if x.Invested and x.Symbol not in self.symbols] 

        self.EmitInsights(insights)