Overall Statistics
Total Trades
253
Average Win
1.43%
Average Loss
-0.88%
Compounding Annual Return
0.126%
Drawdown
26.400%
Expectancy
0.020
Net Profit
0.698%
Sharpe Ratio
0.05
Probabilistic Sharpe Ratio
0.509%
Loss Rate
61%
Win Rate
39%
Profit-Loss Ratio
1.63
Alpha
0.005
Beta
-0.013
Annual Standard Deviation
0.073
Annual Variance
0.005
Information Ratio
-0.492
Tracking Error
0.18
Treynor Ratio
-0.283
Total Fees
$79060.09
from QuantConnect.Data.Custom.Tiingo import *
from datetime import datetime, timedelta
import numpy as np

class GunStocks(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2015, 1, 1)
        self.SetEndDate(2020, 7, 14)
        self.SetCash(1000000)
        
        self.tickers = ["AXON", "AOBC", "RGR", "VSTO", "SPWH", "OLN", "SWBI"]
        
        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(GunStocksAlphaModel())
        self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel()) 
        self.SetExecution(ImmediateExecutionModel()) 
        self.SetRiskManagement(TrailingStopRiskManagementModel(0.02))

class NewsData():
    def __init__(self, symbol):
        self.Symbol = symbol
        self.Window = RollingWindow[float](100)  
        
class GunStocksAlphaModel(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,
            "conflict": 0.5, "peace": -0.5, "contracts": 0.5, "equipment": 0.5,
            "war": 0.5, "scandal": -0.5, "bribe": -0.5, "tax": -0.5,
            "gun": 0.5, "stocks": 0.5, "stock": 0.5, "invest": 0.5,
            "optamistic": 0.5, "sell": -0.5, "buy": 0.5, "gained": 0.5,
            "lost": -0.5, "riots": 0.5, "riot": 0.5, "terrorism": 0.5,
            "frightened": 0.5, "violence": 0.5
            
        }
        
        self.senators = {
            1999 : "R",
            2000 : "R",
            2001 : "D",
            2002 : "D", 
            2003 : "R",
            2004 : "R", 
            2005 : "R",
            2006 : "R",
            2007 : "D",
            2008 : "D",
            2009 : "D",
            2010 : "D",
            2011 : "D",
            2012 : "D",
            2013 : "D",
            2014 : "D",
            2015 : "R",
            2016 : "R",
            2017 : "R",
            2018 : "R",
            2019 : "R",
            2020 : "R"
        }
    
        
        self.lastmonth = -1
        
    def Update(self, algorithm, data):
        
        insights = []
        
        month = algorithm.Time.month
        if month == self.lastmonth:
            return insights
        self.lastmonth = month
        
        politicalPoints = 0
        
        timeYear = algorithm.Time.year
        
        for key, value in self.senators.items():
            
            if (key == timeYear) and value == "D":
                politicalPoints = 3
            elif (key == timeYear) and value == "R":
                politicalPoints = -3
        
        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])
            
            symbol = article.Symbol.Underlying 
    
            self.newsData[symbol].Window.Add(score)
            
            
            sentiment = sum(self.newsData[symbol].Window) + politicalPoints 
            #algorithm.Debug(str(sentiment))
            if sentiment > 10:
                insights.append(Insight.Price(symbol, timedelta(days=5), InsightDirection.Up, None, None))
            elif sentiment < -1:
                insights.append(Insight.Price(symbol, timedelta(days=5), InsightDirection.Down, 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)