Overall Statistics
Total Trades
1061
Average Win
0.26%
Average Loss
-0.18%
Compounding Annual Return
13.428%
Drawdown
12.800%
Expectancy
0.099
Net Profit
8.750%
Sharpe Ratio
0.979
Loss Rate
55%
Win Rate
45%
Profit-Loss Ratio
1.45
Alpha
0.123
Beta
-0.094
Annual Standard Deviation
0.112
Annual Variance
0.012
Information Ratio
-0.229
Tracking Error
0.163
Treynor Ratio
-1.159
Total Fees
$1159.28
using MathNet.Numerics.Distributions;
using QuantConnect.Data;
using QuantConnect.Data.Market;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Indicators;
using QuantConnect.Orders;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace QuantConnect.Algorithm.CSharp
{
    public class BasicTemplateAlgorithm : QCAlgorithm
    {
        //Count the number of days that pass, so that the algo only executes every 2 weeks
        int countDay = 0;

        //Create a Dictionary to store each security and a rolling window of their closing price for the past 20 trading days 
        Dictionary<Symbol, RollingWindow<decimal>> _storage = new Dictionary<Symbol, RollingWindow<decimal>>();

        //Create a list to capture the stocks that are entered into the universe
        List<Symbol> top10Gainers = new List<Symbol>();
        List<Symbol> top10Losers = new List<Symbol>();

        //Create list to record the positive and negative price movers each iteration of the algo
        List<Symbol> recordPositiveChanges = new List<Symbol>();
        List<Symbol> recordNegativeChanges = new List<Symbol>();

        public override void Initialize()
        {
            SetStartDate(2012, 9, 01);
            SetEndDate(2013, 5, 01);
            SetCash(50000);
            UniverseSettings.Resolution = Resolution.Daily;

            AddUniverse(CoarseSelectionFunction);
        }

        public IEnumerable<Symbol> CoarseSelectionFunction(IEnumerable<CoarseFundamental> coarse)
        {
            ///Add each security in the coarse library to the dictionary, along with the price for that day to its rolling window
            ///if the security already exists in the Dictionary, just add that day's price to that security's 
            ///Rolling window.
            foreach (var coarseItem in coarse)
            {
                if (!_storage.ContainsKey(coarseItem.Symbol))
                {
                    _storage.Add(coarseItem.Symbol, new RollingWindow<decimal>(20));
                }
                _storage[coarseItem.Symbol].Add(coarseItem.Price);
            }

            //Create a list of the top 100 stocks by dollar volume and store by their symbol
            var findTop100 = (from coarseItem in coarse
                              where _storage[coarseItem.Symbol].Count == 20
                              orderby coarseItem.DollarVolume descending
                              select coarseItem.Symbol).Take(100);


            //Count how many days have passed
            countDay++;

            //Return empty / nothing until 20 days pass
            //Then, only return the universe if 1 week has passed yet

            if (!(countDay >= 20))
                return new List<Symbol>();


            else if (Time.DayOfWeek == DayOfWeek.Thursday)
            {

                //If 1 week has passed, then return a new universe
                //Clear out the universe list so it can be updated
                top10Gainers.Clear();
                top10Losers.Clear();

                //Create a list to contain the top 10 stocks with the highest positive price change
                top10Gainers = (from symbol in findTop100
                                let start = _storage[symbol][19]
                                let end = _storage[symbol][0]
                                let delta = (end - start) / start
                                orderby delta descending
                                select symbol).Take(10).ToList();

                //Create a list to contain the top 10 stocks with the highest negative price change
                top10Losers = (from symbol in findTop100
                               let start = _storage[symbol][19]
                               let end = _storage[symbol][0]
                               let delta = (end - start) / start
                               orderby delta ascending
                               select symbol).Take(10).ToList();

                //Create a universe which will be returned to include all stocks that need to be analyzed
                var universe = new List<Symbol>();
                universe.AddRange(top10Gainers);
                universe.AddRange(top10Losers);

                return universe;
            }

            else return new List<Symbol>();
        }
        public void OnData(TradeBars data)
        {
            // schedule an event to fire on certain days of the week
            if (Time.DayOfWeek == DayOfWeek.Friday)
            {
                Liquidate();
                //Short stocks that are doing well, and long stocks that have not done well in the past 2 weeks
                //Then add the respective stocks to a list to be used the next iteration of the algo
                foreach (var security in top10Gainers)
                {
                    //Order(security, -10);
                    SetHoldings(security, -.07m);
                }
                foreach (var security in top10Losers)
                {
                    //Order(security, 10);
                    SetHoldings(security, .07m);
                }
            }
            //Console.WriteLine(Portfolio.Cash);
        }
    }
}