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
using QuantConnect.Data;
using QuantConnect.Data.Auxiliary;
using QuantConnect.Data.Custom.PsychSignal;

namespace QuantConnect.Algorithm.CSharp
{
	/// <summary>
	/// Momentum based strategy that follows bullish rated stocks
	/// </summary>
    public class PsychSignalSentimentAlgorithm : QCAlgorithm
    {
    	private List<Symbol> _sentimentSymbols = new List<Symbol>();
    	private DateTime _timeEntered = DateTime.MinValue;

        /// <summary>
        /// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.
        /// </summary>
        public override void Initialize()
        {
            SetStartDate(2018, 3, 1);
            SetEndDate(2018, 10, 1);
            SetCash(100000);
            
            AddUniverseSelection(new CoarseFundamentalUniverseSelectionModel(CoarseUniverse));
            
            // Request underlying equity data.
			var ibm = AddEquity("IBM", Resolution.Minute).Symbol;
			// Add news data for the underlying IBM asset
			var psy = AddData<PsychSignalSentiment>(ibm).Symbol;
			// Request 120 minutes of history with the PsychSignal IBM Custom Data Symbol.
			var history = History<PsychSignalSentiment>(psy, 120, Resolution.Minute);
			
			// Count the number of items we get from our history request
            Debug($"We got {history.Count()} items from our history request");
        }
        
        /// <summary>
        /// You can use custom data with a universe of assets
        /// </summary>
		public IEnumerable<Symbol> CoarseUniverse(IEnumerable<CoarseFundamental> coarse)
		{
			if (Time.Subtract(_timeEntered) <= TimeSpan.FromDays(10))
			{
				return Universe.Unchanged;
			}
			
			// Ask for the universe like normal and then filter it
			var symbols = coarse.Where(x => x.HasFundamentalData && x.DollarVolume > 50000000)
				.Select(x => x.Symbol)
				.Take(20);
			
			// Add the custom data to the underlying security
			foreach (var symbol in symbols)
			{
				AddData<PsychSignalSentiment>(symbol);
			}
			
			return symbols;
		}
		
		public override void OnData(Slice data)
		{
			// Scan our last time traded to prevent churn
			if (Time.Subtract(_timeEntered) <= TimeSpan.FromDays(10))
			{
				return;
			}
			
			// Fetch the PsychSignal data for the active securities and trade on any
			foreach (var security in ActiveSecurities.Values)
			{
				var tweets = security.Data.PsychSignalSentiment;
				
				foreach (var sentiment in tweets)
				{
					if (sentiment.BullIntensity > 2.0m && sentiment.BullScoredMessages > 3m)
					{
						SetHoldings(sentiment.Symbol.Underlying, 0.05);
						_timeEntered = Time;
					}
				}
			}
		}
		
		/// <summary>
		/// When adding custom data from a universe we should also remove the data afterwards
		/// </summary>
		public override void OnSecuritiesChanged(SecurityChanges changes)
		{
			// Make sure to filter out other security removals (i.e. custom data)
			foreach (var r in changes.RemovedSecurities.Where(x => x.Symbol.SecurityType == SecurityType.Equity))
            {
            	Liquidate(r.Symbol);
            	// Remove the custom data from our algorithm and collection
                RemoveSecurity(QuantConnect.Symbol.CreateBase(typeof(PsychSignalSentiment), r.Symbol, Market.USA));
            }
		}
    }
}