Overall Statistics
Total Trades
629
Average Win
0.65%
Average Loss
-0.42%
Compounding Annual Return
273.929%
Drawdown
14.000%
Expectancy
0.212
Net Profit
32.529%
Sharpe Ratio
3.388
Probabilistic Sharpe Ratio
69.114%
Loss Rate
52%
Win Rate
48%
Profit-Loss Ratio
1.55
Alpha
1.964
Beta
-0.191
Annual Standard Deviation
0.577
Annual Variance
0.332
Information Ratio
2.211
Tracking Error
0.859
Treynor Ratio
-10.205
Total Fees
$2763.31
import re
from datetime import datetime, timedelta
from QuantConnect.Data.Custom.Tiingo import *

class MultidimensionalOptimizedCompensator(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2020, 3, 1)  # Set Start Date
        self.SetEndDate(2020, 5, 17)  # Date video was filmed
        self.SetCash(100000)  # Set Strategy Cash
        
        tickers = ['GILD', 'MRNA', 'JNJ', 'INO', 'PFE',
                   'NVAX', 'URGN', 'CODX', 'SNGX',
                   'EGRX', 'GRFS', 'SRNE']
        
        symbols = [Symbol.Create(ticker, SecurityType.Equity, Market.USA) for ticker in tickers]
        
        self.UniverseSettings.Resolution = Resolution.Daily
        self.SetUniverseSelection(ManualUniverseSelectionModel(symbols))
        
        self.SetAlpha(BiotechNewsAlpha(symbols))
        
        self.SetExecution(ImmediateExecutionModel())
        
        self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel(lambda time: None))


class BiotechNewsAlpha:
    
    def __init__(self, symbols):
        self.symbols = {}
        self.keywords = keywords = [('fda', 'approval'), ('fda', 'approved'), ('start','clinical', 'trials'),
                                    ('start', 'human', 'trials'), ('begin', 'trials'), ('start', 'trials')]
        
    def Update(self, algorithm, data):
        ## swap out for notebook code after first backtest
        insights = []
        
        tiingo_data = data.Get(TiingoNews)
        for sym in tiingo_data.Keys:
            article = tiingo_data[sym]
            for key in self.keywords:
                match = all([bool(re.search(x, article.Description, re.IGNORECASE)) for x in key])
                if match:
                    insights += [Insight(article.Symbol.Underlying, timedelta(1), InsightType.Price,
                                     InsightDirection.Up)]
        return insights
        
    
    def OnSecuritiesChanged(self, algorithm, changes):
        for security in changes.AddedSecurities:
            self.symbols[security.Symbol] = algorithm.AddData(TiingoNews, security.Symbol).Symbol