Overall Statistics
Total Trades
9
Average Win
0.01%
Average Loss
-0.05%
Compounding Annual Return
-1.924%
Drawdown
0.300%
Expectancy
-0.762
Net Profit
-0.208%
Sharpe Ratio
-3.503
Probabilistic Sharpe Ratio
0.043%
Loss Rate
80%
Win Rate
20%
Profit-Loss Ratio
0.19
Alpha
-0.015
Beta
-0.001
Annual Standard Deviation
0.004
Annual Variance
0
Information Ratio
-4.837
Tracking Error
0.103
Treynor Ratio
10.872
Total Fees
$9.00
class CalibratedUncoupledCoreWave(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2019, 10, 1)  # Set Start Date
        self.SetEndDate(2019, 11, 10)  # Set End Date
        self.SetCash(100000)          # Set Strategy Cash
        
        # Setup universe
        self.UniverseSettings.Resolution = Resolution.Minute 
        self.AddUniverse(self.SelectCoarse,self.SelectFine)
        self.AddEquity("SPY", Resolution.Minute)
        
        # Liquidate all positions before the market close each day
        self.Schedule.On(self.DateRules.EveryDay("SPY"), self.TimeRules.BeforeMarketClose("SPY", 30), self.ClosePositions)
        
        self.coarseclose={}    # Store yesterday's close in a dictionary for reference
        self.traded={}         # Ensure only 1 trade per day per stock
        self.targetentry=2.00  # Only enter a trade if today's price doubles yesterday's close
        self.stops = {}        # Keep track of stop loss orders so we can update them

    def SelectCoarse(self, coarse):
        # Penny Stock filter
        myuniverse = [x for x in coarse if x.HasFundamentalData and \
                                           x.DollarVolume > 1000000 and \
                                           x.DollarVolume < 5000000 and \
                                           x.Price > 0 and x.Price <= 5.0]

        self.coarseclose.clear()  # Clear the dictionary each day before re-populating it
        
        # Save yesterday's close
        for c in myuniverse:
            self.coarseclose[c.Symbol] = c.AdjustedPrice
        
        return [x.Symbol for x in myuniverse] # Return filtered stocks for further filtering by the SelectFine
        
    def SelectFine(self,fine):
        ''' 
        This function takes the stock of the CoarceFundamental function and narrow the list adding specific fundamental filters
        Largely to ensure that only common stock is traded and not EG Preference Shares or ETFs
        '''
        # Primary share, common stock, not limited partnership, and not ADR
        fine_filter = [x.Symbol for x in fine if x.SecurityReference.IsPrimaryShare == 1 and \
                                                 x.SecurityReference.SecurityType == 'ST00000001' and \
                                                 x.CompanyReference.IsLimitedPartnership == 0 and \
                                                 x.SecurityReference.IsDepositaryReceipt == 0 ]
        self.traded.clear()
        self.traded = {k: 0 for k in fine_filter}
        return fine_filter

    def OnData(self, data):
        '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
        Arguments:
            data: Slice object keyed by symbol containing the stock data
        '''
        for kvp in data.Bars:
            symbol = kvp.Key
            close = kvp.Value.Close
            
            # Entry conditions:
            #  - We have no position in this stock
            #  - We haven't traded this symbol today
            #  - Bar closed above our target
            #  - Before 10:30am
            #  - Large dollar volume for this bar
            if (self.Portfolio[symbol].Quantity == 0.0 and
                symbol in self.traded.keys() and
                self.traded[symbol] == 0 and              
                close >= self.coarseclose[symbol]*self.targetentry and 
                self.Time.hour <= 10 and self.Time.minute <=29 and   
                close * kvp.Value.Volume >= 50000): 
                
                # Signal today's entry
                self.traded[symbol] = 1

                # Determine position size
                quantity = int(self.Portfolio.TotalPortfolioValue / 100 / data[symbol].Close) #self.CalculateOrderQuantity(symbol, 0.01) // 2
                if quantity < 4:
                    continue
                
                # Enter with market order
                enter_ticket = self.MarketOrder(symbol, quantity)
                
                # Set profit targets 
                quarter = int(quantity / 4)
                final = quantity - 3 * quarter
                for i in range(3):
                    order = self.LimitOrder(symbol, -quarter, enter_ticket.AverageFillPrice * (1 + (i+1)*0.05))
                    updateSettings = UpdateOrderFields()
                    updateSettings.Tag = "pt"
                    order.Update(updateSettings)
                order = self.LimitOrder(symbol, -final, enter_ticket.AverageFillPrice * 1.2)
                order.Update(updateSettings)
            
                # Set stop loss
                self.stops[symbol] = self.StopMarketOrder(symbol, -quantity, enter_ticket.AverageFillPrice * 0.95)
                updateSettings.Tag = "sl"
                self.stops[symbol].Update(updateSettings)

    def OnOrderEvent(self, orderEvent):
        if orderEvent.Status == OrderStatus.Filled: 
            order = self.Transactions.GetOrderById(orderEvent.OrderId)
            if order.Tag == 'pt':  # If hit profit target, update stop order quantity
                updateSettings = UpdateOrderFields()
                updateSettings.Quantity = self.stops[orderEvent.Symbol].Quantity - orderEvent.Quantity
                self.stops[orderEvent.Symbol].Update(updateSettings)

            elif order.Tag == 'sl': # If hit stop loss, cancel profit target orders
                self.Transactions.CancelOpenOrders(orderEvent.Symbol, "Hit stop price")

    def ClosePositions(self):        
        if self.Portfolio.Invested:
            self.Transactions.CancelOpenOrders()
            self.Liquidate()