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