Overall Statistics
Total Trades
1653
Average Win
0.75%
Average Loss
-0.53%
Compounding Annual Return
15.204%
Drawdown
56.100%
Expectancy
0.685
Net Profit
1960.005%
Sharpe Ratio
0.692
Probabilistic Sharpe Ratio
3.674%
Loss Rate
31%
Win Rate
69%
Profit-Loss Ratio
1.43
Alpha
0.157
Beta
-0.086
Annual Standard Deviation
0.218
Annual Variance
0.047
Information Ratio
0.267
Tracking Error
0.29
Treynor Ratio
-1.745
Total Fees
$3783.40
Estimated Strategy Capacity
$6.50
'''
File Rebalancing
'''

import pandas as pd
import numpy as np
from io import StringIO
from datetime import date, timedelta, datetime

class FocusedYellowGreenSheep(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2000, 1, 1)  # Set Start Date
        self.SetCash(100000)  # Set Strategy Cash
        
        self.csv = self.Download("https://www.dropbox.com/s/qur4qqfgwvdh4ti/new_factor_signaux_presentable.csv?dl=1")
        self.df = pd.read_csv(StringIO(self.csv))
        
        self.allSecurities = {}
        self.symbols = ['A','AAL','AAP','AAPL','ABBV','ABC','ABMD','ABT','ACN','ADBE','ADI','ADM','ADP','ADSK','AEE','AEP','AES','AFL','AIG','AIZ','AJG','AKAM','ALB','ALGN','ALK','ALL','ALLE','ALXN','AMAT','AMCR','AMD','AME','AMGN','AMP','AMT','AMZN','ANET','ANSS','ANTM','AON','AOS','APA','APD','APH','APTV','ARE','ATO','ATVI','AVB','AVGO','AVY','AWK','AXP','AZO','BA','BAC','BAX','BBY','BDX','BEN','BFb','BIIB','BIO','BK','BKNG','BKR','BLK','BLL','BMY','BR','BRKb','BSX','BWA','BXP','C','CAG','CAH','CARR','CAT','CB','CBOE','CBRE','CCI','CCL','CDNS','CDW','CE','CERN','CF','CFG','CHD','CHRW','CHTR','CI','CINF','CL','CLX','CMA','CMCSA','CME','CMG','CMI','CMS','CNC','CNP','COF','COG','COO','COP','COST','CPB','CPRT','CRM','CSCO','CSX','CTAS','CTLT','CTSH','CTVA','CTXS','CVS','CVX','D','DAL','DD','DE','DFS','DG','DGX','DHI','DHR','DIS','DISCA','DISCK','DISH','DLR','DLTR','DOV','DOW','DPZ','DRE','DRI','DTE','DUK','DVA','DVN','DXC','DXCM','EA','EBAY','ECL','ED','EFX','EIX','EL','EMN','EMR','ENPH','EOG','EQIX','EQR','ES','ESS','ETN','ETR','ETSY','EVRG','EW','EXC','EXPD','EXPE','EXR','F','FANG','FAST','FB','FBHS','FCX','FDX','FE','FFIV','FIS','FISV','FITB','FLIR','FLS','FLT','FMC','FOXA','FRC','FRT','FTNT','FTV','GD','GE','GILD','GIS','GL','GLW','GM','GOOG','GOOGL','GPC','GPN','GPS','GRMN','GS','GWW','HAL','HAS','HBAN','HBI','HCA','HD','HES','HFC','HIG','HII','HLT','HOLX','HON','HPE','HPQ','HRL','HSIC','HST','HSY','HUM','HWM','IBM','ICE','IDXX','IEX','IFF','ILMN','INCY','INFO','INTC','INTU','IP','IPG','IPGP','IQV','IR','IRM','ISRG','IT','ITW','IVZ','JBHT','JCI','JEC','JKHY','JNJ','JNPR','JPM','K','KEY','KEYS','KHC','KIM','KLAC','KMB','KMI','KMX','KO','KR','KSU','L','LB','LDOS','LEG','LEN','LH','LHX','LIN','LKQ','LLY','LMT','LNC','LNT','LOW','LRCX','LUMN','LUV','LVS','LW','LYB','LYV','MA','MAA','MAR','MAS','MCD','MCHP','MCK','MCO','MDLZ','MDT','MET','MGM','MHK','MKC','MKTX','MLM','MMC','MMM','MNST','MO','MOS','MPC','MPWR','MRK','MRO','MS','MSCI','MSFT','MSI','MTB','MTD','MU','MXIM','NCLH','NDAQ','NEE','NEM','NFLX','NI','NKE','NLOK','NLSN','NOC','NOV','NOW','NRG','NSC','NTAP','NTRS','NUE','NVDA','NVR','NWL','NWSA','O','ODFL','OKE','OMC','ORCL','ORLY','OTIS','OXY','PAYC','PAYX','PBCT','PCAR','PEAK','PEG','PEP','PFE','PFG','PG','PGR','PH','PHM','PKG','PKI','PLD','PM','PNC','PNR','PNW','POOL','PPG','PPL','PRGO','PRU','PSA','PSX','PVH','PWR','PXD','PYPL','QCOM','QRVO','RCL','RE','REG','REGN','RF','RHI','RJF','RL','RMD','ROK','ROL','ROP','ROST','RSG','RTX','SBAC','SBUX','SCHW','SEE','SHW','SIVB','SJM','SLB','SLG','SNA','SNPS','SO','SPG','SPGI','SRE','STE','STT','STX','STZ','SWK','SWKS','SYF','SYK','SYY','T','TAP','TDG','TDY','TEL','TER','TFC','TFX','TGT','TJX','TMO','TMUS','TPR','TRMB','TROW','TRV','TSCO','TSLA','TSN','TT','TTWO','TWTR','TXN','TXT','TYL','UA','UAA','UAL','UDR','UHS','ULTA','UNH','UNM','UNP','UPS','URI','USB','V','VAR','VFC','VIAC','VLO','VMC','VNO','VNT','VRSK','VRSN','VRTX','VTR','VTRS','VZ','WAB','WAT','WBA','WDC','WEC','WELL','WFC','WHR','WLTW','WM','WMB','WMT','WRB','WRK','WST','WU','WY','WYNN','XEL','XLNX','XOM','XRAY','XRX','XYL','YUM','ZBH','ZBRA','ZION','ZTS']
        for symbol in self.symbols:
            security = self.AddEquity(symbol, Resolution.Daily).Symbol
            self.allSecurities[symbol] = security
            
        self.spy = self.AddEquity("SPY", Resolution.Daily).Symbol
            
        self.Schedule.On(self.DateRules.MonthStart("SPY"),
        self.TimeRules.At(0, 0), # We receive the signal monday 22h swiss
        self.MonthlyRebalance)
        
        self.yearCounter = 0
        
    ''' Handles monthly counter and if conditions are met, pick trades '''
    def MonthlyRebalance(self):
        if self.yearCounter == 11:
            self.PickTrades()
            self.yearCounter = 0
        else:
            self.yearCounter += 1
            
    ''' Parses csv file, and picks the corresponding trades based on year '''
    def PickTrades(self):
        enterPositions = []
        currentlyInvested = [x.Key for x in self.Portfolio if x.Value.Invested]
        foundDate = False
        for tuple in self.df.itertuples():
            date = datetime.strptime(tuple.Date, "%d/%m/%Y")
            if self.Time.year == date.year and tuple.position == 1:
                foundDate = True
                if not self.currentData.ContainsKey(tuple.Symbol):
                    continue
                enterPositions.append(self.allSecurities[tuple.Symbol])
                continue
                
            if foundDate == True:
                break
        
        self.MakeTrades(currentlyInvested, enterPositions)
            
    ''' Submited orders '''
    def MakeTrades(self, currentlyInvested, enterPositions):

        for symbol in currentlyInvested:
            if symbol not in enterPositions:
                self.Liquidate(symbol)

        # Si rien dans enterPositions on ne rebalance pas le portefeuille
        if len(enterPositions) == 0:
            self.Debug("enterPosition is empty")
            return                
        
        weight = 1/len(enterPositions)
        for symbol in enterPositions:
            self.SetHoldings([PortfolioTarget(symbol, weight)])

    def OnData(self, data):
        self.currentData = data
        pass