Overall Statistics
Total Trades
629
Average Win
0.66%
Average Loss
-0.42%
Compounding Annual Return
278.976%
Drawdown
14.000%
Expectancy
0.213
Net Profit
32.909%
Sharpe Ratio
3.436
Probabilistic Sharpe Ratio
69.444%
Loss Rate
53%
Win Rate
47%
Profit-Loss Ratio
1.56
Alpha
1.991
Beta
-0.191
Annual Standard Deviation
0.576
Annual Variance
0.332
Information Ratio
2.243
Tracking Error
0.859
Treynor Ratio
-10.344
Total Fees
$2757.64
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