Overall Statistics
Total Trades
12
Average Win
0.04%
Average Loss
0%
Compounding Annual Return
3.537%
Drawdown
0.700%
Expectancy
0
Net Profit
2.068%
Sharpe Ratio
1.586
Probabilistic Sharpe Ratio
70.288%
Loss Rate
0%
Win Rate
100%
Profit-Loss Ratio
0
Alpha
0.024
Beta
0.002
Annual Standard Deviation
0.015
Annual Variance
0
Information Ratio
-0.801
Tracking Error
0.101
Treynor Ratio
9.993
Total Fees
$12.00
from datetime import datetime, timedelta
from QuantConnect.Data.Custom.PsychSignal import *

class PsychSignalAlgorithm(QCAlgorithm):
    
    def Initialize(self):
        self.SetStartDate(2018, 3, 1)
        self.SetEndDate(2018, 10, 1)
        self.SetCash(100000)

        self.AddUniverseSelection(CoarseFundamentalUniverseSelectionModel(self.CoarseUniverse))
        self.timeEntered = datetime(1, 1, 1)
        self.sentimentSymbols = []
        
        # Request underlying equity data.
        ibm = self.AddEquity("IBM", Resolution.Minute).Symbol
        # Add sentiment data for the underlying IBM asset
        psy = self.AddData(PsychSignalSentiment, ibm).Symbol
        # Request 120 minutes of history with the PsychSignal IBM Custom Data Symbol
        history = self.History(PsychSignalSentiment, psy, 120, Resolution.Minute)
        
        # Count the number of items we get from our history request
        self.Debug(f"We got {len(history)} items from our history request")

    # You can use custom data with a universe of assets. 
    def CoarseUniverse(self, coarse):
        if (self.Time - self.timeEntered) <= timedelta(days=10):
            return Universe.Unchanged 
        
        # Ask for the universe like normal and then filter it
        symbols = [i.Symbol for i in coarse if i.HasFundamentalData and i.DollarVolume > 50000000][:20]

        # Add the custom data to the underlying security.
        for symbol in symbols:
            self.AddData(PsychSignalSentiment, symbol)

        return symbols

    def OnData(self, data):
        # Scan our last time traded to prevent churn.
        if (self.Time - self.timeEntered) <= timedelta(days=10):
            return

        # Fetch the PsychSignal data for the active securities and trade on any 
        for security in self.ActiveSecurities.Values:
            tweets = security.Data.GetAll(PsychSignalSentiment)
            for sentiment in tweets:
                if sentiment.BullIntensity > 2.0 and sentiment.BullScoredMessages > 3:
                    self.SetHoldings(sentiment.Symbol.Underlying, 0.05)
                    self.timeEntered = self.Time
    
    # When adding custom data from a universe we should also remove the data afterwards.
    def OnSecuritiesChanged(self, changes):
        # Make sure to filter out other security removals (i.e. custom data)
        for r in [i for i in changes.RemovedSecurities if i.Symbol.SecurityType == SecurityType.Equity]:
            self.Liquidate(r.Symbol) 
            # Remove the custom data from our algorithm and collection
            self.RemoveSecurity(Symbol.CreateBase(PsychSignalSentiment, r.Symbol, Market.USA))