Hello,

I'm a total newbie to Quantconnect and am still struggling with how the classes are built in the Quantconnect API, so please forgive me if there are stupid mistakes in my code.

The strategy I want to design is to coarse-filter for stocks with their CCI being oversold (<-100) to create a universe of candidates to buy from, until I hold 10 Stocks. If the CCI of any of the holdings gets overbought (>100), I want to sell that position.

What mainly challenges me in this scenario is, that other than in the common EMA-examples, the CCI function needs a complete bar to update (and not just the current price). However, the history(symbol)-function just spits out a pandas dataframe and I assume that I cannot just feed this rowwise into cci.Update()?

The other challenge is, that I don't know how to attach the current cci value to each of my Portfolio holdings, so I don't have to initialize it with 20 history bars again each time I check the current cci value in self.OnData()...

Of course, if there are any other stupid mistakes in my code, please feel free to critizise me as well - I'm not very used  to the structure of object oriented programs, mainly did functional coding in Python before...

Thanks a lot in advance for any answers, Johannes

--- 

Since Somehow I cannot find my backtests in the "Select a Backtest" Drawdown (maybe because they throw errors?), I will just paste my code in here:

 

class EMAMomentumUniverse(QCAlgorithm):
    
    def Initialize(self):
        self.SetStartDate(2019, 1, 7)
        self.SetEndDate(2019, 4, 1)
        self.SetCash(100000)
        self.UniverseSettings.Resolution = Resolution.Daily
        self.AddUniverse(self.CoarseSelectionFunction) 
        self.cciscan = { }
    
    def CoarseSelectionFunction(self, universe):  
        selected = []
        universe = sorted(universe, key=lambda c: c.DollarVolume, reverse=True)  
        universe = [c for c in universe if c.Price > 10][:100]

        for coarse in universe:  
            symbol = coarse.Symbol
            
            if symbol not in self.cciscan:
                history = self.History(symbol, 20, Resolution.Daily)
                self.cciscan[symbol] = SelectionData(symbol, history) 

            self.cciscan[symbol].update(self.History(symbol, 1, Resolution.Daily).FirstOrDefault())
            if  self.cciscan[symbol].is_ready() and self.cciscan[symbol].cci < -100:
                selected.append(symbol)
        
        return selected[:10]
            
    def OnData(self, data):
        
        if self.Portfolio.keys < 10:
            # here I want to buy another symbol from the  "CCI-Oversold"-universe
            self.SetHoldings(data[1].Symbol, 0.1)
            
            # if CCI gets overbought -> Liquidate that Position
            for security in self.Portfolio.securities.Symbol:
                history = self.History(symbol, 20, Resolution.Daily)
                if SelectionData(security.Symbol, history).cci > 100: # somehow throwing an error
                    self.Liquidate(security.Symbol)
        
class SelectionData():
    def __init__(self, symbol, history):
        self.Symbol = symbol
        self.cci = CommodityChannelIndex(20, MovingAverageType.Simple);

        #4. Loop over the history data and update the indicators
        for bar in history.itertuples():
            #need some way to update CCI with history - currently throws an error.
            self.cci.Update(history)
            #self.cci.Update(bar.Index[1], bar.close)
              
    def is_ready(self):
        return self.cci.IsReady
    
    def update(self, bar):
        self.cci.Update(bar)

Author