| 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;
}
}
}