Overall Statistics |
Total Trades 24 Average Win 0.31% Average Loss -0.04% Compounding Annual Return 7.670% Drawdown 0.300% Expectancy 0.532 Net Profit 0.243% Sharpe Ratio 2.174 Loss Rate 83% Win Rate 17% Profit-Loss Ratio 8.19 Alpha 0.136 Beta -4.514 Annual Standard Deviation 0.028 Annual Variance 0.001 Information Ratio 1.585 Tracking Error 0.028 Treynor Ratio -0.014 Total Fees $30.79 |
namespace QuantConnect.Algorithm.CSharp { public class BasicTemplateFrameworkAlgorithm : QCAlgorithmFramework { public SecurityChanges _changes = SecurityChanges.None; public override void Initialize() { SetStartDate(2018, 1, 1); //Set Start Date SetEndDate(2018, 1, 15); //Set End Date SetCash(100000); //Set Strategy Cash // SetTimeZone(TimeZones.Phoenix); UniverseSettings.Resolution = Resolution.Daily; UniverseSettings.Leverage = 1; SetUniverseSelection(new CoarseFundamentalUniverseSelectionModel(CoarseSelectionFunction)); // Example defining an alpha model as a composite of the rsi and ema cross models. // Replace this with your own combination of alpha models. SetAlpha(new CompositeAlphaModel( //new EmaCrossAlphaModel(50, 200, Resolution.Daily) new MacdAlphaNewModel() )); SetPortfolioConstruction(new EqualWeightingPortfolioConstructionModel()); // SetExecution(new StandardDeviationExecutionModel(60, 2, Resolution.Minute)); // SetRiskManagement(new MaximumDrawdownPercentPerSecurity(0.01m)); } public static IEnumerable<Symbol> CoarseSelectionFunction(IEnumerable<CoarseFundamental> coarse) { // sort descending by daily dollar volume var sortedByDollarVolume = coarse.OrderByDescending(x => x.DollarVolume); // take the top 5 entries from our sorted collection var top5 = sortedByDollarVolume.Take(5); // we need to return only the symbols return top5.Select(x => x.Symbol); } //Data Event Handler: New data arrives here. "TradeBars" type is a dictionary of strings so you can access it by symbol. public void OnData(TradeBars data) { // Log($"OnData({UtcTime:o}): Keys: {string.Join(", ", data.Keys.OrderBy(x => x))}"); // if we have no changes, do nothing if (_changes == SecurityChanges.None) return; // liquidate removed securities foreach (var security in _changes.RemovedSecurities) { if (security.Invested) { Liquidate(security.Symbol); } } // we want 20% allocation in each security in our universe foreach (var security in _changes.AddedSecurities) { SetHoldings(security.Symbol, 0.2m); } _changes = SecurityChanges.None; } // this event fires whenever we have changes to our universe public override void OnSecuritiesChanged(SecurityChanges changes) { _changes = changes; } public override void OnOrderEvent(OrderEvent fill) { Log($"OnOrderEvent({UtcTime:o}):: {fill}"); } } } // using System.Collections.Generic; // using QuantConnect.Data; // using QuantConnect.Data.Consolidators; // using QuantConnect.Data.UniverseSelection; // using QuantConnect.Indicators; // using QuantConnect.Securities; namespace QuantConnect.Algorithm.Framework.Alphas { /// <summary> /// Defines a custom alpha model that uses MACD crossovers. The MACD signal line is /// used to generate up/down insights if it's stronger than the bounce threshold. /// If the MACD signal is within the bounce threshold then a flat price insight is returned. /// </summary> public class MacdAlphaNewModel : AlphaModel { private readonly int _fastPeriod; private readonly int _slowPeriod; private readonly int _signalPeriod; private readonly MovingAverageType _movingAverageType; private readonly Resolution _resolution; private const decimal BounceThresholdPercent = 0.01m; private readonly Dictionary<Symbol, SymbolData> _symbolData; /// <summary> /// Initializes a new instance of the <see cref="MacdAlphaModel"/> class /// </summary> /// <param name="fastPeriod">The MACD fast period</param> /// <param name="slowPeriod">The MACD slow period</param> /// <param name="signalPeriod">The smoothing period for the MACD signal</param> /// <param name="movingAverageType">The type of moving average to use in the MACD</param> /// <param name="resolution">The resolution of data sent into the MACD indicator</param> public MacdAlphaNewModel( int fastPeriod = 12, int slowPeriod = 26, int signalPeriod = 9, MovingAverageType movingAverageType = MovingAverageType.Exponential, Resolution resolution = Resolution.Daily ) { _fastPeriod = fastPeriod; _slowPeriod = slowPeriod; _signalPeriod = signalPeriod; _movingAverageType = movingAverageType; _resolution = resolution; _symbolData = new Dictionary<Symbol, SymbolData>(); Name = $"{nameof(MacdAlphaModel)}({fastPeriod},{slowPeriod},{signalPeriod},{movingAverageType},{resolution})"; } /// <summary> /// Determines an insight for each security based on it's current MACD signal /// </summary> /// <param name="algorithm">The algorithm instance</param> /// <param name="data">The new data available</param> /// <returns>The new insights generated</returns> public override IEnumerable<Insight> Update(QCAlgorithmFramework algorithm, Slice data) { foreach (var sd in _symbolData.Values) { if (sd.Security.Price == 0) { continue; } var direction = InsightDirection.Flat; var normalizedSignal = sd.MACD.Signal / sd.Security.Price; if (normalizedSignal > BounceThresholdPercent) { direction = InsightDirection.Up; } else if (normalizedSignal < -BounceThresholdPercent) { direction = InsightDirection.Down; } // ignore signal for same direction as previous signal if (direction == sd.PreviousDirection) { continue; } var insightPeriod = _resolution.ToTimeSpan().Multiply(_fastPeriod); var insight = Insight.Price(sd.Security.Symbol, insightPeriod, direction); sd.PreviousDirection = insight.Direction; yield return insight; } } /// <summary> /// Event fired each time the we add/remove securities from the data feed. /// This initializes the MACD for each added security and cleans up the indicator for each removed security. /// </summary> /// <param name="algorithm">The algorithm instance that experienced the change in securities</param> /// <param name="changes">The security additions and removals from the algorithm</param> public override void OnSecuritiesChanged(QCAlgorithmFramework algorithm, SecurityChanges changes) { foreach (var added in changes.AddedSecurities) { if (!_symbolData.ContainsKey(added.Symbol)){ _symbolData.Add(added.Symbol, new SymbolData(algorithm, added, _fastPeriod, _slowPeriod, _signalPeriod, _movingAverageType, _resolution)); } } foreach (var removed in changes.RemovedSecurities) { SymbolData data; if (_symbolData.TryGetValue(removed.Symbol, out data)) { // clean up our consolidator algorithm.SubscriptionManager.RemoveConsolidator(data.Security.Symbol, data.Consolidator); } } } class SymbolData { public InsightDirection? PreviousDirection { get; set; } public readonly Security Security; public readonly IDataConsolidator Consolidator; public readonly MovingAverageConvergenceDivergence MACD; public SymbolData(QCAlgorithmFramework algorithm, Security security, int fastPeriod, int slowPeriod, int signalPeriod, MovingAverageType movingAverageType, Resolution resolution) { Security = security; Consolidator = algorithm.ResolveConsolidator(security.Symbol, resolution); algorithm.SubscriptionManager.AddConsolidator(security.Symbol, Consolidator); MACD = new MovingAverageConvergenceDivergence(fastPeriod, slowPeriod, signalPeriod, movingAverageType); algorithm.RegisterIndicator(security.Symbol, MACD, Consolidator); } } } }