Overall Statistics
Total Trades
9242
Average Win
0.10%
Average Loss
-0.11%
Compounding Annual Return
27.527%
Drawdown
29.400%
Expectancy
0.241
Net Profit
237.750%
Sharpe Ratio
1.256
Probabilistic Sharpe Ratio
61.782%
Loss Rate
34%
Win Rate
66%
Profit-Loss Ratio
0.87
Alpha
0.268
Beta
-0.144
Annual Standard Deviation
0.195
Annual Variance
0.038
Information Ratio
0.323
Tracking Error
0.275
Treynor Ratio
-1.698
Total Fees
$18373.41
Estimated Strategy Capacity
$11000000.00
Lowest Capacity Asset
APAM VEP0P25V1AW5
#intro de livefeatures:
from clr import AddReference
AddReference("System.Core")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Common")
 
from clr import AddReference                                        
AddReference("System")
AddReference("QuantConnect.Algorithm")
AddReference("QuantConnect.Algorithm.Framework")
AddReference("QuantConnect.Common")

#intro de coarsefine:
AddReference("System.Core")
AddReference("System.Collections")

#intro de indicadores, warmup:
AddReference("QuantConnect.Indicators")

#de livefeatures:
from System import *
from System.Globalization import *
from QuantConnect import *
from QuantConnect.Algorithm import *
from QuantConnect.Data import *
from QuantConnect.Data.Market import *
from QuantConnect.Python import PythonData

#De generico:
from System import *
from QuantConnect import *
from QuantConnect.Orders import *
from QuantConnect.Algorithm import *
from QuantConnect.Algorithm.Framework import *
from QuantConnect.Algorithm.Framework.Selection import *
from Alphas.HistoricalReturnsAlphaModel import HistoricalReturnsAlphaModel
from QuantConnect.Algorithm.Framework.Execution import *
from QuantConnect.Algorithm.Framework.Risk import *
from QuantConnect.Algorithm.Framework.Alphas import AlphaModel, Insight, InsightType, InsightDirection            #Q.2.1: Why can not add confidence, magnitude, confidence?
 
 #De coarsefine:
from System.Collections.Generic import List
from QuantConnect.Data.UniverseSelection import *       
from QuantConnect.Algorithm import QCAlgorithm #debe de ser el mismo que Algorithm import*
 
 #from LITTER-MAN:
from Portfolio.BlackLittermanOptimizationPortfolioConstructionModel import *
from Portfolio.UnconstrainedMeanVariancePortfolioOptimizer import UnconstrainedMeanVariancePortfolioOptimizer       #Q.2.2: Could you send me a complex frame algo about unconstrained mean variance?
from random import random

 #from meanvariance:
from QuantConnect.Algorithm.Framework.Alphas import *
from Portfolio.MeanVarianceOptimizationPortfolioConstructionModel import *
 
 #de indicadores, warmup:
from QuantConnect.Indicators import *
from QuantConnect.Data import *
from datetime import datetime
 

import numpy as np
from datetime import datetime
from datetime import timedelta
import json
  
#from indicatorwarmup:
from QuantConnect.Securities import *

#del contruction alpha:
from Alphas.MacdAlphaModel import MacdAlphaModel
from Alphas.PearsonCorrelationPairsTradingAlphaModel import PearsonCorrelationPairsTradingAlphaModel
from Portfolio.BlackLittermanOptimizationPortfolioConstructionModel import BlackLittermanOptimizationPortfolioConstructionModel

from QuantConnect.Algorithm.Framework.Risk import RiskManagementModel
from Execution.ImmediateExecutionModel import ImmediateExecutionModel
 
from Selection.FundamentalUniverseSelectionModel import FundamentalUniverseSelectionModel

from QuantConnect.Data.Custom.Tiingo import*

class LiveAlpha0(QCAlgorithm):

    def Initialize(self):
        
        self.SetBrokerageModel(BrokerageName.AlphaStreams)
        self.SetCash(250000)  # 250,000 now 100,000                                                                          
        self.UniverseSettings.Resolution = Resolution.Daily
        self.UniverseSettings.Leverage = 1
        self.UniverseSettings.FillForward = False
        self.UniverseSettings.ExtendedMarketHours = False                                                     #Q.2.3How can i activate this because is not working
        self.SetStartDate(2016,5,16)    #SUBPRIME (2018,10,1)  #COVID (2020,3,21-23 & 2020,2,14 & 2020,2,24)   
        self.SetEndDate(2021,5,16)      #SUBPRIME (2018,12,31) #COVID (2020,3,27    & 2020,5,8  & 2020,4,6)  #Q.2.4: Reasons of this error: self.SetEndDate(datetime.now() - timedelta (1)) #Trying to dynamically access a method that does not exist throws a TypeError exception. To prevent the exception, ensure each parameter type matches those required by the 'float'>) method. Please checkout the API documentation.at Updateself.roc.Update(utcTime in BlackLittermanOptimizationPortfolioConstructionModel.py:299TypeError : No method matches given arguments for Update: (<class 'datetime.datetime'>, <class 'float'>)     (Open Stacktrace) # le faltara el update p que actualice fechas mas de 6 meses? 
        self.numberOfSymbolsCoarse = 888    #Hasta 9999, can I introduce more stocks and how much?                              #Q.2.5 How many stocks can I write here ? more than 9999?
        self.numberOfSymbolsFine = 5        #Hasta 555
        self.dollarVolumeBySymbol= { }
        self._changes = None
        self.month = None
        self.universe = { }
        self.SetWarmUp(200)             # Warm up 200 bars for all subscribed data.
        self.SetWarmUp(timedelta(1800)) # Warm up 7 o 1800? days of data.
        self.AddUniverse(self.CoarseSelectionFunction, self.FineSelectionFunction)                          #Q.2.6: Can I add more functions here besides coarse and fine and how?
        self.spy = self.AddEquity("SPY", Resolution.Daily).Symbol
        self.amat = self.AddEquity("AMAT", Resolution.Daily).Symbol
        self.intc = self.AddEquity("INTC", Resolution.Daily).Symbol
        self.SetBenchmark("SPY")
        self.long = []
        self.short = []
        
####...........................................CODE IM TESTING :.................................    
        
        self.SetPortfolioConstruction(BlackLittermanOptimizationPortfolioConstructionModel())               #Q.1.1 How can i pass arguments inside BLO? How can interconnect?
        self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())                           #Q.1.2 Same question as Q.1.1 
        #self.SetUniverseSelection(TechnologyUniverseModule())                                              #Q.1.3 How connect modules in separate pages?
        
        self.SetAlpha(MyBLOAlpha())
        #self.AddAlpha(MacdAlphaModel(12, 26, 9, MovingAverageType.Simple, Resolution.Daily)).               #Q.2.How tight can i designate this MACD´s dates? 6,13,3 perhaps?
        #self.SetAlpha(ConstantAlphaModel(InsightType.Price, InsightDirection.Up, timedelta(minutes = 20), 0.025, 0.25)) # Q.1.4 How can I make this work but with more strict arguments to filter more insights?  Why is not workingg!! CON timedelta(1)))  #SI INFLUYE aunque menos positivo, 0.8??, HOUR= 2?? 
        #self.SetAlpha(TiingoSentimentNews())                                                                   #Q.1.5 Why i get worst results when i add constant alpha and tiingo!! Why is not workingg!!
        
      
                            # self.SetRiskManagement(MaximumSectorExposureRiskManagementModel(0.33))  
        self.SetRiskManagement(MaximumDrawdownPercentPortfolio()) #0.33?                                #Q.1.6 Difference  between .Set... and .Add..?
        self.AddRiskManagement(MaximumDrawdownPercentPortfolio()) 
        self.SetExecution(ImmediateExecutionModel())    
        
               # Save a RollingWindow with type TradeBar and length of 5 as self.window
        self.window = RollingWindow[TradeBar](30)                                                           #NOt Active
#..........................................................................................................      
        
    def CoarseSelectionFunction(self, coarse):
                                    #short long no lleva volume
        sortedByDollarVolume = sorted([x for x in coarse if x.HasFundamentalData and x.Volume > 100000 and (float(x.Price) > 5) and x.DollarVolume >1e7],  # and x.Price < 500
            key = lambda x: x.DollarVolume, reverse = True) [:self.numberOfSymbolsCoarse]
            
                                     # return [ x.Symbol for x in sortedByDollarVolume[:self.__numberOfSymbols] ]    # return the symbol objects of the top entries from our sorted collection
        self.dollarVolumeBySymbol = {x.Symbol:x.DollarVolume for x in sortedByDollarVolume}
        
                                     #if no security has meet the QC500 criteria, the Universe is Unchanged:
        if len(self.dollarVolumeBySymbol) == 0:
            self.Debug("Universe.Unchanged!!")
            return Universe.Unchanged
            
        return list(self.dollarVolumeBySymbol.keys())
        
    
    def FineSelectionFunction(self, fine):
                                                     # drop stocks which don't have the information we need.
        sortedByPau = sorted([x for x in fine if x.FinancialStatements.IncomeStatement.NormalizedIncomeAsReported.Value >= 0.001    #Q.1.7: I assume .Value is the value from previus month isn´t? or which value im getting when im write .Value?
                                                   and x.FinancialStatements.IncomeStatement.TotalRevenue.Value >= 0.03
                                                   and x.ValuationRatios.PERatio >= 10          # Amazon = 50 S&P:13-15 P/E of 25, above the S&P average, trades at 25 times earnings
                                                   and x.MarketCap >= 1e5
                                            
                                                   and x.OperationRatios.AVG5YrsROIC.Value != 0  # 10% # Net Income / (Total Equity + Long-term Debt and Capital Lease Obligation + Short-term Debt and Capital Lease Obligation)
                                                   and x.OperationRatios.ROA5YrAvg.Value != 0    # > 0.02, Amazon=5%. Antes:0.11. .02=2%, .002=.2%, # Net Income / Average Total Assets
                                          
                                                   and x.OperationRatios.ROIC.OneYear >= 0.001                                      #Q.1.8: Why sometimes if is multiperiod throws an error of float if im using decimals?
                                                   and x.OperationRatios.ROIC.SixMonths >= 0.001  
                                                   and x.OperationRatios.ROIC.ThreeMonths >= 0.03  
                                                   and x.OperationRatios.ROIC.Value >= 0.03 
                                                   and x.OperationRatios.ROA.OneYear >= 0.001   
                                   
                                                   and x.OperationRatios.GrossMargin.OneYear >= 0.001 
                                                   and x.OperationRatios.OperationMargin.Value >= 0.05
                                                   
                                                   and x.OperationRatios.TotalAssetsGrowth.Value > 0.03
                                                   and x.OperationRatios.OperationRevenueGrowth3MonthAvg.GetPeriodValues().Values != 0  # 15%  /SI con:GetPeriodValues() != 0, .Value != 0, > 0.1, #Q.1.9: What is difference between write GetPeriodValues().Values and just write .Values??
                                                   
                                                   and x.FinancialStatements.CashFlowStatement.EarningsLossesFromEquityInvestments.Value != 0
                                                   and x.OperationRatios.DebttoAssets.Value >= 0.08
                                                   and x.OperationRatios.OperationMargin.Value >= 0.08
                                                   and x.OperationRatios.TotalAssetsGrowth.Value > 0.06
                                                   
                                                   and x.OperationRatios.FCFNetIncomeRatio.Value >=0.02  # >=0.1 # ya con estos ya me salia algo pesimista..
                                                   and x.OperationRatios.FCFtoCFO.Value >=0.2
                                                   #......
                                                   and x.OperationRatios.ROE5YrAvg.Value != 0                  # > 0.02             #Q.1.10: Why sometimes when i ask further than inequal (!=0) writing for example > or >= 0.02 throw me an error?
                                                   and x.OperationRatios.ProfitMargin5YrAvg.Value != 0         # > 0.02
                                                   and x.OperationRatios.GrossMargin5YrAvg.Value  != 0         # > 0.02
                                                   and x.OperationRatios.GrossProfitAnnual5YrGrowth.Value != 0 # > 0.02
                                                   
                                                   and x.OperationRatios.ROE.OneYear >= 0.001               # Net Income / Average Total Common Equity
                                               
                                                                ],
                        key = lambda x: self.dollarVolumeBySymbol[x.Symbol], reverse = True)               
                        
        self.Debug('remained to select %d'%(len(sortedByPau)))
                        
        if len(sortedByPau) == 0:
            self.Debug("aqui ya no jalo, por? muchos parametros o?")
            return Universe.Unchanged
            
        self.sortedByPau = [ ]
 
                # store the top stocks into the long_list and the bottom ones into the short_list
        self.long = [x.Symbol for x in sortedByPau[:self.numberOfSymbolsFine]]    
        self.short = [x.Symbol for x in sortedByPau[-self.numberOfSymbolsFine:]]
        
        # return [x.Symbol for x in sortedByPau[:self.numberOfSymbolsFine]] 
        return self.long + self.short                                       #Q.2... How can I do to fix this  Error: Insufficient buying power to complete order
       
                       
    def OnData(self, data):
        if self.LiveMode:
         self.Debug("Trading Live!")
                                        
        if self._changes is None: return
        if self.month == self.Time.month : return         #self.Debug("si return means weve already rebalanced that self.month") #Q.3.1 How rebalance daily? or weekly?
        self.month  = self.Time.month 
###      
        for symbol in self.universe.keys():
            if data.Bars.ContainsKey(symbol):
                self.universe[symbol].update(data[symbol].EndTime, data[symbol].Close)
                
                                             # If our window is not full use return to wait for tomorrow
        if not self.window.IsReady:
            self.Debug("no ready")
            return
                             # change overnight price # si abrimos en positivos y cerro antes en negativos (-5 -(-2.5) = -2.5 ASUMOO q subira
        delta = self.window[0].Open - self.window[1].Close 
        
#..........................Q.1.11 WHY IS NOT WORKING THIS BELOW CODE?................

        securities = data.Keys
        n_securities = len(securities)
        for security in self._changes.AddedSecurities:
                            # antes del brokerage.alpha : if security.Fundamentals.EarningRatios.EquityPerShareGrowth.Value > 0.25):
            if delta < -25.5:                                                                   #Q.1.12: How can I do to make work delta?        
                self.Debug("delta es menor -25.5")
                self.SetHoldings(security.Symbol, 1/len(securities))                            #Q.1.13. Why doesnt divide ? 1/len(securities?)
              # self.SetHoldings(s, 1/n_securities)
              
        for security in self._changes.RemovedSecurities:
            if security.Invested or self.Portfolio.TotalUnrealizedProfit < -41209:               # Q.1.14 : Why is not working TotalUnrealized ?!  and the entires block code? because is passing through another changes?:(...... total portf value if we sold holding at current market rates
                self.Liquidate(security.Symbol)      
#..........................Q.1.15 WHY IS NOT WORKING THIS ABOVE CODE?................

    def OnSecuritiesChanged(self, changes):
        self._changes = changes
        self.Debug("{}: {}".format(self.Time, changes))
        
    def Update():
        pass

class MaximumDrawdownPercentPortfolio(RiskManagementModel):
                      
                         # Initializes a new instance of the MaximumDrawdownPercentPerSecurity class.   Args:  maximumDrawdownPercent: The maximum percentage drawdown allowed for any single security holding
    def __init__(self, MaximumDrawdownPercentPortfolio = 0.15): #0.15 (este fue mas alto .15 ) ahora 0.33 ahora 0.85 muy bajo lo dejo en 0.15 #Q.1.15 How can i hange Draddown to result <10% in more than 6 months as alpha streams require?
                      
        self.maximumDrawdownPercent = -abs(MaximumDrawdownPercentPortfolio)
                        
                        # Manages the algorithm's risk at each time step. #Args: algorithm: The algorithm instance. 
    def ManageRisk(self, LiveAlpha0, targets):
                
                         #targets: The current portfolio targets to be assessed for risk
        targets = []
        for stocks in LiveAlpha0.Securities: #for self.longShortPau instead of stocks?
            security = stocks.Value     

           # if not security.Invested:
            #    continue

            pnl = security.Holdings.UnrealizedProfitPercent
                        
            if pnl < self.maximumDrawdownPercent:
                # liquidate
                #si llega aqui xq bota los 2 deug  self.Debug("?????")
                targets.append(PortfolioTarget(security.Symbol, 0))
                

        return targets
        
class MyBLOAlpha(AlphaModel):
    symbols = []
    
    def Update(self, LiveAlpha0, data):
        insights = []
        for symbol in self.symbols:
            if not (data.ContainsKey(symbol) and data.Bars.ContainsKey(symbol) and data[symbol] is not None): 
                continue
            
            # The BlackLittermanOptimizationPortfolioConstructionModel uses the insight magnitude to optimize the portfolio allocations
            magnitude = round(random(), 4) #Main: 4. Later tried: 5,6,10
            
            insightUp = Insight.Price(symbol, timedelta(days=1), InsightDirection.Up, magnitude, confidence=1, sourceModel='MyBLOAlpha', weight=0.08)  #base confidence: 1, Tested:2. Weight: 0.1, tested: 0.08 
            insightDown = Insight.Price(symbol, timedelta(days=1), InsightDirection.Down, magnitude, confidence=1, sourceModel='MyBLOAlpha', weight=0.08)
            insights.append(insightUp)
            #insights.append(insightDown)
        return insights
    
    def OnSecuritiesChanged(self, LiveAlpha0, changes):
        for security in changes.AddedSecurities:
            self.symbols.append(security.Symbol)       #Q.1.16: Why 1/len(self.symbols)) throws zero? how can i retrieve  total length of my symbols  ?Why i cant use self.SetHoldings here?
            
        
        for security in changes.RemovedSecurities:
            if security.Symbol in self.symbols:         #Q.1.17: Why I cant use  self.Portfolio or .Invested in here?   if security.Invested or self.Portfolio.TotalUnrealizedProfit < -41209:
                self.symbols.remove(security.Symbol)

"""            
                
class NewsData():
    def __init__(self, symbol):
        self.Symbol = symbol
                 # Configue the window to accept 100 data points and save to Window
        self.Window = RollingWindow[float](1000)          #de 100 a 1000             
        
                
class TiingoSentimentNews(AlphaModel):
    def __init__(self): 
        self.newsData = {} 
        
        # Assign polarity scores to words
        self.wordScores = {
            "bad": -0.5, "good": 0.5, "negative": -0.5, 
            "great": 0.5, "growth": 0.5, "fail": -0.5, 
            "failed": -0.5, "success": 0.5, "nailed": 0.5,
            "beat": 0.5, "missed": -0.5, "profitable": 0.5,
            "beneficial": 0.5, "right": 0.5, "positive": 0.5, 
            "large":0.5, "attractive": 0.5, "sound": 0.5, 
            "excellent": 0.5, "wrong": -0.5, "unproductive": -0.5, 
            "lose": -0.5, "missing": -0.5, "mishandled": -0.5, 
            "un_lucrative": -0.5, "up": 0.5, "down": -0.5,
            "unproductive": -0.5, "poor": -0.5, "wrong": -0.5,
            "worthwhile": 0.5, "lucrative": 0.5, "solid": 0.5,
            
            
               "losses": -0.5, "plunges":-0.5,"worst":-0.5, "points":-0.5, 
            "worst day": -0.5, "market crash":-0.5, "Black Monday":-0.5, 
            "more than 1,000 points lower":-0.5,"more than 3,000 points lower":-0.5,
            "circuit breaker": -0.5, "cut interest rates down to zero": -0-5,
            "lowest level": -0.5,"shares plunged by": -0.5, "plunging":-0.5,
            "recession":-0.5,"to its lowest point since":-0.5,"it fell more than 20%":-0.5,
            "crisis": -0.5,"depression": -0.5,"banking crisis": -0.5,         #aqui
            "bank crisis": -0.5,"financial crisis": -0.5,"devaluation": -0.5,"economic crisis": -0.5,
            }
            
    def Update(self, LiveAlpha0, data):
        insights = []
                                # Access TiingoNews and save to the variable news
        news = data.Get(TiingoNews) 
        
        for article in news.Values:
                            # Iterate through the article descriptions and save to the variable words convert text to lowercase, and split the descriptions into a list of words
            words = article.Description.lower().split(" ")
            
                        #Assign a self.wordScore to the word if the word exists in self.wordScores and save to the variable self.score 
            score = sum([self.wordScores[word] for word in words
                if word in self.wordScores])
                
                        #Get the underlying symbol and save to the variable symbol
            symbol = article.Symbol.Underlying 
                            #2. Add scores to the rolling window associated with its newsData symbol
            self.newsData[symbol].Window.Add(score)
            
                     #3. Sum the rolling window scores, save to sentiment
                     # If sentiment aggregate score for the time period is greater than 5, emit an up insight
            sentiment = sum(self.newsData[symbol].Window)
            magnitude = round(random(), 4) #why not 3 or 5? meaning?! %?, points? what?
            if sentiment < 0:
                insights.append(Insight.Price(symbol, timedelta(days=1), InsightDirection.Down, magnitude, confidence=1, sourceModel='TiingoSentimentNews', weight=0.1)) #shapes not aligned when 0.025
            elif sentiment >= 13:
                insights.append(Insight.Price(symbol, timedelta(days=1), InsightDirection.Up, magnitude, confidence=1, sourceModel='TiingoSentimentNews', weight=0.1))
            #insightUp = Insight.Price(symbol, timedelta(days=1), InsightDirection.Up, magnitude, confidence=1, sourceModel='MyBLOAlpha', weight=0.1)
            #insightDown = Insight.Price(symbol, timedelta(days=1), InsightDirection.Down, magnitude, confidence=1, sourceModel='MyBLOAlpha', weight=0.1)
            #insights.append(insightUp)
            #insights.append(insightDown)
                
                
        return insights
    
    def OnSecuritiesChanged(self, LiveAlpha0, changes):
        for security in changes.AddedSecurities:
            symbol = security.Symbol
            newsAsset = LiveAlpha0.AddData(TiingoNews, symbol)
                         # 2. Create a new instance of the NewsData() and store in self.newsData[symbol]
            self.newsData[symbol] = NewsData(newsAsset.Symbol)
        
                        # 3. Remove news data once assets are removed from our universe
        for security in changes.RemovedSecurities:
            newsData = self.newsData.pop(security.Symbol, None)
            if newsData is not None:
                LiveAlpha0.RemoveSecurity(newsData.Symbol)



class ConstantAlphaModel(LiveAlpha0):
    
    def __init__(self): #error takes 1 arg and 6 were given?
     self.mom = []
         
    def OnSecuritiesChanged(self, LiveAlpha0, changes):
       # self.mom = []
        self._changes = changes
        for security in changes.AddedSecurities:
            symbol = security.Symbol
            self.mom.append({"symbol":symbol, "indicator":LiveAlpha0.MOM(symbol, 14, Resolution.Daily)})
        
    def Update(self, LiveAlpha0, data):   
                        # Perform analysis, then and emit insights: /We can return a set of Insights together as a group, which signal to the execution model that the insights need to be traded simultaneously.
                        #return Insight.Price("SPY", timedelta(1), InsightDirection.Up)
        
        ordered = sorted(self.mom, key=lambda kv: kv["indicator"].Current.Value, reverse=True)
        return Insight.Group([Insight.Price(ordered[0]['symbol'], timedelta(1), InsightDirection.Up), # IndexError : list index out of range at Update return Insight.Group([Insight.Price(ordered[0]['symbol'] in main.py:line 356
                            Insight.Price(ordered[1]['symbol'], timedelta(1), InsightDirection.Flat) ])
        
        

class ConstantAlphaModel(LiveAlpha0):    
    def Update(self, LiveAlpha0, slice): 
                                            #self.spy = self.AddEquity("SPY")
     
      señales = self.long + self.short           # por vacio no activa
     # insights=[]
      señal = Insight.Price("?", timedelta(minutes = 20), InsightDirection.Up, None, None, None, 0.25) #Insight' object is not iterable
      return señal
  #     pass
#    self.AddAlpha(ConstantAlphaModel(InsightType.Price, InsightDirection.Up, timedelta(minutes = 20), 0.025, 0.8)) # CON timedelta(1)))  #SI INFLUYE aunque menos positivo
    def OnSecuritiesChanged(self, LiveAlpha0, changes):
       self._changes = changes
       #self.Debug("{}: {}".format(self.Time, changes))
       pass
"""