Overall Statistics |
Total Trades 35623 Average Win 0.03% Average Loss -0.02% Compounding Annual Return 40.917% Drawdown 16.900% Expectancy 0.163 Net Profit 74.091% Sharpe Ratio 1.745 Probabilistic Sharpe Ratio 77.217% Loss Rate 59% Win Rate 41% Profit-Loss Ratio 1.81 Alpha 0.374 Beta -0.083 Annual Standard Deviation 0.203 Annual Variance 0.041 Information Ratio 0.365 Tracking Error 0.338 Treynor Ratio -4.253 Total Fees $36010.68 Estimated Strategy Capacity $98000000.00 Lowest Capacity Asset NWSVV VHJF6S7EZRL1 |
max_drawdown = 0.05 market = 'SPY' silver = 'SLV' gold = 'GLD' utility = 'XLU' industrial = 'XLI' safe = 'FXF' risk = 'FXA' debt_short = 'SHY' debt_inflation = 'TIP' metal = 'DBB' inp = 'IGE' cash = 'UUP' equities = ['A','AAP','AAPL','ABC','ABMD','ABT','ADBE','ADI','ADM','ADP','ADSK','AGN','AGR','AKAM','ALB','ALGN','ALK','ALLE','ALV','ALXN','AMAT','AMD','AME','AMGN','AMT','ANET','ANSS','AOS','APD','APTV','ARW','ASH','ATO','ATVI','AVB','AVY','AYI','AZO','BAX','BBY','BG','BIIB','BIO','BKNG','BKR','BMRN','BSX','BURL','BWA','CAH','CCEP','CDNS','CDW','CERN','CF','CGNX','CHD','CHRW','CL','CLX','CMI','COG','COO','COP','CPRI','CPRT','CRM','CSCO','CSX','CTAS','CTSH','CTVA','CTXS','CVS','CVX','CXO','DAL','DD','DGX','DHI','DHR','DLTR','DOV','DOW','DOX','DRE','DVA','DVN','EBAY','ECL','EIX','EL','ELAN','EMR','EOG','EQIX','ETN','EW','EXC','EXPD','EXPE','FANG','FAST','FB','FCX','FDX','FFIV','FISV','FL','FLEX','FLS','FLT','FMC','FTI','FTNT','FTV','GDDY','GILD','GLW','GNTX','GOOG','GOOGL','GPC','GPS','GRMN','GRUB','GWW','HAL','HAS','HD','HEI','HEIA','HES','HFC','HOLX','HP','HPE','HPQ','HSIC','HSY','IBM','IDXX','IEX','IFF','ILMN','INCY','INFO','INTC','INTU','IP','IPG','IPGP','IR','ISRG','IT','ITW','JAZZ','JBHT','JBL','JCI','JNJ','JNPR','JWN','KDP','KEYS','KHC','KLAC','KMB','KNX','KO','KSS','KSU','LDOS','LEA','LEN','LIN','LKQ','LLY','LOW','LRCX','LULU','LUV','LW','LYB','M','MAS','MCD','MCK','MDLZ','MDT','MDU','MHK','MKC','MLM','MMM','MNST','MOS','MPC','MRK','MRO','MRVL','MSFT','MSI','MTD','MU','MXIM','NBL','NEM','NKE','NLOK','NOV','NOW','NSC','NTAP','NUE','NVDA','NVR','NWS','NWSA','NXPI','ODFL','OGE','OMC','ORCL','ORLY','OXY','PAYC','PAYX','PCG','PEG','PEP','PFE','PG','PHM','PKG','PKI','PLD','PNR','PNW','PPG','PRGO','PSA','PSX','PTC','PVH','PXD','QCOM','QRVO','REGN','RHI','RL','RMD','ROK','ROL','ROP','ROST','SBUX','SCCO','SHW','SLB','SNA','SNPS','ST','STE','STLD','STX','SWK','SWKS','SYK','TEL','TFX','TGT','TIF','TJX','TMO','TOL','TPR','TRMB','TSCO','TSLA','TT','TWTR','TXN','TYL','UA','UAA','UAL','ULTA','UNP','UPS','VAR','VFC','VLO','VMC','VMW','VRSN','VRTX','WAB','WAT','WBA','WBC','WDAY','WDC','WHR','WLK','WY','XEC','XOM','XRAY','XRX','XYL','YNDX','ZBRA'] #equities = ['ATVI', 'ADBE', 'AMD', 'ALGN', 'ALXN', 'AMZN', 'AMGN', 'AAL', 'ADI', 'AAPL', 'AMAT', 'ASML', 'ADSK', 'ADP', 'AVGO', 'BIDU', 'BIIB', 'BMRN', 'CDNS', 'CERN', 'CHKP', 'CHTR', 'TCOM', 'CTAS', 'CSCO', 'CTXS', 'CMCSA', 'COST', 'CSX', 'CTSH', 'DLTR', 'EA', 'EBAY', 'EXC', 'EXPE', 'FAST', 'FB', 'FISV', 'GILD', 'GOOG', 'GOOGL', 'HAS', 'HSIC', 'ILMN', 'INCY', 'INTC', 'INTU', 'ISRG', 'IDXX', 'JBHT', 'JD', 'KLAC', 'KHC', 'LRCX', 'LBTYA', 'LBTYK', 'LULU', 'MELI', 'MAR', 'MCHP', 'MDLZ', 'MNST', 'MSFT', 'MU', 'MXIM', 'MYL', 'NTAP', 'NFLX', 'NTES', 'NVDA', 'NXPI', 'ORLY', 'PAYX', 'PCAR', 'BKNG', 'PYPL', 'PEP', 'QCOM', 'REGN', 'ROST', 'SIRI', 'SWKS', 'SBUX', 'NLOK', 'SNPS', 'TTWO', 'TSLA', 'TXN', 'TMUS', 'ULTA', 'UAL', 'VRSN', 'VRSK', 'VRTX', 'WBA', 'WDC', 'WDAY', 'WYNN', 'XEL', 'XLNX'] #'AAN', 'AAOI', 'AAON', 'AAT', 'AAWW', 'AAXN', 'ABCB', 'ABEO', 'ABG', 'ABM', 'ABTX', 'AC', 'ACA', 'ACAD', 'ACBI', 'ACCO', 'ACER', 'ACHN', 'ACIA', 'ACIW', 'ACLS', 'ACNB', 'ACOR', 'ACRE', 'ACRS', 'ACRX', 'ACTG', 'ADC', 'ADES', 'ADMA', 'ADMS', 'ADNT', 'ADRO', 'ADSW', 'ADTN', 'ADUS', 'ADVM', 'AEGN', 'AEIS', 'AEL', 'AEO', 'AERI', 'AFI', 'AFIN', 'AFMD', 'AGE', 'AGEN', 'AGLE', 'AGM', 'AGS', 'AGX', 'AGYS', 'AHH', 'AHT', 'AI', 'AIMC', 'AIMT', 'AIN', 'AIR', 'AIRG', 'AIT', 'AJRD', 'AJX', 'AKBA', 'AKCA', 'AKR', 'AKRO', 'AKRX', 'AKS', 'AKTS', 'ALBO', 'ALCO', 'ALDR', 'ALDX', 'ALE', 'ALEC', 'ALEX', 'ALG', 'ALGT', 'ALLK', 'ALLO', 'ALOT', 'ALRM', 'ALTM', 'ALTR', 'ALX', 'AMAG', 'AMAL', 'AMBA', 'AMBC', 'AMC', 'AMED', 'AMEH', 'AMK', 'AMKR', 'AMN', 'AMNB', 'AMOT', 'AMPH', 'AMRC', 'AMRS', 'AMRX', 'AMSC', 'AMSF', 'AMSWA', 'AMTB', 'AMWD', 'ANAB', 'ANDE', 'ANF', 'ANGO', 'ANH', 'ANIK', 'ANIP', 'AOBC', 'AOSL', 'APAM', 'APEI', 'APLS', 'APOG', 'APPF', 'APPN', 'APPS', 'APTS', 'APYX', 'AQUA', 'ARA', 'ARAY', 'ARCB', 'ARCH', 'ARDX', 'ARES', 'ARGO', 'ARI', 'ARL', 'ARLO', 'ARNA', 'AROC', 'AROW', 'ARQL', 'ARR', 'ARTNA', 'ARVN', 'ARWR', 'ASC', 'ASGN', 'ASIX', 'ASMB', 'ASNA', 'ASPS', 'ASRT', 'ASTE', 'AT', 'ATEC', 'ATEN', 'ATEX', 'ATGE', 'ATHX', 'ATI', 'ATKR', 'ATLO', 'ATNI', 'ATNX', 'ATRA', 'ATRC', 'ATRI', 'ATRO', 'ATRS', 'ATSG', 'AUB', 'AVA', 'AVAV', 'AVCO', 'AVD', 'AVDR', 'AVID', 'AVNS', 'AVRO', 'AVX', 'AVXL', 'AVYA', 'AWR', 'AX', 'AXAS', 'AXDX', 'AXE', 'AXGN', 'AXL', 'AXLA', 'AXNX', 'AXSM', 'AXTI', 'AYR', 'AZZ', 'B', 'BANC', 'BAND', 'BANF', 'BANR', 'BATRA', 'BATRK', 'BBBY', 'BBCP', 'BBIO', 'BBSI', 'BBX', 'BCBP', 'BCC', 'BCEI', 'BCEL', 'BCML', 'BCO', 'BCOR', 'BCOV', 'BCPC', 'BCRX', 'BDC', 'BDGE', 'BDSI', 'BE', 'BEAT', 'BECN', 'BELFB', 'BFC', 'BFIN', 'BFS', 'BFST', 'BGG', 'BGS', 'BGSF', 'BH', 'BHB', 'BHE', 'BHLB', 'BHR', 'BHVN', 'BIG', 'BIOS', 'BJ', 'BJRI', 'BKD', 'BKE', 'BKH', 'BL', 'BLBD', 'BLD', 'BLDR', 'BLFS', 'BLKB', 'BLMN', 'BLX', 'BMCH', 'BMI', 'BMRC', 'BMTC', 'BNED', 'BNFT', 'BOCH', 'BOLD', 'BOMN', 'BOOM', 'BOOT', 'BOX', 'BPFH', 'BPMC', 'BPRN', 'BRC', 'BREW', 'BRG', 'BRID', 'BRKL', 'BRKS', 'BRT', 'BRY', 'BSET', 'BSGM', 'BSIG', 'BSRR', 'BSTC', 'BSVN', 'BTAI', 'BTU', 'BUSE', 'BV', 'BWB', 'BWFG', 'BXC', 'BXG', 'BXMT', 'BXS', 'BY', 'BYD', 'BYSI', 'BZH', 'CAC', 'CADE', 'CAI', 'CAKE', 'CAL', 'CALA', 'CALM', 'CALX', 'CAMP', 'CAR', 'CARA', 'CARB', 'CARE', 'CARG', 'CARO', 'CARS', 'CASA', 'CASH', 'CASI', 'CASS', 'CATC', 'CATM', 'CATO', 'CATS', 'CATY', 'CBAN', 'CBAY', 'CBB', 'CBL', 'CBLK', 'CBM', 'CBMG', 'CBNK', 'CBPX', 'CBRL', 'CBTX', 'CBU', 'CBZ', 'CCB', 'CCBG', 'CCF', 'CCMP', 'CCNE', 'CCO', 'CCOI', 'CCRN', 'CCS', 'CCXI', 'CDE', 'CDLX', 'CDMO', 'CDNA', 'CDR', 'CDXC', 'CDXS', 'CDZI', 'CECE', 'CECO', 'CEIX', 'CELC', 'CELH', 'CENT', 'CENTA', 'CENX', 'CERC', 'CERS', 'CETV', 'CEVA', 'CFB', 'CFFI', 'CFFN', 'CFMS', 'CHAP', 'CHCO', 'CHCT', 'CHDN', 'CHEF', 'CHGG', 'CHMA', 'CHMG', 'CHMI', 'CHRA', 'CHRS', 'CHS', 'CHUY', 'CIA', 'CIO', 'CIR', 'CISN', 'CIVB', 'CIX', 'CJ', 'CKH', 'CKPT', 'CLAR', 'CLBK', 'CLCT', 'CLDR', 'CLDT', 'CLF', 'CLFD', 'CLI', 'CLNC', 'CLNE', 'CLPR', 'CLVS', 'CLW', 'CLXT', 'CMBM', 'CMC', 'CMCO', 'CMCT', 'CMLS', 'CMO', 'CMP', 'CMPR', 'CMRE', 'CMRX', 'CMTL', 'CNBKA', 'CNCE', 'CNDT', 'CNMD', 'CNNE', 'CNO', 'CNOB', 'CNR', 'CNS', 'CNSL', 'CNST', 'CNTY', 'CNX', 'CNXN', 'CODA', 'COHU', 'COKE', 'COLB', 'COLL', 'CONN', 'COOP', 'CORE', 'CORR', 'CORT', 'COWN', 'CPE', 'CPF', 'CPK', 'CPLG', 'CPRX', 'CPS', 'CPSI', 'CRAI', 'CRBP', 'CRC', 'CRCM', 'CRD.A', 'CRK', 'CRMD', 'CRMT', 'CRNX', 'CROX', 'CRS', 'CRTX', 'CRUS', 'CRVL', 'CRY', 'CRZO', 'CSFL', 'CSGS', 'CSII', 'CSLT', 'CSOD', 'CSTE', 'CSTL', 'CSTR', 'CSV', 'CSWI', 'CTB', 'CTBI', 'CTMX', 'CTO', 'CTRA', 'CTRC', 'CTRE', 'CTRN', 'CTS', 'CTSO', 'CTT', 'CTWS', 'CUB', 'CUBI', 'CUE', 'CULP', 'CURO', 'CUTR', 'CVA', 'CVBF', 'CVCO', 'CVCY', 'CVGI', 'CVGW', 'CVI', 'CVIA', 'CVLT', 'CVLY', 'CVM', 'CVRS', 'CVTI', 'CWCO', 'CWEN', 'CWEN.A', 'CWH', 'CWK', 'CWST', 'CWT', 'CXW', 'CYCN', 'CYH', 'CYRX', 'CYTK', 'CZNC', 'DAKT', 'DAN', 'DAR', 'DBD', 'DBI', 'DCO', 'DCOM', 'DCPH', 'DDD', 'DDS', 'DEA', 'DECK', 'DENN', 'DERM', 'DF', 'DFIN', 'DGICA', 'DGII', 'DHIL', 'DHT', 'DHX', 'DIN', 'DIOD', 'DJCO', 'DK', 'DLA', 'DLTH', 'DLX', 'DMRC', 'DNBF', 'DNLI', 'DNOW', 'DNR', 'DO', 'DOC', 'DOMO', 'DOOR', 'DORM', 'DOVA', 'DPLO', 'DRH', 'DRNA', 'DRQ', 'DS', 'DSKE', 'DSPG', 'DSSI', 'DTIL', 'DVAX', 'DX', 'DXPE', 'DY', 'DZSI', 'EAT', 'EB', 'EBF', 'EBIX', 'EBS', 'EBSB', 'EBTC', 'ECHO', 'ECOL', 'ECOM', 'ECOR', 'ECPG', 'EDIT', 'EE', 'EEX', 'EFC', 'EFSC', 'EGAN', 'EGBN', 'EGHT', 'EGLE', 'EGOV', 'EGP', 'EGRX', 'EHTH', 'EIDX', 'EIG', 'EIGI', 'EIGR', 'ELF', 'ELOX', 'ELVT', 'ELY', 'EME', 'EML', 'ENDP', 'ENFC', 'ENOB', 'ENPH', 'ENS', 'ENSG', 'ENTA', 'ENV', 'ENVA', 'ENZ', 'EOLS', 'EPAY', 'EPC', 'EPM', 'EPRT', 'EPZM', 'EQBK', 'ERA', 'ERI', 'ERII', 'EROS', 'ESCA', 'ESE', 'ESGR', 'ESNT', 'ESPR', 'ESQ', 'ESSA', 'ESTE', 'ESXB', 'ETH', 'ETM', 'EVBG', 'EVBN', 'EVC', 'EVER', 'EVFM', 'EVH', 'EVI', 'EVLO', 'EVOP', 'EVRI', 'EVTC', 'EXLS', 'EXPI', 'EXPO', 'EXPR', 'EXTN', 'EXTR', 'EYE', 'EYPT', 'EZPW', 'FARM', 'FARO', 'FATE', 'FBC', 'FBIZ', 'FBK', 'FBM', 'FBMS', 'FBNC', 'FBP', 'FC', 'FCAP', 'FCBC', 'FCBP', 'FCCY', 'FCF', 'FCFS', 'FCN', 'FCPT', 'FDBC', 'FDEF', 'FDP', 'FELE', 'FET', 'FF', 'FFBC', 'FFG', 'FFIC', 'FFIN', 'FFNW', 'FFWM', 'FG', 'FGBI', 'FGEN', 'FI', 'FIBK', 'FII', 'FISI', 'FIT', 'FIVN', 'FIX', 'FIXX', 'FIZZ', 'FLDM', 'FLIC', 'FLMN', 'FLNT', 'FLOW', 'FLWS', 'FLXN', 'FLXS', 'FMAO', 'FMBH', 'FMBI', 'FMNB', 'FN', 'FNCB', 'FNHC', 'FNKO', 'FNLC', 'FNWB', 'FOCS', 'FOE', 'FOLD', 'FOR', 'FORM', 'FORR', 'FOSL', 'FOXF', 'FPI', 'FPRX', 'FR', 'FRAC', 'FRAF', 'FRBA', 'FRBK', 'FRGI', 'FRME', 'FRPH', 'FRPT', 'FRTA', 'FSB', 'FSBW', 'FSCT', 'FSP', 'FSS', 'FSTR', 'FTK', 'FTR', 'FTSI', 'FTSV', 'FUL', 'FULC', 'FULT', 'FVCB', 'FWRD', 'GABC', 'GAIA', 'GALT', 'GATX', 'GBCI', 'GBL', 'GBLI', 'GBT', 'GBX', 'GCAP', 'GCBC', 'GCI', 'GCO', 'GCP', 'GDEN', 'GDOT', 'GDP', 'GEF', 'GEF.B', 'GEN', 'GENC', 'GEO', 'GEOS', 'GERN', 'GES', 'GFF', 'GFN', 'GHDX', 'GHL', 'GHM', 'GIII', 'GKOS', 'GLDD', 'GLNG', 'GLOG', 'GLRE', 'GLT', 'GLUU', 'GLYC', 'GME', 'GMED', 'GMRE', 'GMS', 'GNC', 'GNE', 'GNK', 'GNL', 'GNLN', 'GNMK', 'GNRC', 'GNTY', 'GNW', 'GOGO', 'GOLF', 'GOOD', 'GORO', 'GOSS', 'GPI', 'GPMT', 'GPOR', 'GPRE', 'GPRO', 'GPX', 'GRBK', 'GRC', 'GRIF', 'GRPN', 'GRTS', 'GSBC', 'GSHD', 'GSIT', 'GTHX', 'GTLS', 'GTN', 'GTS', 'GTT', 'GTY', 'GTYH', 'GVA', 'GWB', 'GWGH', 'GWRS', 'HA', 'HABT', 'HAE', 'HAFC', 'HALL', 'HALO', 'HARP', 'HASI', 'HAYN', 'HBB', 'HBCP', 'HBMD', 'HBNC', 'HCAT', 'HCC', 'HCCI', 'HCI', 'HCKT', 'HCSG', 'HEES', 'HELE', 'HFFG', 'HFWA', 'HI', 'HIBB', 'HIFS', 'HIIQ', 'HL', 'HLI', 'HLIO', 'HLIT', 'HLNE', 'HLX', 'HMHC', 'HMN', 'HMST', 'HMSY', 'HMTV', 'HNGR', 'HNI', 'HNRG', 'HOFT', 'HOMB', 'HOME', 'HONE', 'HOOK', 'HOPE', 'HPR', 'HQY', 'HR', 'HRI', 'HRTG', 'HRTX', 'HSC', 'HSII', 'HSKA', 'HSTM', 'HT', 'HTBI', 'HTBK', 'HTH', 'HTLD', 'HTLF', 'HTZ', 'HUBG', 'HUD', 'HURC', 'HURN', 'HVT', 'HWBK', 'HWC', 'HWKN', 'HY', 'HZO', 'I', 'IBCP', 'IBKC', 'IBOC', 'IBP', 'IBTX', 'ICD', 'ICFI', 'ICHR', 'ICPT', 'IDCC', 'IDEX', 'IDT', 'IESC', 'IHC', 'III', 'IIIN', 'IIIV', 'IIN', 'IIPR', 'IIVI', 'ILPT', 'IMAX', 'IMGN', 'IMKTA', 'IMMR', 'IMMU', 'IMXI', 'INBK', 'INDB', 'INFN', 'INGN', 'INN', 'INO', 'INOV', 'INS', 'INSE', 'INSG', 'INSM', 'INSP', 'INST', 'INSW', 'INT', 'INTL', 'INVA', 'INWK', 'IOSP', 'IOTS', 'IOVA', 'IPAR', 'IPHI', 'IPHS', 'IPI', 'IRBT', 'IRDM', 'IRET', 'IRMD', 'IRT', 'IRTC', 'IRWD', 'ISBC', 'ISCA', 'ISRL', 'ISTR', 'ITCI', 'ITGR', 'ITI', 'ITIC', 'ITRI', 'IVC', 'IVR', 'JACK', 'JAG', 'JAX', 'JBSS', 'JBT', 'JCAP', 'JCOM', 'JCP', 'JELD', 'JILL', 'JJSF', 'JNCE', 'JOE', 'JOUT', 'JRVR', 'JYNT', 'KAI', 'KALA', 'KALU', 'KALV', 'KAMN', 'KBAL', 'KBH', 'KBR', 'KDMN', 'KE', 'KELYA', 'KEM', 'KFRC', 'KFY', 'KIDS', 'KIN', 'KLDO', 'KLXE', 'KMT', 'KN', 'KNL', 'KNSA', 'KNSL', 'KOD', 'KOP', 'KPTI', 'KRA', 'KREF', 'KRG', 'KRNY', 'KRO', 'KRTX', 'KRUS', 'KRYS', 'KTB', 'KTOS', 'KURA', 'KVHI', 'KW', 'KWR', 'KZR', 'LAD', 'LADR', 'LANC', 'LAND', 'LASR', 'LAUR', 'LAWS', 'LBAI', 'LBC', 'LBRT', 'LC', 'LCI', 'LCII', 'LCNB', 'LCTX', 'LCUT', 'LDL', 'LE', 'LEAF', 'LEE', 'LEGH', 'LEVL', 'LFVN', 'LGIH', 'LGND', 'LHCG', 'LILA', 'LILAK', 'LIND', 'LITE', 'LIVN', 'LIVX', 'LJPC', 'LKFN', 'LKSD', 'LL', 'LLNW', 'LMAT', 'LMNR', 'LMNX', 'LNDC', 'LNN', 'LNTH', 'LOB', 'LOCO', 'LOGC', 'LORL', 'LOVE', 'LPG', 'LPI', 'LPSN', 'LPX', 'LQDA', 'LQDT', 'LRN', 'LSCC', 'LTC', 'LTHM', 'LTRPA', 'LTS', 'LTXB', 'LVGO', 'LXFR', 'LXP', 'LXRX', 'LXU', 'LZB', 'MANT', 'MATW', 'MATX', 'MAXR', 'MBI', 'MBII', 'MBIN', 'MBIO', 'MBUU', 'MBWM', 'MC', 'MCB', 'MCBC', 'MCFT', 'MCHX', 'MCRB', 'MCRI', 'MCRN', 'MCS', 'MDC', 'MDCA', 'MDCO', 'MDGL', 'MDP', 'MDR', 'MDRX', 'MEC', 'MED', 'MEDP', 'MEET', 'MEI', 'MEIP', 'MESA', 'METC', 'MFIN', 'MFNC', 'MFSF', 'MG', 'MGEE', 'MGLN', 'MGNX', 'MGPI', 'MGRC', 'MGTA', 'MGTX', 'MGY', 'MHO', 'MIK', 'MINI', 'MIRM', 'MITK', 'MITT', 'MJCO', 'MLAB', 'MLHR', 'MLI', 'MLND', 'MLP', 'MLR', 'MLVF', 'MMAC', 'MMI', 'MMS', 'MMSI', 'MNK', 'MNKD', 'MNLO', 'MNOV', 'MNR', 'MNRL', 'MNRO', 'MNSB', 'MNTA', 'MOBL', 'MOD', 'MODN', 'MOFG', 'MOG.A', 'MORF', 'MOV', 'MPAA', 'MPB', 'MPX', 'MR', 'MRC', 'MRCY', 'MRKR', 'MRLN', 'MRNS', 'MRSN', 'MRTN', 'MRTX', 'MSA', 'MSBI', 'MSEX', 'MSGN', 'MSON', 'MSTR', 'MTDR', 'MTEM', 'MTH', 'MTOR', 'MTRN', 'MTRX', 'MTSC', 'MTSI', 'MTW', 'MTX', 'MTZ', 'MUSA', 'MVBF', 'MWA', 'MXL', 'MYE', 'MYGN', 'MYOK', 'MYRG', 'NANO', 'NAT', 'NATH', 'NATR', 'NAV', 'NBEV', 'NBHC', 'NBN', 'NBR', 'NBTB', 'NC', 'NCBS', 'NCI', 'NCMI', 'NCSM', 'NDLS', 'NE', 'NEO', 'NEOG', 'NERV', 'NESR', 'NEWM', 'NEXT', 'NFBK', 'NG', 'NGHC', 'NGM', 'NGS', 'NGVC', 'NGVT', 'NHC', 'NHI', 'NINE', 'NJR', 'NKSH', 'NL', 'NMIH', 'NMRK', 'NNBR', 'NNI', 'NODK', 'NOG', 'NOVA', 'NOVT', 'NP', 'NPK', 'NPO', 'NPTN', 'NR', 'NRC', 'NRCG', 'NRIM', 'NSA', 'NSIT', 'NSP', 'NSSC', 'NSTG', 'NTB', 'NTCT', 'NTGN', 'NTGR', 'NTLA', 'NTRA', 'NTUS', 'NUVA', 'NVAX', 'NVCR', 'NVEC', 'NVEE', 'NVRO', 'NVTA', 'NWBI', 'NWE', 'NWFL', 'NWLI', 'NWN', 'NWPX', 'NX', 'NXGN', 'NXRT', 'NXTC', 'NYMT', 'NYNY', 'OAS', 'OBNK', 'OCFC', 'OCN', 'OCUL', 'OCX', 'ODC', 'ODP', 'ODT', 'OEC', 'OFG', 'OFIX', 'OFLX', 'OGS', 'OII', 'OIS', 'OLBK', 'OLP', 'OMCL', 'OMER', 'OMI', 'OMN', 'ONB', 'ONCE', 'ONDK', 'OOMA', 'OPB', 'OPBK', 'OPI', 'OPK', 'OPRX', 'OPTN', 'OPY', 'ORA', 'ORBC', 'ORC', 'ORGO', 'ORIT', 'ORRF', 'OSBC', 'OSG', 'OSIS', 'OSMT', 'OSPN', 'OSTK', 'OSUR', 'OSW', 'OTTR', 'OVBC', 'OVLY', 'OXM', 'PACB', 'PACD', 'PAHC', 'PAR', 'PARR', 'PATK', 'PAYS', 'PBFS', 'PBH', 'PBI', 'PBIP', 'PBPB', 'PBYI', 'PCB', 'PCH', 'PCRX', 'PCSB', 'PCYO', 'PDCE', 'PDCO', 'PDFS', 'PDLB', 'PDLI', 'PDM', 'PEB', 'PEBK', 'PEBO', 'PEGI', 'PEI', 'PENN', 'PETQ', 'PETS', 'PFBC', 'PFBI', 'PFGC', 'PFIS', 'PFNX', 'PFS', 'PFSI', 'PGC', 'PGNX', 'PGTI', 'PHAS', 'PHR', 'PHUN', 'PHX', 'PI', 'PICO', 'PIRS', 'PJC', 'PJT', 'PKBK', 'PKD', 'PKE', 'PKOH', 'PLAB', 'PLAY', 'PLCE', 'PLMR', 'PLOW', 'PLPC', 'PLSE', 'PLT', 'PLUG', 'PLUS', 'PLXS', 'PMBC', 'PMT', 'PNM', 'PNRG', 'PNTG', 'POL', 'POR', 'POWI', 'POWL', 'PPBI', 'PQG', 'PRA', 'PRAA', 'PRFT', 'PRGS', 'PRGX', 'PRIM', 'PRK', 'PRLB', 'PRMW', 'PRNB', 'PRO', 'PROS', 'PROV', 'PRPL', 'PRSC', 'PRSP', 'PRTA', 'PRTH', 'PRTK', 'PRTY', 'PRVL', 'PSB', 'PSDO', 'PSMT', 'PSN', 'PSNL', 'PTCT', 'PTE', 'PTGX', 'PTLA', 'PTN', 'PTSI', 'PTVCB', 'PUB', 'PUMP', 'PVAC', 'PVBC', 'PWOD', 'PYX', 'PZN', 'PZZA', 'QADA', 'QCRH', 'QDEL', 'QEP', 'QLYS', 'QNST', 'QTRX', 'QTS', 'QTWO', 'QUAD', 'QUOT', 'RAD', 'RAMP', 'RARE', 'RARX', 'RAVN', 'RBB', 'RBBN', 'RBCAA', 'RBNC', 'RC', 'RCII', 'RCKT', 'RCKY', 'RCM', 'RCUS', 'RDFN', 'RDI', 'RDN', 'RDNT', 'RDUS', 'REAL', 'RECN', 'REGI', 'REI', 'REPH', 'REPL', 'RES', 'RESI', 'RETA', 'REV', 'REVG', 'REX', 'REXR', 'RFL', 'RGCO', 'RGEN', 'RGNX', 'RGR', 'RGS', 'RH', 'RHP', 'RICK', 'RIGL', 'RILY', 'RLGT', 'RLGY', 'RLH', 'RLI', 'RLJ', 'RM', 'RMAX', 'RMBI', 'RMBS', 'RMNI', 'RMR', 'RMTI', 'RNET', 'RNST', 'ROAD', 'ROAN', 'ROCK', 'ROG', 'ROIC', 'ROLL', 'ROSE', 'RPD', 'RPT', 'RRBI', 'RRD', 'RRGB', 'RRR', 'RRTS', 'RST', 'RTEC', 'RTIX', 'RTRX', 'RTW', 'RUBI', 'RUBY', 'RUN', 'RUSHA', 'RUSHB', 'RUTH', 'RVI', 'RVNC', 'RVSB', 'RWT', 'RXN', 'RYAM', 'RYI', 'RYTM', 'SAFE', 'SAFM', 'SAFT', 'SAH', 'SAIA', 'SAIC', 'SAIL', 'SALT', 'SAM', 'SAMG', 'SANM', 'SASR', 'SAVE', 'SB', 'SBBP', 'SBBX', 'SBCF', 'SBH', 'SBOW', 'SBRA', 'SBSI', 'SBT', 'SCHL', 'SCHN', 'SCL', 'SCOR', 'SCS', 'SCSC', 'SCU', 'SCVL', 'SCWX', 'SD', 'SDRL', 'SEAS', 'SEM', 'SEMG', 'SENEA', 'SENS', 'SF', 'SFBS', 'SFE', 'SFIX', 'SFL', 'SFNC', 'SFST', 'SGA', 'SGC', 'SGH', 'SGMO', 'SGMS', 'SGRY', 'SHAK', 'SHBI', 'SHEN', 'SHO', 'SHOO', 'SHSP', 'SIBN', 'SIC', 'SIEB', 'SIEN', 'SIG', 'SIGA', 'SIGI', 'SILK', 'SITE', 'SJI', 'SJW', 'SKT', 'SKY', 'SKYW', 'SLAB', 'SLCA', 'SLCT', 'SLDB', 'SLP', 'SM', 'SMBC', 'SMBK', 'SMHI', 'SMMF', 'SMP', 'SMPL', 'SMTC', 'SNBR', 'SNCR', 'SND', 'SNDX', 'SNH', 'SNR', 'SOI', 'SOLY', 'SONA', 'SONM', 'SONO', 'SP', 'SPAR', 'SPFI', 'SPKE', 'SPNE', 'SPOK', 'SPPI', 'SPRO', 'SPSC', 'SPTN', 'SPWH', 'SPWR', 'SPXC', 'SR', 'SRCE', 'SRCI', 'SRDX', 'SRG', 'SRI', 'SRNE', 'SRRK', 'SRT', 'SSB', 'SSD', 'SSP', 'SSTI', 'SSTK', 'SSYS', 'STAA', 'STAG', 'STAR', 'STBA', 'STC', 'STFC', 'STIM', 'STML', 'STMP', 'STNG', 'STOK', 'STRA', 'STRL', 'STRO', 'STRS', 'STXB', 'SUM', 'SUPN', 'SVMK', 'SVRA', 'SWAV', 'SWM', 'SWN', 'SWX', 'SXC', 'SXI', 'SXT', 'SYBT', 'SYBX', 'SYKE', 'SYNA', 'SYNH', 'SYNL', 'SYRS', 'SYX', 'TACO', 'TALO', 'TAST', 'TBBK', 'TBI', 'TBIO', 'TBK', 'TBNK', 'TBPH', 'TCBK', 'TCDA', 'TCFC', 'TCI', 'TCMD', 'TCRR', 'TCS', 'TCX', 'TDOC', 'TDW', 'TECD', 'TELL', 'TEN', 'TENB', 'TERP', 'TESS', 'TEUM', 'TEX', 'TG', 'TGH', 'TGI', 'TGNA', 'TGTX', 'TH', 'THC', 'THFF', 'THOR', 'THR', 'THRM', 'TILE', 'TIPT', 'TISI', 'TITN', 'TIVO', 'TK', 'TLRA', 'TLRD', 'TLYS', 'TMDX', 'TMHC', 'TMP', 'TMST', 'TNAV', 'TNC', 'TNDM', 'TNET', 'TNK', 'TOCA', 'TORC', 'TOWN', 'TPB', 'TPC', 'TPCO', 'TPH', 'TPIC', 'TPRE', 'TPTX', 'TR', 'TRC', 'TREC', 'TREX', 'TRHC', 'TRMK', 'TRNO', 'TRNS', 'TROX', 'TRS', 'TRST', 'TRTN', 'TRTX', 'TRUE', 'TRUP', 'TRWH', 'TRXC', 'TSBK', 'TSC', 'TSE', 'TTEC', 'TTEK', 'TTGT', 'TTI', 'TTMI', 'TTS', 'TUP', 'TUSK', 'TVTY', 'TWI', 'TWIN', 'TWNK', 'TWST', 'TXMD', 'TXRH', 'TYME', 'TYPE', 'TZOO', 'UBA', 'UBFO', 'UBNK', 'UBSI', 'UBX', 'UCBI', 'UCFC', 'UCTT', 'UE', 'UEC', 'UEIC', 'UFCS', 'UFI', 'UFPI', 'UFPT', 'UHT', 'UIHC', 'UIS', 'ULH', 'UMBF', 'UMH', 'UNB', 'UNF', 'UNFI', 'UNIT', 'UNT', 'UNTY', 'UPLD', 'UPWK', 'URGN', 'USCR', 'USLM', 'USNA', 'USPH', 'USWS', 'USX', 'UTL', 'UTMD', 'UUUU', 'UVE', 'UVSP', 'UVV', 'VAC', 'VALU', 'VAPO', 'VBIV', 'VBTX', 'VC', 'VCEL', 'VCRA', 'VCYT', 'VEC', 'VECO', 'VG', 'VGR', 'VHC', 'VHI', 'VIAV', 'VICR', 'VIVO', 'VKTX', 'VLGEA', 'VLY', 'VNCE', 'VNDA', 'VPG', 'VRA', 'VRAY', 'VRCA', 'VREX', 'VRNS', 'VRNT', 'VRRM', 'VRS', 'VRTS', 'VRTU', 'VRTV', 'VSEC', 'VSH', 'VSLR', 'VSTO', 'VVI', 'VYGR', 'WAAS', 'WABC', 'WAFD', 'WAIR', 'WASH', 'WATT', 'WBT', 'WD', 'WDFC', 'WDR', 'WERN', 'WETF', 'WEYS', 'WGO', 'WHD', 'WHG', 'WIFI', 'WINA', 'WING', 'WIRE', 'WK', 'WLDN', 'WLFC', 'WLH', 'WLL', 'WMC', 'WMGI', 'WMK', 'WMS', 'WNC', 'WNEB', 'WOR', 'WOW', 'WPG', 'WRE', 'WRLD', 'WRTC', 'WSBC', 'WSBF', 'WSC', 'WSFS', 'WSR', 'WTBA', 'WTI', 'WTRE', 'WTRH', 'WTS', 'WTTR', 'WVE', 'WW', 'WWW', 'XAN', 'XBIT', 'XELA', 'XENT', 'XERS', 'XFOR', 'XHR', 'XLRN', 'XNCR', 'XOG', 'XON', 'XPER', 'XXII', 'YCBD', 'YELP', 'YETI', 'YEXT', 'YGYI', 'YMAB', 'YORW', 'YRCW', 'ZAGG', 'ZEUS', 'ZGNX', 'ZIOP', 'ZIXI', 'ZUMZ', 'ZUO', 'ZYNE', 'ZYXI'] safeties = ['FXF', 'FXA', 'UUP'] Invest = 100000 resolution = Resolution.Daily InOut_resolution = Resolution.Hour returns_resolution = Resolution.Daily disableSupertrend = True disableSqueeze = True disableInAndOut = True bull = True inOutLookbackBull = 30 inOutLookbackBear = 5 waitDaysConstant = 1 iniWaitDays = 1 minWaitDays = 1 superTrendPeriod = 1 superTrendMultiple = 3 superTrendUseHA = False squeezeTrendPeriod = 1 squeezeBBMultiple = 2 squeezeKeltMultiple = 1 max_drawdown = 0.01 drawdown_waitdays = 0 drawdown_lookback = 3 max_alloc = .1 returns_lookback = 2 rebalance = 1 equities_weight = 1 debug = False dev_mode = False if dev_mode: from AlgorithmImports import * from collections import deque from collections.abc import Iterable from datetime import datetime from typing import Deque, Dict, List, Union import numpy as np import pandas as pd import operator class MySuperTrend: def __init__(self, period, multiple, movingAverageType=MovingAverageType.Exponential): self.Name = "SuperTrend" self.Time = datetime.min self.Value = 0 self.multiplier = multiple self.atr = AverageTrueRange(period, movingAverageType) self.values = deque(maxlen=period) self.previousTrailingLowerBand = 0 self.previousTrailingUpperBand = 0 self.previousClose = 0 self.previousTrend = 0 def __repr__(self): return "{0} -> IsReady: {1}. Time: {2}. Value: {3}".format(self.Name, self.IsReady, self.Time, self.Value) def Update(self, input:TradeBar): self.Time = input.EndTime self.atr.Update(input) superTrend = 0 currentClose = input.Close currentBasicLowerBand = (input.Low + input.High) / 2 - self.multiplier * self.atr.Current.Value currentBasicUpperBand = (input.Low + input.High) / 2 + self.multiplier * self.atr.Current.Value if self.previousClose > self.previousTrailingLowerBand: currentTrailingLowerBand = max(currentBasicLowerBand, self.previousTrailingLowerBand) else: currentTrailingLowerBand = currentBasicLowerBand if self.previousClose < self.previousTrailingUpperBand: currentTrailingUpperBand = min(currentBasicUpperBand, self.previousTrailingUpperBand) else: currentTrailingUpperBand = currentBasicUpperBand if currentClose > currentTrailingUpperBand: currentTrend = 1 elif currentClose < currentTrailingLowerBand: currentTrend = -1 else: currentTrend = self.previousTrend if currentTrend == 1: superTrend = currentTrailingLowerBand elif currentTrend == -1: superTrend = currentTrailingUpperBand self.previousTrailingLowerBand = currentTrailingLowerBand self.previousTrailingUpperBand = currentTrailingUpperBand self.previousClose = currentClose self.previousTrend = currentTrend if not self.atr.IsReady: return 0 self.Value = superTrend return self.IsReady @property def IsReady(self): return self.atr.IsReady and self.Value != 0 class Squeeze: def __init__(self, period, squeezeBBMultiple, squeezeKeltMultiple, movingAverageType=MovingAverageType.Exponential): ''' Value = 1 iff "squeezed" else .Value = 0 ''' self.Name = "Squeeze" self.Time = datetime.min self.Value = 0 self.bb = BollingerBands(period, squeezeBBMultiple, movingAverageType) self.kelt = KeltnerChannels(period, squeezeKeltMultiple, movingAverageType) def __repr__(self): return "{0} -> IsReady: {1}. Time: {2}. Value: {3}".format(self.Name, self.IsReady, self.Time, self.Value) def Update(self, input:TradeBar): self.Time = input.EndTime self.kelt.Update(input) self.bb.Update(input.EndTime, input.Close) isSqueeze = self.bb.UpperBand.Current.Value > self.kelt.UpperBand.Current.Value self.Value = int(isSqueeze) return self.IsReady @property def IsReady(self): return self.kelt.IsReady and self.bb.IsReady class Drawdown: def __init__(self, period:int): self.values = deque(maxlen=period) self.Value = 0 def Update(self, input:Union[TradeBar, float]): if isinstance(input, float): self.values.append(input) else: self.values.append(input.Close) cum_returns = (1 + pd.Series(self.values)).cumprod() self.Value = 1 - cum_returns.div(cum_returns.cummax()).iloc[-1] return self.IsReady @property def IsReady(self): return len(self.values) == self.values.maxlen class InAndOut: def __init__(self, algo:QCAlgorithm, InOut_resolution, symbols:List[str], period:int, iniWaitDays, minWaitDays, waitDaysConst, bull=True): self.Time = datetime.min self.period = period self.iniWaitDays = iniWaitDays self.minWaitDays = minWaitDays self.waitDaysConst = waitDaysConst self.bull = bull (self.market, self.silver, self.gold, self.utility, self.industrial, self.safe, self.risk, self.debt_short, self.debt_inflation, self.metal, self.input, self.cash) = symbols self.bull_signal_indices = [self.industrial, self.metal, self.input] self.history: dict[Symbol, Deque[float]] = {} history_df = algo.History(symbols, period, resolution) for symbol in symbols: if symbol in history_df and len(history_df[symbol]) > 0: self.history[symbol] = deque(history_df[symbol]['close'], maxlen=period) else: self.history[symbol] = deque(maxlen=period) self.wait_days = 0 def Update(self, input:Slice): self.Time = input.Time for symbol, history in self.history.items(): if input.Bars.ContainsKey(symbol): history.append(input[symbol].Close) def is_bullish(self): history_dict = {symbol: pd.Series(data) for symbol, data in self.history.items()} cust_returns_dict: dict[Union[Symbol, str], pd.Series] = {} for symbol in history_dict: if len(history_dict[symbol]) != self.period: return False, 0 hist_series = history_dict[symbol] cust_returns_dict[symbol] = (hist_series / hist_series.rolling(5, center=True).mean().shift(10)).dropna() - 1 history_dict[symbol] = history_dict[symbol][-len(cust_returns_dict[symbol]):] gold_min_silver = 'gold_min_silver' industrial_min_utility = 'industrial_min_utility' risk_min_safe = 'risk_min_safe' cash_inverse = 'cash_inverse' cust_returns_dict[gold_min_silver] = cust_returns_dict[self.gold] - cust_returns_dict[self.silver] cust_returns_dict[industrial_min_utility] = cust_returns_dict[self.industrial] - cust_returns_dict[self.utility] cust_returns_dict[risk_min_safe] = cust_returns_dict[self.risk] - cust_returns_dict[self.safe] cust_returns_dict[cash_inverse] = -1 * cust_returns_dict[self.cash] is_extreme_returns_dict: dict[Union[Symbol, str], bool] = {} for symbol, returns in cust_returns_dict.items(): is_extreme_returns_dict[symbol] = returns.iloc[-1] < np.percentile(returns, 1) inflation = 'inflation' history_dict[inflation] = cust_returns_dict[self.debt_short] - cust_returns_dict[self.debt_inflation] isabovemedian_dict = { symbol: (series.iloc[-1] > series.median()) for symbol, series in history_dict.items() } interest_expected = 'interest_expected' if is_extreme_returns_dict[self.debt_short] and isabovemedian_dict[self.metal] and isabovemedian_dict[self.input]: is_extreme_returns_dict[interest_expected] = False else: is_extreme_returns_dict[interest_expected] = is_extreme_returns_dict[self.debt_short] gold_min_silver_adj = 'gold_min_silver_adj' if is_extreme_returns_dict[gold_min_silver] and isabovemedian_dict[inflation]: is_extreme_returns_dict[gold_min_silver_adj] = False else: is_extreme_returns_dict[gold_min_silver_adj] = is_extreme_returns_dict[gold_min_silver] def wait_days_helper(symbol0, symbol1): series0 = cust_returns_dict[symbol0] series1 = cust_returns_dict[symbol1] if series0.iloc[-1] > 0 and series1.iloc[-1] < 0 and series1.iloc[-2] > 0: return self.iniWaitDays else: return 1 self.wait_days = int( max( self.wait_days/2, self.iniWaitDays * max ( 1, wait_days_helper(self.gold, self.silver), wait_days_helper(self.utility, self.industrial), wait_days_helper(self.safe, self.risk) ) ) ) signals = self.bull_signal_indices + [gold_min_silver_adj, industrial_min_utility, risk_min_safe, cash_inverse] bullish = any([is_extreme_returns_dict[signal] for signal in signals]) return bullish, min(self.minWaitDays, self.wait_days) def is_bearish(self): market_returns = pd.Series(self.history[self.market]).pct_change().dropna() volatililty = .6 * np.sqrt(252) * np.log1p(market_returns).std() returns_lookback = int(min( (1-volatililty)*self.waitDaysConst, self.period )) wait_days = int(volatililty * self.waitDaysConst) signals = [self.silver, self.gold, self.industrial, self.utility, self.metal, self.cash] returns = {} for signal in signals: data = self.history[signal] if len(data) < returns_lookback: return False, 0 returns[signal] = pd.Series(data).pct_change(returns_lookback).iloc[-1] def compare(symbol0, symbol1): return returns[symbol0] < returns[symbol1] compares = compare(self.silver, self.gold) and compare(self.industrial, self.utility) and compare(self.metal, self.cash) return compares, wait_days def minmax(self, n1, min_val, max_val): return max(min(n1, min_val), max_val) def get_signal(self): if self.bull: return self.is_bullish() else: return self.is_bearish() class ReturnsManager: def __init__(self, algo, period, returns_resolution, max_drawdown, drawdown_lookback, max_alloc): self.algo = algo self.period = period self.drawdown_lookback = drawdown_lookback self.daily_returns_dict: Dict[Symbol, RateOfChange] = {} self.returns_dict: Dict[Symbol, RateOfChange] = {} self.dd = Drawdown(self.drawdown_lookback) self.weights_dict: Dict[Symbol, float] = {} self.max_drawdown = max_drawdown self.max_alloc = max_alloc def Update(self, input:Slice): portfolio_returns_cross_section = 0 for symbol in self.returns_dict: if input.Bars.ContainsKey(symbol): daily_returns = self.daily_returns_dict[symbol] daily_returns.Update(input.Time, input[symbol].Close) self.returns_dict[symbol].Update(input.Time, input[symbol].Close) if symbol in self.weights_dict and daily_returns.IsReady: item_returns = self.weights_dict[symbol] * daily_returns.Current.Value portfolio_returns_cross_section += item_returns if portfolio_returns_cross_section: self.dd.Update(portfolio_returns_cross_section) def UpdateWeights(self): total_weight = sum( returns.Current.Value for returns in self.returns_dict.values() if returns.IsReady ) if not total_weight: return {} self.weights_dict = { symbol: min(returns.Current.Value / total_weight, self.max_alloc) for symbol, returns in self.returns_dict.items() } return self.weights_dict def GetWeights(self): return self.weights_dict def IsSell(self): return self.dd.Value > self.max_drawdown @property def IsReady(self): return np.any([returns.IsReady for symbol, returns in self.returns_dict.items()]) and len(self.weights_dict) > 0 def WarmUp(self, symbols:Union[Symbol, None]): if not isinstance(symbols, Iterable): symbols = [symbols] hist = self.algo.History(symbols, self.period, self.resolution) for symbol in symbols: if symbol not in hist.index or not len(hist.loc[symbol]): continue closes = hist.loc[symbol]['close'] for dt, close in closes.iteritems(): self.daily_returns_dict[symbol].Update(dt, close) self.returns_dict[symbol].Update(dt, close) def AddSecurity(self, symbol:Symbol): if symbol not in self.returns_dict: self.daily_returns_dict[symbol] = RateOfChange(1) self.returns_dict[symbol] = RateOfChange(self.period) class AdaptableRedSnake(QCAlgorithm): def load_configs_and_indicators(self): self.Cash = Invest index_tickers = [market, silver, gold, utility, industrial, safe, risk, debt_short, debt_inflation, metal, inp, cash] self.indices = [ self.AddEquity(ticker, resolution).Symbol for ticker in index_tickers ] inOutLookback = inOutLookbackBull if bull else inOutLookbackBear self.inandout = InAndOut(self, resolution, self.indices, inOutLookback, iniWaitDays, minWaitDays, waitDaysConstant, bull) self.returnsmanager = ReturnsManager(self, returns_lookback, resolution, max_drawdown, drawdown_lookback, max_alloc) self.equities = [ self.AddEquity(ticker, resolution).Symbol for ticker in equities ] for equity in self.equities: self.Securities[equity].SetDataNormalizationMode(DataNormalizationMode.Raw) self.safeties = [ self.AddEquity(ticker, resolution).Symbol for ticker in safeties ] for safety in self.safeties: self.Securities[safety].SetDataNormalizationMode(DataNormalizationMode.Raw) self.symbolData = { symbol: SymbolData(self, symbol, resolution, superTrendPeriod, superTrendMultiple, squeezeTrendPeriod, squeezeBBMultiple, squeezeKeltMultiple, superTrendUseHA) for symbol in self.equities + self.safeties } self.universe = self.equities self.UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw self.next_reentry = self.Time self.was_bull = False self.inout_signal = False self.inout_waitdays = 0 for symbol in self.equities + self.safeties: self.returnsmanager.AddSecurity(symbol) self.SetWarmUp(max( inOutLookbackBear, inOutLookbackBull, returns_lookback ), InOut_resolution) self.SetWarmUp(max( superTrendPeriod, squeezeTrendPeriod ), resolution) def Initialize(self): self.load_configs_and_indicators() self.market = market self.SetBenchmark(self.market) self.SetBrokerageModel(BrokerageName.InteractiveBrokersBrokerage) self.SetStartDate(2020, 1, 1) self.SetCash(Invest) self.days_count = 0 self.curr_day = -1 self.init_rebalance = True def Print(self, msg): if debug: self.Debug(msg) def OnData(self, data:Slice): for symbol, symbolData in self.symbolData.items(): if data.Bars.ContainsKey(symbol): symbolData.Update(data[symbol]) if self.was_bull and not self.IsWarmingUp: self.rebalance(data) if self.curr_day == self.Time.day: return self.curr_day = self.Time.day if not any([data.Bars.ContainsKey(symbol) for symbol in self.equities]): return self.days_count += 1 self.inandout.Update(data) self.returnsmanager.Update(data) if self.init_rebalance or self.days_count % rebalance == 0: self.init_rebalance = False self.returnsmanager.UpdateWeights() self.inout_signal, self.inout_waitdays = self.inandout.get_signal() if self.IsWarmingUp: return if self.returnsmanager.IsSell(): self.Liquidate() self.next_reentry = self.Time + timedelta(days=drawdown_waitdays) elif (self.inout_signal or disableInAndOut): debug and self.Print('Bull Condition Reached') if not self.was_bull and self.Time >= self.next_reentry: self.Print('Going Bull') self.go_bull() self.was_bull = True elif self.was_bull: self.Print(f'Going Bear:') self.go_bear() self.was_bull = False self.next_reentry = self.Time + timedelta(days=self.inout_waitdays) self.PlotSeries() def PlotSeries(self): self.Plot('BullBear', 'bull=1,bear=0', int(self.was_bull)) def go_bear(self): if self.IsWarmingUp: return self.Liquidate() self.universe = self.safeties self.UniverseSettings.DataNormalizationMode = DataNormalizationMode.Raw for symbol in self.safeties: self.SetHoldings(symbol, equities_weight/len(self.safeties)) self.was_bull = False def go_bull(self): if self.IsWarmingUp: return self.Liquidate() for symbol, symbolData in self.symbolData.items(): if symbolData.IsBuy(self.Securities[symbol].Price): weight = self.returnsmanager.GetWeights().get(symbol, 0) if weight: self.SetHoldings(symbol, weight * equities_weight) def rebalance(self, data:Slice): bought = [] for symbol, symbolData in self.symbolData.items(): if symbol not in self.universe: continue isbuy = symbolData.IsBuy(self.Securities[symbol].Price) if not isbuy: self.Liquidate(symbol) elif not self.Portfolio[symbol].Invested: weight = self.returnsmanager.GetWeights().get(symbol, 0) self.SetHoldings(symbol, weight * equities_weight) bought.append(symbol) class SymbolData: def __init__(self, algo:QCAlgorithm, symbol, resolution, periodST, multipleST, periodSQ, BBmultipleSQ, KELTmultipleSQ, useHA): self.symbol = symbol self.supertrend = MySuperTrend(periodST, multipleST) self.squeeze = Squeeze(periodSQ, BBmultipleSQ, KELTmultipleSQ) self.algo = algo self.useHA = useHA if useHA: self.ha = HeikinAshi(symbol) def Update(self, input:TradeBar): if self.useHA: self.ha.Update(input) if self.ha.IsReady: haBar = TradeBar(self.algo.Time, self.symbol, self.ha.Open.Current.Value, self.ha.High.Current.Value, self.ha.Low.Current.Value, self.ha.Close.Current.Value, self.ha.Volume.Current.Value) self.supertrend.Update(haBar) else: self.supertrend.Update(input) self.squeeze.Update(input) def IsBuy(self, price): return (self.squeeze.Value or disableSqueeze) or (price > self.supertrend.Value or disableSupertrend)