| Overall Statistics |
|
Total Trades 1183 Average Win 0.22% Average Loss -0.36% Compounding Annual Return 13.866% Drawdown 8.000% Expectancy 0.026 Net Profit 18.830% Sharpe Ratio 0.878 Probabilistic Sharpe Ratio 41.119% Loss Rate 36% Win Rate 64% Profit-Loss Ratio 0.61 Alpha 0.117 Beta 0.04 Annual Standard Deviation 0.141 Annual Variance 0.02 Information Ratio -0.122 Tracking Error 0.285 Treynor Ratio 3.105 Total Fees $1281.03 |
namespace QuantConnect {
public class SellHigh7s : QCAlgorithm {
private int _month = -1;
public override void Initialize()
{
SetStartDate(2019, 1, 1);
SetEndDate(DateTime.Now);
SetCash(100000);
UniverseSettings.Resolution = Resolution.Daily;
AddUniverseSelection(new FineFundamentalUniverseSelectionModel(SelectCoarse, SelectFine));
AddAlpha( new MyAlphaModel() );
SetPortfolioConstruction( new EqualWeightingPortfolioConstructionModel() );
AddRiskManagement( new MaximumDrawdownPercentPerSecurity() );
SetExecution( new ImmediateExecutionModel() );
}
IEnumerable<Symbol> SelectCoarse(IEnumerable<CoarseFundamental> coarse) {
const int size = 9;
if (Time.Month == _month)
return Universe.Unchanged;
// The securities with the most dollar volume
return (from x in coarse
where x.Volume > 0 && x.Price > 0
orderby x.DollarVolume descending
select x.Symbol).Take(size).ToList();
}
IEnumerable<Symbol> SelectFine(IEnumerable<FineFundamental> fine) {
_month = Time.Month;
return fine.Select(f => f.Symbol);
}
}
// Algorithm framework model that produces insights
public class MyAlphaModel : IAlphaModel, INotifiedSecurityChanges {
private readonly Dictionary<Symbol, RelativeStrengthIndex> _rsiBySymbol = new Dictionary<Symbol, RelativeStrengthIndex>();
private readonly int _period = 1;
private readonly Resolution _resolution = Resolution.Daily;
private int _month = -1;
// Updates this alpha model with the latest data from the algorithm.
// This is called each time the algorithm receives data for subscribed securities
public IEnumerable<Insight> Update(QCAlgorithm algorithm, Slice data) {
// Generate insights on the securities in universe.
var insights = new List<Insight>();
if (algorithm.Time.Month == _month)
return insights;
_month = algorithm.Time.Month;
// Insights for 22 days
var insightPeriod = _resolution.ToTimeSpan().Multiply(22);
// Long the lowest RSI; Short the highest RSI
var i = 0;
var numInsightsPerSide = _rsiBySymbol.Count / 3;
foreach (KeyValuePair<Symbol, RelativeStrengthIndex> sym in _rsiBySymbol.OrderBy(key => key.Value)) {
if (i < numInsightsPerSide)
insights.Add(Insight.Price(sym.Key, insightPeriod, InsightDirection.Up));
else if (i >= _rsiBySymbol.Count - numInsightsPerSide)
insights.Add(Insight.Price(sym.Key, insightPeriod, InsightDirection.Down));
i++;
}
return insights;
}
public void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes) {
// Handle security changes in from your universe model.
// clean up data for removed securities
if (changes.RemovedSecurities.Count > 0) {
var removed = changes.RemovedSecurities.ToHashSet(x => x.Symbol);
foreach (var subscription in _rsiBySymbol.Keys.ToList())
if (removed.Contains(subscription))
_rsiBySymbol.Remove(subscription);
}
// initialize data for added securities
var addedSymbols = new List<Symbol>();
foreach (var added in changes.AddedSecurities)
if (!_rsiBySymbol.ContainsKey(added.Symbol)) {
// Add RSI indicator
_rsiBySymbol[added.Symbol] = algorithm.RSI(added.Symbol, _period, MovingAverageType.Simple, _resolution);
addedSymbols.Add(added.Symbol);
}
if (addedSymbols.Count > 0)
// warmup our indicators by pushing history through the consolidators
algorithm.History(addedSymbols, _period, _resolution)
.PushThrough(data =>
{
RelativeStrengthIndex rsi;
if (_rsiBySymbol.TryGetValue(data.Symbol, out rsi))
rsi.Update(data.EndTime, data.Value);
});
}
}
}