Overall Statistics
Total Trades
652
Average Win
2.00%
Average Loss
-1.45%
Compounding Annual Return
84.360%
Drawdown
27.800%
Expectancy
0.151
Net Profit
84.670%
Sharpe Ratio
1.378
Loss Rate
52%
Win Rate
48%
Profit-Loss Ratio
1.37
Alpha
1.329
Beta
-45.549
Annual Standard Deviation
0.426
Annual Variance
0.181
Information Ratio
1.34
Tracking Error
0.426
Treynor Ratio
-0.013
Total Fees
$18964.95
''' Set the starting cash amount '''
starting_cash = 100000

''' Set True to recieve email notifications '''
email_notify = True

''' Set the email address to recieve notifications '''
email = "jmoore@trifectaky.com"

''' Set True to enable logging '''
log = True

''' Set True for liquidating stocks at end of day'''
liquidate_at_end_of_day = True

'''
These filters the stock based on a lower % change and higher % change so only stock between this lower limit and upper limit will pass
(i.e -10 and 0 will find a price drop of at least 10% and a maximum of 0% gain)
'''
lower_day_price_change_percent = -10
upper_day_price_change_percent = -15


maximum_stocks = 5

'''using 1yr Price Range profit 6, loss 3'''
TargetProfit = 6
StopLoss = 3



'''
Specify the timing of the functions x time before close 
'''
entry_time_beforeclose = 10
exit_time_beforeclose = 12  ##this number has to be greater than entry time 

'''

'''
'''1yr Price Range'''
custom_tickers=['SGH','TLND','AM','AMGP','DLR','PLUG','MDB','AKBA','ASMB','DRYS','CYTK','TRXC','MGNX','CNSL','ADMS','TPL','HRTX','CDXS','NVAX','CTL','PRQR','BPT','SNAP','SALT','KRNY','CLVS','ATNX','DSX','SECO','SRCI','GNK','HOME','TWLO','QNST','SEND','EQT','CVNA','YEXT','SPKE','RDFN','FLXN','FSCT','XXII','RDUS','GTT','SIEB','EPD','EVI','SBLK','SENS','DERM','DGII','ICHR','ANGI','EGLE','SSTI','HQY','LSTR','NYMT','RIGL','SKY','NEWR','THR','DE','SBRA','RVNC','TBPH','ENTA','GCAP','GRUB','NFX','JHG','EVRG','SMHI','RNG','INVH','UPLD','PGNX','CHCT','REXR','MKL','OLBK','IIPR','RESI','SASR','VCEL','CSWC','EQM','PEN','MCB','COUP','ETSY','FIVE','AKCA','ERI','BOMN','ALBO','NFLX','PCH','HLNE','GDEN','ZEN','SE','INST','GOGL','SAFE','MB','RILY','CODI','MIME','WTM','TRC','NTNX','UBSH','VST','BL','TTD','RGEN','LBRDA','KREF','PBYI','GLIBA','ONCE','PVAC','QDEL','KPTI','BXMT','EQBK','BPMC','NCOM','STWD','ESIO','MRUS','LADR','ARRY','SSP','PUB','HPR','TNK','PPBI','SCACU','AGNC','CALM','ICPT','IRMD','SGMO','DX','FBNC','EQGP','LOXO','TWO','IAC','OKTA','HTGC','ADAP','CSFL','RBBN','CRM','LHCG','SYNH','NBHC','BMTC','NBLX','LPI','FFBC','KNOP','AMZN','TDW','WEN','PLT','CAMT','JAG','AVD','GLNG','MTCH','SFLY','MITK','IMMR','WDAY','APTS','DM','ATTU','OMP','VYGR','NNI','TBBK','HUBS','FBMS','DMLP','NLY','MUX','TBK','NVTR','STL','CIR','OCFC','ERIE','GLP','GWRE','JCAP','SFNC','USAC','YY','SCHN','MDR','HLX','DWDP','NOW','PKE','SAIL','GLUU','AYX','EFC','LND','ANET','CLR','CNX','FMC','MOS','CARG','NKTR','VLO','QTRX','IART','EXTR','EDN','WUBA','NMIH','NOG','CARO','BCEI','TTI','WB','CKH','FHN','DISCA','AVAV','MBUU','SPLK','ETM','REI','CARA','GPRK','QRTEA','RYAM','CQP','LABL','RCM','PETX','OPI','VICI','SSW','MCFT','BOOM','APPN','XNCR','PARR','IRTC','FTAI','CORT','LGND','BHGE','ENLC','QIWI','KRP','GFF','QD','SUN','MSBI','ASR','TRHC','PLNT','NVDA','TEAM','AVX','PAYC','FUL','NGL','MGLN','COWN','DLTH','GHL','TWOU','CTSO','DSKE','NANO','WNC','FB','TGS','ABEO','KALV','ATRO','RP','SUPN','PNFP','SSNC','WVE','JT','RLJ','MOMO','AMTD','EXPI','OXY','MSB','VRTS','LNG','PSTG','EVBG','FOLD','ENLK','KMPR','GPK','KNX','PGTI','SHI','EBS','ET','KKR','FPRX','KDP','CRY','WIX','TNDM','WPX','PAA','GRBK','SRPT','PE','PFPT','PRLB','MPLX','JEC','ICLR','EXEL','EXAS','SEDG','SNHY','YNDX','SANW','NBIX','SONA','EBIX','DK','AMWD','DNR','MDP','LFUS','PANW','RBNC','ROKU','GPOR','MTLS','GEL','STAA','XOG','SGRY','SUPV','PETQ','TSLA','TDOC','YPF','HCLP','OAS','ECHO','BCML','SBGL','FOXF','BFR','CDEV','CLDR','MTDR','SRLP','INGN','VECO','SMPL','APPF','PAGP','VEEV','PRAH','BDX','PXD','PBF','W','GGB','VRAY','SIVB','AGIO','CERS','TOL','HBMD','EVH','GRVY','FANG','RARE','MEET','PAM','GLPG','TUSK','AXDX','PTLA','BECN','VIRT','KEX','MRO','HBCP','TELL','JOBS','SINA','RGNX','DVAX','TECD','CRZO','BEAT','CZR','BSTI','DRNA','PTCT','EOG','REDU','APA','ZTO','BABA','MEDP','CDNA','OIS','SGEN','EDIT','FET','PATK','NYNY','SQ','TEO','COLL','POPE','CYRX','SUZ','RRC','GNMK','NVTA','AXGN','CJ','CXO','HP','LIVX','CPE','KOS','LMRK','SFIX','MAXR','MED','LOMA','SM','NVCR','ENVA','DXCM','ALGN','CCS','SIEN','SLCA','FRAC','ESTE','GGAL','GDS','WLL','RUN','TAL','SIGA','XELA','EDU','PTEN','BRY','SOI','MU','VNOM','WBAI','PUMP','LEN','ABMD','ACAD','GSM','MYOK','WTTR','WRD','GOGO']

'''VERY STABLE STOCKS
custom_tickers=['AEP','AJG','CMS','DTE','DUK','ES','ETR','EXC']

HIGH VOLATILITY WITH PE OVER 50
custom_tickers=['BEAT','UNIT','FIVE','PCG','EHTH','ABMD','CIG.C','DAVA','STAA','LOGM','VREX','AROC','SUM','ELLI','SHAK','RHT','CMPR','PEN','QLYS','MRCY','SONO','AAXN','HOME','GRUB','CROX','SYNA','ZAYO','LMNX','TCMD','TRIP','NXGN','VICR','PRGO','HQY','CSII','CIG','SFIX','AZUL','EIGI','YELP','ALGN','ANET','NFLX','INCY','AMD','NBIX','EPAY','MYGN','SMTC','APPF','EDU','HTHT','PAYC','INGN','BAND','TAL','GHDX','CARG','TME','ETSY','JD','BZUN','ACIA','CATM','OLED','TTD']

Top 10 Most Volatile
custom_tickers=['NKTR','COTY','SYMC','IGGP','AMD','NVDA','TWTR']

PE GREATER THAN 50
custom_tickers=['UNIT','GHDX','DPLO','EXTN','AROC','MTLS','TFX','IRT','BZUN','HTHT','FLS','CTK','BEAT','GRUB','THRM','MPAA','NXGN','NBIX','INXN','UIHC','CARB','CSII','Y','USWS','AZUL','SFIX','NEBU','NSA','BVN','KLXE','LASR','ETSY','TYL','HOME','CAH','KOP','BLX','HSKA','YELP','MRCY','NTGR','CCOI','SONO','TRIP','HMN','BIP','PEN','DLR','GOOD','ILMN','ALXN','TPRE','DCP','WELL','PRAH','FORR','JD','VICR','EXLS','TME','KEYW','RGEN','ZNGA','ENV','SPNS','EW','MMSI','ASH','OFIX','VRRM','NPO','ALGN','ANGI','EQIX','WES','CSGP','PRGO','SJR','CMSS','BHGE','CIG.C','EDU','HMSY','QUAD','PLYA','STN','INGN','ABMD','NKE','RXN','DAVA','MWA','HSTM','GTYH','MPWR','KRNT','ELAN','TFSL','MTRN','VEEV','KEX','MRVL','CHCT','AAXN','STFC','MYGN','FIVE','ALTM','LTM','SEAS','MANU','TPIC','NFLX','LGC','HQY','SUM','KWR','MCHP','ALRM','ADUS','LMNX','AIG','SMG','VRTU','ZAYO','PVAC','ESGR','EIGI','HR','BDX','CARG','ABT','IMAX','HPP','INCY','SCHL','ANIP','HAE','FNV','AXS','OLED','PLNT','MMDM','DAKT','CAMP','AGNC','VPV','VIOT','FNKO','CROX','LL','VKQ','BHE','VGM','ACM','WRE','FTAI','CCI','SUI','COLD','AMZN','CMPR','USPH','SSNC','PTC','AMD','AZPN','DEA','AMT','AAT','REXR','EHIC','ANET','ULTI','ELLI','CHTR','IDTI','CIVI','MSG','MDSO','SYNA','LBRDA','ICUI','LULU','ZYME','OPI','FSP','RPAI','ARRS','AOSL','MG','CUZ','IRMD','ISRG','EPAY','CXP','TRC','RGS','LNN','LBRDK','GNL','TECH','PGRE','ADSW','SHAK','TDC','COT','TPGH','BLKB','PYPL','WWE','CEVA','DSW','IPI','ALCO','TTD','NEO','GCI','RP','MOV','QRVO','OSIR','RHT','WING','CLBK','PACQ','QLYS','TCMD','BMI','RDWR','TYPE','DXCM','IT','BXP','RE','CRCM','EVI','DOC','DEI','CVLT','STAA','CMG','IQV','SMTC','SYKE','COO','JBGS','MKTX','ROL','AKR','CRM','DSGX','CPB','ACIW','CLNC','ARCE','FICO','TCO','HIMX','KEYS','CPT','PCTY','ACC','GTLS','QTNA','GSAH','UDR','TAL','AES','NOVT','MAC','VTR','MLAB','FRGI','MAA','APPF','PAYC','O','CUB','UFCS','OMCL','TCS','GORO','LOGM','UEIC','BAND','EGAN','SSRM','SPSC','VRNT','AMSWA','CNMD','MSTR','FARO','VREX','CYBR','BLFS','S','SAND','NUVA','OSPN','TNC','TPNL','GDDY','MSA','IIPR','PCG','IART','PEGA','KNDI','ATTU']

GARP
custom_tickers=['EIF.TO','PPL.TO','CVCO','UFPI','WGP','CTO','GSY.TO','LTXB','APOG','THO','SCHW','AAN','AMAT','AX','SBBX','FANG','ABCB','PXT.TO','ZAGG','COHR']

RELATIVE STRENGTH
'EMIS','WM.TO','KL.TO','KL','WRR.V','OSS.V','PAR','NOA.TO','TVK.TO','ALEF.V','KTOS','CSU.TO','CUSI','FCNE','EACO','AUTLY','MLR','WDO.TO','CNSWF','MRTX','UBNT','ENSG','GTY','ATAI','HEI','PMCUF','FBP','NXST','OMCL','FLWS','FICO','NILSY','AAIGF','VMW','VRSN','CRL','MKTX','INSG','EPAM','WDOFF','CWT','HEI.A','ANTM','GPRK','AMD','AGB.V','LION','EXPO','EEFT','IPHI','MSEX','CHGG','CDNS','TC.TO','MLNX','SPVEF','AAGIY','TCX','ATGN','SMTC','NEO','MNSB','MTA.V','SCIA','FTNT','XLNX','IEHC','KHRN.V','ZBRA','GLVMF','IPAR','NUAG.V','VTSYF','EBR','ULBI','EOG.V','SLP','NUPMF','MSON','ERIE','INTU','ALMFF','DXR','NRTH.V','VFF.TO','STBI','EXAS','GLXZ','NOAH','LLC.V','BOOM','IGCC']

17 FACTOR GROWTH
custom_tickers=['AVGO','LUV','MKSI','AC.TO','TMUS','LPX','SFTBF','UFPI','TBNGY','KDDIF','SZKMF','ASHTF','DLAKF','FCAU','AMCX','LRCX','LEA','TFII.TO','BABWF','GC.TO','SKX','AEIS','CFP.TO','SWKS','DXC','LCII','OSB.TO','THO','MPW','UTHR','FB','STLD','LNR.TO','URI','KLAC','DHI','BAK','AAN','AEO','AMAT','ALSN','ON','FANG','PXT.TO','WFT.TO','TX','MU','MOH','TECK.B.TO','COHR']

SMALL CAP ROCKETS
custom_tickers=['SMU.UN.TO','CVG.TO','EACO','ACNB','CTRE','CHMI','MSB','FBNC','DMLP','PBL.TO','MDC','MNSB','HTGC','HICKA']

TOP STOCKS
custom_tickers=['ATEYY','GRP.U','CALM','GRT.UN.TO','SPKKY','FBGBY','TBNGY','AHCHF','EYUBY','MOHCY','ITAYY','LBRDB','LKREF','AMCX','TOSBF','NUE','TOSYY','LBRDA','AGLXY','H','LBRDK','BPR','AHCHY','TSM','UTHR','AGLNF','INTC','CCU']
'''
import numpy as np
from custom_tickers import custom_tickers
from filters import *

class FinalAlgo(QCAlgorithm):

    def Initialize(self):

        self.SetStartDate(2018,2,26)  #Set Start Date
        self.SetEndDate(2019, 2,26)    #Set End Date
        self.SetCash(100000)           #Set Strategy Cash

        self.UniverseSettings.Resolution = Resolution.Minute
        self.AddUniverse(self.CoarseSelectionFunction)
        self.AddEquity("SPY",Resolution.Minute)

        self.__numberOfSymbols = maximum_stocks

        self.entry_minute = entry_time_beforeclose
        self.custom_tickers=custom_tickers  
        self.universe = None
        self.filtered_symbols = []
        self.lower_percentage_change_limit = float(lower_day_price_change_percent)
        self.upper_percentage_change_limit = float(upper_day_price_change_percent)
        
        self.TargetProfit = float(TargetProfit)
        self.StopLoss = float(StopLoss)

        '''
        buy filtered stocks
        at min before market close
        '''
        self.Schedule.On(self.DateRules.EveryDay("SPY"),
                         self.TimeRules.BeforeMarketClose("SPY",self.entry_minute),
                         Action(self.EnterPosition))
        
        '''
        liquidate all holdings before market close
        '''
        if liquidate_at_end_of_day:
            self.Schedule.On(self.DateRules.EveryDay("SPY"), 
                         self.TimeRules.BeforeMarketClose("SPY", exit_time_beforeclose), 
                         Action(self.long_exit))
        
            
        #Set true if you want to see the stoploss and target for each stock in logs     
        self._logTargets = True
        
        self.log = log
        self.email_notify = email_notify
        self.email=email
        if email_notify:
            self.Notify.Email(email, "Live!", "Algorithm is now live.")
                         
    def CoarseSelectionFunction(self, coarse):
        self.universe = [x.Symbol for x in coarse if (x.Symbol.Value in self.custom_tickers and x.Price > 1)]
        self.Log(f'Coarse length: {len(self.universe)}')
        return self.universe

    def EnterPosition(self):
       
        self.filtered_symbols = []
        if self.universe is None: return
        for stock in self.universe:
            hist = self.History([str(stock),], 1, Resolution.Daily)
  
            if hist.empty: continue
  
            day_close = float(self.Securities[stock].Price)

            prev_close = float(hist["close"][-1]) 
            day_change_percent = 100*((day_close-prev_close) / prev_close)
            
            if day_change_percent < self.lower_percentage_change_limit and day_change_percent > self.upper_percentage_change_limit and len(self.filtered_symbols) < self.__numberOfSymbols:
                self.Log('stock=' + str(stock) + ' day change percent '+ str(day_change_percent))
                self.filtered_symbols.append(stock)

        if len(self.filtered_symbols) < 1: return
        if not self.Portfolio.Invested:
            for stock in self.filtered_symbols:
                self.SetHoldings(stock, 1 / len(self.filtered_symbols))
                self.Log('here2')
                
        self._logTargets = True
        
    def OnData(self, data):
        
        if len(self.filtered_symbols) < 1: return
    
        for stock in self.filtered_symbols:
            
            if not self.Securities[stock].Invested: 
                self.filtered_symbols.remove(stock)
                continue
            
            '''
            calculation of cost basis (average holding cost)
            '''
            abs_hold_cost = self.Portfolio[stock].AbsoluteHoldingsCost
            abs_hold_q = self.Portfolio[stock].AbsoluteQuantity
            Cost_Basis = float(abs_hold_cost/abs_hold_q) # Determine cost basis of each stock in the portfolio
            
            Current_Price = self.Securities[stock].Price # Determine current price of each stock
            
            '''
            stop loss check
            '''
            StopLossCondition = Current_Price <= 0.01*(100.0-self.StopLoss)*Cost_Basis
            
            '''
            target profit check
            '''
            TargetProfitCondition = Current_Price >= 0.01*(100.0+self.TargetProfit)*Cost_Basis
            
            
            if self._logTargets == True:
                self.Log('Ticker='+ str(stock) + ' current_price=' + str(Current_Price) + 
                ' stop_loss=' + str(0.01*(100.0-self.StopLoss)*Cost_Basis) + ' target=' + str(0.01*(100.0+self.TargetProfit)*Cost_Basis))
                
            
            if (StopLossCondition):
                self.Liquidate(stock,"Liquidated: Stop Loss")
                
            if (TargetProfitCondition):
                self.Liquidate(stock,"Liquidated: Target Profit")
                
                
        self._logTargets = False
        
    '''
    liquidate all holdings
    '''
    def long_exit(self):
        self.Liquidate()
    
    def OnOrderEvent(self, orderEvent):
        s = orderEvent.Symbol
        if orderEvent.FillQuantity < 0:
            if self.email_notify:
                self.Notify.Email(self.email, 'New Order', 'Sold {0} FillQuantity: {1} FillPrice: {2}'.format(s.Value, orderEvent.FillQuantity, orderEvent.FillPrice))
        elif self.email_notify:
            self.Notify.Email(self.email, 'New Order', 'Bought: {0} FillQuantity: {1} FillPrice: {2}'.format(s.Value, orderEvent.FillQuantity, orderEvent.FillPrice))
        if self.log:
            self.Log(str(orderEvent))