Overall Statistics
Total Trades
3492
Average Win
0.20%
Average Loss
-0.38%
Compounding Annual Return
31.175%
Drawdown
29.600%
Expectancy
0.236
Net Profit
322.304%
Sharpe Ratio
1.217
Probabilistic Sharpe Ratio
60.493%
Loss Rate
19%
Win Rate
81%
Profit-Loss Ratio
0.52
Alpha
0.112
Beta
1.008
Annual Standard Deviation
0.187
Annual Variance
0.035
Information Ratio
1.153
Tracking Error
0.098
Treynor Ratio
0.225
Total Fees
$11965.74
Estimated Strategy Capacity
$34000000.00
Lowest Capacity Asset
AMZN R735QTJ8XC9X
# Oversold CCI portfolio with Take Profit and Stop Loss

# -------------------------------------------------------------------------------
TICKERS = ["SPY", "AAPL", "MSFT", "AMZN"]; CCI_PERIOD = 14; TP = 0.10; SL = 0.05;
# -------------------------------------------------------------------------------

class BasicTemplateAlgorithm(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2017, 1, 1)  
        self.SetEndDate(2022, 4, 22)
        self.SetCash(1000000)
        self.cci = {}
        self.SetWarmUp(CCI_PERIOD + 1, Resolution.Daily)
        self.symbols = [self.AddEquity(ticker, Resolution.Minute).Symbol for ticker in TICKERS]
        for sec in self.symbols:
            self.cci[sec] = self.CCI(sec,  CCI_PERIOD, MovingAverageType.Simple, Resolution.Daily)
        self.selected = []    
        self.Schedule.On(self.DateRules.EveryDay(self.symbols[0]), self.TimeRules.AfterMarketOpen(self.symbols[0], 31),
            self.Trade)

        
    def Trade(self):
        if self.IsWarmingUp: return
        
        for sec in self.symbols:
            if not self.cci[sec].IsReady: continue
            cci = self.cci[sec].Current.Value
            pnl = self.Securities[sec].Holdings.UnrealizedProfitPercent
            
            self.Plot("CCI", sec, self.cci[sec].Current.Value)
            self.Plot("CCI", 'threshold', -100) 
            self.Plot("Selected", 'N', len(self.selected))   
            
            if not self.Portfolio[sec].Invested:
                if cci < -100:
                    self.selected.append(sec)

            elif self.Portfolio[sec].Invested:
                if pnl >= TP:
                    if sec in self.selected:
                        self.selected.remove(sec)
                    
                elif pnl < -SL:
                    if sec in self.selected:
                        self.selected.remove(sec)
                        
        for sec in self.Portfolio.Keys:
            if sec not in self.selected:  
                self.Liquidate(sec)
                
        for sec in self.selected:            
            self.SetHoldings(sec, 1/len(self.selected))