Overall Statistics
Total Trades
4382
Average Win
0.17%
Average Loss
-0.11%
Compounding Annual Return
1.423%
Drawdown
47.600%
Expectancy
0.058
Net Profit
7.832%
Sharpe Ratio
0.173
Loss Rate
58%
Win Rate
42%
Profit-Loss Ratio
1.52
Alpha
0.284
Beta
-12.492
Annual Standard Deviation
0.221
Annual Variance
0.049
Information Ratio
0.084
Tracking Error
0.221
Treynor Ratio
-0.003
Total Fees
$6129.16
using MathNet.Numerics.Statistics;
using QuantConnect.Data.Fundamental;
using QuantConnect.Data.Market;
using QuantConnect.Data.UniverseSelection;
using QuantConnect.Indicators;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;

namespace QuantConnect.Algorithm.CSharp
{
    public sealed class PETestAlgorithm : QCAlgorithm
    {
        private const int _numFine = 10;
        private const int _numCoarse = 400;
        private const decimal _target = 1m / _numFine;
        private SecurityChanges _changes = SecurityChanges.None;
        private readonly ConcurrentDictionary<Symbol, SelectionData> _averages = new ConcurrentDictionary<Symbol, SelectionData>();

        private class SelectionData
        {
            private static readonly Symbol _whoCares = "XXXXXXXXXXXXXXX";

            private int _lastCoarseMonth = -1;
            private int _lastFineMonth = -1;

			public decimal CoarseRankingStat;
            public decimal FineRankingStat;

            public bool UpdateFineFundamental(FineFundamental fine)
            {
                if (_lastFineMonth < 0 || _lastFineMonth != fine.Time.Month)
                {
                    _lastFineMonth = fine.Time.Month;

					decimal pe = fine.ValuationRatios.PERatio;
					if (pe == 0)
						FineRankingStat = -100000m;
					else if (pe > 0)
                    	FineRankingStat = -pe;
                    else //pe < 0
                    	FineRankingStat = 1m / pe;
                }

                return true;
            }

            public bool UpdateCoarseFundamental(CoarseFundamental coarse)
            {
                if (_lastCoarseMonth < 0 || _lastCoarseMonth != coarse.Time.Month)
                {
                    _lastCoarseMonth = coarse.Time.Month;

                   CoarseRankingStat = coarse.DollarVolume;
                }

                return true;
            }
        }

        /// <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()
        {
            UniverseSettings.Resolution = Resolution.Daily;

            SetStartDate(2014, 01, 01);
            //SetEndDate(2015, 01, 01);
            SetCash(100 * 1000);

            AddUniverse(CoarseSelection, FineSelection);
        }

        private IEnumerable<Symbol> CoarseSelection(IEnumerable<CoarseFundamental> coarse)
        {
            var hasFundamental = coarse.Where(x => x.HasFundamentalData);
            return (from cf in hasFundamental
                    let avg = _averages.GetOrAdd(cf.Symbol, sym => new SelectionData())
                    where avg.UpdateCoarseFundamental(cf)
                    orderby avg.CoarseRankingStat descending
                    select cf.Symbol).Take(_numCoarse);
        }

        private IEnumerable<Symbol> FineSelection(IEnumerable<FineFundamental> fine)
        {
            return (from f in fine
                    let avg = _averages.GetOrAdd(f.Symbol, sym => new SelectionData())
                    where avg.UpdateFineFundamental(f)
                    orderby avg.FineRankingStat descending
                    select f.Symbol).Take(_numFine);
        }

        public void OnData(TradeBars data)
        {
            if (_changes == SecurityChanges.None) return;

            // liquidate securities removed from our universe
            foreach (var security in _changes.RemovedSecurities)
            {
                if (security.Invested)
                {
                    Liquidate(security.Symbol);
                }
            }

            // we'll simply go long each security we added to the universe
            foreach (var security in _changes.AddedSecurities)
            {
                SetHoldings(security.Symbol, _target);
            }
        }

        public override void OnSecuritiesChanged(SecurityChanges changes)
        {
            _changes = changes;
        }
    }
}