| 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)