Overall Statistics
Total Trades
379
Average Win
1.87%
Average Loss
-2.59%
Compounding Annual Return
8.536%
Drawdown
65.600%
Expectancy
0.060
Net Profit
55.248%
Sharpe Ratio
0.394
Probabilistic Sharpe Ratio
5.460%
Loss Rate
38%
Win Rate
62%
Profit-Loss Ratio
0.72
Alpha
0.15
Beta
-0.12
Annual Standard Deviation
0.336
Annual Variance
0.113
Information Ratio
-0.037
Tracking Error
0.385
Treynor Ratio
-1.108
Total Fees
$18597.43
Estimated Strategy Capacity
$32000000.00
Lowest Capacity Asset
WY R735QTJ8XC9X
'''
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(2016, 1, 1)  # Set Start Date
        self.SetCash(2000000)  # Set Strategy Cash
        
        ## Don't execute too often because risk that importing from dropbox won't work
        
        # https://www.dropbox.com/s/ly58k3jbw35265i/signaux_5_titres.csv?dl=0
        # https://www.dropbox.com/s/lvye1cffc38z33i/signaux_5_titres_correct.csv?dl=1
        # https://www.dropbox.com/s/qur4qqfgwvdh4ti/new_factor_signaux_presentable.csv?dl=1

        # ça n'a aucun impact car on n'utilise pas le jour mais uniquement mois et année
    
        # https://www.dropbox.com/s/pclfy4j872wduqf/signaux_5_titres_correct_sans_j_ferie.csv?dl=0
        # https://www.dropbox.com/s/rauf6rxypu1vck2/signaux_5_titres_correct_2016_test_1.csv?dl=0 on retire les signaux du 4 jan 2016
        # https://www.dropbox.com/s/qyjwkvqea8givyb/signaux_5_titres_correct_2016_test_2.csv?dl=0 on retire les signaux du 4et 11 jan 2016 
        # https://www.dropbox.com/s/9u78yvd1fb6nvkm/signaux_5_titres_correct_2016_test_3.csv?dl=0 on retire les signaux du 4, 11 et 18 jan 2016 
        self.csv = self.Download("https://www.dropbox.com/s/lvye1cffc38z33i/signaux_5_titres_correct.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 = 1
        
    ''' Handles monthly counter and if conditions are met, pick trades '''
    def MonthlyRebalance(self):
        self.PickTrades()

            
    ''' 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 self.Time.month == date.month and tuple.position == 1:
                foundDate = True
                if not self.currentData.ContainsKey(tuple.Symbol):
                    self.Debug("missing key :" + str(date))
                    # manage missing key
                    continue
                enterPositions.append(self.allSecurities[tuple.Symbol])
                continue
                
            if foundDate == True:
                break
        
        self.MakeTrades(currentlyInvested, enterPositions)
            
    ''' Submited orders '''
    def MakeTrades(self, currentlyInvested, enterPositions):

        # gestion du cas où le enterPositions est vide
        # dans ce cas, on garde le portefeuille currentlyInvested

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

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