| Overall Statistics |
|
Total Trades 148 Average Win 1.58% Average Loss -0.82% Compounding Annual Return 9.030% Drawdown 9.100% Expectancy 0.527 Net Profit 35.765% Sharpe Ratio 0.846 Probabilistic Sharpe Ratio 33.442% Loss Rate 48% Win Rate 52% Profit-Loss Ratio 1.94 Alpha 0.057 Beta 0.073 Annual Standard Deviation 0.077 Annual Variance 0.006 Information Ratio -0.214 Tracking Error 0.177 Treynor Ratio 0.889 Total Fees $7915.85 |
from QuantConnect.Data.Custom.Tiingo import *
from datetime import datetime, timedelta
import takeprofit
import numpy as np
class SentimentAlpha(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2017, 1, 1)
self.SetEndDate(2020, 7, 14)
self.SetCash(1000000)
self.tickers = ["TSLA", "MSFT", "GS", "PEP", "NIO", "F", "MTCH","DDOG", "LUV", "TMUS", "AMD", "INO"]
symbols = []
for i in self.tickers:
symbols.append(Symbol.Create(i, SecurityType.Equity, Market.USA))
self.UniverseSettings.Resolution = Resolution.Hour
self.SetUniverseSelection(ManualUniverseSelectionModel(symbols))
self.SetAlpha(SentimentWindow())
self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())
self.SetExecution(ImmediateExecutionModel())
self.SetRiskManagement(takeprofit.TrailingStopRiskManagementModel())
class NewsData():
def __init__(self, symbol):
self.Symbol = symbol
#two month rolling window if insights are emitted daily
self.Window = RollingWindow[float](60)
class SentimentWindow(AlphaModel):
def __init__(self):
self.newsData = {}
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,
"beat": 0.5, "missed": -0.5
}
self.lastday = -1
def Update(self, algorithm, data):
insights = []
day = algorithm.Time.day
if day == self.lastday:
return insights
self.lastday = day
news = data.Get(TiingoNews)
for article in news.Values:
words = article.Description.lower().split(" ")
score = sum([self.wordScores[word] for word in words
if word in self.wordScores])
if score == 0.0:
continue
symbol = article.Symbol.Underlying
self.newsData[symbol].Window.Add(score)
if self.newsData[symbol].Window.Count < 3:
return insights
currentWindow = self.newsData[symbol].Window[0]
sentimentMean = sum(self.newsData[symbol].Window)/self.newsData[symbol].Window.Count
algorithm.Debug("Mean "+ str(sentimentMean))
algorithm.Debug("Window "+ str(currentWindow))
if currentWindow > (sentimentMean*1.1):
insights.append(Insight.Price(symbol, timedelta(days=2), InsightDirection.Up, None, None))
elif currentWindow < -1:
insights.append(Insight.Price(symbol, timedelta(days=1), InsightDirection.Down, None, None))
else:
insights.append(Insight.Price(symbol, timedelta(days=1), InsightDirection.Flat, None, None))
return insights
def OnSecuritiesChanged(self, algorithm, changes):
for security in changes.AddedSecurities:
symbol = security.Symbol
newsAsset = algorithm.AddData(TiingoNews, symbol)
self.newsData[symbol] = NewsData(newsAsset.Symbol)
for security in changes.RemovedSecurities:
newsData = self.newsData.pop(security.Symbol, None)
if newsData is not None:
algorithm.RemoveSecurity(newsData.Symbol)class TrailingStopRiskManagementModel(RiskManagementModel):
'''Provides an implementation of IRiskManagementModel that limits the maximum possible loss
measured from the highest unrealized profit'''
def __init__(self):
'''Initializes a new instance of the TrailingStopRiskManagementModel class'''
self.liquidated = set()
self.lastmonth=-1
def ManageRisk(self, algorithm, targets):
'''Manages the algorithm's risk at each time step
Args:
algorithm: The algorithm instance
targets: The current portfolio targets to be assessed for risk'''
month= algorithm.Time.month
if month!= self.lastmonth:
self.liquidated.clear()
self.lastmonth= month
#if different month clear all liquidations
riskAdjustedTargets = list()
for kvp in algorithm.Securities:
symbol = kvp.Key
security = kvp.Value
if security.Holdings.UnrealizedProfitPercent>0.05 or security.Holdings.UnrealizedProfitPercent<-0.03 or security.Symbol in self.liquidated:
riskAdjustedTargets.append(PortfolioTarget(symbol, 0))
if algorithm.Securities[security.Symbol].Invested:
self.liquidated.add(security.Symbol)
return riskAdjustedTargets