Overall Statistics
Total Trades
1
Average Win
0%
Average Loss
0%
Compounding Annual Return
2037255753670440000000000%
Drawdown
11.700%
Expectancy
0
Net Profit
52.532%
Sharpe Ratio
81407470.15
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
99648490.313
Beta
51.035
Annual Standard Deviation
1.224
Annual Variance
1.498
Information Ratio
82603443.263
Tracking Error
1.206
Treynor Ratio
1952534.258
Total Fees
$183.15
class BreakOutExample(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2020, 12, 1) # Set Start Date
        self.SetEndDate(2020, 12, 3) # Set End Date
        self.SetCash(1000000) # Set Strategy Cash
        
        # Subscribe and set our expiry filter for the futures chain
        future = self.AddFuture(Futures.Metals.Gold) #(Futures.Indices.SP500EMini)
        future.SetFilter(timedelta(0), timedelta(182))
        
        self.symbol_data_by_symbol = {}
        

    def OnData(self, data):
        if self.Portfolio.Invested:
            return
        
        for chain in data.FutureChains:
            contracts = [contract for contract in chain.Value if self.symbol_data_by_symbol[contract.Symbol].IsReady]
            if len(contracts) == 0:
                continue
            
            # Sort contracts
            
            
            # Select contract
            contract = contracts[0]
            symbol = contract.Symbol
        
            price = self.Securities[symbol].Close
            
            symbol_data = self.symbol_data_by_symbol[contract.Symbol]

            if price >= symbol_data.max.Current.Value:
                self.SetHoldings(symbol, 1)
            if price <= symbol_data.min.Current.Value:
                self.SetHoldings(symbol,-1)
    
    
    def OnSecuritiesChanged(self, changes):
        for security in changes.AddedSecurities:
            symbol = security.Symbol
            self.symbol_data_by_symbol[symbol] = SymbolData(symbol, self)
            
        for security in changes.RemovedSecurities:
            symbol = security.Symbol
            symbol_data = self.symbol_data_by_symbol.pop(symbol, None)
            if symbol_data:
                symbol_data.dispose()
                
                
class SymbolData:
    def __init__(self, symbol, algorithm):
        self.symbol = symbol
        self.algorithm = algorithm
        
        self.min = Minimum(3)
        self.max = Maximum(3)
        
        self.consolidator = algorithm.Consolidate(symbol, timedelta(minutes=60), self.OnDataConsolidated)
        
    
    def OnDataConsolidated(self, bar):
        self.algorithm.Log(f"OnDataConsolidated at {bar.EndTime} for {bar.Symbol}")
        
        self.min.Update(bar.EndTime, bar.Low)
        self.max.Update(bar.EndTime, bar.High)
        
        
    def dispose(self):
        self.SubscriptionManager.RemoveConsolidator(self.symbol, self.consolidator)
    
    @property
    def IsReady(self):
        return self.min.IsReady and self.max.IsReady