Overall Statistics
Total Trades
0
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Net Profit
0%
Sharpe Ratio
0
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
-1.099
Tracking Error
0.3
Treynor Ratio
0
Total Fees
$0.00
Estimated Strategy Capacity
$0
from QuantConnect.Data.UniverseSelection import *
import math
import numpy as np
import pandas as pd
import scipy as sp

class MicroGrowth(QCAlgorithm):

    def Initialize(self):
        #self.SetStartDate(2020, 2, 12)  # Set Start Date
        self.SetStartDate(2020, 2, 28)
        self.SetEndDate(2021, 3, 1)
        self.SetCash(100000)  # Set Strategy Cash
        self.UniverseSettings.Resolution = Resolution.Daily
        self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)
        self.lastmonth = -1
        self.monthinterval = 3
        self.Symbols = None

    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
        '''
    def CoarseSelectionFunction(self,coarse):
        if self.lastmonth == -1 or ((self.Time.month-self.lastmonth) % self.monthinterval == 0 and self.Time.month != self.lastmonth):
            self.lastmonth = self.Time.month
            return [x.Symbol for x in coarse if x.HasFundamentalData]
        else:
            return Universe.Unchanged
    
    def FineSelectionFunction(self,fine):
        #momo_dict = {}
        momo_list = []
        MKTCAP_dict = {}
        #exclude delisted
        excluded_delisted = [i for i in fine if isinstance(i.SecurityReference.DelistingDate.date(),datetime) == False]
        
        #filter by mkt_cap
        for i in fine:
            if isinstance(i.MarketCap,(float,int)) and i.MarketCap != 0:
                MKTCAP_dict[i]=i.MarketCap
        microcap = [i for i in excluded_delisted if isinstance(MKTCAP_dict.get(i),(int,float)) and MKTCAP_dict.get(i)>25e6 and MKTCAP_dict.get(i)<250e6]
        
        #filter by Price-to-Sales Ratio < 1 (defined to be null if result <= 0)
        micro_PSR = [i for i in microcap if isinstance(i.ValuationRatios.PSRatio,(float,int)) and i.ValuationRatios.PSRatio < 1 and i.ValuationRatios.PSRatio > 0]
        
        #sorting by momentum
        hist = self.History([i.Symbol for i in micro_PSR], 365, Resolution.Daily)
        for i in micro_PSR:
            curr_price = hist.loc[str(i.Symbol)]['close'][-1]
            baseline_price = hist.loc[str(i.Symbol)]['close'][0]
            if i.Symbol.Value == "TOPS":
                self.Log(f'Start price: {baseline_price}; End price: {curr_price}; Return: {(curr_price - baseline_price) / baseline_price}')
            momo = curr_price/baseline_price
            momo_list.append(momo)
            #momo_dict[i] = momo
        
        micro_PSR_symbols = [f.Symbol.Value for f in micro_PSR]
        MKTCAP_list = ["{:e}".format(f.MarketCap) for f in micro_PSR]
        PSR_list = [f.ValuationRatios.PSRatio for f in micro_PSR]
        momo_zip = list(zip(micro_PSR, micro_PSR_symbols, MKTCAP_list, PSR_list, momo_list))

        micro_PSR_momo = sorted(momo_zip,key = lambda i: i[-1], reverse = True)
        output = [f[0].Symbol for f in micro_PSR_momo[:50]]
        self.Symbols = [f[1] for f in micro_PSR_momo[:50]]
        #self.Log(f'CURRENT STATE: {[f[1:] for f in micro_PSR_momo[:50]]}')
        return output
        
    def OnSecuritiesChanged(self, changes):
        return 
        # selected symbols will be found in Log
        self.Log(f'New Securities Added: {[security.Symbol.Value for security in changes.AddedSecurities]}')
        self.Log(f'Securities Removed{[security.Symbol.Value for security in changes.RemovedSecurities]}')
        #self.Log(f'CURRENT STATE: {self.Symbols}')