diff --git a/Algorithm.CSharp/AddOptionContractExpiresRegressionAlgorithm.cs b/Algorithm.CSharp/AddOptionContractExpiresRegressionAlgorithm.cs index 7b3cd2e256d5..b352ec10ef57 100644 --- a/Algorithm.CSharp/AddOptionContractExpiresRegressionAlgorithm.cs +++ b/Algorithm.CSharp/AddOptionContractExpiresRegressionAlgorithm.cs @@ -135,33 +135,33 @@ public override void OnData(Slice slice) public Dictionary ExpectedStatistics => new Dictionary { {"Total Orders", "3"}, - {"Average Win", "2.73%"}, + {"Average Win", "2.67%"}, {"Average Loss", "-2.98%"}, - {"Compounding Annual Return", "-4.619%"}, - {"Drawdown", "0.300%"}, - {"Expectancy", "-0.042"}, + {"Compounding Annual Return", "-5.432%"}, + {"Drawdown", "0.400%"}, + {"Expectancy", "-0.052"}, {"Start Equity", "100000"}, - {"End Equity", "99668"}, - {"Net Profit", "-0.332%"}, - {"Sharpe Ratio", "-4.614"}, - {"Sortino Ratio", "0"}, - {"Probabilistic Sharpe Ratio", "0.427%"}, + {"End Equity", "99608"}, + {"Net Profit", "-0.392%"}, + {"Sharpe Ratio", "-5.487"}, + {"Sortino Ratio", "-2.607"}, + {"Probabilistic Sharpe Ratio", "0.016%"}, {"Loss Rate", "50%"}, {"Win Rate", "50%"}, - {"Profit-Loss Ratio", "0.92"}, - {"Alpha", "-0.022"}, - {"Beta", "-0.012"}, + {"Profit-Loss Ratio", "0.90"}, + {"Alpha", "-0.028"}, + {"Beta", "-0.01"}, {"Annual Standard Deviation", "0.005"}, {"Annual Variance", "0"}, - {"Information Ratio", "-2.823"}, + {"Information Ratio", "-2.949"}, {"Tracking Error", "0.049"}, - {"Treynor Ratio", "2.01"}, + {"Treynor Ratio", "3.063"}, {"Total Fees", "$2.00"}, {"Estimated Strategy Capacity", "$5700000.00"}, {"Lowest Capacity Asset", "AOL VRKS95ENPM9Y|AOL R735QTJ8XC9X"}, - {"Portfolio Turnover", "0.55%"}, + {"Portfolio Turnover", "0.54%"}, {"Drawdown Recovery", "0"}, - {"OrderListHash", "d314aef81752b6583fd58f9e49054cd4"} + {"OrderListHash", "65d9c6a5991648c8c54a23423a51340d"} }; } } diff --git a/Algorithm.CSharp/AutomaticSeedBaseRegressionAlgorithm.cs b/Algorithm.CSharp/AutomaticSeedBaseRegressionAlgorithm.cs index a39b4c19f68e..530c896e620e 100644 --- a/Algorithm.CSharp/AutomaticSeedBaseRegressionAlgorithm.cs +++ b/Algorithm.CSharp/AutomaticSeedBaseRegressionAlgorithm.cs @@ -31,6 +31,7 @@ public abstract class AutomaticSeedBaseRegressionAlgorithm : QCAlgorithm, IRegre protected virtual bool ShouldHaveTradeData { get; } protected virtual bool ShouldHaveQuoteData { get; } protected virtual bool ShouldHaveOpenInterestData { get; } + protected virtual List SecuritiesToIgnoreForChecking => Enumerable.Empty().ToList(); public override void OnSecuritiesChanged(SecurityChanges changes) { @@ -38,7 +39,9 @@ public override void OnSecuritiesChanged(SecurityChanges changes) var gotQuotes = false; var gotOpenInterest = false; - foreach (var addedSecurity in changes.AddedSecurities.Where(x => !x.Symbol.IsCanonical() || x.Symbol.SecurityType == SecurityType.Future)) + var securitiesToCheck = changes.AddedSecurities.Where(x => (!x.Symbol.IsCanonical() || x.Symbol.SecurityType == SecurityType.Future) && !SecuritiesToIgnoreForChecking.Contains(x.Symbol.Value)).ToList(); + + foreach (var addedSecurity in securitiesToCheck) { if (addedSecurity.Price == 0) { @@ -55,7 +58,7 @@ public override void OnSecuritiesChanged(SecurityChanges changes) gotOpenInterest |= addedSecurity.Cache.GetData() != null; } - if (changes.AddedSecurities.Count > 0) + if (securitiesToCheck.Count > 0) { if (ShouldHaveTradeData && !gotTrades) { diff --git a/Algorithm.CSharp/BacktestingBrokerageRegressionAlgorithm.cs b/Algorithm.CSharp/BacktestingBrokerageRegressionAlgorithm.cs index 57fb83f684cc..1b7c3b8c0d44 100644 --- a/Algorithm.CSharp/BacktestingBrokerageRegressionAlgorithm.cs +++ b/Algorithm.CSharp/BacktestingBrokerageRegressionAlgorithm.cs @@ -316,30 +316,30 @@ public override OrderEvent MarketFill(Security asset, MarketOrder order) {"Total Orders", "3"}, {"Average Win", "0%"}, {"Average Loss", "-0.40%"}, - {"Compounding Annual Return", "-21.378%"}, - {"Drawdown", "0.400%"}, + {"Compounding Annual Return", "119.386%"}, + {"Drawdown", "0.800%"}, {"Expectancy", "-1"}, {"Start Equity", "100000"}, - {"End Equity", "99671.06"}, - {"Net Profit", "-0.329%"}, - {"Sharpe Ratio", "-14.095"}, + {"End Equity", "101082.06"}, + {"Net Profit", "1.082%"}, + {"Sharpe Ratio", "12.594"}, {"Sortino Ratio", "0"}, - {"Probabilistic Sharpe Ratio", "1.216%"}, + {"Probabilistic Sharpe Ratio", "95.977%"}, {"Loss Rate", "100%"}, {"Win Rate", "0%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "-0.01"}, - {"Beta", "0.097"}, - {"Annual Standard Deviation", "0.002"}, - {"Annual Variance", "0"}, - {"Information Ratio", "7.39"}, - {"Tracking Error", "0.015"}, - {"Treynor Ratio", "-0.234"}, + {"Alpha", "0.504"}, + {"Beta", "-6.672"}, + {"Annual Standard Deviation", "0.111"}, + {"Annual Variance", "0.012"}, + {"Information Ratio", "12.001"}, + {"Tracking Error", "0.127"}, + {"Treynor Ratio", "-0.209"}, {"Total Fees", "$2.00"}, {"Estimated Strategy Capacity", "$0"}, {"Lowest Capacity Asset", "GOOCV VP83T1ZUHROL"}, {"Portfolio Turnover", "17.02%"}, - {"Drawdown Recovery", "0"}, + {"Drawdown Recovery", "4"}, {"OrderListHash", "1be5073f2cf8802ffa163f7dab7d040e"} }; } diff --git a/Algorithm.CSharp/BasicTemplateContinuousFutureAlgorithm.cs b/Algorithm.CSharp/BasicTemplateContinuousFutureAlgorithm.cs index 4791436519bf..2ae3f3cecb0d 100644 --- a/Algorithm.CSharp/BasicTemplateContinuousFutureAlgorithm.cs +++ b/Algorithm.CSharp/BasicTemplateContinuousFutureAlgorithm.cs @@ -36,6 +36,9 @@ public class BasicTemplateContinuousFutureAlgorithm : QCAlgorithm, IRegressionAl private SimpleMovingAverage _fast; private SimpleMovingAverage _slow; + // Minimum SMA gap required before acting on a cross; see the workaround note in OnData. + private const decimal CrossThreshold = 0.001m; + /// /// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized. /// @@ -69,15 +72,17 @@ public override void OnData(Slice slice) } } + // Workaround so the C# and Python versions take the exact same trades on the limited + // sample data in the repository (decimal vs double rounding can disagree at a cross). if (!Portfolio.Invested) { - if(_fast > _slow) + if(_fast.Current.Value - _slow.Current.Value > CrossThreshold) { _currentContract = Securities[_continuousContract.Mapped]; Buy(_currentContract.Symbol, 1); } } - else if(_fast < _slow) + else if(_slow.Current.Value - _fast.Current.Value > CrossThreshold) { Liquidate(); } @@ -134,34 +139,34 @@ public override void OnSecuritiesChanged(SecurityChanges changes) /// public Dictionary ExpectedStatistics => new Dictionary { - {"Total Orders", "5"}, - {"Average Win", "2.48%"}, - {"Average Loss", "0%"}, - {"Compounding Annual Return", "11.325%"}, - {"Drawdown", "1.500%"}, - {"Expectancy", "0"}, + {"Total Orders", "9"}, + {"Average Win", "2.85%"}, + {"Average Loss", "-0.43%"}, + {"Compounding Annual Return", "11.019%"}, + {"Drawdown", "0.900%"}, + {"Expectancy", "2.818"}, {"Start Equity", "100000"}, - {"End Equity", "105549.6"}, - {"Net Profit", "5.550%"}, - {"Sharpe Ratio", "1.332"}, - {"Sortino Ratio", "879.904"}, - {"Probabilistic Sharpe Ratio", "79.894%"}, - {"Loss Rate", "0%"}, - {"Win Rate", "100%"}, - {"Profit-Loss Ratio", "0"}, - {"Alpha", "0.075"}, - {"Beta", "-0.017"}, - {"Annual Standard Deviation", "0.053"}, - {"Annual Variance", "0.003"}, - {"Information Ratio", "-1.48"}, - {"Tracking Error", "0.099"}, - {"Treynor Ratio", "-4.187"}, - {"Total Fees", "$10.75"}, - {"Estimated Strategy Capacity", "$7100000.00"}, + {"End Equity", "105403.5"}, + {"Net Profit", "5.404%"}, + {"Sharpe Ratio", "1.531"}, + {"Sortino Ratio", "2.106"}, + {"Probabilistic Sharpe Ratio", "82.864%"}, + {"Loss Rate", "50%"}, + {"Win Rate", "50%"}, + {"Profit-Loss Ratio", "6.64"}, + {"Alpha", "0.067"}, + {"Beta", "0.009"}, + {"Annual Standard Deviation", "0.045"}, + {"Annual Variance", "0.002"}, + {"Information Ratio", "-1.606"}, + {"Tracking Error", "0.093"}, + {"Treynor Ratio", "7.237"}, + {"Total Fees", "$19.35"}, + {"Estimated Strategy Capacity", "$1000000000.00"}, {"Lowest Capacity Asset", "ES VMKLFZIH2MTD"}, - {"Portfolio Turnover", "2.33%"}, - {"Drawdown Recovery", "37"}, - {"OrderListHash", "223735440010fcec5889bb7becacfa82"} + {"Portfolio Turnover", "4.18%"}, + {"Drawdown Recovery", "19"}, + {"OrderListHash", "eb3bed9886f79a56c631225a6445adb2"} }; } } diff --git a/Algorithm.CSharp/BasicTemplateContinuousFutureWithExtendedMarketAlgorithm.cs b/Algorithm.CSharp/BasicTemplateContinuousFutureWithExtendedMarketAlgorithm.cs index e606c0e79ce0..96b1c5a95bb6 100644 --- a/Algorithm.CSharp/BasicTemplateContinuousFutureWithExtendedMarketAlgorithm.cs +++ b/Algorithm.CSharp/BasicTemplateContinuousFutureWithExtendedMarketAlgorithm.cs @@ -37,6 +37,9 @@ public class BasicTemplateContinuousFutureWithExtendedMarketAlgorithm : QCAlgori private SimpleMovingAverage _fast; private SimpleMovingAverage _slow; + // Minimum SMA gap required before acting on a cross; see the workaround note in OnData. + private const decimal CrossThreshold = 0.001m; + /// /// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized. /// @@ -76,17 +79,24 @@ public override void OnData(Slice slice) return; } - if (!Portfolio.Invested) + // This is just to limit the amount of orders done in this regression test, since data in the repo is limited. + // Also limit it to 3 orders so that the continuous contract rolls happens with an open position. + if (Time < new DateTime(2013, 11, 12) && Transactions.OrdersCount < 3) { - if(_fast > _slow) + // Workaround so the C# and Python versions take the exact same trades on the limited + // sample data in the repository (decimal vs double rounding can disagree at a cross). + if (!Portfolio.Invested) { - _currentContract = Securities[_continuousContract.Mapped]; - Buy(_currentContract.Symbol, 1); + if (_fast.Current.Value - _slow.Current.Value > CrossThreshold) + { + _currentContract = Securities[_continuousContract.Mapped]; + Buy(_currentContract.Symbol, 1); + } + } + else if (_slow.Current.Value - _fast.Current.Value > CrossThreshold) + { + Liquidate(); } - } - else if(_fast < _slow) - { - Liquidate(); } if (_currentContract != null && _currentContract.Symbol != _continuousContract.Mapped) @@ -140,34 +150,34 @@ public override void OnSecuritiesChanged(SecurityChanges changes) /// public Dictionary ExpectedStatistics => new Dictionary { - {"Total Orders", "5"}, - {"Average Win", "2.86%"}, + {"Total Orders", "3"}, + {"Average Win", "6.15%"}, {"Average Loss", "0%"}, - {"Compounding Annual Return", "12.959%"}, - {"Drawdown", "1.100%"}, + {"Compounding Annual Return", "13.813%"}, + {"Drawdown", "1.400%"}, {"Expectancy", "0"}, {"Start Equity", "100000"}, - {"End Equity", "106337.1"}, - {"Net Profit", "6.337%"}, - {"Sharpe Ratio", "1.41"}, - {"Sortino Ratio", "1.242"}, - {"Probabilistic Sharpe Ratio", "77.992%"}, + {"End Equity", "106741.4"}, + {"Net Profit", "6.741%"}, + {"Sharpe Ratio", "2.003"}, + {"Sortino Ratio", "2.845"}, + {"Probabilistic Sharpe Ratio", "92.590%"}, {"Loss Rate", "0%"}, {"Win Rate", "100%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "0.071"}, - {"Beta", "0.054"}, - {"Annual Standard Deviation", "0.059"}, - {"Annual Variance", "0.003"}, - {"Information Ratio", "-1.392"}, - {"Tracking Error", "0.097"}, - {"Treynor Ratio", "1.518"}, - {"Total Fees", "$10.75"}, - {"Estimated Strategy Capacity", "$890000000.00"}, + {"Alpha", "0.069"}, + {"Beta", "0.086"}, + {"Annual Standard Deviation", "0.044"}, + {"Annual Variance", "0.002"}, + {"Information Ratio", "-1.506"}, + {"Tracking Error", "0.086"}, + {"Treynor Ratio", "1.023"}, + {"Total Fees", "$6.45"}, + {"Estimated Strategy Capacity", "$3700000000.00"}, {"Lowest Capacity Asset", "ES VMKLFZIH2MTD"}, - {"Portfolio Turnover", "2.32%"}, - {"Drawdown Recovery", "34"}, - {"OrderListHash", "1504a8892da8d8c0650018732f315753"} + {"Portfolio Turnover", "1.37%"}, + {"Drawdown Recovery", "18"}, + {"OrderListHash", "764ab9f6ea662a60e41daedb9613b246"} }; } } diff --git a/Algorithm.CSharp/BasicTemplateFutureRolloverAlgorithm.cs b/Algorithm.CSharp/BasicTemplateFutureRolloverAlgorithm.cs index 0755d12267e4..945ce7f483e6 100644 --- a/Algorithm.CSharp/BasicTemplateFutureRolloverAlgorithm.cs +++ b/Algorithm.CSharp/BasicTemplateFutureRolloverAlgorithm.cs @@ -193,34 +193,34 @@ public void Dispose() /// public Dictionary ExpectedStatistics => new Dictionary { - {"Total Orders", "1"}, - {"Average Win", "0%"}, + {"Total Orders", "3"}, + {"Average Win", "0.14%"}, {"Average Loss", "0%"}, - {"Compounding Annual Return", "-0.010%"}, - {"Drawdown", "0.000%"}, + {"Compounding Annual Return", "0.770%"}, + {"Drawdown", "0.100%"}, {"Expectancy", "0"}, {"Start Equity", "1000000"}, - {"End Equity", "999983.2"}, - {"Net Profit", "-0.002%"}, - {"Sharpe Ratio", "-225.214"}, - {"Sortino Ratio", "0"}, - {"Probabilistic Sharpe Ratio", "0.135%"}, + {"End Equity", "1001341.4"}, + {"Net Profit", "0.134%"}, + {"Sharpe Ratio", "-0.494"}, + {"Sortino Ratio", "-0.544"}, + {"Probabilistic Sharpe Ratio", "55.093%"}, {"Loss Rate", "0%"}, - {"Win Rate", "0%"}, + {"Win Rate", "100%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "-0.008"}, - {"Beta", "0"}, - {"Annual Standard Deviation", "0"}, + {"Alpha", "-0.015"}, + {"Beta", "0.03"}, + {"Annual Standard Deviation", "0.004"}, {"Annual Variance", "0"}, - {"Information Ratio", "-5.146"}, - {"Tracking Error", "0.083"}, - {"Treynor Ratio", "-542.359"}, - {"Total Fees", "$2.15"}, - {"Estimated Strategy Capacity", "$0"}, + {"Information Ratio", "-5.235"}, + {"Tracking Error", "0.081"}, + {"Treynor Ratio", "-0.069"}, + {"Total Fees", "$6.45"}, + {"Estimated Strategy Capacity", "$780000000000.00"}, {"Lowest Capacity Asset", "ES VMKLFZIH2MTD"}, - {"Portfolio Turnover", "0.13%"}, - {"Drawdown Recovery", "0"}, - {"OrderListHash", "a6ccce3a1a7f549f887d83e84bfa878d"} + {"Portfolio Turnover", "0.42%"}, + {"Drawdown Recovery", "3"}, + {"OrderListHash", "d17bbe62c86730e5178528a3153df0e6"} }; } } diff --git a/Algorithm.CSharp/BasicTemplateFuturesDailyAlgorithm.cs b/Algorithm.CSharp/BasicTemplateFuturesDailyAlgorithm.cs index 4fc724fc02a7..d4d26dd4dfb1 100644 --- a/Algorithm.CSharp/BasicTemplateFuturesDailyAlgorithm.cs +++ b/Algorithm.CSharp/BasicTemplateFuturesDailyAlgorithm.cs @@ -127,7 +127,7 @@ public override void OnSecuritiesChanged(SecurityChanges changes) /// /// Data Points count of all timeslices of algorithm /// - public virtual long DataPoints => 5874; + public virtual long DataPoints => 5876; /// /// Data Points count of the algorithm history @@ -145,33 +145,33 @@ public override void OnSecuritiesChanged(SecurityChanges changes) public virtual Dictionary ExpectedStatistics => new Dictionary { {"Total Orders", "22"}, - {"Average Win", "0.61%"}, + {"Average Win", "0.24%"}, {"Average Loss", "-0.49%"}, - {"Compounding Annual Return", "0.117%"}, + {"Compounding Annual Return", "-0.252%"}, {"Drawdown", "0.300%"}, - {"Expectancy", "0.124"}, + {"Expectancy", "-0.258"}, {"Start Equity", "1000000"}, - {"End Equity", "1001178.23"}, - {"Net Profit", "0.118%"}, - {"Sharpe Ratio", "-1.834"}, - {"Sortino Ratio", "-0.52"}, - {"Probabilistic Sharpe Ratio", "15.902%"}, + {"End Equity", "997465.73"}, + {"Net Profit", "-0.253%"}, + {"Sharpe Ratio", "-5.753"}, + {"Sortino Ratio", "-1.032"}, + {"Probabilistic Sharpe Ratio", "0.001%"}, {"Loss Rate", "50%"}, {"Win Rate", "50%"}, - {"Profit-Loss Ratio", "1.25"}, - {"Alpha", "-0.007"}, - {"Beta", "0.002"}, - {"Annual Standard Deviation", "0.004"}, + {"Profit-Loss Ratio", "0.48"}, + {"Alpha", "-0.009"}, + {"Beta", "0"}, + {"Annual Standard Deviation", "0.002"}, {"Annual Variance", "0"}, - {"Information Ratio", "-1.352"}, + {"Information Ratio", "-1.381"}, {"Tracking Error", "0.089"}, - {"Treynor Ratio", "-4.239"}, + {"Treynor Ratio", "-19.581"}, {"Total Fees", "$6.77"}, {"Estimated Strategy Capacity", "$290000000.00"}, {"Lowest Capacity Asset", "GC VOFJUCDY9XNH"}, {"Portfolio Turnover", "0.12%"}, - {"Drawdown Recovery", "69"}, - {"OrderListHash", "064f8f56389ceecb333b5a4bb79622c1"} + {"Drawdown Recovery", "0"}, + {"OrderListHash", "140ff4560d532192be3041846667deca"} }; } } diff --git a/Algorithm.CSharp/BasicTemplateFuturesWithExtendedMarketDailyAlgorithm.cs b/Algorithm.CSharp/BasicTemplateFuturesWithExtendedMarketDailyAlgorithm.cs index 7c61ec8d41ab..20f90c55cdd0 100644 --- a/Algorithm.CSharp/BasicTemplateFuturesWithExtendedMarketDailyAlgorithm.cs +++ b/Algorithm.CSharp/BasicTemplateFuturesWithExtendedMarketDailyAlgorithm.cs @@ -36,7 +36,7 @@ public class BasicTemplateFuturesWithExtendedMarketDailyAlgorithm : BasicTemplat /// /// Data Points count of all timeslices of algorithm /// - public override long DataPoints => 5978; + public override long DataPoints => 5980; /// /// This is used by the regression test system to indicate what the expected statistics are from running the algorithm @@ -44,33 +44,33 @@ public class BasicTemplateFuturesWithExtendedMarketDailyAlgorithm : BasicTemplat public override Dictionary ExpectedStatistics => new Dictionary { {"Total Orders", "22"}, - {"Average Win", "0.61%"}, + {"Average Win", "0.24%"}, {"Average Loss", "-0.49%"}, - {"Compounding Annual Return", "0.117%"}, + {"Compounding Annual Return", "-0.252%"}, {"Drawdown", "0.300%"}, - {"Expectancy", "0.124"}, + {"Expectancy", "-0.258"}, {"Start Equity", "1000000"}, - {"End Equity", "1001178.23"}, - {"Net Profit", "0.118%"}, - {"Sharpe Ratio", "-1.834"}, - {"Sortino Ratio", "-0.52"}, - {"Probabilistic Sharpe Ratio", "15.902%"}, + {"End Equity", "997465.73"}, + {"Net Profit", "-0.253%"}, + {"Sharpe Ratio", "-5.753"}, + {"Sortino Ratio", "-1.032"}, + {"Probabilistic Sharpe Ratio", "0.001%"}, {"Loss Rate", "50%"}, {"Win Rate", "50%"}, - {"Profit-Loss Ratio", "1.25"}, - {"Alpha", "-0.007"}, - {"Beta", "0.002"}, - {"Annual Standard Deviation", "0.004"}, + {"Profit-Loss Ratio", "0.48"}, + {"Alpha", "-0.009"}, + {"Beta", "0"}, + {"Annual Standard Deviation", "0.002"}, {"Annual Variance", "0"}, - {"Information Ratio", "-1.352"}, + {"Information Ratio", "-1.381"}, {"Tracking Error", "0.089"}, - {"Treynor Ratio", "-4.239"}, + {"Treynor Ratio", "-19.581"}, {"Total Fees", "$6.77"}, {"Estimated Strategy Capacity", "$290000000.00"}, {"Lowest Capacity Asset", "GC VOFJUCDY9XNH"}, {"Portfolio Turnover", "0.12%"}, - {"Drawdown Recovery", "69"}, - {"OrderListHash", "064f8f56389ceecb333b5a4bb79622c1"} + {"Drawdown Recovery", "0"}, + {"OrderListHash", "140ff4560d532192be3041846667deca"} }; } } diff --git a/Algorithm.CSharp/BasicTemplateOptionsFilterUniverseAlgorithm.cs b/Algorithm.CSharp/BasicTemplateOptionsFilterUniverseAlgorithm.cs index 4950cff1c710..60ea0caaa4e5 100644 --- a/Algorithm.CSharp/BasicTemplateOptionsFilterUniverseAlgorithm.cs +++ b/Algorithm.CSharp/BasicTemplateOptionsFilterUniverseAlgorithm.cs @@ -119,30 +119,30 @@ public override void OnOrderEvent(OrderEvent orderEvent) {"Total Orders", "2"}, {"Average Win", "0%"}, {"Average Loss", "-0.40%"}, - {"Compounding Annual Return", "-20.338%"}, - {"Drawdown", "0.300%"}, + {"Compounding Annual Return", "122.246%"}, + {"Drawdown", "0.800%"}, {"Expectancy", "-1"}, {"Start Equity", "100000"}, - {"End Equity", "99689"}, - {"Net Profit", "-0.311%"}, - {"Sharpe Ratio", "0"}, + {"End Equity", "101100"}, + {"Net Profit", "1.100%"}, + {"Sharpe Ratio", "12.688"}, {"Sortino Ratio", "0"}, - {"Probabilistic Sharpe Ratio", "0%"}, + {"Probabilistic Sharpe Ratio", "95.977%"}, {"Loss Rate", "100%"}, {"Win Rate", "0%"}, {"Profit-Loss Ratio", "0"}, {"Alpha", "0"}, {"Beta", "0"}, - {"Annual Standard Deviation", "0"}, - {"Annual Variance", "0"}, - {"Information Ratio", "0"}, - {"Tracking Error", "0"}, + {"Annual Standard Deviation", "0.112"}, + {"Annual Variance", "0.013"}, + {"Information Ratio", "12.777"}, + {"Tracking Error", "0.112"}, {"Treynor Ratio", "0"}, {"Total Fees", "$1.00"}, {"Estimated Strategy Capacity", "$0"}, {"Lowest Capacity Asset", "GOOCV VP83T1ZUHROL"}, {"Portfolio Turnover", "15.08%"}, - {"Drawdown Recovery", "0"}, + {"Drawdown Recovery", "4"}, {"OrderListHash", "c53bc9318676161ed3b7797c945e2113"} }; } diff --git a/Algorithm.CSharp/BasicTemplateSPXWeeklyIndexOptionsAlgorithm.cs b/Algorithm.CSharp/BasicTemplateSPXWeeklyIndexOptionsAlgorithm.cs index a9b121363b77..2eab94c7b148 100644 --- a/Algorithm.CSharp/BasicTemplateSPXWeeklyIndexOptionsAlgorithm.cs +++ b/Algorithm.CSharp/BasicTemplateSPXWeeklyIndexOptionsAlgorithm.cs @@ -103,7 +103,7 @@ public override void OnOrderEvent(OrderEvent orderEvent) /// /// Data Points count of all timeslices of algorithm /// - public virtual long DataPoints => 21467; + public virtual long DataPoints => 26326; /// /// Data Points count of the algorithm history @@ -122,32 +122,32 @@ public override void OnOrderEvent(OrderEvent orderEvent) { {"Total Orders", "5"}, {"Average Win", "0.63%"}, - {"Average Loss", "-0.03%"}, - {"Compounding Annual Return", "54.478%"}, - {"Drawdown", "0.400%"}, - {"Expectancy", "23.219"}, + {"Average Loss", "-0.02%"}, + {"Compounding Annual Return", "23.182%"}, + {"Drawdown", "1.200%"}, + {"Expectancy", "26.062"}, {"Start Equity", "1000000"}, - {"End Equity", "1006025"}, - {"Net Profit", "0.602%"}, - {"Sharpe Ratio", "2.62"}, - {"Sortino Ratio", "0"}, - {"Probabilistic Sharpe Ratio", "63.221%"}, + {"End Equity", "1002884"}, + {"Net Profit", "0.288%"}, + {"Sharpe Ratio", "-3.925"}, + {"Sortino Ratio", "-9.873"}, + {"Probabilistic Sharpe Ratio", "28.473%"}, {"Loss Rate", "0%"}, {"Win Rate", "100%"}, - {"Profit-Loss Ratio", "23.22"}, - {"Alpha", "0.067"}, - {"Beta", "-0.013"}, - {"Annual Standard Deviation", "0.004"}, - {"Annual Variance", "0"}, - {"Information Ratio", "-50.808"}, - {"Tracking Error", "0.086"}, - {"Treynor Ratio", "-0.725"}, + {"Profit-Loss Ratio", "26.06"}, + {"Alpha", "-1.151"}, + {"Beta", "0.233"}, + {"Annual Standard Deviation", "0.035"}, + {"Annual Variance", "0.001"}, + {"Information Ratio", "-63.342"}, + {"Tracking Error", "0.071"}, + {"Treynor Ratio", "-0.591"}, {"Total Fees", "$0.00"}, - {"Estimated Strategy Capacity", "$580000.00"}, - {"Lowest Capacity Asset", "SPXW 31K54PVWHYTTA|SPX 31"}, - {"Portfolio Turnover", "0.40%"}, + {"Estimated Strategy Capacity", "$200000.00"}, + {"Lowest Capacity Asset", "SPXW 31K35TP65TBHQ|SPX 31"}, + {"Portfolio Turnover", "0.28%"}, {"Drawdown Recovery", "0"}, - {"OrderListHash", "03148bbb5453fc1056a3285bd31ce158"} + {"OrderListHash", "dc3fdd20abc50b79fd2f2a1005225277"} }; } } diff --git a/Algorithm.CSharp/BasicTemplateSPXWeeklyIndexOptionsStrategyAlgorithm.cs b/Algorithm.CSharp/BasicTemplateSPXWeeklyIndexOptionsStrategyAlgorithm.cs index 01cc595854ed..1d84d9fc174c 100644 --- a/Algorithm.CSharp/BasicTemplateSPXWeeklyIndexOptionsStrategyAlgorithm.cs +++ b/Algorithm.CSharp/BasicTemplateSPXWeeklyIndexOptionsStrategyAlgorithm.cs @@ -109,7 +109,7 @@ public override void OnOrderEvent(OrderEvent orderEvent) /// /// Data Points count of all timeslices of algorithm /// - public virtual long DataPoints => 16680; + public virtual long DataPoints => 26399; /// /// Data Points count of the algorithm history @@ -129,31 +129,31 @@ public override void OnOrderEvent(OrderEvent orderEvent) {"Total Orders", "10"}, {"Average Win", "0.46%"}, {"Average Loss", "-0.01%"}, - {"Compounding Annual Return", "101.998%"}, - {"Drawdown", "0.100%"}, - {"Expectancy", "24.137"}, + {"Compounding Annual Return", "60.924%"}, + {"Drawdown", "0.600%"}, + {"Expectancy", "29.469"}, {"Start Equity", "1000000"}, - {"End Equity", "1009050"}, - {"Net Profit", "0.905%"}, - {"Sharpe Ratio", "8.44"}, - {"Sortino Ratio", "0"}, - {"Probabilistic Sharpe Ratio", "95.546%"}, + {"End Equity", "1006115"}, + {"Net Profit", "0.612%"}, + {"Sharpe Ratio", "-0.533"}, + {"Sortino Ratio", "-2.937"}, + {"Probabilistic Sharpe Ratio", "43.837%"}, {"Loss Rate", "50%"}, {"Win Rate", "50%"}, - {"Profit-Loss Ratio", "49.27"}, - {"Alpha", "-2.01"}, - {"Beta", "0.307"}, - {"Annual Standard Deviation", "0.021"}, - {"Annual Variance", "0"}, - {"Information Ratio", "-144.654"}, - {"Tracking Error", "0.048"}, - {"Treynor Ratio", "0.589"}, + {"Profit-Loss Ratio", "59.94"}, + {"Alpha", "-3.337"}, + {"Beta", "0.465"}, + {"Annual Standard Deviation", "0.033"}, + {"Annual Variance", "0.001"}, + {"Information Ratio", "-191.859"}, + {"Tracking Error", "0.037"}, + {"Treynor Ratio", "-0.037"}, {"Total Fees", "$0.00"}, - {"Estimated Strategy Capacity", "$13000000.00"}, - {"Lowest Capacity Asset", "SPXW XKX6S2GMDZSE|SPX 31"}, - {"Portfolio Turnover", "0.28%"}, - {"Drawdown Recovery", "2"}, - {"OrderListHash", "9d03f85003416861df07ccb31a18af9a"} + {"Estimated Strategy Capacity", "$2800000.00"}, + {"Lowest Capacity Asset", "SPXW XKZ5O96YJI3Y|SPX 31"}, + {"Portfolio Turnover", "0.35%"}, + {"Drawdown Recovery", "0"}, + {"OrderListHash", "6d3578ad120bcbbe1fc4ed6d189cdd0d"} }; } } diff --git a/Algorithm.CSharp/ContinuousBackMonthRawFutureRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousBackMonthRawFutureRegressionAlgorithm.cs index 4801a5f69f24..2d8a794c8b98 100644 --- a/Algorithm.CSharp/ContinuousBackMonthRawFutureRegressionAlgorithm.cs +++ b/Algorithm.CSharp/ContinuousBackMonthRawFutureRegressionAlgorithm.cs @@ -157,33 +157,33 @@ public override void OnEndOfAlgorithm() public Dictionary ExpectedStatistics => new Dictionary { {"Total Orders", "2"}, - {"Average Win", "1.48%"}, + {"Average Win", "6.43%"}, {"Average Loss", "0%"}, - {"Compounding Annual Return", "2.968%"}, + {"Compounding Annual Return", "13.184%"}, {"Drawdown", "1.600%"}, {"Expectancy", "0"}, {"Start Equity", "100000"}, - {"End Equity", "101483.2"}, - {"Net Profit", "1.483%"}, - {"Sharpe Ratio", "0.521"}, - {"Sortino Ratio", "0.124"}, - {"Probabilistic Sharpe Ratio", "42.535%"}, + {"End Equity", "106433.2"}, + {"Net Profit", "6.433%"}, + {"Sharpe Ratio", "1.346"}, + {"Sortino Ratio", "0.782"}, + {"Probabilistic Sharpe Ratio", "73.094%"}, {"Loss Rate", "0%"}, {"Win Rate", "100%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "-0.011"}, - {"Beta", "0.113"}, - {"Annual Standard Deviation", "0.026"}, - {"Annual Variance", "0.001"}, - {"Information Ratio", "-2.674"}, - {"Tracking Error", "0.076"}, - {"Treynor Ratio", "0.117"}, + {"Alpha", "0.069"}, + {"Beta", "0.07"}, + {"Annual Standard Deviation", "0.063"}, + {"Annual Variance", "0.004"}, + {"Information Ratio", "-1.356"}, + {"Tracking Error", "0.098"}, + {"Treynor Ratio", "1.195"}, {"Total Fees", "$4.30"}, - {"Estimated Strategy Capacity", "$76000000.00"}, + {"Estimated Strategy Capacity", "$100000000.00"}, {"Lowest Capacity Asset", "ES VP274HSU1AF5"}, {"Portfolio Turnover", "0.91%"}, {"Drawdown Recovery", "2"}, - {"OrderListHash", "a472060eeb87c7474d25f7035fa150c4"} + {"OrderListHash", "825ea8c1a4d37ce547f5698ffcdf5e89"} }; } } diff --git a/Algorithm.CSharp/ContinuousFutureBackMonthRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureBackMonthRegressionAlgorithm.cs index 0b2eeba0bc96..698adc343516 100644 --- a/Algorithm.CSharp/ContinuousFutureBackMonthRegressionAlgorithm.cs +++ b/Algorithm.CSharp/ContinuousFutureBackMonthRegressionAlgorithm.cs @@ -173,33 +173,33 @@ public override void OnEndOfAlgorithm() public Dictionary ExpectedStatistics => new Dictionary { {"Total Orders", "3"}, - {"Average Win", "1.48%"}, + {"Average Win", "6.43%"}, {"Average Loss", "0%"}, - {"Compounding Annual Return", "4.603%"}, + {"Compounding Annual Return", "14.898%"}, {"Drawdown", "1.600%"}, {"Expectancy", "0"}, {"Start Equity", "100000"}, - {"End Equity", "102291.4"}, - {"Net Profit", "2.291%"}, - {"Sharpe Ratio", "0.892"}, - {"Sortino Ratio", "0.312"}, - {"Probabilistic Sharpe Ratio", "55.781%"}, + {"End Equity", "107241.4"}, + {"Net Profit", "7.241%"}, + {"Sharpe Ratio", "1.511"}, + {"Sortino Ratio", "1.208"}, + {"Probabilistic Sharpe Ratio", "80.992%"}, {"Loss Rate", "0%"}, {"Win Rate", "100%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "-0.006"}, - {"Beta", "0.14"}, - {"Annual Standard Deviation", "0.028"}, - {"Annual Variance", "0.001"}, - {"Information Ratio", "-2.584"}, - {"Tracking Error", "0.075"}, - {"Treynor Ratio", "0.175"}, + {"Alpha", "0.075"}, + {"Beta", "0.096"}, + {"Annual Standard Deviation", "0.063"}, + {"Annual Variance", "0.004"}, + {"Information Ratio", "-1.256"}, + {"Tracking Error", "0.097"}, + {"Treynor Ratio", "0.996"}, {"Total Fees", "$6.45"}, - {"Estimated Strategy Capacity", "$230000000.00"}, + {"Estimated Strategy Capacity", "$240000000.00"}, {"Lowest Capacity Asset", "ES VP274HSU1AF5"}, - {"Portfolio Turnover", "1.39%"}, + {"Portfolio Turnover", "1.37%"}, {"Drawdown Recovery", "16"}, - {"OrderListHash", "6a5b2e6b3f140e9bb7f32c07cbf5f36c"} + {"OrderListHash", "c2eacc46e837feb8bf019c43f5c03f40"} }; } } diff --git a/Algorithm.CSharp/ContinuousFutureOpenPositionsLiquidationOnDelistingRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureOpenPositionsLiquidationOnDelistingRegressionAlgorithm.cs index d4cfacd2674b..6b733db4516b 100644 --- a/Algorithm.CSharp/ContinuousFutureOpenPositionsLiquidationOnDelistingRegressionAlgorithm.cs +++ b/Algorithm.CSharp/ContinuousFutureOpenPositionsLiquidationOnDelistingRegressionAlgorithm.cs @@ -214,24 +214,24 @@ public override void OnEndOfAlgorithm() {"Start Equity", "100000"}, {"End Equity", "107016.6"}, {"Net Profit", "7.017%"}, - {"Sharpe Ratio", "3.217"}, - {"Sortino Ratio", "0"}, - {"Probabilistic Sharpe Ratio", "99.828%"}, + {"Sharpe Ratio", "3.872"}, + {"Sortino Ratio", "134.511"}, + {"Probabilistic Sharpe Ratio", "99.843%"}, {"Loss Rate", "0%"}, {"Win Rate", "100%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "0.227"}, - {"Beta", "0.109"}, - {"Annual Standard Deviation", "0.084"}, - {"Annual Variance", "0.007"}, - {"Information Ratio", "-1.122"}, - {"Tracking Error", "0.112"}, - {"Treynor Ratio", "2.49"}, + {"Alpha", "0.158"}, + {"Beta", "0.28"}, + {"Annual Standard Deviation", "0.07"}, + {"Annual Variance", "0.005"}, + {"Information Ratio", "-1.429"}, + {"Tracking Error", "0.089"}, + {"Treynor Ratio", "0.961"}, {"Total Fees", "$2.15"}, {"Estimated Strategy Capacity", "$1700000000.00"}, {"Lowest Capacity Asset", "ES VMKLFZIH2MTD"}, {"Portfolio Turnover", "2.01%"}, - {"Drawdown Recovery", "16"}, + {"Drawdown Recovery", "19"}, {"OrderListHash", "838e662caaa5a385c43ef27df1efbaf4"} }; } diff --git a/Algorithm.CSharp/ContinuousFutureRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRegressionAlgorithm.cs index 6a9a7e210449..2177a8eb5c9a 100644 --- a/Algorithm.CSharp/ContinuousFutureRegressionAlgorithm.cs +++ b/Algorithm.CSharp/ContinuousFutureRegressionAlgorithm.cs @@ -191,33 +191,33 @@ public override void OnEndOfAlgorithm() public Dictionary ExpectedStatistics => new Dictionary { {"Total Orders", "4"}, - {"Average Win", "0.84%"}, + {"Average Win", "3.31%"}, {"Average Loss", "0%"}, - {"Compounding Annual Return", "3.380%"}, + {"Compounding Annual Return", "13.589%"}, {"Drawdown", "1.600%"}, {"Expectancy", "0"}, {"Start Equity", "100000"}, - {"End Equity", "101687.3"}, - {"Net Profit", "1.687%"}, - {"Sharpe Ratio", "0.605"}, - {"Sortino Ratio", "0.202"}, - {"Probabilistic Sharpe Ratio", "45.198%"}, + {"End Equity", "106624.8"}, + {"Net Profit", "6.625%"}, + {"Sharpe Ratio", "1.696"}, + {"Sortino Ratio", "1.497"}, + {"Probabilistic Sharpe Ratio", "83.369%"}, {"Loss Rate", "0%"}, {"Win Rate", "100%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "-0.013"}, - {"Beta", "0.134"}, - {"Annual Standard Deviation", "0.027"}, - {"Annual Variance", "0.001"}, - {"Information Ratio", "-2.687"}, - {"Tracking Error", "0.075"}, - {"Treynor Ratio", "0.121"}, + {"Alpha", "0.049"}, + {"Beta", "0.171"}, + {"Annual Standard Deviation", "0.051"}, + {"Annual Variance", "0.003"}, + {"Information Ratio", "-1.571"}, + {"Tracking Error", "0.084"}, + {"Treynor Ratio", "0.504"}, {"Total Fees", "$6.45"}, - {"Estimated Strategy Capacity", "$2600000000.00"}, + {"Estimated Strategy Capacity", "$2900000000.00"}, {"Lowest Capacity Asset", "ES VMKLFZIH2MTD"}, - {"Portfolio Turnover", "1.88%"}, - {"Drawdown Recovery", "16"}, - {"OrderListHash", "1973b0beb9bc5e618e0387d960553d7a"} + {"Portfolio Turnover", "1.84%"}, + {"Drawdown Recovery", "19"}, + {"OrderListHash", "93ec1ff41936971c765cd3a1e3613f09"} }; } } diff --git a/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataRegressionAlgorithm.cs index c982f8b4d0c6..2d3db5e30fe2 100644 --- a/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataRegressionAlgorithm.cs +++ b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataRegressionAlgorithm.cs @@ -33,7 +33,7 @@ public class ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataRegressionA /// /// Data Points count of all timeslices of algorithm /// - public override long DataPoints => 483; + public override long DataPoints => 485; /// /// Data Points count of the algorithm history diff --git a/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs index 2ffbe7e930c9..d984d7fe0b51 100644 --- a/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs +++ b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs @@ -28,6 +28,6 @@ public class ContinuousFutureRolloverDailyExchangeTimeZoneAheadOfDataWithInitial /// /// Data Points count of the algorithm history /// - public override int AlgorithmHistoryDataPoints => 15; + public override int AlgorithmHistoryDataPoints => 24; } } diff --git a/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneBehindOfDataRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneBehindOfDataRegressionAlgorithm.cs index 4cc8c2d8f74c..b263f8aeabad 100644 --- a/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneBehindOfDataRegressionAlgorithm.cs +++ b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneBehindOfDataRegressionAlgorithm.cs @@ -33,6 +33,6 @@ public class ContinuousFutureRolloverDailyExchangeTimeZoneBehindOfDataRegression /// /// Data Points count of all timeslices of algorithm /// - public override long DataPoints => 479; + public override long DataPoints => 481; } } diff --git a/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm.cs index def2d23bca51..4d38090a57f3 100644 --- a/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm.cs +++ b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm.cs @@ -29,6 +29,6 @@ public class ContinuousFutureRolloverDailyExchangeTimeZoneBehindOfDataWithInitia /// /// Data Points count of the algorithm history /// - public override int AlgorithmHistoryDataPoints => 17; + public override int AlgorithmHistoryDataPoints => 24; } } diff --git a/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneSameAsDataRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneSameAsDataRegressionAlgorithm.cs index 59b1b92f7b3a..432d44dcc2af 100644 --- a/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneSameAsDataRegressionAlgorithm.cs +++ b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneSameAsDataRegressionAlgorithm.cs @@ -33,6 +33,6 @@ public class ContinuousFutureRolloverDailyExchangeTimeZoneSameAsDataRegressionAl /// /// Data Points count of all timeslices of algorithm /// - public override long DataPoints => 483; + public override long DataPoints => 485; } } diff --git a/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneSameAsDataWithIntialSeedRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneSameAsDataWithIntialSeedRegressionAlgorithm.cs index 1a5713bac8e3..df3a48c76387 100644 --- a/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneSameAsDataWithIntialSeedRegressionAlgorithm.cs +++ b/Algorithm.CSharp/ContinuousFutureRolloverDailyExchangeTimeZoneSameAsDataWithIntialSeedRegressionAlgorithm.cs @@ -30,6 +30,6 @@ public class ContinuousFutureRolloverDailyExchangeTimeZoneSameAsDataWithInitialS /// /// Data Points count of the algorithm history /// - public override int AlgorithmHistoryDataPoints => 17; + public override int AlgorithmHistoryDataPoints => 24; } } diff --git a/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs index 9e088413d171..6c0af94896e7 100644 --- a/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs +++ b/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs @@ -29,6 +29,6 @@ public class ContinuousFutureRolloverHourExchangeTimeZoneAheadOfDataWithInitialS /// /// Data Points count of the algorithm history /// - public override int AlgorithmHistoryDataPoints => 65; + public override int AlgorithmHistoryDataPoints => 155; } } diff --git a/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm.cs index 9ed875f9d432..d1ef1bc7b594 100644 --- a/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm.cs +++ b/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneBehindOfDataWithInitialSeedRegressionAlgorithm.cs @@ -29,6 +29,6 @@ public class ContinuousFutureRolloverHourExchangeTimeZoneBehindOfDataWithInitial /// /// Data Points count of the algorithm history /// - public override int AlgorithmHistoryDataPoints => 64; + public override int AlgorithmHistoryDataPoints => 154; } } diff --git a/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneSameAsDataWithInitialSeedRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneSameAsDataWithInitialSeedRegressionAlgorithm.cs index 894d12d113f0..ab2c59d2a9c4 100644 --- a/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneSameAsDataWithInitialSeedRegressionAlgorithm.cs +++ b/Algorithm.CSharp/ContinuousFutureRolloverHourExchangeTimeZoneSameAsDataWithInitialSeedRegressionAlgorithm.cs @@ -29,6 +29,6 @@ public class ContinuousFutureRolloverHourExchangeTimeZoneSameAsDataWithInitialSe /// /// Data Points count of the algorithm history /// - public override int AlgorithmHistoryDataPoints => 64; + public override int AlgorithmHistoryDataPoints => 154; } } diff --git a/Algorithm.CSharp/ContinuousFutureRolloverMinuteExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverMinuteExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs index 6774f5fcdc9e..d38a91071cbd 100644 --- a/Algorithm.CSharp/ContinuousFutureRolloverMinuteExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs +++ b/Algorithm.CSharp/ContinuousFutureRolloverMinuteExchangeTimeZoneAheadOfDataWithInitialSeedRegressionAlgorithm.cs @@ -29,6 +29,6 @@ public class ContinuousFutureRolloverMinuteExchangeTimeZoneAheadOfDataWithInitia /// /// Data Points count of the algorithm history /// - public override int AlgorithmHistoryDataPoints => 1958; + public override int AlgorithmHistoryDataPoints => 2048; } } diff --git a/Algorithm.CSharp/ContinuousFutureRolloverMinuteExchangeTimeZoneSameAsDataWithInitialSeedRegressionAlgorithm.cs b/Algorithm.CSharp/ContinuousFutureRolloverMinuteExchangeTimeZoneSameAsDataWithInitialSeedRegressionAlgorithm.cs index cc2cc354c353..940cc2488d7e 100644 --- a/Algorithm.CSharp/ContinuousFutureRolloverMinuteExchangeTimeZoneSameAsDataWithInitialSeedRegressionAlgorithm.cs +++ b/Algorithm.CSharp/ContinuousFutureRolloverMinuteExchangeTimeZoneSameAsDataWithInitialSeedRegressionAlgorithm.cs @@ -29,6 +29,6 @@ public class ContinuousFutureRolloverMinuteExchangeTimeZoneSameAsDataWithInitial /// /// Data Points count of the algorithm history /// - public override int AlgorithmHistoryDataPoints => 668; + public override int AlgorithmHistoryDataPoints => 758; } } diff --git a/Algorithm.CSharp/CustomDataUsingMapFileRegressionAlgorithm.cs b/Algorithm.CSharp/CustomDataUsingMapFileRegressionAlgorithm.cs index 636291d812c6..a7a991b0f2a5 100644 --- a/Algorithm.CSharp/CustomDataUsingMapFileRegressionAlgorithm.cs +++ b/Algorithm.CSharp/CustomDataUsingMapFileRegressionAlgorithm.cs @@ -139,31 +139,31 @@ public override void OnEndOfAlgorithm() {"Total Orders", "1"}, {"Average Win", "0%"}, {"Average Loss", "0%"}, - {"Compounding Annual Return", "-99.907%"}, - {"Drawdown", "11.000%"}, + {"Compounding Annual Return", "12.433%"}, + {"Drawdown", "2.600%"}, {"Expectancy", "0"}, {"Start Equity", "100000"}, - {"End Equity", "89657.2"}, - {"Net Profit", "-10.343%"}, - {"Sharpe Ratio", "-1.708"}, - {"Sortino Ratio", "-1.361"}, - {"Probabilistic Sharpe Ratio", "0.009%"}, + {"End Equity", "100183.6"}, + {"Net Profit", "0.184%"}, + {"Sharpe Ratio", "0.516"}, + {"Sortino Ratio", "0"}, + {"Probabilistic Sharpe Ratio", "47.590%"}, {"Loss Rate", "0%"}, {"Win Rate", "0%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "-0.974"}, - {"Beta", "-5.612"}, - {"Annual Standard Deviation", "0.587"}, - {"Annual Variance", "0.345"}, - {"Information Ratio", "-1.517"}, - {"Tracking Error", "0.664"}, - {"Treynor Ratio", "0.179"}, + {"Alpha", "0.101"}, + {"Beta", "1.58"}, + {"Annual Standard Deviation", "0.211"}, + {"Annual Variance", "0.045"}, + {"Information Ratio", "0.627"}, + {"Tracking Error", "0.166"}, + {"Treynor Ratio", "0.069"}, {"Total Fees", "$0.00"}, - {"Estimated Strategy Capacity", "$0"}, + {"Estimated Strategy Capacity", "$29000.00"}, {"Lowest Capacity Asset", "NWSA.CustomDataUsingMapping T3MO1488O0H0"}, - {"Portfolio Turnover", "16.62%"}, + {"Portfolio Turnover", "14.58%"}, {"Drawdown Recovery", "0"}, - {"OrderListHash", "fe95edf1a3eabc0ac044b85eb833da5a"} + {"OrderListHash", "f5ad14d0317a5cbb81984dd92969423c"} }; /// diff --git a/Algorithm.CSharp/DailyConsolidationExtendedMarketHoursWarningRegressionAlgorithm.cs b/Algorithm.CSharp/DailyConsolidationExtendedMarketHoursWarningRegressionAlgorithm.cs index 1c1e7e0e8798..13dee2075be3 100644 --- a/Algorithm.CSharp/DailyConsolidationExtendedMarketHoursWarningRegressionAlgorithm.cs +++ b/Algorithm.CSharp/DailyConsolidationExtendedMarketHoursWarningRegressionAlgorithm.cs @@ -128,4 +128,4 @@ public override void OnEndOfAlgorithm() {"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"} }; } -} \ No newline at end of file +} diff --git a/Algorithm.CSharp/DelistedFutureLiquidateDailyRegressionAlgorithm.cs b/Algorithm.CSharp/DelistedFutureLiquidateDailyRegressionAlgorithm.cs index 996557d344f9..684d16e47f37 100644 --- a/Algorithm.CSharp/DelistedFutureLiquidateDailyRegressionAlgorithm.cs +++ b/Algorithm.CSharp/DelistedFutureLiquidateDailyRegressionAlgorithm.cs @@ -28,7 +28,7 @@ public class DelistedFutureLiquidateDailyRegressionAlgorithm : DelistedFutureLiq /// /// Data Points count of all timeslices of algorithm /// - public override long DataPoints => 1235; + public override long DataPoints => 1237; /// /// This is used by the regression test system to indicate what the expected statistics are from running the algorithm @@ -36,33 +36,33 @@ public class DelistedFutureLiquidateDailyRegressionAlgorithm : DelistedFutureLiq public override Dictionary ExpectedStatistics => new Dictionary { {"Total Orders", "2"}, - {"Average Win", "7.78%"}, + {"Average Win", "8.18%"}, {"Average Loss", "0%"}, - {"Compounding Annual Return", "38.609%"}, - {"Drawdown", "0.200%"}, + {"Compounding Annual Return", "40.865%"}, + {"Drawdown", "1.600%"}, {"Expectancy", "0"}, {"Start Equity", "100000"}, - {"End Equity", "107779.1"}, - {"Net Profit", "7.779%"}, - {"Sharpe Ratio", "3.132"}, - {"Sortino Ratio", "0"}, - {"Probabilistic Sharpe Ratio", "99.474%"}, + {"End Equity", "108179.1"}, + {"Net Profit", "8.179%"}, + {"Sharpe Ratio", "3.949"}, + {"Sortino Ratio", "6.572"}, + {"Probabilistic Sharpe Ratio", "95.141%"}, {"Loss Rate", "0%"}, {"Win Rate", "100%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "0.145"}, - {"Beta", "0.271"}, - {"Annual Standard Deviation", "0.081"}, - {"Annual Variance", "0.006"}, - {"Information Ratio", "-1.459"}, - {"Tracking Error", "0.099"}, - {"Treynor Ratio", "0.932"}, + {"Alpha", "-0.041"}, + {"Beta", "0.774"}, + {"Annual Standard Deviation", "0.067"}, + {"Annual Variance", "0.005"}, + {"Information Ratio", "-4.972"}, + {"Tracking Error", "0.026"}, + {"Treynor Ratio", "0.343"}, {"Total Fees", "$2.15"}, - {"Estimated Strategy Capacity", "$150000000000.00"}, + {"Estimated Strategy Capacity", "$140000000000.00"}, {"Lowest Capacity Asset", "ES VMKLFZIH2MTD"}, {"Portfolio Turnover", "1.98%"}, - {"Drawdown Recovery", "2"}, - {"OrderListHash", "b337ac27f46a6298dd4e9f0f04b49427"} + {"Drawdown Recovery", "14"}, + {"OrderListHash", "5cb101c65356e52ff42296ef0adff743"} }; } } diff --git a/Algorithm.CSharp/DelistedFutureLiquidateFromChainAndContinuousRegressionAlgorithm.cs b/Algorithm.CSharp/DelistedFutureLiquidateFromChainAndContinuousRegressionAlgorithm.cs index 873f7a015838..4d4c9f22ff25 100644 --- a/Algorithm.CSharp/DelistedFutureLiquidateFromChainAndContinuousRegressionAlgorithm.cs +++ b/Algorithm.CSharp/DelistedFutureLiquidateFromChainAndContinuousRegressionAlgorithm.cs @@ -172,24 +172,24 @@ public override void OnOrderEvent(OrderEvent orderEvent) {"Start Equity", "100000"}, {"End Equity", "107016.6"}, {"Net Profit", "7.017%"}, - {"Sharpe Ratio", "3.217"}, - {"Sortino Ratio", "0"}, - {"Probabilistic Sharpe Ratio", "99.828%"}, + {"Sharpe Ratio", "3.872"}, + {"Sortino Ratio", "134.511"}, + {"Probabilistic Sharpe Ratio", "99.843%"}, {"Loss Rate", "0%"}, {"Win Rate", "100%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "0.228"}, - {"Beta", "0.108"}, - {"Annual Standard Deviation", "0.084"}, - {"Annual Variance", "0.007"}, - {"Information Ratio", "-1.122"}, - {"Tracking Error", "0.112"}, - {"Treynor Ratio", "2.501"}, + {"Alpha", "0.158"}, + {"Beta", "0.28"}, + {"Annual Standard Deviation", "0.07"}, + {"Annual Variance", "0.005"}, + {"Information Ratio", "-1.428"}, + {"Tracking Error", "0.089"}, + {"Treynor Ratio", "0.963"}, {"Total Fees", "$2.15"}, {"Estimated Strategy Capacity", "$1700000000.00"}, {"Lowest Capacity Asset", "ES VMKLFZIH2MTD"}, {"Portfolio Turnover", "2.01%"}, - {"Drawdown Recovery", "16"}, + {"Drawdown Recovery", "19"}, {"OrderListHash", "640ce720644ff0b580687e80105d0a92"} }; } diff --git a/Algorithm.CSharp/DelistedFutureLiquidateRegressionAlgorithm.cs b/Algorithm.CSharp/DelistedFutureLiquidateRegressionAlgorithm.cs index f1294c24de1f..d9e998cbfd46 100644 --- a/Algorithm.CSharp/DelistedFutureLiquidateRegressionAlgorithm.cs +++ b/Algorithm.CSharp/DelistedFutureLiquidateRegressionAlgorithm.cs @@ -133,24 +133,24 @@ public override void OnOrderEvent(OrderEvent orderEvent) {"Start Equity", "100000"}, {"End Equity", "107016.6"}, {"Net Profit", "7.017%"}, - {"Sharpe Ratio", "3.217"}, - {"Sortino Ratio", "0"}, - {"Probabilistic Sharpe Ratio", "99.828%"}, + {"Sharpe Ratio", "3.872"}, + {"Sortino Ratio", "134.511"}, + {"Probabilistic Sharpe Ratio", "99.843%"}, {"Loss Rate", "0%"}, {"Win Rate", "100%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "0.228"}, - {"Beta", "0.108"}, - {"Annual Standard Deviation", "0.084"}, - {"Annual Variance", "0.007"}, - {"Information Ratio", "-1.122"}, - {"Tracking Error", "0.112"}, - {"Treynor Ratio", "2.501"}, + {"Alpha", "0.158"}, + {"Beta", "0.28"}, + {"Annual Standard Deviation", "0.07"}, + {"Annual Variance", "0.005"}, + {"Information Ratio", "-1.428"}, + {"Tracking Error", "0.089"}, + {"Treynor Ratio", "0.963"}, {"Total Fees", "$2.15"}, {"Estimated Strategy Capacity", "$1700000000.00"}, {"Lowest Capacity Asset", "ES VMKLFZIH2MTD"}, {"Portfolio Turnover", "2.01%"}, - {"Drawdown Recovery", "16"}, + {"Drawdown Recovery", "19"}, {"OrderListHash", "640ce720644ff0b580687e80105d0a92"} }; } diff --git a/Algorithm.CSharp/DuplicateOptionAssignmentRegressionAlgorithm.cs b/Algorithm.CSharp/DuplicateOptionAssignmentRegressionAlgorithm.cs index 0e412d41a747..ababd3677a6f 100644 --- a/Algorithm.CSharp/DuplicateOptionAssignmentRegressionAlgorithm.cs +++ b/Algorithm.CSharp/DuplicateOptionAssignmentRegressionAlgorithm.cs @@ -233,30 +233,30 @@ public override void OnEndOfAlgorithm() {"Total Orders", "3"}, {"Average Win", "4.48%"}, {"Average Loss", "0%"}, - {"Compounding Annual Return", "-19.248%"}, + {"Compounding Annual Return", "25.553%"}, {"Drawdown", "1.100%"}, {"Expectancy", "-1"}, {"Start Equity", "100000"}, - {"End Equity", "99319"}, - {"Net Profit", "-0.681%"}, - {"Sharpe Ratio", "-6.361"}, - {"Sortino Ratio", "-4.623"}, - {"Probabilistic Sharpe Ratio", "0.018%"}, + {"End Equity", "100730"}, + {"Net Profit", "0.730%"}, + {"Sharpe Ratio", "2.317"}, + {"Sortino Ratio", "5.211"}, + {"Probabilistic Sharpe Ratio", "61.993%"}, {"Loss Rate", "100%"}, {"Win Rate", "0%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "-0.139"}, - {"Beta", "-0.082"}, - {"Annual Standard Deviation", "0.024"}, - {"Annual Variance", "0.001"}, - {"Information Ratio", "-2.525"}, - {"Tracking Error", "0.137"}, - {"Treynor Ratio", "1.883"}, + {"Alpha", "0.202"}, + {"Beta", "-0.146"}, + {"Annual Standard Deviation", "0.075"}, + {"Annual Variance", "0.006"}, + {"Information Ratio", "-0.111"}, + {"Tracking Error", "0.161"}, + {"Treynor Ratio", "-1.19"}, {"Total Fees", "$1.00"}, {"Estimated Strategy Capacity", "$1300000.00"}, {"Lowest Capacity Asset", "GOOCV 305RBQ20WLZZA|GOOCV VP83T1ZUHROL"}, {"Portfolio Turnover", "7.07%"}, - {"Drawdown Recovery", "0"}, + {"Drawdown Recovery", "5"}, {"OrderListHash", "79ecc4dd8b045ddf0aa38057b8eb69bf"} }; } diff --git a/Algorithm.CSharp/EquityMarginCallAlgorithm.cs b/Algorithm.CSharp/EquityMarginCallAlgorithm.cs index 68fb3e00a8a7..1eb2c1d37c70 100644 --- a/Algorithm.CSharp/EquityMarginCallAlgorithm.cs +++ b/Algorithm.CSharp/EquityMarginCallAlgorithm.cs @@ -126,30 +126,30 @@ public override void OnEndOfAlgorithm() {"Total Orders", "7"}, {"Average Win", "0%"}, {"Average Loss", "-6.17%"}, - {"Compounding Annual Return", "-100.000%"}, + {"Compounding Annual Return", "48311.308%"}, {"Drawdown", "72.300%"}, {"Expectancy", "-1"}, {"Start Equity", "100000"}, - {"End Equity", "50554.98"}, - {"Net Profit", "-49.445%"}, - {"Sharpe Ratio", "-1.155"}, + {"End Equity", "113866.54"}, + {"Net Profit", "13.867%"}, + {"Sharpe Ratio", "1535787524789540"}, {"Sortino Ratio", "0"}, - {"Probabilistic Sharpe Ratio", "0.982%"}, + {"Probabilistic Sharpe Ratio", "87.489%"}, {"Loss Rate", "100%"}, {"Win Rate", "0%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "-0.961"}, - {"Beta", "1.583"}, - {"Annual Standard Deviation", "0.87"}, - {"Annual Variance", "0.756"}, - {"Information Ratio", "-1.135"}, - {"Tracking Error", "0.861"}, - {"Treynor Ratio", "-0.635"}, + {"Alpha", "11835996770264000"}, + {"Beta", "-13.194"}, + {"Annual Standard Deviation", "7.707"}, + {"Annual Variance", "59.395"}, + {"Information Ratio", "1533248041772298"}, + {"Tracking Error", "7.72"}, + {"Treynor Ratio", "-897105767214540.6"}, {"Total Fees", "$91.53"}, - {"Estimated Strategy Capacity", "$8000.00"}, + {"Estimated Strategy Capacity", "$18000.00"}, {"Lowest Capacity Asset", "GOOCV VP83T1ZUHROL"}, {"Portfolio Turnover", "2904.79%"}, - {"Drawdown Recovery", "0"}, + {"Drawdown Recovery", "5"}, {"OrderListHash", "80d456f6613030d3ff67b6c59dba5707"} }; } diff --git a/Algorithm.CSharp/FutureOptionChainFullDataRegressionAlgorithm.cs b/Algorithm.CSharp/FutureOptionChainFullDataRegressionAlgorithm.cs index 970699ae6d2e..c6605cffb403 100644 --- a/Algorithm.CSharp/FutureOptionChainFullDataRegressionAlgorithm.cs +++ b/Algorithm.CSharp/FutureOptionChainFullDataRegressionAlgorithm.cs @@ -95,14 +95,14 @@ public override void OnData(Slice slice) /// public Dictionary ExpectedStatistics => new Dictionary { - {"Total Orders", "450"}, + {"Total Orders", "304"}, {"Average Win", "0%"}, {"Average Loss", "0%"}, {"Compounding Annual Return", "0%"}, {"Drawdown", "0%"}, {"Expectancy", "0"}, {"Start Equity", "100000"}, - {"End Equity", "65398.86"}, + {"End Equity", "75031.84"}, {"Net Profit", "0%"}, {"Sharpe Ratio", "0"}, {"Sortino Ratio", "0"}, @@ -117,12 +117,12 @@ public override void OnData(Slice slice) {"Information Ratio", "0"}, {"Tracking Error", "0"}, {"Treynor Ratio", "0"}, - {"Total Fees", "$34601.14"}, + {"Total Fees", "$25095.66"}, {"Estimated Strategy Capacity", "$0"}, {"Lowest Capacity Asset", "ES XCZJLCGM7IF8|ES XCZJLC9NOB29"}, - {"Portfolio Turnover", "112.25%"}, + {"Portfolio Turnover", "76.32%"}, {"Drawdown Recovery", "0"}, - {"OrderListHash", "4000aa7b360b9146b9f184d0cc188980"} + {"OrderListHash", "1e039ca8743895c1c57d53138cb06ae4"} }; } } diff --git a/Algorithm.CSharp/FutureOptionChainsMultipleFullDataRegressionAlgorithm.cs b/Algorithm.CSharp/FutureOptionChainsMultipleFullDataRegressionAlgorithm.cs index a2fb0a1903a3..2b7cfcd96d08 100644 --- a/Algorithm.CSharp/FutureOptionChainsMultipleFullDataRegressionAlgorithm.cs +++ b/Algorithm.CSharp/FutureOptionChainsMultipleFullDataRegressionAlgorithm.cs @@ -98,7 +98,7 @@ public override void OnData(Slice slice) /// /// Data Points count of all timeslices of algorithm /// - public long DataPoints => 1819; + public long DataPoints => 1939; /// /// Data Points count of the algorithm history @@ -115,14 +115,14 @@ public override void OnData(Slice slice) /// public Dictionary ExpectedStatistics => new Dictionary { - {"Total Orders", "450"}, + {"Total Orders", "304"}, {"Average Win", "0%"}, {"Average Loss", "0%"}, {"Compounding Annual Return", "0%"}, {"Drawdown", "0%"}, {"Expectancy", "0"}, {"Start Equity", "100000"}, - {"End Equity", "80983.36"}, + {"End Equity", "86704.62"}, {"Net Profit", "0%"}, {"Sharpe Ratio", "0"}, {"Sortino Ratio", "0"}, @@ -137,12 +137,12 @@ public override void OnData(Slice slice) {"Information Ratio", "0"}, {"Tracking Error", "0"}, {"Treynor Ratio", "0"}, - {"Total Fees", "$19016.64"}, + {"Total Fees", "$13367.88"}, {"Estimated Strategy Capacity", "$0"}, {"Lowest Capacity Asset", "ES XCZJLCGM7IF8|ES XCZJLC9NOB29"}, - {"Portfolio Turnover", "49.52%"}, + {"Portfolio Turnover", "35.03%"}, {"Drawdown Recovery", "0"}, - {"OrderListHash", "8ef148c1100cb53bdd6a833c7a958974"} + {"OrderListHash", "3f98435e7fc61b79c7ff9d1690457c9f"} }; } } diff --git a/Algorithm.CSharp/FutureOptionMultipleContractsInDifferentContractMonthsWithSameUnderlyingFutureRegressionAlgorithm.cs b/Algorithm.CSharp/FutureOptionMultipleContractsInDifferentContractMonthsWithSameUnderlyingFutureRegressionAlgorithm.cs index f3f8d0968b54..f0b2b76ad8a1 100644 --- a/Algorithm.CSharp/FutureOptionMultipleContractsInDifferentContractMonthsWithSameUnderlyingFutureRegressionAlgorithm.cs +++ b/Algorithm.CSharp/FutureOptionMultipleContractsInDifferentContractMonthsWithSameUnderlyingFutureRegressionAlgorithm.cs @@ -129,31 +129,31 @@ private static Symbol CreateOption(DateTime expiry, OptionRight optionRight, dec {"Total Orders", "4"}, {"Average Win", "0%"}, {"Average Loss", "0%"}, - {"Compounding Annual Return", "-25.338%"}, - {"Drawdown", "0.200%"}, + {"Compounding Annual Return", "-58.987%"}, + {"Drawdown", "3.500%"}, {"Expectancy", "0"}, {"Start Equity", "100000"}, - {"End Equity", "99760.12"}, - {"Net Profit", "-0.240%"}, - {"Sharpe Ratio", "-10.528"}, + {"End Equity", "99270.12"}, + {"Net Profit", "-0.730%"}, + {"Sharpe Ratio", "-7.623"}, {"Sortino Ratio", "0"}, {"Probabilistic Sharpe Ratio", "0%"}, {"Loss Rate", "0%"}, {"Win Rate", "0%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "0.09"}, - {"Beta", "-0.629"}, - {"Annual Standard Deviation", "0.027"}, - {"Annual Variance", "0.001"}, - {"Information Ratio", "-12.58"}, - {"Tracking Error", "0.07"}, - {"Treynor Ratio", "0.451"}, + {"Alpha", "0.512"}, + {"Beta", "-1.913"}, + {"Annual Standard Deviation", "0.082"}, + {"Annual Variance", "0.007"}, + {"Information Ratio", "-9.767"}, + {"Tracking Error", "0.125"}, + {"Treynor Ratio", "0.326"}, {"Total Fees", "$9.88"}, - {"Estimated Strategy Capacity", "$31000000.00"}, - {"Lowest Capacity Asset", "OG 31BFX0QKBZZS0|GC XE1Y0ZJ8NQ8T"}, - {"Portfolio Turnover", "2.65%"}, + {"Estimated Strategy Capacity", "$520000.00"}, + {"Lowest Capacity Asset", "OG XD5G9X7YX280|GC XE1Y0ZJ8NQ8T"}, + {"Portfolio Turnover", "2.83%"}, {"Drawdown Recovery", "0"}, - {"OrderListHash", "9b619fad030ef229690386aabbaedb4d"} + {"OrderListHash", "96439fefcbefabf89df31aef24b7f4da"} }; } } diff --git a/Algorithm.CSharp/FuturesExpiredContractRegression.cs b/Algorithm.CSharp/FuturesExpiredContractRegression.cs index 6a2c4cea53d7..7d11fdb4e344 100644 --- a/Algorithm.CSharp/FuturesExpiredContractRegression.cs +++ b/Algorithm.CSharp/FuturesExpiredContractRegression.cs @@ -89,7 +89,7 @@ public override void OnEndOfAlgorithm() /// /// Data Points count of all timeslices of algorithm /// - public long DataPoints => 24508; + public long DataPoints => 35128; /// /// Data Points count of the algorithm history diff --git a/Algorithm.CSharp/FuturesFrameworkRegressionAlgorithm.cs b/Algorithm.CSharp/FuturesFrameworkRegressionAlgorithm.cs index 252e96ff0d3f..8c7971e4f39b 100644 --- a/Algorithm.CSharp/FuturesFrameworkRegressionAlgorithm.cs +++ b/Algorithm.CSharp/FuturesFrameworkRegressionAlgorithm.cs @@ -204,32 +204,32 @@ public override void OnEndOfAlgorithm() { {"Total Orders", "10"}, {"Average Win", "0%"}, - {"Average Loss", "-4.59%"}, + {"Average Loss", "-4.51%"}, {"Compounding Annual Return", "-100.000%"}, {"Drawdown", "33.200%"}, {"Expectancy", "-1"}, {"Start Equity", "100000"}, - {"End Equity", "79014"}, - {"Net Profit", "-20.986%"}, - {"Sharpe Ratio", "-0.537"}, + {"End Equity", "79364"}, + {"Net Profit", "-20.636%"}, + {"Sharpe Ratio", "-0.531"}, {"Sortino Ratio", "0"}, - {"Probabilistic Sharpe Ratio", "18.566%"}, + {"Probabilistic Sharpe Ratio", "20.065%"}, {"Loss Rate", "100%"}, {"Win Rate", "0%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "-11.401"}, - {"Beta", "5.262"}, - {"Annual Standard Deviation", "1.875"}, - {"Annual Variance", "3.515"}, - {"Information Ratio", "-1.71"}, - {"Tracking Error", "1.744"}, - {"Treynor Ratio", "-0.191"}, + {"Alpha", "-11.342"}, + {"Beta", "5.231"}, + {"Annual Standard Deviation", "1.896"}, + {"Annual Variance", "3.593"}, + {"Information Ratio", "-1.687"}, + {"Tracking Error", "1.768"}, + {"Treynor Ratio", "-0.193"}, {"Total Fees", "$86.00"}, {"Estimated Strategy Capacity", "$410000.00"}, {"Lowest Capacity Asset", "ES VRJST036ZY0X"}, - {"Portfolio Turnover", "766.37%"}, + {"Portfolio Turnover", "764.63%"}, {"Drawdown Recovery", "0"}, - {"OrderListHash", "97cfbcf973995ceb72b937f0f4684f88"} + {"OrderListHash", "3d14700af93152895c4bceae6ad37620"} }; } } diff --git a/Algorithm.CSharp/HistoryWithDifferentContinuousContractDepthOffsetsRegressionAlgorithm.cs b/Algorithm.CSharp/HistoryWithDifferentContinuousContractDepthOffsetsRegressionAlgorithm.cs index 6754fe124d2c..0d0793d5afe5 100644 --- a/Algorithm.CSharp/HistoryWithDifferentContinuousContractDepthOffsetsRegressionAlgorithm.cs +++ b/Algorithm.CSharp/HistoryWithDifferentContinuousContractDepthOffsetsRegressionAlgorithm.cs @@ -129,7 +129,7 @@ public override void OnEndOfAlgorithm() /// /// Data Points count of all timeslices of algorithm /// - public long DataPoints => 968; + public long DataPoints => 970; /// /// Data Points count of the algorithm history diff --git a/Algorithm.CSharp/HistoryWithDifferentDataMappingModeRegressionAlgorithm.cs b/Algorithm.CSharp/HistoryWithDifferentDataMappingModeRegressionAlgorithm.cs index 78f686943ec5..3af9d8a174f7 100644 --- a/Algorithm.CSharp/HistoryWithDifferentDataMappingModeRegressionAlgorithm.cs +++ b/Algorithm.CSharp/HistoryWithDifferentDataMappingModeRegressionAlgorithm.cs @@ -101,7 +101,7 @@ public override void OnEndOfAlgorithm() /// /// Data Points count of all timeslices of algorithm /// - public long DataPoints => 968; + public long DataPoints => 970; /// /// Data Points count of the algorithm history diff --git a/Algorithm.CSharp/HistoryWithDifferentDataNormalizationModeRegressionAlgorithm.cs b/Algorithm.CSharp/HistoryWithDifferentDataNormalizationModeRegressionAlgorithm.cs index 8c2ec3022076..c4821653e3e2 100644 --- a/Algorithm.CSharp/HistoryWithDifferentDataNormalizationModeRegressionAlgorithm.cs +++ b/Algorithm.CSharp/HistoryWithDifferentDataNormalizationModeRegressionAlgorithm.cs @@ -93,7 +93,7 @@ private void CheckHistoryResultsForDataNormalizationModes(Symbol symbol, DateTim /// /// Data Points count of all timeslices of algorithm /// - public long DataPoints => 1026; + public long DataPoints => 1028; /// /// Data Points count of the algorithm history diff --git a/Algorithm.CSharp/IndexOptionBuySellCallIntradayRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionBuySellCallIntradayRegressionAlgorithm.cs index f85442ad3521..15af8bc757ed 100644 --- a/Algorithm.CSharp/IndexOptionBuySellCallIntradayRegressionAlgorithm.cs +++ b/Algorithm.CSharp/IndexOptionBuySellCallIntradayRegressionAlgorithm.cs @@ -136,33 +136,33 @@ public override void OnEndOfAlgorithm() public Dictionary ExpectedStatistics => new Dictionary { {"Total Orders", "4"}, - {"Average Win", "0%"}, - {"Average Loss", "-0.08%"}, - {"Compounding Annual Return", "-2.251%"}, - {"Drawdown", "0.200%"}, - {"Expectancy", "-1"}, + {"Average Win", "2.46%"}, + {"Average Loss", "-2.58%"}, + {"Compounding Annual Return", "-2.473%"}, + {"Drawdown", "0.900%"}, + {"Expectancy", "0.956"}, {"Start Equity", "100000"}, - {"End Equity", "99840"}, - {"Net Profit", "-0.160%"}, - {"Sharpe Ratio", "-3.642"}, + {"End Equity", "99824"}, + {"Net Profit", "-0.176%"}, + {"Sharpe Ratio", "-0.672"}, {"Sortino Ratio", "0"}, - {"Probabilistic Sharpe Ratio", "0.427%"}, - {"Loss Rate", "100%"}, - {"Win Rate", "0%"}, - {"Profit-Loss Ratio", "0"}, - {"Alpha", "-0.018"}, - {"Beta", "-0.006"}, - {"Annual Standard Deviation", "0.005"}, - {"Annual Variance", "0"}, - {"Information Ratio", "-0.44"}, + {"Probabilistic Sharpe Ratio", "30.735%"}, + {"Loss Rate", "0%"}, + {"Win Rate", "100%"}, + {"Profit-Loss Ratio", "0.96"}, + {"Alpha", "-0.02"}, + {"Beta", "0.014"}, + {"Annual Standard Deviation", "0.029"}, + {"Annual Variance", "0.001"}, + {"Information Ratio", "-0.448"}, {"Tracking Error", "0.139"}, - {"Treynor Ratio", "3.118"}, + {"Treynor Ratio", "-1.397"}, {"Total Fees", "$0.00"}, {"Estimated Strategy Capacity", "$0"}, {"Lowest Capacity Asset", "SPX XL80P3HB9YI6|SPX 31"}, - {"Portfolio Turnover", "0.51%"}, + {"Portfolio Turnover", "0.56%"}, {"Drawdown Recovery", "0"}, - {"OrderListHash", "9237e1fd3cf099a47a2adae18f91aa2f"} + {"OrderListHash", "de57068f577da644fba18d85710fcea2"} }; } } diff --git a/Algorithm.CSharp/IndexOptionCallITMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionCallITMExpiryRegressionAlgorithm.cs index dd29a2052f9f..1a2cfb228e58 100644 --- a/Algorithm.CSharp/IndexOptionCallITMExpiryRegressionAlgorithm.cs +++ b/Algorithm.CSharp/IndexOptionCallITMExpiryRegressionAlgorithm.cs @@ -188,33 +188,33 @@ public override void OnEndOfAlgorithm() public virtual Dictionary ExpectedStatistics => new Dictionary { {"Total Orders", "2"}, - {"Average Win", "9.07%"}, - {"Average Loss", "0%"}, - {"Compounding Annual Return", "243.722%"}, - {"Drawdown", "2.500%"}, + {"Average Win", "0%"}, + {"Average Loss", "-2.49%"}, + {"Compounding Annual Return", "-30.082%"}, + {"Drawdown", "2.800%"}, {"Expectancy", "0"}, {"Start Equity", "100000"}, - {"End Equity", "109074"}, - {"Net Profit", "9.074%"}, - {"Sharpe Ratio", "4.877"}, - {"Sortino Ratio", "139.754"}, - {"Probabilistic Sharpe Ratio", "87.949%"}, + {"End Equity", "97514"}, + {"Net Profit", "-2.486%"}, + {"Sharpe Ratio", "-3.294"}, + {"Sortino Ratio", "-1.128"}, + {"Probabilistic Sharpe Ratio", "0.044%"}, {"Loss Rate", "0%"}, {"Win Rate", "100%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "1.511"}, - {"Beta", "-0.204"}, - {"Annual Standard Deviation", "0.308"}, - {"Annual Variance", "0.095"}, - {"Information Ratio", "4.185"}, - {"Tracking Error", "0.349"}, - {"Treynor Ratio", "-7.347"}, + {"Alpha", "-0.227"}, + {"Beta", "0.044"}, + {"Annual Standard Deviation", "0.068"}, + {"Annual Variance", "0.005"}, + {"Information Ratio", "-1.803"}, + {"Tracking Error", "0.148"}, + {"Treynor Ratio", "-5.144"}, {"Total Fees", "$0.00"}, {"Estimated Strategy Capacity", "$0"}, {"Lowest Capacity Asset", "SPX XL80P3GHIA9A|SPX 31"}, - {"Portfolio Turnover", "1.95%"}, - {"Drawdown Recovery", "9"}, - {"OrderListHash", "59551fdea61b6d4436ffd4a60aed1f40"} + {"Portfolio Turnover", "2.44%"}, + {"Drawdown Recovery", "0"}, + {"OrderListHash", "a7f4ffe1fd2aa48a17b3ceedd604ca25"} }; } } diff --git a/Algorithm.CSharp/IndexOptionCallOTMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionCallOTMExpiryRegressionAlgorithm.cs index 1b42c4bacf34..68d7424b452d 100644 --- a/Algorithm.CSharp/IndexOptionCallOTMExpiryRegressionAlgorithm.cs +++ b/Algorithm.CSharp/IndexOptionCallOTMExpiryRegressionAlgorithm.cs @@ -197,32 +197,32 @@ public override void OnEndOfAlgorithm() { {"Total Orders", "2"}, {"Average Win", "0%"}, - {"Average Loss", "-0.01%"}, - {"Compounding Annual Return", "-0.142%"}, + {"Average Loss", "0.00%"}, + {"Compounding Annual Return", "-0.071%"}, {"Drawdown", "0.000%"}, {"Expectancy", "-1"}, {"Start Equity", "100000"}, - {"End Equity", "99990"}, - {"Net Profit", "-0.010%"}, - {"Sharpe Ratio", "-15.959"}, - {"Sortino Ratio", "-124989.863"}, - {"Probabilistic Sharpe Ratio", "0.015%"}, + {"End Equity", "99995"}, + {"Net Profit", "-0.005%"}, + {"Sharpe Ratio", "-18.923"}, + {"Sortino Ratio", "0"}, + {"Probabilistic Sharpe Ratio", "0.427%"}, {"Loss Rate", "100%"}, {"Win Rate", "0%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "-0.004"}, + {"Alpha", "-0.003"}, {"Beta", "0"}, {"Annual Standard Deviation", "0"}, {"Annual Variance", "0"}, - {"Information Ratio", "-0.334"}, + {"Information Ratio", "-0.331"}, {"Tracking Error", "0.138"}, - {"Treynor Ratio", "-32.969"}, + {"Treynor Ratio", "-621.415"}, {"Total Fees", "$0.00"}, - {"Estimated Strategy Capacity", "$22000.00"}, + {"Estimated Strategy Capacity", "$0"}, {"Lowest Capacity Asset", "SPX XL80P59H9OI6|SPX 31"}, {"Portfolio Turnover", "0.00%"}, {"Drawdown Recovery", "0"}, - {"OrderListHash", "0a8db8bba3b2198ba4675fc909426c35"} + {"OrderListHash", "59fc97ee81847842c5b82fae7f4fddb1"} }; } } diff --git a/Algorithm.CSharp/IndexOptionPutITMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionPutITMExpiryRegressionAlgorithm.cs index c3ac8a75e13c..d1422834709c 100644 --- a/Algorithm.CSharp/IndexOptionPutITMExpiryRegressionAlgorithm.cs +++ b/Algorithm.CSharp/IndexOptionPutITMExpiryRegressionAlgorithm.cs @@ -203,33 +203,33 @@ public override void OnEndOfAlgorithm() public Dictionary ExpectedStatistics => new Dictionary { {"Total Orders", "2"}, - {"Average Win", "0%"}, - {"Average Loss", "-9.85%"}, - {"Compounding Annual Return", "-77.114%"}, - {"Drawdown", "12.500%"}, + {"Average Win", "2.00%"}, + {"Average Loss", "0%"}, + {"Compounding Annual Return", "32.437%"}, + {"Drawdown", "0.700%"}, {"Expectancy", "0"}, {"Start Equity", "100000"}, - {"End Equity", "90146"}, - {"Net Profit", "-9.854%"}, - {"Sharpe Ratio", "-1.957"}, - {"Sortino Ratio", "-0.569"}, - {"Probabilistic Sharpe Ratio", "0.709%"}, + {"End Equity", "101996"}, + {"Net Profit", "1.996%"}, + {"Sharpe Ratio", "4.434"}, + {"Sortino Ratio", "0"}, + {"Probabilistic Sharpe Ratio", "98.454%"}, {"Loss Rate", "0%"}, {"Win Rate", "100%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "-0.64"}, - {"Beta", "0.196"}, - {"Annual Standard Deviation", "0.323"}, - {"Annual Variance", "0.104"}, - {"Information Ratio", "-1.982"}, - {"Tracking Error", "0.34"}, - {"Treynor Ratio", "-3.216"}, + {"Alpha", "0.221"}, + {"Beta", "-0.031"}, + {"Annual Standard Deviation", "0.049"}, + {"Annual Variance", "0.002"}, + {"Information Ratio", "1.175"}, + {"Tracking Error", "0.15"}, + {"Treynor Ratio", "-7.09"}, {"Total Fees", "$0.00"}, {"Estimated Strategy Capacity", "$0"}, {"Lowest Capacity Asset", "SPX 31KC0UJHCBG4U|SPX 31"}, - {"Portfolio Turnover", "1.94%"}, + {"Portfolio Turnover", "1.46%"}, {"Drawdown Recovery", "0"}, - {"OrderListHash", "3f315a4d5124203fb8ed466926314824"} + {"OrderListHash", "354808f681cbe762e97e9657538ade43"} }; } } diff --git a/Algorithm.CSharp/IndexOptionPutOTMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionPutOTMExpiryRegressionAlgorithm.cs index 399d03431b81..2a1e10c2b33d 100644 --- a/Algorithm.CSharp/IndexOptionPutOTMExpiryRegressionAlgorithm.cs +++ b/Algorithm.CSharp/IndexOptionPutOTMExpiryRegressionAlgorithm.cs @@ -188,32 +188,32 @@ public override void OnEndOfAlgorithm() { {"Total Orders", "2"}, {"Average Win", "0%"}, - {"Average Loss", "-0.37%"}, - {"Compounding Annual Return", "-5.133%"}, - {"Drawdown", "0.400%"}, + {"Average Loss", "-0.01%"}, + {"Compounding Annual Return", "-0.142%"}, + {"Drawdown", "0.200%"}, {"Expectancy", "-1"}, {"Start Equity", "100000"}, - {"End Equity", "99630"}, - {"Net Profit", "-0.370%"}, - {"Sharpe Ratio", "-3.525"}, - {"Sortino Ratio", "-1.255"}, - {"Probabilistic Sharpe Ratio", "0.175%"}, + {"End Equity", "99990"}, + {"Net Profit", "-0.010%"}, + {"Sharpe Ratio", "-15.959"}, + {"Sortino Ratio", "-124989.863"}, + {"Probabilistic Sharpe Ratio", "0.015%"}, {"Loss Rate", "100%"}, {"Win Rate", "0%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "-0.039"}, - {"Beta", "0.007"}, - {"Annual Standard Deviation", "0.011"}, + {"Alpha", "-0.004"}, + {"Beta", "0"}, + {"Annual Standard Deviation", "0"}, {"Annual Variance", "0"}, - {"Information Ratio", "-0.595"}, - {"Tracking Error", "0.137"}, - {"Treynor Ratio", "-5.965"}, + {"Information Ratio", "-0.334"}, + {"Tracking Error", "0.138"}, + {"Treynor Ratio", "-32.969"}, {"Total Fees", "$0.00"}, {"Estimated Strategy Capacity", "$0"}, {"Lowest Capacity Asset", "SPX 31KC0UJFOS3N2|SPX 31"}, - {"Portfolio Turnover", "0.01%"}, + {"Portfolio Turnover", "0.00%"}, {"Drawdown Recovery", "0"}, - {"OrderListHash", "22c6e3e24145b1d57ef6a7f2b30108a7"} + {"OrderListHash", "defdd069def9d1e625e55d2e3a15da2f"} }; } } diff --git a/Algorithm.CSharp/IndexOptionShortCallITMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionShortCallITMExpiryRegressionAlgorithm.cs index 91f0feb9ead6..44a21a9d4ffb 100644 --- a/Algorithm.CSharp/IndexOptionShortCallITMExpiryRegressionAlgorithm.cs +++ b/Algorithm.CSharp/IndexOptionShortCallITMExpiryRegressionAlgorithm.cs @@ -201,33 +201,33 @@ public override void OnEndOfAlgorithm() public Dictionary ExpectedStatistics => new Dictionary { {"Total Orders", "2"}, - {"Average Win", "0%"}, - {"Average Loss", "-0.95%"}, - {"Compounding Annual Return", "-12.719%"}, - {"Drawdown", "1.200%"}, + {"Average Win", "0.20%"}, + {"Average Loss", "0%"}, + {"Compounding Annual Return", "2.875%"}, + {"Drawdown", "0.100%"}, {"Expectancy", "-1"}, {"Start Equity", "1000000"}, - {"End Equity", "990476"}, - {"Net Profit", "-0.952%"}, - {"Sharpe Ratio", "-3.064"}, - {"Sortino Ratio", "-0.889"}, - {"Probabilistic Sharpe Ratio", "0.542%"}, + {"End Equity", "1001996"}, + {"Net Profit", "0.200%"}, + {"Sharpe Ratio", "3.365"}, + {"Sortino Ratio", "0"}, + {"Probabilistic Sharpe Ratio", "97.734%"}, {"Loss Rate", "100%"}, {"Win Rate", "0%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "-0.095"}, - {"Beta", "0.019"}, - {"Annual Standard Deviation", "0.031"}, - {"Annual Variance", "0.001"}, - {"Information Ratio", "-0.985"}, - {"Tracking Error", "0.139"}, - {"Treynor Ratio", "-5.019"}, + {"Alpha", "0.018"}, + {"Beta", "-0.003"}, + {"Annual Standard Deviation", "0.005"}, + {"Annual Variance", "0"}, + {"Information Ratio", "-0.179"}, + {"Tracking Error", "0.138"}, + {"Treynor Ratio", "-5.279"}, {"Total Fees", "$0.00"}, {"Estimated Strategy Capacity", "$0"}, {"Lowest Capacity Asset", "SPX XL80P3GHIA9A|SPX 31"}, - {"Portfolio Turnover", "0.19%"}, + {"Portfolio Turnover", "0.24%"}, {"Drawdown Recovery", "0"}, - {"OrderListHash", "358b15e6d71c9fab8de9f53e667df96e"} + {"OrderListHash", "b05e3fa7f5b336125ddfb0b28e21fa26"} }; } } diff --git a/Algorithm.CSharp/IndexOptionShortCallOTMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionShortCallOTMExpiryRegressionAlgorithm.cs index b439ff57964b..5cf7ee5d475c 100644 --- a/Algorithm.CSharp/IndexOptionShortCallOTMExpiryRegressionAlgorithm.cs +++ b/Algorithm.CSharp/IndexOptionShortCallOTMExpiryRegressionAlgorithm.cs @@ -181,33 +181,33 @@ public override void OnEndOfAlgorithm() public Dictionary ExpectedStatistics => new Dictionary { {"Total Orders", "2"}, - {"Average Win", "0.01%"}, + {"Average Win", "0.00%"}, {"Average Loss", "0%"}, - {"Compounding Annual Return", "0.142%"}, + {"Compounding Annual Return", "0.071%"}, {"Drawdown", "0%"}, {"Expectancy", "0"}, {"Start Equity", "100000"}, - {"End Equity", "100010"}, - {"Net Profit", "0.010%"}, - {"Sharpe Ratio", "-6.787"}, + {"End Equity", "100005"}, + {"Net Profit", "0.005%"}, + {"Sharpe Ratio", "-12.573"}, {"Sortino Ratio", "0"}, - {"Probabilistic Sharpe Ratio", "98.983%"}, + {"Probabilistic Sharpe Ratio", "91.467%"}, {"Loss Rate", "0%"}, {"Win Rate", "100%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "-0.001"}, + {"Alpha", "-0.002"}, {"Beta", "-0"}, {"Annual Standard Deviation", "0"}, {"Annual Variance", "0"}, - {"Information Ratio", "-0.32"}, + {"Information Ratio", "-0.323"}, {"Tracking Error", "0.138"}, - {"Treynor Ratio", "14.02"}, + {"Treynor Ratio", "412.889"}, {"Total Fees", "$0.00"}, - {"Estimated Strategy Capacity", "$22000.00"}, + {"Estimated Strategy Capacity", "$0"}, {"Lowest Capacity Asset", "SPX XL80P59H9OI6|SPX 31"}, {"Portfolio Turnover", "0.00%"}, {"Drawdown Recovery", "0"}, - {"OrderListHash", "b2d0a0970bfbb57c5b20d251b0366e29"} + {"OrderListHash", "6383580692a8a32a8184ae2cfc2b5d8a"} }; } } diff --git a/Algorithm.CSharp/IndexOptionShortPutITMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionShortPutITMExpiryRegressionAlgorithm.cs index 84b872f11072..75244b3d821e 100644 --- a/Algorithm.CSharp/IndexOptionShortPutITMExpiryRegressionAlgorithm.cs +++ b/Algorithm.CSharp/IndexOptionShortPutITMExpiryRegressionAlgorithm.cs @@ -204,33 +204,33 @@ public override void OnEndOfAlgorithm() public Dictionary ExpectedStatistics => new Dictionary { {"Total Orders", "2"}, - {"Average Win", "0.94%"}, - {"Average Loss", "0%"}, - {"Compounding Annual Return", "14.183%"}, + {"Average Win", "0%"}, + {"Average Loss", "-0.25%"}, + {"Compounding Annual Return", "-3.476%"}, {"Drawdown", "0.300%"}, {"Expectancy", "-1"}, {"Start Equity", "1000000"}, - {"End Equity", "1009374"}, - {"Net Profit", "0.937%"}, - {"Sharpe Ratio", "2.997"}, - {"Sortino Ratio", "34.286"}, - {"Probabilistic Sharpe Ratio", "86.840%"}, + {"End Equity", "997514"}, + {"Net Profit", "-0.249%"}, + {"Sharpe Ratio", "-4.227"}, + {"Sortino Ratio", "-1.626"}, + {"Probabilistic Sharpe Ratio", "0.024%"}, {"Loss Rate", "100%"}, {"Win Rate", "0%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "0.098"}, - {"Beta", "-0.021"}, - {"Annual Standard Deviation", "0.032"}, - {"Annual Variance", "0.001"}, - {"Information Ratio", "0.374"}, - {"Tracking Error", "0.144"}, - {"Treynor Ratio", "-4.521"}, + {"Alpha", "-0.027"}, + {"Beta", "0.004"}, + {"Annual Standard Deviation", "0.006"}, + {"Annual Variance", "0"}, + {"Information Ratio", "-0.508"}, + {"Tracking Error", "0.137"}, + {"Treynor Ratio", "-6.665"}, {"Total Fees", "$0.00"}, {"Estimated Strategy Capacity", "$0"}, {"Lowest Capacity Asset", "SPX 31KC0UJHCBG4U|SPX 31"}, - {"Portfolio Turnover", "0.19%"}, - {"Drawdown Recovery", "9"}, - {"OrderListHash", "86a79c56040bedf9067b7255131e0387"} + {"Portfolio Turnover", "0.15%"}, + {"Drawdown Recovery", "0"}, + {"OrderListHash", "a472e1e5d517deecd310365211efe2da"} }; } } diff --git a/Algorithm.CSharp/IndexOptionShortPutOTMExpiryRegressionAlgorithm.cs b/Algorithm.CSharp/IndexOptionShortPutOTMExpiryRegressionAlgorithm.cs index 76d7e117ecc3..b335247e8859 100644 --- a/Algorithm.CSharp/IndexOptionShortPutOTMExpiryRegressionAlgorithm.cs +++ b/Algorithm.CSharp/IndexOptionShortPutOTMExpiryRegressionAlgorithm.cs @@ -183,30 +183,30 @@ public override void OnEndOfAlgorithm() {"Average Win", "0.34%"}, {"Average Loss", "0%"}, {"Compounding Annual Return", "4.943%"}, - {"Drawdown", "0.000%"}, + {"Drawdown", "0%"}, {"Expectancy", "0"}, {"Start Equity", "100000"}, {"End Equity", "100340"}, {"Net Profit", "0.340%"}, - {"Sharpe Ratio", "2.906"}, + {"Sharpe Ratio", "3.044"}, {"Sortino Ratio", "0"}, - {"Probabilistic Sharpe Ratio", "89.631%"}, + {"Probabilistic Sharpe Ratio", "92.276%"}, {"Loss Rate", "0%"}, {"Win Rate", "100%"}, {"Profit-Loss Ratio", "0"}, {"Alpha", "0.033"}, - {"Beta", "-0.008"}, + {"Beta", "-0.007"}, {"Annual Standard Deviation", "0.011"}, {"Annual Variance", "0"}, {"Information Ratio", "-0.073"}, {"Tracking Error", "0.139"}, - {"Treynor Ratio", "-4.22"}, + {"Treynor Ratio", "-4.753"}, {"Total Fees", "$0.00"}, {"Estimated Strategy Capacity", "$0"}, {"Lowest Capacity Asset", "SPX 31KC0UJFOS3N2|SPX 31"}, {"Portfolio Turnover", "0.01%"}, - {"Drawdown Recovery", "9"}, - {"OrderListHash", "0b39fcedbea77ba71bf0d4547a3b8fc5"} + {"Drawdown Recovery", "0"}, + {"OrderListHash", "6c95f8f5c85c35810f776d2b47a6b342"} }; } } diff --git a/Algorithm.CSharp/InsufficientBuyingPowerForAutomaticExerciseRegressionAlgorithm.cs b/Algorithm.CSharp/InsufficientBuyingPowerForAutomaticExerciseRegressionAlgorithm.cs index 86aff0d031be..f38d669ea730 100644 --- a/Algorithm.CSharp/InsufficientBuyingPowerForAutomaticExerciseRegressionAlgorithm.cs +++ b/Algorithm.CSharp/InsufficientBuyingPowerForAutomaticExerciseRegressionAlgorithm.cs @@ -191,30 +191,30 @@ public override void OnEndOfAlgorithm() {"Total Orders", "4"}, {"Average Win", "8.96%"}, {"Average Loss", "-1.95%"}, - {"Compounding Annual Return", "-67.963%"}, + {"Compounding Annual Return", "248.965%"}, {"Drawdown", "2.900%"}, {"Expectancy", "-1"}, {"Start Equity", "100000"}, - {"End Equity", "98248.35"}, - {"Net Profit", "-1.752%"}, - {"Sharpe Ratio", "-6.542"}, + {"End Equity", "101959.28"}, + {"Net Profit", "1.959%"}, + {"Sharpe Ratio", "14.873"}, {"Sortino Ratio", "0"}, - {"Probabilistic Sharpe Ratio", "1.125%"}, + {"Probabilistic Sharpe Ratio", "85.812%"}, {"Loss Rate", "100%"}, {"Win Rate", "0%"}, {"Profit-Loss Ratio", "4.60"}, - {"Alpha", "-0.007"}, - {"Beta", "1.181"}, - {"Annual Standard Deviation", "0.036"}, - {"Annual Variance", "0.001"}, - {"Information Ratio", "-1.422"}, - {"Tracking Error", "0.03"}, - {"Treynor Ratio", "-0.2"}, + {"Alpha", "2.459"}, + {"Beta", "-8.745"}, + {"Annual Standard Deviation", "0.279"}, + {"Annual Variance", "0.078"}, + {"Information Ratio", "15.029"}, + {"Tracking Error", "0.289"}, + {"Treynor Ratio", "-0.475"}, {"Total Fees", "$3.30"}, {"Estimated Strategy Capacity", "$2400000.00"}, {"Lowest Capacity Asset", "GOOCV 305RBQ20WLZZA|GOOCV VP83T1ZUHROL"}, {"Portfolio Turnover", "54.01%"}, - {"Drawdown Recovery", "0"}, + {"Drawdown Recovery", "5"}, {"OrderListHash", "2f22fc5e9584c2d201b9e0b767a7160d"} }; } diff --git a/Algorithm.CSharp/ManualContinuousFuturesPositionRolloverRegressionAlgorithm.cs b/Algorithm.CSharp/ManualContinuousFuturesPositionRolloverRegressionAlgorithm.cs index 278346447aff..32d3cfb61297 100644 --- a/Algorithm.CSharp/ManualContinuousFuturesPositionRolloverRegressionAlgorithm.cs +++ b/Algorithm.CSharp/ManualContinuousFuturesPositionRolloverRegressionAlgorithm.cs @@ -122,33 +122,33 @@ public override void OnEndOfAlgorithm() public Dictionary ExpectedStatistics => new Dictionary { {"Total Orders", "3"}, - {"Average Win", "7.01%"}, + {"Average Win", "7.02%"}, {"Average Loss", "0%"}, - {"Compounding Annual Return", "15.617%"}, + {"Compounding Annual Return", "15.644%"}, {"Drawdown", "1.600%"}, {"Expectancy", "0"}, {"Start Equity", "100000"}, - {"End Equity", "107578.9"}, - {"Net Profit", "7.579%"}, - {"Sharpe Ratio", "1.706"}, - {"Sortino Ratio", "0.919"}, - {"Probabilistic Sharpe Ratio", "88.924%"}, + {"End Equity", "107591.4"}, + {"Net Profit", "7.591%"}, + {"Sharpe Ratio", "2.021"}, + {"Sortino Ratio", "1.533"}, + {"Probabilistic Sharpe Ratio", "92.380%"}, {"Loss Rate", "0%"}, {"Win Rate", "100%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "0.08"}, - {"Beta", "0.094"}, - {"Annual Standard Deviation", "0.059"}, - {"Annual Variance", "0.003"}, - {"Information Ratio", "-1.246"}, - {"Tracking Error", "0.094"}, - {"Treynor Ratio", "1.06"}, + {"Alpha", "0.062"}, + {"Beta", "0.175"}, + {"Annual Standard Deviation", "0.049"}, + {"Annual Variance", "0.002"}, + {"Information Ratio", "-1.429"}, + {"Tracking Error", "0.082"}, + {"Treynor Ratio", "0.57"}, {"Total Fees", "$6.45"}, {"Estimated Strategy Capacity", "$2900000000.00"}, {"Lowest Capacity Asset", "ES VMKLFZIH2MTD"}, {"Portfolio Turnover", "1.37%"}, - {"Drawdown Recovery", "16"}, - {"OrderListHash", "7591ea8b91c4aa958b305555fea96862"} + {"Drawdown Recovery", "19"}, + {"OrderListHash", "d68967ba4f7c5f6bbd41efde01a477e1"} }; } } diff --git a/Algorithm.CSharp/MarketOrderStaleDataFillRegressionAlgorithm.cs b/Algorithm.CSharp/MarketOrderStaleDataFillRegressionAlgorithm.cs new file mode 100644 index 000000000000..c5576e50aa0e --- /dev/null +++ b/Algorithm.CSharp/MarketOrderStaleDataFillRegressionAlgorithm.cs @@ -0,0 +1,158 @@ +/* + * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. + * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. +*/ + +using System.Collections.Generic; +using QuantConnect.Data; +using QuantConnect.Interfaces; +using QuantConnect.Orders; + +namespace QuantConnect.Algorithm.CSharp +{ + /// + /// Regression algorithm reproducing the stale fill issue: a market order must not be filled on data that is older + /// than the subscribed resolution (the latest available bar is more than one resolution behind the fill time), + /// regardless of the time of day. The fill should wait until fresh data is available. + /// + /// Two orders are submitted to cover both cases: + /// - right after the market open (9:30:01), when the only data available is the previous trading date's bar + /// (the original reported case), and + /// - mid-session (noon), where data is continuous and the order fills normally on fresh data. + /// + /// + public class MarketOrderStaleDataFillRegressionAlgorithm : QCAlgorithm, IRegressionAlgorithmDefinition + { + private Symbol _spy; + private System.TimeSpan _resolutionSpan; + + /// + /// Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. + /// + public override void Initialize() + { + SetStartDate(2013, 10, 07); + SetEndDate(2013, 10, 11); + SetCash(100000); + + var resolution = Resolution.Minute; + _resolutionSpan = resolution.ToTimeSpan(); + _spy = AddEquity("SPY", resolution).Symbol; + + // Market open: order one second after the open, before the first minute bar of the session is available + Schedule.On(DateRules.EveryDay(_spy), TimeRules.At(9, 30, 1), Trade); + // Mid-session: data is continuous here, so the order fills normally on fresh data + Schedule.On(DateRules.EveryDay(_spy), TimeRules.At(12, 0, 0), Trade); + } + + private void Trade() + { + // Only trade once the security already has data, so a stale fill would be attempted against an older bar + // (the data we want to avoid filling on) rather than against an empty cache + if (Securities[_spy].HasData) + { + MarketOrder(_spy, 1); + } + } + + /// + /// Asserts that market orders are never filled on data staler than the subscribed resolution, at any time of day + /// + public override void OnOrderEvent(OrderEvent orderEvent) + { + if (orderEvent.Status != OrderStatus.Filled) + { + return; + } + + var security = Securities[orderEvent.Symbol]; + var lastData = security.GetLastData(); + if (lastData == null) + { + return; + } + + // The latest available data must be within one resolution bar of the fill time. Without the fix, a market + // order placed when only stale data is available (e.g. right after the open, before the first session bar) + // would fill on that stale price instead of waiting for fresh data. + var dataGap = orderEvent.UtcTime - lastData.EndTime.ConvertToUtc(security.Exchange.TimeZone); + if (dataGap > _resolutionSpan) + { + throw new RegressionTestException( + $"Order {orderEvent.OrderId} for {orderEvent.Symbol} filled at {orderEvent.UtcTime} UTC on stale " + + $"data ending {lastData.EndTime} ({dataGap} behind, more than the {_resolutionSpan} resolution). " + + $"The fill should have waited for fresh data."); + } + } + + /// + /// This is used by the regression test system to indicate if the open source Lean repository has the required data to run this algorithm. + /// + public bool CanRunLocally { get; } = true; + + /// + /// This is used by the regression test system to indicate which languages this algorithm is written in. + /// + public List Languages { get; } = new() { Language.CSharp }; + + /// + /// Data Points count of all timeslices of algorithm + /// + public long DataPoints => 3943; + + /// + /// Data Points count of the algorithm history + /// + public int AlgorithmHistoryDataPoints => 0; + + /// + /// Final status of the algorithm + /// + public AlgorithmStatus AlgorithmStatus => AlgorithmStatus.Completed; + + /// + /// This is used by the regression test system to indicate what the expected statistics are from running the algorithm + /// + public Dictionary ExpectedStatistics => new Dictionary + { + {"Total Orders", "9"}, + {"Average Win", "0%"}, + {"Average Loss", "0%"}, + {"Compounding Annual Return", "1.007%"}, + {"Drawdown", "0.000%"}, + {"Expectancy", "0"}, + {"Start Equity", "100000"}, + {"End Equity", "100012.81"}, + {"Net Profit", "0.013%"}, + {"Sharpe Ratio", "1.079"}, + {"Sortino Ratio", "3.268"}, + {"Probabilistic Sharpe Ratio", "73.812%"}, + {"Loss Rate", "0%"}, + {"Win Rate", "0%"}, + {"Profit-Loss Ratio", "0"}, + {"Alpha", "-0.012"}, + {"Beta", "0.007"}, + {"Annual Standard Deviation", "0.002"}, + {"Annual Variance", "0"}, + {"Information Ratio", "-8.931"}, + {"Tracking Error", "0.221"}, + {"Treynor Ratio", "0.244"}, + {"Total Fees", "$9.00"}, + {"Estimated Strategy Capacity", "$290000000.00"}, + {"Lowest Capacity Asset", "SPY R735QTJ8XC9X"}, + {"Portfolio Turnover", "0.26%"}, + {"Drawdown Recovery", "2"}, + {"OrderListHash", "c849aa80f00dde3d93bf4cc6d65c4d5e"} + }; + } +} diff --git a/Algorithm.CSharp/OptionAssignmentStatisticsRegressionAlgorithm.cs b/Algorithm.CSharp/OptionAssignmentStatisticsRegressionAlgorithm.cs index 42a3c3962f57..53116d96fb5e 100644 --- a/Algorithm.CSharp/OptionAssignmentStatisticsRegressionAlgorithm.cs +++ b/Algorithm.CSharp/OptionAssignmentStatisticsRegressionAlgorithm.cs @@ -214,7 +214,7 @@ private void AssertPortfolioStatistics() throw new RegressionTestException($"AssertPortfolioStatistics(): Expected loss rate to be 1/3. Actual {portfolioStatistics.LossRate}"); } - var expectedAverageWinRate = 0.32962000910479m; + var expectedAverageWinRate = 0.3425273813030554588544037705m; if (!AreEqual(expectedAverageWinRate, portfolioStatistics.AverageWinRate)) { throw new RegressionTestException($@"AssertPortfolioStatistics(): Expected average win rate to be {expectedAverageWinRate}. Actual { @@ -228,14 +228,14 @@ private void AssertPortfolioStatistics() portfolioStatistics.AverageLossRate}"); } - var expectedProfitLossRatio = 2.43142881621545m; + var expectedProfitLossRatio = 2.5266395310920343630590960734m; if (!AreEqual(expectedProfitLossRatio, portfolioStatistics.ProfitLossRatio)) { throw new RegressionTestException($@"AssertPortfolioStatistics(): Expected profit loss ratio to be {expectedProfitLossRatio}. Actual { portfolioStatistics.ProfitLossRatio}"); } - var totalNetProfit = -0.00697m; + var totalNetProfit = 0.00267m; if (!AreEqual(totalNetProfit, portfolioStatistics.TotalNetProfit)) { throw new RegressionTestException($@"AssertPortfolioStatistics(): Expected total net profit to be {totalNetProfit}. Actual { @@ -278,34 +278,34 @@ private static bool AreEqual(decimal expected, decimal actual) /// public virtual Dictionary ExpectedStatistics => new Dictionary { - {"Total Orders", "6"}, - {"Average Win", "32.96%"}, + {"Total Orders", "5"}, + {"Average Win", "34.25%"}, {"Average Loss", "-13.56%"}, - {"Compounding Annual Return", "-36.270%"}, + {"Compounding Annual Return", "18.738%"}, {"Drawdown", "1.400%"}, - {"Expectancy", "1.288"}, + {"Expectancy", "1.351"}, {"Start Equity", "100000"}, - {"End Equity", "99303"}, - {"Net Profit", "-0.697%"}, - {"Sharpe Ratio", "-8.675"}, - {"Sortino Ratio", "-6.769"}, - {"Probabilistic Sharpe Ratio", "0.012%"}, + {"End Equity", "100267"}, + {"Net Profit", "0.267%"}, + {"Sharpe Ratio", "4.957"}, + {"Sortino Ratio", "0"}, + {"Probabilistic Sharpe Ratio", "71.274%"}, {"Loss Rate", "33%"}, {"Win Rate", "67%"}, - {"Profit-Loss Ratio", "2.43"}, - {"Alpha", "-0.011"}, - {"Beta", "0.825"}, - {"Annual Standard Deviation", "0.02"}, - {"Annual Variance", "0"}, - {"Information Ratio", "1.705"}, - {"Tracking Error", "0.014"}, - {"Treynor Ratio", "-0.207"}, + {"Profit-Loss Ratio", "2.53"}, + {"Alpha", "0.024"}, + {"Beta", "-1.724"}, + {"Annual Standard Deviation", "0.072"}, + {"Annual Variance", "0.005"}, + {"Information Ratio", "6.8"}, + {"Tracking Error", "0.081"}, + {"Treynor Ratio", "-0.208"}, {"Total Fees", "$3.00"}, - {"Estimated Strategy Capacity", "$0"}, - {"Lowest Capacity Asset", "GOOCV VP83T1ZUHROL"}, - {"Portfolio Turnover", "50.31%"}, - {"Drawdown Recovery", "0"}, - {"OrderListHash", "65544a2eaccc912e8c81519f5975da1a"} + {"Estimated Strategy Capacity", "$10000000.00"}, + {"Lowest Capacity Asset", "GOOCV W6NBKMB4N492|GOOCV VP83T1ZUHROL"}, + {"Portfolio Turnover", "50.23%"}, + {"Drawdown Recovery", "5"}, + {"OrderListHash", "9d48744bc10d9c00aeba0f7a11dbbee0"} }; } } diff --git a/Algorithm.CSharp/OptionShortCallMarginCallEventsAlgorithm.cs b/Algorithm.CSharp/OptionShortCallMarginCallEventsAlgorithm.cs index 6192dc406e60..3018f93677e3 100644 --- a/Algorithm.CSharp/OptionShortCallMarginCallEventsAlgorithm.cs +++ b/Algorithm.CSharp/OptionShortCallMarginCallEventsAlgorithm.cs @@ -79,7 +79,7 @@ public override void OnData(Slice slice) /// /// Data Points count of all timeslices of algorithm /// - public override long DataPoints => 46957; + public override long DataPoints => 47108; /// /// Data Points count of the algorithm history @@ -119,7 +119,7 @@ public override void OnData(Slice slice) {"Tracking Error", "0.088"}, {"Treynor Ratio", "-2.981"}, {"Total Fees", "$7.50"}, - {"Estimated Strategy Capacity", "$66000.00"}, + {"Estimated Strategy Capacity", "$64000.00"}, {"Lowest Capacity Asset", "GOOCV W78ZFMML4BUU|GOOCV VP83T1ZUHROL"}, {"Portfolio Turnover", "1.01%"}, {"Drawdown Recovery", "0"}, diff --git a/Algorithm.CSharp/OptionsAutomaticSeedRegressionAlgorithm.cs b/Algorithm.CSharp/OptionsAutomaticSeedRegressionAlgorithm.cs index b864cf8823a0..47e3b734811a 100644 --- a/Algorithm.CSharp/OptionsAutomaticSeedRegressionAlgorithm.cs +++ b/Algorithm.CSharp/OptionsAutomaticSeedRegressionAlgorithm.cs @@ -16,6 +16,7 @@ using QuantConnect.Data; using QuantConnect.Data.UniverseSelection; +using System.Collections.Generic; namespace QuantConnect.Algorithm.CSharp { @@ -30,9 +31,12 @@ public class OptionsAutomaticSeedRegressionAlgorithm : AutomaticSeedBaseRegressi protected override bool ShouldHaveQuoteData => true; protected override bool ShouldHaveOpenInterestData => true; + // SPY will be added with daily resolution, will not have quotes + protected override List SecuritiesToIgnoreForChecking => ["SPY"]; + public override void Initialize() { - SetStartDate(2015, 12, 28); + SetStartDate(2015, 12, 24); SetEndDate(2015, 12, 28); SetCash(100000); @@ -91,11 +95,46 @@ public override void OnEndOfAlgorithm() /// /// Data Points count of all timeslices of algorithm /// - public override long DataPoints => 4044; + public override long DataPoints => 38649; /// /// Data Points count of the algorithm history /// - public override int AlgorithmHistoryDataPoints => 218; + public override int AlgorithmHistoryDataPoints => 185; + + /// + /// This is used by the regression test system to indicate what the expected statistics are from running the algorithm + /// + public override Dictionary ExpectedStatistics => new Dictionary + { + {"Total Orders", "0"}, + {"Average Win", "0%"}, + {"Average Loss", "0%"}, + {"Compounding Annual Return", "0%"}, + {"Drawdown", "0%"}, + {"Expectancy", "0"}, + {"Start Equity", "100000"}, + {"End Equity", "100000"}, + {"Net Profit", "0%"}, + {"Sharpe Ratio", "0"}, + {"Sortino Ratio", "0"}, + {"Probabilistic Sharpe Ratio", "0%"}, + {"Loss Rate", "0%"}, + {"Win Rate", "0%"}, + {"Profit-Loss Ratio", "0"}, + {"Alpha", "0"}, + {"Beta", "0"}, + {"Annual Standard Deviation", "0"}, + {"Annual Variance", "0"}, + {"Information Ratio", "7.438"}, + {"Tracking Error", "0.017"}, + {"Treynor Ratio", "0"}, + {"Total Fees", "$0.00"}, + {"Estimated Strategy Capacity", "$0"}, + {"Lowest Capacity Asset", ""}, + {"Portfolio Turnover", "0%"}, + {"Drawdown Recovery", "0"}, + {"OrderListHash", "d41d8cd98f00b204e9800998ecf8427e"} + }; } } diff --git a/Algorithm.CSharp/RegressionTests/Collective2IndexOptionAlgorithm.cs b/Algorithm.CSharp/RegressionTests/Collective2IndexOptionAlgorithm.cs index bddb8bfe1e39..3cd4e9f43430 100644 --- a/Algorithm.CSharp/RegressionTests/Collective2IndexOptionAlgorithm.cs +++ b/Algorithm.CSharp/RegressionTests/Collective2IndexOptionAlgorithm.cs @@ -127,9 +127,9 @@ public override void OnData(Slice slice) /// public Dictionary ExpectedStatistics => new Dictionary { - {"Total Orders", "10"}, + {"Total Orders", "55"}, {"Average Win", "0%"}, - {"Average Loss", "0.00%"}, + {"Average Loss", "-0.01%"}, {"Compounding Annual Return", "-0.468%"}, {"Drawdown", "0.000%"}, {"Expectancy", "-1"}, @@ -150,11 +150,11 @@ public override void OnData(Slice slice) {"Tracking Error", "0.103"}, {"Treynor Ratio", "5.946"}, {"Total Fees", "$0.00"}, - {"Estimated Strategy Capacity", "$8000.00"}, + {"Estimated Strategy Capacity", "$20000.00"}, {"Lowest Capacity Asset", "SPXW XKX6S2GMDZSE|SPX 31"}, - {"Portfolio Turnover", "0.01%"}, + {"Portfolio Turnover", "0.00%"}, {"Drawdown Recovery", "0"}, - {"OrderListHash", "ad9c0f3aa3b311065df12bcff9a2b4de"} + {"OrderListHash", "a15fe0e8fc66f7d6a83433525c33a2c1"} }; } } diff --git a/Algorithm.CSharp/RestingMarketOrderFillsAtBarOpenRegressionAlgorithm.cs b/Algorithm.CSharp/RestingMarketOrderFillsAtBarOpenRegressionAlgorithm.cs index 57cfb96cb1b4..4ead5eadd757 100644 --- a/Algorithm.CSharp/RestingMarketOrderFillsAtBarOpenRegressionAlgorithm.cs +++ b/Algorithm.CSharp/RestingMarketOrderFillsAtBarOpenRegressionAlgorithm.cs @@ -165,7 +165,7 @@ public override void OnEndOfAlgorithm() /// /// Data Points count of all timeslices of algorithm /// - public long DataPoints => 1242; + public long DataPoints => 1244; /// /// Data Points count of the algorithm history @@ -183,33 +183,33 @@ public override void OnEndOfAlgorithm() public Dictionary ExpectedStatistics => new Dictionary { {"Total Orders", "2"}, - {"Average Win", "0.77%"}, + {"Average Win", "0.66%"}, {"Average Loss", "0%"}, - {"Compounding Annual Return", "3.362%"}, - {"Drawdown", "0.000%"}, + {"Compounding Annual Return", "2.861%"}, + {"Drawdown", "0.200%"}, {"Expectancy", "0"}, {"Start Equity", "1000000"}, - {"End Equity", "1007708.2"}, - {"Net Profit", "0.771%"}, - {"Sharpe Ratio", "1.942"}, - {"Sortino Ratio", "0"}, - {"Probabilistic Sharpe Ratio", "99.419%"}, + {"End Equity", "1006570.7"}, + {"Net Profit", "0.657%"}, + {"Sharpe Ratio", "1.931"}, + {"Sortino Ratio", "2.91"}, + {"Probabilistic Sharpe Ratio", "89.795%"}, {"Loss Rate", "0%"}, {"Win Rate", "100%"}, {"Profit-Loss Ratio", "0"}, - {"Alpha", "0.005"}, - {"Beta", "0.027"}, - {"Annual Standard Deviation", "0.008"}, + {"Alpha", "-0.016"}, + {"Beta", "0.068"}, + {"Annual Standard Deviation", "0.006"}, {"Annual Variance", "0"}, - {"Information Ratio", "-4.838"}, - {"Tracking Error", "0.081"}, - {"Treynor Ratio", "0.59"}, + {"Information Ratio", "-5.117"}, + {"Tracking Error", "0.078"}, + {"Treynor Ratio", "0.182"}, {"Total Fees", "$4.30"}, - {"Estimated Strategy Capacity", "$4000000000.00"}, + {"Estimated Strategy Capacity", "$4700000000.00"}, {"Lowest Capacity Asset", "ES VP274HSU1AF5"}, {"Portfolio Turnover", "0.20%"}, - {"Drawdown Recovery", "2"}, - {"OrderListHash", "6a9015ff0968f198b3a13df5f27416c0"} + {"Drawdown Recovery", "12"}, + {"OrderListHash", "6a53aee5b55140888033e93db779c2e9"} }; } } diff --git a/Algorithm.CSharp/SecurityInitializationOnReAdditionForManuallyAddedFutureContractRegressionAlgorithm.cs b/Algorithm.CSharp/SecurityInitializationOnReAdditionForManuallyAddedFutureContractRegressionAlgorithm.cs index fe86a481efbf..37a03a34e645 100644 --- a/Algorithm.CSharp/SecurityInitializationOnReAdditionForManuallyAddedFutureContractRegressionAlgorithm.cs +++ b/Algorithm.CSharp/SecurityInitializationOnReAdditionForManuallyAddedFutureContractRegressionAlgorithm.cs @@ -44,12 +44,12 @@ protected override Security AddSecurity() /// /// Data Points count of all timeslices of algorithm /// - public override long DataPoints => 101; + public override long DataPoints => 109; /// /// Data Points count of the algorithm history /// - public override int AlgorithmHistoryDataPoints => 80; + public override int AlgorithmHistoryDataPoints => 92; /// /// This is used by the regression test system to indicate what the expected statistics are from running the algorithm diff --git a/Algorithm.CSharp/SingleOptionPositionGroupBuyingPowerModelRegressionAlgorithm.cs b/Algorithm.CSharp/SingleOptionPositionGroupBuyingPowerModelRegressionAlgorithm.cs index 9a58bcf25e16..09f7851aec96 100644 --- a/Algorithm.CSharp/SingleOptionPositionGroupBuyingPowerModelRegressionAlgorithm.cs +++ b/Algorithm.CSharp/SingleOptionPositionGroupBuyingPowerModelRegressionAlgorithm.cs @@ -162,7 +162,7 @@ private void PerfomQuantityCalculations(IPositionGroup positionGroup, Security s /// /// Data Points count of all timeslices of algorithm /// - public long DataPoints => 46957; + public long DataPoints => 47108; /// /// Data Points count of the algorithm history @@ -202,7 +202,7 @@ private void PerfomQuantityCalculations(IPositionGroup positionGroup, Security s {"Tracking Error", "0.084"}, {"Treynor Ratio", "-4.737"}, {"Total Fees", "$19.50"}, - {"Estimated Strategy Capacity", "$49000.00"}, + {"Estimated Strategy Capacity", "$47000.00"}, {"Lowest Capacity Asset", "GOOCV W78ZFMML4BUU|GOOCV VP83T1ZUHROL"}, {"Portfolio Turnover", "0.45%"}, {"Drawdown Recovery", "0"}, diff --git a/Algorithm.CSharp/TradingNotAddedOptionsRegressionAlgorithm.cs b/Algorithm.CSharp/TradingNotAddedOptionsRegressionAlgorithm.cs index db93057f0f4f..fb1cbf338f50 100644 --- a/Algorithm.CSharp/TradingNotAddedOptionsRegressionAlgorithm.cs +++ b/Algorithm.CSharp/TradingNotAddedOptionsRegressionAlgorithm.cs @@ -161,7 +161,7 @@ public override void OnOrderEvent(OrderEvent orderEvent) /// /// Data Points count of the algorithm history /// - public override int AlgorithmHistoryDataPoints => 22; + public override int AlgorithmHistoryDataPoints => 24; /// /// Final status of the algorithm @@ -173,34 +173,34 @@ public override void OnOrderEvent(OrderEvent orderEvent) /// public override Dictionary ExpectedStatistics => new Dictionary { - {"Total Orders", "8"}, + {"Total Orders", "6"}, {"Average Win", "0%"}, - {"Average Loss", "-0.02%"}, - {"Compounding Annual Return", "-5.436%"}, - {"Drawdown", "0.100%"}, - {"Expectancy", "-1"}, + {"Average Loss", "0%"}, + {"Compounding Annual Return", "0%"}, + {"Drawdown", "0%"}, + {"Expectancy", "0"}, {"Start Equity", "1000000"}, - {"End Equity", "999327"}, - {"Net Profit", "-0.067%"}, - {"Sharpe Ratio", "-9.644"}, + {"End Equity", "1000000"}, + {"Net Profit", "0%"}, + {"Sharpe Ratio", "0"}, {"Sortino Ratio", "0"}, - {"Probabilistic Sharpe Ratio", "1.216%"}, - {"Loss Rate", "100%"}, + {"Probabilistic Sharpe Ratio", "0%"}, + {"Loss Rate", "0%"}, {"Win Rate", "0%"}, {"Profit-Loss Ratio", "0"}, {"Alpha", "0"}, {"Beta", "0"}, - {"Annual Standard Deviation", "0.005"}, + {"Annual Standard Deviation", "0"}, {"Annual Variance", "0"}, - {"Information Ratio", "-7.772"}, - {"Tracking Error", "0.005"}, + {"Information Ratio", "0"}, + {"Tracking Error", "0"}, {"Treynor Ratio", "0"}, - {"Total Fees", "$8.00"}, + {"Total Fees", "$0.00"}, {"Estimated Strategy Capacity", "$0"}, - {"Lowest Capacity Asset", "GOOCV WBGM92QHN8ZQ|GOOCV VP83T1ZUHROL"}, - {"Portfolio Turnover", "0.86%"}, + {"Lowest Capacity Asset", ""}, + {"Portfolio Turnover", "0%"}, {"Drawdown Recovery", "0"}, - {"OrderListHash", "fc224d8177907f98e3381d2d58067b48"} + {"OrderListHash", "7477e579cd79b8256f5a7185f752a5f3"} }; } } diff --git a/Algorithm.Python/BasicTemplateContinuousFutureAlgorithm.py b/Algorithm.Python/BasicTemplateContinuousFutureAlgorithm.py index 6441ab6d1b99..6f7635c03f4a 100644 --- a/Algorithm.Python/BasicTemplateContinuousFutureAlgorithm.py +++ b/Algorithm.Python/BasicTemplateContinuousFutureAlgorithm.py @@ -34,6 +34,9 @@ def initialize(self): self._slow = self.sma(self._continuous_contract.symbol, 10, Resolution.DAILY) self._current_contract = None + # Minimum SMA gap required before acting on a cross; see the workaround note in on_data. + self._cross_threshold = 0.001 + def on_data(self, data): '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. @@ -44,11 +47,13 @@ def on_data(self, data): if changed_event.symbol == self._continuous_contract.symbol: self.log(f"SymbolChanged event: {changed_event}") + # Workaround so the C# and Python versions take the exact same trades on the limited + # sample data in the repository (decimal vs double rounding can disagree at a cross). if not self.portfolio.invested: - if self._fast.current.value > self._slow.current.value: + if self._fast.current.value - self._slow.current.value > self._cross_threshold: self._current_contract = self.securities[self._continuous_contract.mapped] self.buy(self._current_contract.symbol, 1) - elif self._fast.current.value < self._slow.current.value: + elif self._slow.current.value - self._fast.current.value > self._cross_threshold: self.liquidate() # We check exchange hours because the contract mapping can call OnData outside of regular hours. diff --git a/Algorithm.Python/BasicTemplateContinuousFutureWithExtendedMarketAlgorithm.py b/Algorithm.Python/BasicTemplateContinuousFutureWithExtendedMarketAlgorithm.py index 416f2ccaa589..b5ffaacf1f5a 100644 --- a/Algorithm.Python/BasicTemplateContinuousFutureWithExtendedMarketAlgorithm.py +++ b/Algorithm.Python/BasicTemplateContinuousFutureWithExtendedMarketAlgorithm.py @@ -35,6 +35,9 @@ def initialize(self): self._slow = self.sma(self._continuous_contract.symbol, 10, Resolution.DAILY) self._current_contract = None + # Minimum SMA gap required before acting on a cross; see the workaround note in on_data. + self._cross_threshold = 0.001 + def on_data(self, data): '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here. @@ -47,13 +50,18 @@ def on_data(self, data): if not self.is_market_open(self._continuous_contract.symbol): return - - if not self.portfolio.invested: - if self._fast.current.value > self._slow.current.value: - self._current_contract = self.securities[self._continuous_contract.mapped] - self.buy(self._current_contract.symbol, 1) - elif self._fast.current.value < self._slow.current.value: - self.liquidate() + + # This is just to limit the amount of orders done in this regression test, since data in the repo is limited. + # Also limit it to 3 orders so that the continuous contract rolls happens with an open position. + if self.time < datetime(2013, 11, 12) and self.transactions.orders_count < 3: + # Workaround so the C# and Python versions take the exact same trades on the limited + # sample data in the repository (decimal vs double rounding can disagree at a cross). + if not self.portfolio.invested: + if self._fast.current.value - self._slow.current.value > self._cross_threshold: + self._current_contract = self.securities[self._continuous_contract.mapped] + self.buy(self._current_contract.symbol, 1) + elif self._slow.current.value - self._fast.current.value > self._cross_threshold: + self.liquidate() if self._current_contract is not None and self._current_contract.symbol != self._continuous_contract.mapped: self.log(f"{Time} - rolling position from {self._current_contract.symbol} to {self._continuous_contract.mapped}") diff --git a/Common/Orders/Fills/EquityFillModel.cs b/Common/Orders/Fills/EquityFillModel.cs index da5167511ca9..7ede05b8b15e 100644 --- a/Common/Orders/Fills/EquityFillModel.cs +++ b/Common/Orders/Fills/EquityFillModel.cs @@ -81,7 +81,7 @@ public override OrderEvent LimitIfTouchedFill(Security asset, LimitIfTouchedOrde if (tradeBar.Low <= order.TriggerPrice || order.TriggerTouched) { order.TriggerTouched = true; - var askCurrent = GetBestEffortAskPrice(asset, order.Time, out var fillMessage, out _); + var askCurrent = GetBestEffortAskPrice(asset, order.Time, out var fillMessage, out _, out _); if (askCurrent <= order.LimitPrice) { @@ -99,7 +99,7 @@ public override OrderEvent LimitIfTouchedFill(Security asset, LimitIfTouchedOrde if (tradeBar.High >= order.TriggerPrice || order.TriggerTouched) { order.TriggerTouched = true; - var bidCurrent = GetBestEffortBidPrice(asset, order.Time, out var fillMessage, out _); + var bidCurrent = GetBestEffortBidPrice(asset, order.Time, out var fillMessage, out _, out _); if (bidCurrent >= order.LimitPrice) { @@ -137,25 +137,30 @@ public override OrderEvent MarketFill(Security asset, MarketOrder order) var fillMessage = string.Empty; var stalePrice = false; + var staleDataEndTimeUtc = default(DateTime); var fillPrice = 0m; switch (order.Direction) { case OrderDirection.Buy: //Order [fill]price for a buy market order model is the current security ask price - fillPrice = GetBestEffortAskPrice(asset, order.Time, out fillMessage, out stalePrice) + slip; + fillPrice = GetBestEffortAskPrice(asset, order.Time, out fillMessage, out stalePrice, out staleDataEndTimeUtc) + slip; break; case OrderDirection.Sell: //Order [fill]price for a buy market order model is the current security bid price - fillPrice = GetBestEffortBidPrice(asset, order.Time, out fillMessage, out stalePrice) - slip; + fillPrice = GetBestEffortBidPrice(asset, order.Time, out fillMessage, out stalePrice, out staleDataEndTimeUtc) - slip; break; } - // On stale data: for coarse resolutions (hour/daily) wait for fresh prices (e.g. the next bar to close) - // instead of filling at an already past, stale bar's price, which happens when a market order is placed - // mid-bar or through an intraday scheduled event. For finer resolutions (minute/second/tick) keep filling - // on the stale price with the warning already set in fillMessage. - if (stalePrice && ShouldWaitForFreshData(asset)) return fill; + // On stale data, wait for fresh prices instead of filling at an already past, stale bar's price when the + // latest data is more than one resolution bar behind the current time (e.g. the first bar of the session + // has not been emitted yet after the open, or there is an intraday data gap). This is independent of the + // time of day. Coarse resolutions (hour/daily) always wait. Otherwise (data within one bar of the current + // time) keep filling on the stale price with the warning already set in fillMessage. + if (stalePrice && ShouldWaitForFreshDataOnStale(asset, staleDataEndTimeUtc, utcTime)) + { + return fill; + } fill.FillPrice = fillPrice; @@ -562,7 +567,7 @@ public override OrderEvent MarketOnOpenFill(Security asset, MarketOnOpenOrder or case OrderDirection.Buy: if (fill.FillPrice == 0) { - fill.FillPrice = GetBestEffortAskPrice(asset, order.Time, out bestEffortMessage, out _); + fill.FillPrice = GetBestEffortAskPrice(asset, order.Time, out bestEffortMessage, out _, out _); fill.Message += bestEffortMessage; } @@ -571,7 +576,7 @@ public override OrderEvent MarketOnOpenFill(Security asset, MarketOnOpenOrder or case OrderDirection.Sell: if (fill.FillPrice == 0) { - fill.FillPrice = GetBestEffortBidPrice(asset, order.Time, out bestEffortMessage, out _); + fill.FillPrice = GetBestEffortBidPrice(asset, order.Time, out bestEffortMessage, out _, out _); fill.Message += bestEffortMessage; } @@ -673,7 +678,7 @@ public override OrderEvent MarketOnCloseFill(Security asset, MarketOnCloseOrder case OrderDirection.Buy: if (fill.FillPrice == 0) { - fill.FillPrice = GetBestEffortAskPrice(asset, order.Time, out bestEffortMessage, out _); + fill.FillPrice = GetBestEffortAskPrice(asset, order.Time, out bestEffortMessage, out _, out _); fill.Message += bestEffortMessage; } @@ -682,7 +687,7 @@ public override OrderEvent MarketOnCloseFill(Security asset, MarketOnCloseOrder case OrderDirection.Sell: if (fill.FillPrice == 0) { - fill.FillPrice = GetBestEffortBidPrice(asset, order.Time, out bestEffortMessage, out _); + fill.FillPrice = GetBestEffortBidPrice(asset, order.Time, out bestEffortMessage, out _, out _); fill.Message += bestEffortMessage; } @@ -726,10 +731,13 @@ protected override HashSet GetSubscribedTypes(Security asset) /// Information about the best effort, whether prices are stale or need to use trade information /// True when no price within the stale price window was found and the returned best /// effort price comes from stale (already past) data, in which case the caller should wait for fresh data - private decimal GetBestEffortAskPrice(Security asset, DateTime orderTime, out string message, out bool stalePrice) + /// When is true, the end time (in UTC) of the + /// stale data the price comes from, so the caller can measure how far behind the current time it is + private decimal GetBestEffortAskPrice(Security asset, DateTime orderTime, out string message, out bool stalePrice, out DateTime staleDataEndTimeUtc) { message = string.Empty; stalePrice = false; + staleDataEndTimeUtc = default; BaseData baseData = null; var bestEffortAskPrice = 0m; @@ -813,6 +821,7 @@ private decimal GetBestEffortAskPrice(Security asset, DateTime orderTime, out st if (baseData != null) { stalePrice = true; + staleDataEndTimeUtc = baseData.EndTime.ConvertToUtc(asset.Exchange.TimeZone); return bestEffortAskPrice; } @@ -829,10 +838,13 @@ private decimal GetBestEffortAskPrice(Security asset, DateTime orderTime, out st /// Information about the best effort, whether prices are stale or need to use trade information /// True when no price within the stale price window was found and the returned best /// effort price comes from stale (already past) data, in which case the caller should wait for fresh data - private decimal GetBestEffortBidPrice(Security asset, DateTime orderTime, out string message, out bool stalePrice) + /// When is true, the end time (in UTC) of the + /// stale data the price comes from, so the caller can measure how far behind the current time it is + private decimal GetBestEffortBidPrice(Security asset, DateTime orderTime, out string message, out bool stalePrice, out DateTime staleDataEndTimeUtc) { message = string.Empty; stalePrice = false; + staleDataEndTimeUtc = default; BaseData baseData = null; var bestEffortBidPrice = 0m; @@ -916,6 +928,7 @@ private decimal GetBestEffortBidPrice(Security asset, DateTime orderTime, out st if (baseData != null) { stalePrice = true; + staleDataEndTimeUtc = baseData.EndTime.ConvertToUtc(asset.Exchange.TimeZone); return bestEffortBidPrice; } diff --git a/Common/Orders/Fills/FillModel.cs b/Common/Orders/Fills/FillModel.cs index d8629c08a926..13517ea02922 100644 --- a/Common/Orders/Fills/FillModel.cs +++ b/Common/Orders/Fills/FillModel.cs @@ -16,6 +16,7 @@ using System; using System.Collections.Generic; using System.Linq; +using QuantConnect.Data; using QuantConnect.Data.Market; using QuantConnect.Python; using QuantConnect.Orders.Fees; @@ -292,13 +293,13 @@ private OrderEvent InternalMarketFill(Security asset, Order order, decimal quant var prices = GetPricesCheckingPythonWrapper(asset, orderDirection); var pricesEndTimeUtc = prices.EndTime.ConvertToUtc(asset.Exchange.TimeZone); - // If the order would be filled on stale (fill-forward / already past) data: for coarse resolutions - // (hour/daily) wait for fresh data, e.g. the next bar to close, instead of filling at a stale price - // (the latest bar is the stale previous close when a market order is placed mid-bar). For finer - // resolutions (minute/second/tick) keep the previous behavior of filling on the stale price with a warning. + // If the order would be filled on stale (fill-forward / already past) data, wait for fresh data instead of + // filling at a stale price when the latest data is more than one resolution bar behind the current time + // (e.g. the first bar of the session after the open, or an intraday data gap). Otherwise fill on the stale + // price with a warning. if (pricesEndTimeUtc.Add(Parameters.StalePriceTimeSpan) < order.Time) { - if (ShouldWaitForFreshData(asset)) + if (ShouldWaitForFreshDataOnStale(asset, pricesEndTimeUtc, utcTime)) { return fill; } @@ -990,6 +991,45 @@ protected bool ShouldWaitForFreshData(Security asset) return configs.Count > 0 && configs.All(x => x.Resolution == Resolution.Hour || x.Resolution == Resolution.Daily); } + /// + /// Determines whether a market order that would be filled on stale data should wait for fresh data instead of + /// filling on the stale price. The order waits when the latest available data is more than one subscribed + /// resolution span behind the current time, i.e. the data is older than a single bar so a newer one is still + /// expected. This is independent of the time of day: it covers the market open (the first bar of the session + /// has not been emitted yet) as well as any intraday data gap larger than the resolution. + /// + /// Coarse resolutions (hour/daily) always wait, since there the stale bar is the previous close and the gap to + /// the current time can be smaller than the resolution while a fresh bar is still expected. Tick subscriptions + /// never wait, since there is no bar to expect. + /// + /// Security being filled + /// End time, in UTC, of the latest data available for the fill + /// Current time of the security, in UTC + protected bool ShouldWaitForFreshDataOnStale(Security asset, DateTime dataEndTimeUtc, DateTime currentTimeUtc) + { + if (ShouldWaitForFreshData(asset)) + { + return true; + } + + // Use the lowest (finest) subscribed resolution to size a single bar. Internal configurations are included + // because, even though their data is not sent to the algorithm, they still drive the security cache and the + // data used for the fill. + var resolutionSpan = Parameters.ConfigProvider + .GetSubscriptionDataConfigs(asset.Symbol, includeInternalConfigs: true) + .GetHighestResolution() + .ToTimeSpan(); + + // Tick data has no bar to wait for (zero span) + if (resolutionSpan == TimeSpan.Zero) + { + return false; + } + + // Wait when the latest available data is more than one resolution bar behind the current time + return currentTimeUtc - dataEndTimeUtc > resolutionSpan; + } + /// /// Gets the fill price for a market order. A hour/daily market order that was resting before the current bar /// opened - it predates the bar, e.g. it was placed after the previous close or while waiting for fresh data - diff --git a/Common/Orders/Fills/FutureFillModel.cs b/Common/Orders/Fills/FutureFillModel.cs index 45e01d96b60f..6193019fe9a4 100644 --- a/Common/Orders/Fills/FutureFillModel.cs +++ b/Common/Orders/Fills/FutureFillModel.cs @@ -46,12 +46,13 @@ public override OrderEvent MarketFill(Security asset, MarketOrder order) var prices = GetPricesCheckingPythonWrapper(asset, order.Direction); var pricesEndTimeUtc = prices.EndTime.ConvertToUtc(asset.Exchange.TimeZone); - // If the order would be filled on stale (fill-forward / already past) data: for coarse resolutions - // (hour/daily) wait for fresh data, e.g. the next bar to close, instead of filling at a stale price. - // For finer resolutions (minute/second/tick) keep filling on the stale price with a warning. + // If the order would be filled on stale (fill-forward / already past) data, wait for fresh data instead of + // filling at a stale price when the latest data is more than one resolution bar behind the current time + // (e.g. the first bar of the session after the open, or an intraday data gap). Otherwise fill on the stale + // price with a warning. if (pricesEndTimeUtc.Add(Parameters.StalePriceTimeSpan) < order.Time) { - if (ShouldWaitForFreshData(asset)) + if (ShouldWaitForFreshDataOnStale(asset, pricesEndTimeUtc, utcTime)) { return fill; } diff --git a/Data/equity/usa/minute/goog/20151228_quote.zip b/Data/equity/usa/minute/goog/20151228_quote.zip new file mode 100644 index 000000000000..8a453368b18a Binary files /dev/null and b/Data/equity/usa/minute/goog/20151228_quote.zip differ diff --git a/Data/equity/usa/minute/goog/20151228_trade.zip b/Data/equity/usa/minute/goog/20151228_trade.zip new file mode 100644 index 000000000000..8a8d6007ba2f Binary files /dev/null and b/Data/equity/usa/minute/goog/20151228_trade.zip differ diff --git a/Data/equity/usa/minute/twx/20140623_trade.zip b/Data/equity/usa/minute/twx/20140623_trade.zip new file mode 100644 index 000000000000..4f8f55cbc9fe Binary files /dev/null and b/Data/equity/usa/minute/twx/20140623_trade.zip differ diff --git a/Data/future/cme/daily/es_quote.zip b/Data/future/cme/daily/es_quote.zip index 7ebc84fd2043..f5541805447a 100644 Binary files a/Data/future/cme/daily/es_quote.zip and b/Data/future/cme/daily/es_quote.zip differ diff --git a/Data/future/cme/daily/es_trade.zip b/Data/future/cme/daily/es_trade.zip index 4301cb0a998e..82f690aa6a77 100644 Binary files a/Data/future/cme/daily/es_trade.zip and b/Data/future/cme/daily/es_trade.zip differ diff --git a/Data/future/cme/minute/es/20131014_quote.zip b/Data/future/cme/minute/es/20131014_quote.zip new file mode 100644 index 000000000000..4f7ab09d199a Binary files /dev/null and b/Data/future/cme/minute/es/20131014_quote.zip differ diff --git a/Data/future/cme/minute/es/20131014_trade.zip b/Data/future/cme/minute/es/20131014_trade.zip new file mode 100644 index 000000000000..268730ce9cf6 Binary files /dev/null and b/Data/future/cme/minute/es/20131014_trade.zip differ diff --git a/Data/future/cme/minute/es/20131029_quote.zip b/Data/future/cme/minute/es/20131029_quote.zip new file mode 100644 index 000000000000..b2c7bc9f6364 Binary files /dev/null and b/Data/future/cme/minute/es/20131029_quote.zip differ diff --git a/Data/future/cme/minute/es/20131029_trade.zip b/Data/future/cme/minute/es/20131029_trade.zip new file mode 100644 index 000000000000..7e930ef3dbd6 Binary files /dev/null and b/Data/future/cme/minute/es/20131029_trade.zip differ diff --git a/Data/future/cme/minute/es/20131030_quote.zip b/Data/future/cme/minute/es/20131030_quote.zip new file mode 100644 index 000000000000..034e55a605b2 Binary files /dev/null and b/Data/future/cme/minute/es/20131030_quote.zip differ diff --git a/Data/future/cme/minute/es/20131030_trade.zip b/Data/future/cme/minute/es/20131030_trade.zip new file mode 100644 index 000000000000..5c530cb24114 Binary files /dev/null and b/Data/future/cme/minute/es/20131030_trade.zip differ diff --git a/Data/future/cme/minute/es/20131203_quote.zip b/Data/future/cme/minute/es/20131203_quote.zip new file mode 100644 index 000000000000..d4257ab5de89 Binary files /dev/null and b/Data/future/cme/minute/es/20131203_quote.zip differ diff --git a/Data/future/cme/minute/es/20131203_trade.zip b/Data/future/cme/minute/es/20131203_trade.zip new file mode 100644 index 000000000000..2aed24a62977 Binary files /dev/null and b/Data/future/cme/minute/es/20131203_trade.zip differ diff --git a/Data/future/comex/minute/gc/20200106_quote.zip b/Data/future/comex/minute/gc/20200106_quote.zip new file mode 100644 index 000000000000..c8fddf3a8418 Binary files /dev/null and b/Data/future/comex/minute/gc/20200106_quote.zip differ diff --git a/Data/future/comex/minute/gc/20200106_trade.zip b/Data/future/comex/minute/gc/20200106_trade.zip new file mode 100644 index 000000000000..eabe7a602349 Binary files /dev/null and b/Data/future/comex/minute/gc/20200106_trade.zip differ diff --git a/Data/futureoption/comex/minute/og/202004/20200106_quote_american.zip b/Data/futureoption/comex/minute/og/202004/20200106_quote_american.zip new file mode 100644 index 000000000000..4a26f7e06fc1 Binary files /dev/null and b/Data/futureoption/comex/minute/og/202004/20200106_quote_american.zip differ diff --git a/Data/indexoption/usa/minute/spxw/20210105_quote_european.zip b/Data/indexoption/usa/minute/spxw/20210105_quote_european.zip new file mode 100644 index 000000000000..a7a5e8a2c247 Binary files /dev/null and b/Data/indexoption/usa/minute/spxw/20210105_quote_european.zip differ diff --git a/Data/indexoption/usa/minute/spxw/20210105_trade_european.zip b/Data/indexoption/usa/minute/spxw/20210105_trade_european.zip new file mode 100644 index 000000000000..86413ab79745 Binary files /dev/null and b/Data/indexoption/usa/minute/spxw/20210105_trade_european.zip differ diff --git a/Data/indexoption/usa/minute/spxw/20210106_quote_european.zip b/Data/indexoption/usa/minute/spxw/20210106_quote_european.zip new file mode 100644 index 000000000000..5c0ba0a15636 Binary files /dev/null and b/Data/indexoption/usa/minute/spxw/20210106_quote_european.zip differ diff --git a/Data/indexoption/usa/minute/spxw/20210106_trade_european.zip b/Data/indexoption/usa/minute/spxw/20210106_trade_european.zip new file mode 100644 index 000000000000..c4d00470b4fe Binary files /dev/null and b/Data/indexoption/usa/minute/spxw/20210106_trade_european.zip differ diff --git a/Data/indexoption/usa/minute/spxw/20210107_quote_european.zip b/Data/indexoption/usa/minute/spxw/20210107_quote_european.zip new file mode 100644 index 000000000000..ca85e7570a2b Binary files /dev/null and b/Data/indexoption/usa/minute/spxw/20210107_quote_european.zip differ diff --git a/Data/indexoption/usa/minute/spxw/20210107_trade_european.zip b/Data/indexoption/usa/minute/spxw/20210107_trade_european.zip new file mode 100644 index 000000000000..0ca8385b51d9 Binary files /dev/null and b/Data/indexoption/usa/minute/spxw/20210107_trade_european.zip differ diff --git a/Data/indexoption/usa/minute/spxw/20210108_quote_european.zip b/Data/indexoption/usa/minute/spxw/20210108_quote_european.zip new file mode 100644 index 000000000000..a81cfdb209ab Binary files /dev/null and b/Data/indexoption/usa/minute/spxw/20210108_quote_european.zip differ diff --git a/Data/indexoption/usa/minute/spxw/20210108_trade_european.zip b/Data/indexoption/usa/minute/spxw/20210108_trade_european.zip new file mode 100644 index 000000000000..4d6429c9bf04 Binary files /dev/null and b/Data/indexoption/usa/minute/spxw/20210108_trade_european.zip differ diff --git a/Data/option/usa/minute/goog/20151228_quote_american.zip b/Data/option/usa/minute/goog/20151228_quote_american.zip new file mode 100644 index 000000000000..e1e6292615bf Binary files /dev/null and b/Data/option/usa/minute/goog/20151228_quote_american.zip differ diff --git a/Data/option/usa/minute/goog/20151228_trade_american.zip b/Data/option/usa/minute/goog/20151228_trade_american.zip new file mode 100644 index 000000000000..e4a85c7304d1 Binary files /dev/null and b/Data/option/usa/minute/goog/20151228_trade_american.zip differ diff --git a/Tests/Common/Orders/Fills/BackwardsCompatibilityFillModelsTests.cs b/Tests/Common/Orders/Fills/BackwardsCompatibilityFillModelsTests.cs index a9151ccb01ca..f45c375fc655 100644 --- a/Tests/Common/Orders/Fills/BackwardsCompatibilityFillModelsTests.cs +++ b/Tests/Common/Orders/Fills/BackwardsCompatibilityFillModelsTests.cs @@ -57,6 +57,9 @@ public void SetUp() var referenceUtc = reference.ConvertToUtc(TimeZones.NewYork); var timeKeeper = new TimeKeeper(referenceUtc); _security.SetLocalTimeKeeper(timeKeeper.GetLocalTimeKeeper(TimeZones.NewYork)); + // Seed fresh market data so market fills are not held back as stale (data within one resolution bar + // of the current time). These tests exercise the fill model plumbing, not the stale-data handling. + _security.SetMarketPrice(new TradeBar(reference.AddMinutes(-1), _security.Symbol, 1m, 1m, 1m, 1m, 1, Time.OneMinute)); } #region InheritImmediateFillModel diff --git a/Tests/Common/Orders/Fills/EquityFillModelTests.cs b/Tests/Common/Orders/Fills/EquityFillModelTests.cs index 5ef644f71454..8dc4c81bbe7a 100644 --- a/Tests/Common/Orders/Fills/EquityFillModelTests.cs +++ b/Tests/Common/Orders/Fills/EquityFillModelTests.cs @@ -47,7 +47,8 @@ public void Setup() [TestCase(11, 11, 11, "")] [TestCase(12, 11, 11, "")] [TestCase(12, 10, 11, "Warning: No quote information")] - [TestCase(12, 10, 10, "Warning: fill at stale price")] + // Note: a (12, 10, 10) case where the only data is a stale (>1h old) minute bar no longer fills; it now waits + // for fresh data. That behavior is covered by MarketOrderWaitsForFreshDataWhenStaleByMoreThanResolution. public void PerformsMarketFillBuy(int orderHour, int quoteBarHour, int tradeBarHour, string message) { var configTradeBar = CreateTradeBarConfig(Symbols.SPY); @@ -90,7 +91,8 @@ public void PerformsMarketFillBuy(int orderHour, int quoteBarHour, int tradeBarH [TestCase(11, 11, 11, "")] [TestCase(12, 11, 11, "")] [TestCase(12, 10, 11, "Warning: No quote information")] - [TestCase(12, 10, 10, "Warning: fill at stale price")] + // Note: a (12, 10, 10) case where the only data is a stale (>1h old) minute bar no longer fills; it now waits + // for fresh data. That behavior is covered by MarketOrderWaitsForFreshDataWhenStaleByMoreThanResolution. public void PerformsMarketFillSell(int orderHour, int quoteBarHour, int tradeBarHour, string message) { var configTradeBar = CreateTradeBarConfig(Symbols.SPY); @@ -1092,12 +1094,14 @@ public void EquityFillModelUsesPriceForTicksWhenBidAskSpreadsAreNotAvailable() security.SetMarketPrice(new IndicatorDataPoint(Symbols.SPY, noon, 101.123m)); // Add both a tradebar and a tick to the security cache - // This is the case when a tick is seeded with minute data in an algorithm - security.Cache.AddData(new TradeBar(DateTime.MinValue, symbol, 1.0m, 1.0m, 1.0m, 1.0m, 1.0m)); - security.Cache.AddData(new Tick(config, "42525000,1000000,100,A,@,0", DateTime.MinValue)); + // This is the case when a tick is seeded with minute data in an algorithm. + // Use fresh timestamps (data within one resolution bar of the current time) so the fill is not held + // back as stale; this test is about which data type is used, not stale-data handling. + security.Cache.AddData(new TradeBar(noon.AddMinutes(-1), symbol, 1.0m, 1.0m, 1.0m, 1.0m, 1.0m, Time.OneMinute)); + security.Cache.AddData(new Tick(config, "42525000,1000000,100,A,@,0", noon.Date)); var fillModel = new EquityFillModel(); - var order = new MarketOrder(symbol, 1000, DateTime.Now); + var order = new MarketOrder(symbol, 1000, noon); var fill = fillModel.Fill(new FillModelParameters( security, order, @@ -1131,12 +1135,14 @@ public void EquityFillModelDoesNotUseTicksWhenThereIsNoTickSubscription() security.SetMarketPrice(new IndicatorDataPoint(Symbols.SPY, noon, 101.123m)); - // This is the case when a tick is seeded with minute data in an algorithm - security.Cache.AddData(new TradeBar(DateTime.MinValue, symbol, 1.0m, 1.0m, 1.0m, 1.0m, 1.0m)); - security.Cache.AddData(new Tick(config, "42525000,1000000,100,A,@,0", DateTime.MinValue)); + // This is the case when a tick is seeded with minute data in an algorithm. + // Use fresh timestamps (data within one resolution bar of the current time) so the fill is not held + // back as stale; this test is about which data type is used, not stale-data handling. + security.Cache.AddData(new TradeBar(noon.AddMinutes(-1), symbol, 1.0m, 1.0m, 1.0m, 1.0m, 1.0m, Time.OneMinute)); + security.Cache.AddData(new Tick(config, "42525000,1000000,100,A,@,0", noon.Date)); var fillModel = new EquityFillModel(); - var order = new MarketOrder(symbol, 1000, DateTime.Now); + var order = new MarketOrder(symbol, 1000, noon); var fill = fillModel.Fill(new FillModelParameters( security, order, @@ -1235,6 +1241,98 @@ public void MarketOrderFillWithStalePriceHasWarningMessage() Assert.IsTrue(fill.Message.Contains("Warning: fill at stale price")); } + // A market order whose only available data is stale by more than one resolution bar must wait for fresh data + // instead of filling on the stale price. This is independent of the time of day: + // - "market open": order one second after the open, only the previous session's bar is available (overnight gap) + // - "mid-session": order at noon, the latest bar is two hours old (e.g. an intraday data gap) + [TestCase(true, OrderDirection.Buy)] + [TestCase(true, OrderDirection.Sell)] + [TestCase(false, OrderDirection.Buy)] + [TestCase(false, OrderDirection.Sell)] + public void MarketOrderWaitsForFreshDataWhenStaleByMoreThanResolution(bool atMarketOpen, OrderDirection direction) + { + var config = CreateTradeBarConfig(Symbols.SPY, Resolution.Minute); + var configProvider = new MockSubscriptionDataConfigProvider(config); + configProvider.SubscriptionDataConfigs.Add(config); + var equity = CreateEquity(config); + var model = (EquityFillModel)equity.FillModel; + + // US equity market opens at 9:30 + var orderTime = atMarketOpen + ? new DateTime(2014, 6, 24, 9, 30, 1) // one second after the open + : new DateTime(2014, 6, 24, 12, 0, 0); // mid-session + var staleBarEnd = atMarketOpen + ? new DateTime(2014, 6, 23, 16, 0, 0) // previous session close (overnight gap) + : new DateTime(2014, 6, 24, 10, 0, 0); // two hours old + + var timeKeeper = TimeKeeper.GetLocalTimeKeeper(TimeZones.NewYork); + timeKeeper.UpdateTime(orderTime.ConvertToUtc(TimeZones.NewYork)); + equity.SetLocalTimeKeeper(timeKeeper); + + const decimal staleClose = 101.123m; + equity.SetMarketPrice(new TradeBar(staleBarEnd.Add(-Time.OneMinute), Symbols.SPY, + 101m, 101.2m, 100.9m, staleClose, 100, Time.OneMinute)); + + var quantity = direction == OrderDirection.Buy ? 100 : -100; + var order = new MarketOrder(Symbols.SPY, quantity, orderTime.ConvertToUtc(equity.Exchange.TimeZone)); + var parameters = new FillModelParameters(equity, order, configProvider, Time.OneHour, null); + + // The latest data is more than one resolution bar (minute) behind: must not fill on the stale price + var fill = model.Fill(parameters).Single(); + Assert.AreNotEqual(OrderStatus.Filled, fill.Status); + Assert.AreNotEqual(OrderStatus.PartiallyFilled, fill.Status); + Assert.AreEqual(0, fill.FillQuantity); + + // Once a fresh bar (within one resolution of the current time) is available, the order fills on it + const decimal freshClose = 102.345m; + var freshBarEnd = orderTime.RoundDown(Time.OneMinute).Add(Time.OneMinute); + timeKeeper.UpdateTime(freshBarEnd.ConvertToUtc(TimeZones.NewYork)); + equity.SetLocalTimeKeeper(timeKeeper); + equity.SetMarketPrice(new TradeBar(freshBarEnd.Add(-Time.OneMinute), Symbols.SPY, + 102m, 102.5m, 101.9m, freshClose, 100, Time.OneMinute)); + + fill = model.Fill(parameters).Single(); + + Assert.AreEqual(OrderStatus.Filled, fill.Status); + Assert.AreEqual(order.Quantity, fill.FillQuantity); + Assert.AreEqual(freshClose, fill.FillPrice); + } + + // A market order fills on stale data when the gap to the current time is within one resolution bar (the data is + // detected as stale by the stale-price window, but a fresh bar is not yet expected). + [TestCase(OrderDirection.Buy)] + [TestCase(OrderDirection.Sell)] + public void MarketOrderFillsOnStaleDataWithinOneResolutionBar(OrderDirection direction) + { + var config = CreateTradeBarConfig(Symbols.SPY, Resolution.Minute); + var configProvider = new MockSubscriptionDataConfigProvider(config); + configProvider.SubscriptionDataConfigs.Add(config); + var equity = CreateEquity(config); + var model = (EquityFillModel)equity.FillModel; + + var orderTime = new DateTime(2014, 6, 24, 12, 0, 0); + var timeKeeper = TimeKeeper.GetLocalTimeKeeper(TimeZones.NewYork); + timeKeeper.UpdateTime(orderTime.ConvertToUtc(TimeZones.NewYork)); + equity.SetLocalTimeKeeper(timeKeeper); + + // Data 30 seconds old: with a zero stale-price window it is detected as stale, but the gap is smaller than + // the minute resolution, so a fresh bar is not yet expected and the order should fill on the stale price. + const decimal staleClose = 101.123m; + var staleBarEnd = orderTime.AddSeconds(-30); + equity.SetMarketPrice(new TradeBar(staleBarEnd.Add(-Time.OneMinute), Symbols.SPY, + 101m, 101.2m, 100.9m, staleClose, 100, Time.OneMinute)); + + var quantity = direction == OrderDirection.Buy ? 100 : -100; + var order = new MarketOrder(Symbols.SPY, quantity, orderTime.ConvertToUtc(equity.Exchange.TimeZone)); + var parameters = new FillModelParameters(equity, order, configProvider, TimeSpan.Zero, null); + + var fill = model.Fill(parameters).Single(); + + Assert.AreEqual(OrderStatus.Filled, fill.Status); + Assert.AreEqual(order.Quantity, fill.FillQuantity); + Assert.AreEqual(staleClose, fill.FillPrice); + } + [TestCase(OrderDirection.Sell, 11)] [TestCase(OrderDirection.Buy, 21)] // uses the trade bar last close diff --git a/Tests/Common/Orders/Fills/FutureFillModelTests.cs b/Tests/Common/Orders/Fills/FutureFillModelTests.cs index d4ffd1426c11..a62469b92f5a 100644 --- a/Tests/Common/Orders/Fills/FutureFillModelTests.cs +++ b/Tests/Common/Orders/Fills/FutureFillModelTests.cs @@ -109,6 +109,54 @@ public void PerformsStopMarketFill( } + // A market order whose only available data is stale by more than one resolution bar must wait for fresh data + // instead of filling on the stale price, independent of the time of day: right at the session open (the first + // bar has not been emitted yet) and mid-session (an intraday data gap). + [TestCase(false, OrderDirection.Buy)] + [TestCase(false, OrderDirection.Sell)] + [TestCase(true, OrderDirection.Buy)] + [TestCase(true, OrderDirection.Sell)] + public void MarketOrderWaitsForFreshDataWhenStaleByMoreThanResolution(bool midSession, OrderDirection orderDirection) + { + var model = new FutureFillModel(); + var config = CreateTradeBarConfig(Symbols.ES_Future_Chain); + var security = GetSecurity(config); + var quantity = orderDirection == OrderDirection.Buy ? 100 : -100; + + var sessionOpen = security.Exchange.Hours.GetPreviousMarketOpen(Noon, extendedMarketHours: false); + // One second into the first bar of the session, or mid-session at noon + var orderTime = midSession ? Noon : sessionOpen.AddSeconds(1); + + var timeKeeper = new TimeKeeper(orderTime.ConvertToUtc(TimeZones.NewYork), new[] { TimeZones.NewYork }); + security.SetLocalTimeKeeper(timeKeeper.GetLocalTimeKeeper(TimeZones.NewYork)); + + // Only a stale bar (two hours old, more than one resolution bar behind) is available in the cache + const decimal staleClose = 101.123m; + security.SetMarketPrice(new TradeBar(orderTime.AddHours(-2), Symbols.ES_Future_Chain, + 101m, 101.2m, 100.9m, staleClose, 100, Time.OneMinute)); + + var order = new MarketOrder(Symbols.ES_Future_Chain, quantity, orderTime.ConvertToUtc(TimeZones.NewYork)); + var parameters = new FillModelParameters(security, order, new MockSubscriptionDataConfigProvider(config), Time.OneHour, null); + + // The latest data is more than one resolution bar (minute) behind: must not fill on the stale price + var fill = model.Fill(parameters).Single(); + Assert.AreNotEqual(OrderStatus.Filled, fill.Status); + Assert.AreNotEqual(OrderStatus.PartiallyFilled, fill.Status); + Assert.AreEqual(0, fill.FillQuantity); + + // Once a fresh bar (within one resolution of the current time) is available, the order fills on it + const decimal freshClose = 102.345m; + var freshBarEnd = orderTime.RoundDown(Time.OneMinute).Add(Time.OneMinute); + timeKeeper.SetUtcDateTime(freshBarEnd.ConvertToUtc(TimeZones.NewYork)); + security.SetMarketPrice(new TradeBar(freshBarEnd.Add(-Time.OneMinute), Symbols.ES_Future_Chain, + 102m, 102.5m, 101.9m, freshClose, 100, Time.OneMinute)); + + fill = model.Fill(parameters).Single(); + Assert.AreEqual(OrderStatus.Filled, fill.Status); + Assert.AreEqual(order.Quantity, fill.FillQuantity); + Assert.AreEqual(freshClose, fill.FillPrice); + } + private SubscriptionDataConfig CreateTradeBarConfig(Symbol symbol, bool isInternal = false, bool extendedMarketHours = true) { return new SubscriptionDataConfig(typeof(TradeBar), symbol, Resolution.Minute, TimeZones.NewYork, TimeZones.NewYork, true, extendedMarketHours, isInternal); diff --git a/Tests/Common/Orders/Fills/ImmediateFillModelTests.cs b/Tests/Common/Orders/Fills/ImmediateFillModelTests.cs index 931271f91c37..3582a44ec67a 100644 --- a/Tests/Common/Orders/Fills/ImmediateFillModelTests.cs +++ b/Tests/Common/Orders/Fills/ImmediateFillModelTests.cs @@ -971,12 +971,14 @@ public void ImmediateFillModelUsesPriceForTicksWhenBidAskSpreadsAreNotAvailable( security.SetMarketPrice(new IndicatorDataPoint(Symbols.SPY, noon, 101.123m)); // Add both a tradebar and a tick to the security cache - // This is the case when a tick is seeded with minute data in an algorithm - security.Cache.AddData(new TradeBar(DateTime.MinValue, symbol, 1.0m, 1.0m, 1.0m, 1.0m, 1.0m)); - security.Cache.AddData(new Tick(config, "42525000,1000000,100,A,@,0", DateTime.MinValue)); + // This is the case when a tick is seeded with minute data in an algorithm. + // Use fresh timestamps (data within one resolution bar of the current time) so the fill is not held + // back as stale; this test is about which data type is used, not stale-data handling. + security.Cache.AddData(new TradeBar(noon.AddMinutes(-1), symbol, 1.0m, 1.0m, 1.0m, 1.0m, 1.0m, Time.OneMinute)); + security.Cache.AddData(new Tick(config, "42525000,1000000,100,A,@,0", noon.Date)); var fillModel = new ImmediateFillModel(); - var order = new MarketOrder(symbol, 1000, DateTime.Now); + var order = new MarketOrder(symbol, 1000, noon); var fill = fillModel.Fill(new FillModelParameters( security, order, @@ -1003,12 +1005,14 @@ public void ImmediateFillModelDoesNotUseTicksWhenThereIsNoTickSubscription(bool security.SetMarketPrice(new IndicatorDataPoint(Symbols.SPY, noon, 101.123m)); - // This is the case when a tick is seeded with minute data in an algorithm - security.Cache.AddData(new TradeBar(DateTime.MinValue, symbol, 1.0m, 1.0m, 1.0m, 1.0m, 1.0m)); - security.Cache.AddData(new Tick(config, "42525000,1000000,100,A,@,0", DateTime.MinValue)); + // This is the case when a tick is seeded with minute data in an algorithm. + // Use fresh timestamps (data within one resolution bar of the current time) so the fill is not held + // back as stale; this test is about which data type is used, not stale-data handling. + security.Cache.AddData(new TradeBar(noon.AddMinutes(-1), symbol, 1.0m, 1.0m, 1.0m, 1.0m, 1.0m, Time.OneMinute)); + security.Cache.AddData(new Tick(config, "42525000,1000000,100,A,@,0", noon.Date)); var fillModel = new ImmediateFillModel(); - var order = new MarketOrder(symbol, 1000, DateTime.Now); + var order = new MarketOrder(symbol, 1000, noon); var fill = fillModel.Fill(new FillModelParameters( security, order, diff --git a/Tests/Research/QuantBookHistoryTests.cs b/Tests/Research/QuantBookHistoryTests.cs index 5f66ce9c50af..a4c940bd8310 100644 --- a/Tests/Research/QuantBookHistoryTests.cs +++ b/Tests/Research/QuantBookHistoryTests.cs @@ -528,8 +528,8 @@ public void OptionHistorySpecifyingFillForwardAndExtendedMarket(bool fillForward [TestCase(true, true, 8640)] [TestCase(true, false, 2700)] - [TestCase(false, true, 6899)] - [TestCase(false, false, 2249)] + [TestCase(false, true, 8279)] + [TestCase(false, false, 2699)] public void FutureHistorySpecifyingFillForwardAndExtendedMarket(bool fillForward, bool extendedMarket, int expectedCount) { using (Py.GIL())